src/roadveh_cmd.cpp
changeset 7928 63e18de69e50
parent 7924 7ef93d919eba
child 7929 6c9b25842b0f
equal deleted inserted replaced
7927:3a3289a049f9 7928:63e18de69e50
   175 	/* The ai_new queries the vehicle cost before building the route,
   175 	/* The ai_new queries the vehicle cost before building the route,
   176 	 * so we must check against cheaters no sooner than now. --pasky */
   176 	 * so we must check against cheaters no sooner than now. --pasky */
   177 	if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR;
   177 	if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR;
   178 	if (!IsTileOwner(tile, _current_player)) return CMD_ERROR;
   178 	if (!IsTileOwner(tile, _current_player)) return CMD_ERROR;
   179 
   179 
   180 	if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE);
   180 	if (HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) != HasBit(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE);
   181 
   181 
   182 	uint num_vehicles = 1 + CountArticulatedParts(p1, false);
   182 	uint num_vehicles = 1 + CountArticulatedParts(p1, false);
   183 
   183 
   184 	/* Allow for the front and the articulated parts, plus one to "terminate" the list. */
   184 	/* Allow for the front and the articulated parts, plus one to "terminate" the list. */
   185 	Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
   185 	Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
   190 	}
   190 	}
   191 
   191 
   192 	v = vl[0];
   192 	v = vl[0];
   193 
   193 
   194 	/* find the first free roadveh id */
   194 	/* find the first free roadveh id */
   195 	unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD);
   195 	unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD);
   196 	if (unit_num > _patches.max_roadveh)
   196 	if (unit_num > _patches.max_roadveh)
   197 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   197 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   198 
   198 
   199 	if (flags & DC_EXEC) {
   199 	if (flags & DC_EXEC) {
   200 		int x;
   200 		int x;
   250 
   250 
   251 		v->cur_image = 0xC15;
   251 		v->cur_image = 0xC15;
   252 		v->random_bits = VehicleRandomBits();
   252 		v->random_bits = VehicleRandomBits();
   253 		SetRoadVehFront(v);
   253 		SetRoadVehFront(v);
   254 
   254 
   255 		v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
   255 		v->u.road.roadtype = HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
   256 		v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
   256 		v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
   257 		v->u.road.cached_veh_length = GetRoadVehLength(v);
   257 		v->u.road.cached_veh_length = GetRoadVehLength(v);
   258 
   258 
   259 		v->vehicle_flags = 0;
   259 		v->vehicle_flags = 0;
   260 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
   260 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
   474 
   474 
   475 	if (v->IsInDepot()) return CMD_ERROR;
   475 	if (v->IsInDepot()) return CMD_ERROR;
   476 
   476 
   477 	/* If the current orders are already goto-depot */
   477 	/* If the current orders are already goto-depot */
   478 	if (v->current_order.type == OT_GOTO_DEPOT) {
   478 	if (v->current_order.type == OT_GOTO_DEPOT) {
   479 		if (!!(p2 & DEPOT_SERVICE) == HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
   479 		if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
   480 			/* We called with a different DEPOT_SERVICE setting.
   480 			/* We called with a different DEPOT_SERVICE setting.
   481 			 * Now we change the setting to apply the new one and let the vehicle head for the same depot.
   481 			 * Now we change the setting to apply the new one and let the vehicle head for the same depot.
   482 			 * Note: the if is (true for requesting service == true for ordered to stop in depot) */
   482 			 * Note: the if is (true for requesting service == true for ordered to stop in depot) */
   483 			if (flags & DC_EXEC) {
   483 			if (flags & DC_EXEC) {
   484 				CLRBIT(v->current_order.flags, OFB_PART_OF_ORDERS);
   484 				CLRBIT(v->current_order.flags, OFB_PART_OF_ORDERS);
   490 
   490 
   491 		if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
   491 		if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
   492 		if (flags & DC_EXEC) {
   492 		if (flags & DC_EXEC) {
   493 			/* If the orders to 'goto depot' are in the orders list (forced servicing),
   493 			/* If the orders to 'goto depot' are in the orders list (forced servicing),
   494 			 * then skip to the next order; effectively cancelling this forced service */
   494 			 * then skip to the next order; effectively cancelling this forced service */
   495 			if (HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS))
   495 			if (HasBit(v->current_order.flags, OFB_PART_OF_ORDERS))
   496 				v->cur_order_index++;
   496 				v->cur_order_index++;
   497 
   497 
   498 			v->current_order.type = OT_DUMMY;
   498 			v->current_order.type = OT_DUMMY;
   499 			v->current_order.flags = 0;
   499 			v->current_order.flags = 0;
   500 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   500 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   595 
   595 
   596 	/* Mark the station entrance as not busy */
   596 	/* Mark the station entrance as not busy */
   597 	rs->SetEntranceBusy(false);
   597 	rs->SetEntranceBusy(false);
   598 
   598 
   599 	/* Free the parking bay */
   599 	/* Free the parking bay */
   600 	rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY));
   600 	rs->FreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY));
   601 }
   601 }
   602 
   602 
   603 static void DeleteLastRoadVeh(Vehicle *v)
   603 static void DeleteLastRoadVeh(Vehicle *v)
   604 {
   604 {
   605 	Vehicle *u = v;
   605 	Vehicle *u = v;
  1272 		best_track = INVALID_TRACKDIR;
  1272 		best_track = INVALID_TRACKDIR;
  1273 		uint best_dist = (uint)-1;
  1273 		uint best_dist = (uint)-1;
  1274 		uint best_maxlen = (uint)-1;
  1274 		uint best_maxlen = (uint)-1;
  1275 		uint bitmask = (uint)trackdirs;
  1275 		uint bitmask = (uint)trackdirs;
  1276 		for (int i = 0; bitmask != 0; bitmask >>= 1, i++) {
  1276 		for (int i = 0; bitmask != 0; bitmask >>= 1, i++) {
  1277 			if (HASBIT(bitmask, 0)) {
  1277 			if (HasBit(bitmask, 0)) {
  1278 				if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track
  1278 				if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track
  1279 				frd.maxtracklen = (uint)-1;
  1279 				frd.maxtracklen = (uint)-1;
  1280 				frd.mindist = (uint)-1;
  1280 				frd.mindist = (uint)-1;
  1281 				FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd);
  1281 				FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd);
  1282 
  1282 
  1289 		}
  1289 		}
  1290 	}
  1290 	}
  1291 
  1291 
  1292 found_best_track:;
  1292 found_best_track:;
  1293 
  1293 
  1294 	if (HASBIT(signal, best_track)) return INVALID_TRACKDIR;
  1294 	if (HasBit(signal, best_track)) return INVALID_TRACKDIR;
  1295 
  1295 
  1296 	return best_track;
  1296 	return best_track;
  1297 }
  1297 }
  1298 
  1298 
  1299 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
  1299 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
  1414 			diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
  1414 			diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
  1415 		}
  1415 		}
  1416 
  1416 
  1417 		if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
  1417 		if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
  1418 		dir = DiagdirToDiagTrackdir(diag_dir);
  1418 		dir = DiagdirToDiagTrackdir(diag_dir);
  1419 	} else if (HASBIT(prev_state, RVS_IN_DT_ROAD_STOP)) {
  1419 	} else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
  1420 		dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
  1420 		dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
  1421 	} else if (prev_state < TRACKDIR_END) {
  1421 	} else if (prev_state < TRACKDIR_END) {
  1422 		if (already_reversed && prev->tile != tile) {
  1422 		if (already_reversed && prev->tile != tile) {
  1423 			/*
  1423 			/*
  1424 			 * The vehicle has reversed, but did not go straight back.
  1424 			 * The vehicle has reversed, but did not go straight back.
  1517 		if (u != NULL && u->First()->cur_speed < v->cur_speed) {
  1517 		if (u != NULL && u->First()->cur_speed < v->cur_speed) {
  1518 			v->cur_speed = u->First()->cur_speed;
  1518 			v->cur_speed = u->First()->cur_speed;
  1519 			return false;
  1519 			return false;
  1520 		}
  1520 		}
  1521 
  1521 
  1522 		if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
  1522 		if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
  1523 			/* Vehicle has just entered a bridge or tunnel */
  1523 			/* Vehicle has just entered a bridge or tunnel */
  1524 			v->cur_image = v->GetImage(v->direction);
  1524 			v->cur_image = v->GetImage(v->direction);
  1525 			v->UpdateDeltaXY(v->direction);
  1525 			v->UpdateDeltaXY(v->direction);
  1526 			SetRoadVehPosition(v,gp.x,gp.y);
  1526 			SetRoadVehPosition(v,gp.x,gp.y);
  1527 			return true;
  1527 			return true;
  1536 
  1536 
  1537 	/* Get move position data for next frame.
  1537 	/* Get move position data for next frame.
  1538 	 * For a drive-through road stop use 'straight road' move data.
  1538 	 * For a drive-through road stop use 'straight road' move data.
  1539 	 * In this case v->u.road.state is masked to give the road stop entry direction. */
  1539 	 * In this case v->u.road.state is masked to give the road stop entry direction. */
  1540 	rd = _road_drive_data[v->u.road.roadtype][(
  1540 	rd = _road_drive_data[v->u.road.roadtype][(
  1541 		(HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) +
  1541 		(HasBit(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) +
  1542 		(_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
  1542 		(_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
  1543 
  1543 
  1544 	if (rd.x & RDE_NEXT_TILE) {
  1544 	if (rd.x & RDE_NEXT_TILE) {
  1545 		TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
  1545 		TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
  1546 		Trackdir dir;
  1546 		Trackdir dir;
  1631 				return false;
  1631 				return false;
  1632 			}
  1632 			}
  1633 		}
  1633 		}
  1634 
  1634 
  1635 		r = VehicleEnterTile(v, tile, x, y);
  1635 		r = VehicleEnterTile(v, tile, x, y);
  1636 		if (HASBIT(r, VETS_CANNOT_ENTER)) {
  1636 		if (HasBit(r, VETS_CANNOT_ENTER)) {
  1637 			if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
  1637 			if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
  1638 				v->cur_speed = 0;
  1638 				v->cur_speed = 0;
  1639 				return false;
  1639 				return false;
  1640 			}
  1640 			}
  1641 			/* Try an about turn to re-enter the previous tile */
  1641 			/* Try an about turn to re-enter the previous tile */
  1653 			if (IsRoadStop(v->tile)) {
  1653 			if (IsRoadStop(v->tile)) {
  1654 				RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
  1654 				RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
  1655 
  1655 
  1656 				/* Vehicle is leaving a road stop tile, mark bay as free
  1656 				/* Vehicle is leaving a road stop tile, mark bay as free
  1657 				 * For drive-through stops, only do it if the vehicle stopped here */
  1657 				 * For drive-through stops, only do it if the vehicle stopped here */
  1658 				if (IsStandardRoadStopTile(v->tile) || HASBIT(v->u.road.state, RVS_IS_STOPPING)) {
  1658 				if (IsStandardRoadStopTile(v->tile) || HasBit(v->u.road.state, RVS_IS_STOPPING)) {
  1659 					rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY));
  1659 					rs->FreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY));
  1660 					CLRBIT(v->u.road.state, RVS_IS_STOPPING);
  1660 					CLRBIT(v->u.road.state, RVS_IS_STOPPING);
  1661 				}
  1661 				}
  1662 				if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false);
  1662 				if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false);
  1663 			}
  1663 			}
  1664 		}
  1664 		}
  1665 
  1665 
  1666 		if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) {
  1666 		if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
  1667 			v->tile = tile;
  1667 			v->tile = tile;
  1668 			v->u.road.state = (byte)dir;
  1668 			v->u.road.state = (byte)dir;
  1669 			v->u.road.frame = start_frame;
  1669 			v->u.road.frame = start_frame;
  1670 		}
  1670 		}
  1671 		if (newdir != v->direction) {
  1671 		if (newdir != v->direction) {
  1728 
  1728 
  1729 		newdir = RoadVehGetSlidingDirection(v, x, y);
  1729 		newdir = RoadVehGetSlidingDirection(v, x, y);
  1730 		if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false;
  1730 		if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false;
  1731 
  1731 
  1732 		r = VehicleEnterTile(v, v->tile, x, y);
  1732 		r = VehicleEnterTile(v, v->tile, x, y);
  1733 		if (HASBIT(r, VETS_CANNOT_ENTER)) {
  1733 		if (HasBit(r, VETS_CANNOT_ENTER)) {
  1734 			v->cur_speed = 0;
  1734 			v->cur_speed = 0;
  1735 			return false;
  1735 			return false;
  1736 		}
  1736 		}
  1737 
  1737 
  1738 		v->u.road.state = dir;
  1738 		v->u.road.state = dir;
  1824 
  1824 
  1825 				/* Check if next inline bay is free */
  1825 				/* Check if next inline bay is free */
  1826 				if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) {
  1826 				if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) {
  1827 					RoadStop *rs_n = GetRoadStopByTile(next_tile, type);
  1827 					RoadStop *rs_n = GetRoadStopByTile(next_tile, type);
  1828 
  1828 
  1829 					if (rs_n->IsFreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY))) {
  1829 					if (rs_n->IsFreeBay(HasBit(v->u.road.state, RVS_USING_SECOND_BAY))) {
  1830 						/* Bay in next stop along is free - use it */
  1830 						/* Bay in next stop along is free - use it */
  1831 						ClearSlot(v);
  1831 						ClearSlot(v);
  1832 						rs_n->num_vehicles++;
  1832 						rs_n->num_vehicles++;
  1833 						v->u.road.slot = rs_n;
  1833 						v->u.road.slot = rs_n;
  1834 						v->dest_tile = rs_n->xy;
  1834 						v->dest_tile = rs_n->xy;
  1895 	}
  1895 	}
  1896 
  1896 
  1897 	/* Check tile position conditions - i.e. stop position in depot,
  1897 	/* Check tile position conditions - i.e. stop position in depot,
  1898 	 * entry onto bridge or into tunnel */
  1898 	 * entry onto bridge or into tunnel */
  1899 	r = VehicleEnterTile(v, v->tile, x, y);
  1899 	r = VehicleEnterTile(v, v->tile, x, y);
  1900 	if (HASBIT(r, VETS_CANNOT_ENTER)) {
  1900 	if (HasBit(r, VETS_CANNOT_ENTER)) {
  1901 		v->cur_speed = 0;
  1901 		v->cur_speed = 0;
  1902 		return false;
  1902 		return false;
  1903 	}
  1903 	}
  1904 
  1904 
  1905 	/* Move to next frame unless vehicle arrived at a stop position
  1905 	/* Move to next frame unless vehicle arrived at a stop position
  1906 	 * in a depot or entered a tunnel/bridge */
  1906 	 * in a depot or entered a tunnel/bridge */
  1907 	if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++;
  1907 	if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++;
  1908 
  1908 
  1909 	v->cur_image = v->GetImage(v->direction);
  1909 	v->cur_image = v->GetImage(v->direction);
  1910 	v->UpdateDeltaXY(v->direction);
  1910 	v->UpdateDeltaXY(v->direction);
  1911 	RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
  1911 	RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
  1912 	return true;
  1912 	return true;
  2124 {
  2124 {
  2125 	Vehicle *v;
  2125 	Vehicle *v;
  2126 	CommandCost cost;
  2126 	CommandCost cost;
  2127 	CargoID new_cid = GB(p2, 0, 8);
  2127 	CargoID new_cid = GB(p2, 0, 8);
  2128 	byte new_subtype = GB(p2, 8, 8);
  2128 	byte new_subtype = GB(p2, 8, 8);
  2129 	bool only_this = HASBIT(p2, 16);
  2129 	bool only_this = HasBit(p2, 16);
  2130 	uint16 capacity = CALLBACK_FAILED;
  2130 	uint16 capacity = CALLBACK_FAILED;
  2131 	uint total_capacity = 0;
  2131 	uint total_capacity = 0;
  2132 
  2132 
  2133 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  2133 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  2134 
  2134 
  2147 		 * [Refit] button near each wagon. */
  2147 		 * [Refit] button near each wagon. */
  2148 		if (!CanRefitTo(v->engine_type, new_cid)) continue;
  2148 		if (!CanRefitTo(v->engine_type, new_cid)) continue;
  2149 
  2149 
  2150 		if (v->cargo_cap == 0) continue;
  2150 		if (v->cargo_cap == 0) continue;
  2151 
  2151 
  2152 		if (HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
  2152 		if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
  2153 			/* Back up the cargo type */
  2153 			/* Back up the cargo type */
  2154 			CargoID temp_cid = v->cargo_type;
  2154 			CargoID temp_cid = v->cargo_type;
  2155 			byte temp_subtype = v->cargo_subtype;
  2155 			byte temp_subtype = v->cargo_subtype;
  2156 			v->cargo_type = new_cid;
  2156 			v->cargo_type = new_cid;
  2157 			v->cargo_subtype = new_subtype;
  2157 			v->cargo_subtype = new_subtype;