diff -r 70d78ac95d6c -r 7bd07f43b0e3 src/vehicle.cpp --- a/src/vehicle.cpp Mon Mar 19 09:33:17 2007 +0000 +++ b/src/vehicle.cpp Mon Mar 19 12:38:16 2007 +0000 @@ -37,7 +37,6 @@ #include "newgrf_engine.h" #include "newgrf_sound.h" #include "helpers.hpp" -#include "cargotype.h" #define INVALID_COORD (-0x8000) #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6)) @@ -87,7 +86,7 @@ * TODO - This is just a temporary stage, this will be removed. */ for (v = GetVehicle(start_item); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) { v->index = start_item++; - v->type = VEH_Invalid; + v->type = VEH_INVALID; } } @@ -119,16 +118,16 @@ StringID VehicleInTheWayErrMsg(const Vehicle* v) { switch (v->type) { - case VEH_Train: return STR_8803_TRAIN_IN_THE_WAY; - case VEH_Road: return STR_9000_ROAD_VEHICLE_IN_THE_WAY; - case VEH_Aircraft: return STR_A015_AIRCRAFT_IN_THE_WAY; + case VEH_TRAIN: return STR_8803_TRAIN_IN_THE_WAY; + case VEH_ROAD: return STR_9000_ROAD_VEHICLE_IN_THE_WAY; + case VEH_AIRCRAFT: return STR_A015_AIRCRAFT_IN_THE_WAY; default: return STR_980E_SHIP_IN_THE_WAY; } } static void *EnsureNoVehicleProc(Vehicle *v, void *data) { - if (v->tile != *(const TileIndex*)data || v->type == VEH_Disaster) + if (v->tile != *(const TileIndex*)data || v->type == VEH_DISASTER) return NULL; _error_message = VehicleInTheWayErrMsg(v); @@ -144,7 +143,7 @@ { const TileInfo *ti = (const TileInfo*)data; - if (v->tile != ti->tile || v->type == VEH_Disaster) return NULL; + if (v->tile != ti->tile || v->type == VEH_DISASTER) return NULL; if (v->z_pos > ti->z) return NULL; _error_message = VehicleInTheWayErrMsg(v); @@ -186,7 +185,7 @@ } FOR_ALL_VEHICLES(veh) { if (without_crashed && (veh->vehstatus & VS_CRASHED) != 0) continue; - if ((veh->type == VEH_Train || veh->type == VEH_Road) && (z==0xFF || veh->z_pos == z)) { + if ((veh->type == VEH_TRAIN || veh->type == VEH_ROAD) && (z==0xFF || veh->z_pos == z)) { if ((veh->x_pos>>4) >= x1 && (veh->x_pos>>4) <= x2 && (veh->y_pos>>4) >= y1 && (veh->y_pos>>4) <= y2) { return veh; @@ -217,26 +216,26 @@ } // Called after load to update coordinates -void AfterLoadVehicles(void) +void AfterLoadVehicles() { Vehicle *v; FOR_ALL_VEHICLES(v) { v->first = NULL; - if (v->type == VEH_Train) v->u.rail.first_engine = INVALID_ENGINE; + if (v->type == VEH_TRAIN) v->u.rail.first_engine = INVALID_ENGINE; } FOR_ALL_VEHICLES(v) { - if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v))) + if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v); } FOR_ALL_VEHICLES(v) { switch (v->type) { - case VEH_Train: v->cur_image = GetTrainImage(v, v->direction); break; - case VEH_Road: v->cur_image = GetRoadVehImage(v, v->direction); break; - case VEH_Ship: v->cur_image = GetShipImage(v, v->direction); break; - case VEH_Aircraft: + case VEH_TRAIN: v->cur_image = GetTrainImage(v, v->direction); break; + case VEH_ROAD: v->cur_image = GetRoadVehImage(v, v->direction); break; + case VEH_SHIP: v->cur_image = GetShipImage(v, v->direction); break; + case VEH_AIRCRAFT: if (IsNormalAircraft(v)) { v->cur_image = GetAircraftImage(v, v->direction); @@ -267,7 +266,7 @@ assert(v->orders == NULL); - v->type = VEH_Invalid; + v->type = VEH_INVALID; v->left_coord = INVALID_COORD; v->first = NULL; v->next = NULL; @@ -284,12 +283,12 @@ * Get a value for a vehicle's random_bits. * @return A random value from 0 to 255. */ -byte VehicleRandomBits(void) +byte VehicleRandomBits() { return GB(Random(), 0, 8); } -Vehicle *ForceAllocateSpecialVehicle(void) +Vehicle *ForceAllocateSpecialVehicle() { /* This stays a strange story.. there should always be room for special * vehicles (special effects all over the map), but with 65k of vehicles @@ -344,7 +343,7 @@ } -Vehicle *AllocateVehicle(void) +Vehicle *AllocateVehicle() { VehicleID counter = 0; return AllocateSingleVehicle(&counter); @@ -446,12 +445,12 @@ } } -void ResetVehiclePosHash(void) +void ResetVehiclePosHash() { memset(_vehicle_position_hash, 0, sizeof(_vehicle_position_hash)); } -void InitializeVehicles(void) +void InitializeVehicles() { uint i; @@ -483,7 +482,7 @@ { Vehicle *u; - FOR_ALL_VEHICLES(u) if (u->type == VEH_Train && u->next == v) return u; + FOR_ALL_VEHICLES(u) if (u->type == VEH_TRAIN && u->next == v) return u; return NULL; } @@ -516,7 +515,7 @@ Vehicle* u; assert(v != NULL); - assert(v->type == VEH_Train); + assert(v->type == VEH_TRAIN); if (v->first != NULL) { if (IsFrontEngine(v->first) || IsFreeWagon(v->first)) return v->first; @@ -553,12 +552,12 @@ bool IsEngineCountable(const Vehicle *v) { switch (v->type) { - case VEH_Aircraft: return IsNormalAircraft(v); // don't count plane shadows and helicopter rotors - case VEH_Train: + case VEH_AIRCRAFT: return IsNormalAircraft(v); // don't count plane shadows and helicopter rotors + case VEH_TRAIN: return !IsArticulatedPart(v) && // tenders and other articulated parts (!IsMultiheaded(v) || IsTrainEngine(v)); // rear parts of multiheaded engines - case VEH_Road: - case VEH_Ship: + case VEH_ROAD: + case VEH_SHIP: return true; default: return false; // Only count player buildable vehicles } @@ -574,9 +573,9 @@ DeleteVehicleNews(v->index, INVALID_STRING_ID); DeleteName(v->string_id); - if (v->type == VEH_Road) ClearSlot(v); - - if (v->type != VEH_Train || (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v)))) { + if (v->type == VEH_ROAD) ClearSlot(v); + + if (v->type != VEH_TRAIN || (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v)))) { InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); } @@ -606,7 +605,6 @@ void Train_Tick(Vehicle *v); static void EffectVehicle_Tick(Vehicle *v); void DisasterVehicle_Tick(Vehicle *v); -static int32 MaybeReplaceVehicle(Vehicle *v, bool check, bool display_costs); // head of the linked list to tell what vehicles that visited a depot in a tick static Vehicle* _first_veh_in_depot_list; @@ -647,7 +645,7 @@ DisasterVehicle_Tick, }; -void CallVehicleTicks(void) +void CallVehicleTicks() { Vehicle *v; @@ -665,12 +663,12 @@ _vehicle_tick_procs[v->type](v); switch (v->type) { - case VEH_Train: - case VEH_Road: - case VEH_Aircraft: - case VEH_Ship: - if (v->type == VEH_Train && IsTrainWagon(v)) continue; - if (v->type == VEH_Aircraft && v->subtype != AIR_HELICOPTER) continue; + case VEH_TRAIN: + case VEH_ROAD: + case VEH_AIRCRAFT: + case VEH_SHIP: + if (v->type == VEH_TRAIN && IsTrainWagon(v)) continue; + if (v->type == VEH_AIRCRAFT && v->subtype != AIR_HELICOPTER) continue; v->motion_counter += (v->direction & 1) ? (v->cur_speed * 3) / 4 : v->cur_speed; /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */ @@ -701,8 +699,8 @@ //if the aircraft carries passengers and is NOT full, then //continue loading, no matter how much mail is in - if (v->type == VEH_Aircraft && - v->cargo_type == CT_PASSENGERS && + if (v->type == VEH_AIRCRAFT && + IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap != v->cargo_count) { return true; } @@ -737,7 +735,7 @@ TileIndex tile = v->tile; if (IsTileType(tile, MP_STATION) || - (v->type == VEH_Ship && ( + (v->type == VEH_SHIP && ( IsTileType(TILE_ADDXY(tile, 1, 0), MP_STATION) || IsTileType(TILE_ADDXY(tile, -1, 0), MP_STATION) || IsTileType(TILE_ADDXY(tile, 0, 1), MP_STATION) || @@ -791,10 +789,10 @@ int32 base_cost = 0; switch (GetEngine(engine_type)->type) { - case VEH_Ship: base_cost = _price.ship_base; break; - case VEH_Road: base_cost = _price.roadveh_base; break; - case VEH_Aircraft: base_cost = _price.aircraft_base; break; - case VEH_Train: + case VEH_SHIP: base_cost = _price.ship_base; break; + case VEH_ROAD: base_cost = _price.roadveh_base; break; + case VEH_AIRCRAFT: base_cost = _price.aircraft_base; break; + case VEH_TRAIN: base_cost = 2 * ((RailVehInfo(engine_type)->railveh_type == RAILVEH_WAGON) ? _price.build_railwagon : _price.build_railvehicle); break; @@ -1098,11 +1096,11 @@ v->u.special.unk2 = 0; } -typedef struct BulldozerMovement { +struct BulldozerMovement { byte direction:2; byte image:2; byte duration:3; -} BulldozerMovement; +}; static const BulldozerMovement _bulldozer_movement[] = { { 0, 0, 4 }, @@ -1172,12 +1170,12 @@ v->progress = 0; } -typedef struct BubbleMovement { +struct BubbleMovement { int8 x:4; int8 y:4; int8 z:4; byte image:4; -} BubbleMovement; +}; #define MK(x, y, z, i) { x, y, z, i } #define ME(i) { i, 4, 0, 0 } @@ -1431,7 +1429,7 @@ v = ForceAllocateSpecialVehicle(); if (v != NULL) { - v->type = VEH_Special; + v->type = VEH_SPECIAL; v->subtype = type; v->x_pos = x; v->y_pos = y; @@ -1542,7 +1540,7 @@ /* calculate reliability value to use in comparison */ rel = v->reliability; - if (v->type == VEH_Ship) rel += 0x6666; + if (v->type == VEH_SHIP) rel += 0x6666; /* disabled breakdowns? */ if (_opt.diff.vehicle_breakdowns < 1) return; @@ -1621,10 +1619,10 @@ bool vehicle_list_window = HASBIT(p2, 6); switch (vehicle_type) { - case VEH_Train: stop_command = CMD_START_STOP_TRAIN; break; - case VEH_Road: stop_command = CMD_START_STOP_ROADVEH; break; - case VEH_Ship: stop_command = CMD_START_STOP_SHIP; break; - case VEH_Aircraft: stop_command = CMD_START_STOP_AIRCRAFT; break; + case VEH_TRAIN: stop_command = CMD_START_STOP_TRAIN; break; + case VEH_ROAD: stop_command = CMD_START_STOP_ROADVEH; break; + case VEH_SHIP: stop_command = CMD_START_STOP_SHIP; break; + case VEH_AIRCRAFT: stop_command = CMD_START_STOP_AIRCRAFT; break; default: return CMD_ERROR; } @@ -1645,7 +1643,7 @@ if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue; if (!vehicle_list_window) { - if (vehicle_type == VEH_Train) { + if (vehicle_type == VEH_TRAIN) { if (CheckTrainInDepot(v, false) == -1) continue; } else { if (!(v->vehstatus & VS_HIDDEN)) continue; @@ -1685,10 +1683,10 @@ byte vehicle_type = GB(p1, 0, 8); switch (vehicle_type) { - case VEH_Train: sell_command = CMD_SELL_RAIL_WAGON; break; - case VEH_Road: sell_command = CMD_SELL_ROAD_VEH; break; - case VEH_Ship: sell_command = CMD_SELL_SHIP; break; - case VEH_Aircraft: sell_command = CMD_SELL_AIRCRAFT; break; + case VEH_TRAIN: sell_command = CMD_SELL_RAIL_WAGON; break; + case VEH_ROAD: sell_command = CMD_SELL_ROAD_VEH; break; + case VEH_SHIP: sell_command = CMD_SELL_SHIP; break; + case VEH_AIRCRAFT: sell_command = CMD_SELL_AIRCRAFT; break; default: return CMD_ERROR; } @@ -1814,7 +1812,7 @@ if (!CheckOwnership(v->owner)) return CMD_ERROR; - if (v->type == VEH_Train && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR; + if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR; // check that we can allocate enough vehicles if (!(flags & DC_EXEC)) { @@ -1857,13 +1855,13 @@ DoCommand(0, w->index, v2->cargo_type | (v2->cargo_subtype << 8), flags, GetCmdRefitVeh(v)); break; // We learned that the engine in question needed a refit. No need to check anymore } - } while (v->type == VEH_Train && (w2 = w2->next) != NULL && (v2 = v2->next) != NULL); - - if (v->type == VEH_Train && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) { + } while (v->type == VEH_TRAIN && (w2 = w2->next) != NULL && (v2 = v2->next) != NULL); + + if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) { SETBIT(w->u.rail.flags, VRF_REVERSE_DIRECTION); } - if (v->type == VEH_Train && !IsFrontEngine(v)) { + if (v->type == VEH_TRAIN && !IsFrontEngine(v)) { // this s a train car // add this unit to the end of the train DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE); @@ -1875,9 +1873,9 @@ } w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop } - } while (v->type == VEH_Train && (v = GetNextVehicle(v)) != NULL); - - if (flags & DC_EXEC && v_front->type == VEH_Train) { + } while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL); + + if (flags & DC_EXEC && v_front->type == VEH_TRAIN) { // for trains this needs to be the front engine due to the callback function _new_vehicle_id = w_front->index; } @@ -1888,400 +1886,6 @@ return total_cost; } -/* - * move the cargo from one engine to another if possible - */ -static void MoveVehicleCargo(Vehicle *dest, Vehicle *source) -{ - Vehicle *v = dest; - int units_moved; - - do { - do { - if (source->cargo_type != dest->cargo_type) - continue; // cargo not compatible - - if (dest->cargo_count == dest->cargo_cap) - continue; // the destination vehicle is already full - - units_moved = min(source->cargo_count, dest->cargo_cap - dest->cargo_count); - source->cargo_count -= units_moved; - dest->cargo_count += units_moved; - dest->cargo_source = source->cargo_source; - - // copy the age of the cargo - dest->cargo_days = source->cargo_days; - dest->day_counter = source->day_counter; - dest->tick_counter = source->tick_counter; - - } while (source->cargo_count > 0 && (dest = dest->next) != NULL); - dest = v; - } while ((source = source->next) != NULL); - - /* - * The of the train will be incorrect at this moment. This is due - * to the fact that removing the old wagon updates the weight of - * the complete train, which is without the weight of cargo we just - * moved back into some (of the) new wagon(s). - */ - if (dest->type == VEH_Train) TrainConsistChanged(dest->first); -} - -static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, const EngineID engine_type) -{ - const Order *o; - const Vehicle *u; - - if (v->type == VEH_Train) { - u = GetFirstVehicleInChain(v); - } else { - u = v; - } - - FOR_VEHICLE_ORDERS(u, o) { - if (!(o->refit_cargo < NUM_CARGO)) continue; - if (!CanRefitTo(v->engine_type, o->refit_cargo)) continue; - if (!CanRefitTo(engine_type, o->refit_cargo)) return false; - } - - return true; -} - -/** - * Function to find what type of cargo to refit to when autoreplacing - * @param *v Original vehicle, that is being replaced - * @param engine_type The EngineID of the vehicle that is being replaced to - * @return The cargo type to replace to - * CT_NO_REFIT is returned if no refit is needed - * CT_INVALID is returned when both old and new vehicle got cargo capacity and refitting the new one to the old one's cargo type isn't possible - */ -static CargoID GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type) -{ - bool new_cargo_capacity = true; - CargoID new_cargo_type = CT_INVALID; - - switch (v->type) { - case VEH_Train: - new_cargo_capacity = (RailVehInfo(engine_type)->capacity > 0); - new_cargo_type = RailVehInfo(engine_type)->cargo_type; - break; - - case VEH_Road: - new_cargo_capacity = (RoadVehInfo(engine_type)->capacity > 0); - new_cargo_type = RoadVehInfo(engine_type)->cargo_type; - break; - case VEH_Ship: - new_cargo_capacity = (ShipVehInfo(engine_type)->capacity > 0); - new_cargo_type = ShipVehInfo(engine_type)->cargo_type; - break; - - case VEH_Aircraft: - /* all aircraft starts as passenger planes with cargo capacity - * new_cargo_capacity is always true for aircraft, which is the init value. No need to set it here */ - new_cargo_type = CT_PASSENGERS; - break; - - default: NOT_REACHED(); break; - } - - if (!new_cargo_capacity) return CT_NO_REFIT; // Don't try to refit an engine with no cargo capacity - - if (v->cargo_type == new_cargo_type || CanRefitTo(engine_type, v->cargo_type)) { - if (VerifyAutoreplaceRefitForOrders(v, engine_type)) { - return v->cargo_type == new_cargo_type ? (CargoID)CT_NO_REFIT : v->cargo_type; - } else { - return CT_INVALID; - } - } - if (v->type != VEH_Train) return CT_INVALID; // We can't refit the vehicle to carry the cargo we want - - /* Below this line it's safe to assume that the vehicle in question is a train */ - - if (v->cargo_cap != 0) return CT_INVALID; // trying to replace a vehicle with cargo capacity into another one with incompatible cargo type - - /* the old engine didn't have cargo capacity, but the new one does - * now we will figure out what cargo the train is carrying and refit to fit this */ - v = GetFirstVehicleInChain(v); - do { - if (v->cargo_cap == 0) continue; - /* Now we found a cargo type being carried on the train and we will see if it is possible to carry to this one */ - if (v->cargo_type == new_cargo_type) return CT_NO_REFIT; - if (CanRefitTo(engine_type, v->cargo_type)) return v->cargo_type; - } while ((v=v->next) != NULL); - return CT_NO_REFIT; // We failed to find a cargo type on the old vehicle and we will not refit the new one -} - -/* Replaces a vehicle (used to be called autorenew) - * This function is only called from MaybeReplaceVehicle() - * Must be called with _current_player set to the owner of the vehicle - * @param w Vehicle to replace - * @param flags is the flags to use when calling DoCommand(). Mainly DC_EXEC counts - * @return value is cost of the replacement or CMD_ERROR - */ -static int32 ReplaceVehicle(Vehicle **w, byte flags, int32 total_cost) -{ - int32 cost; - int32 sell_value; - Vehicle *old_v = *w; - const Player *p = GetPlayer(old_v->owner); - EngineID new_engine_type; - const UnitID cached_unitnumber = old_v->unitnumber; - bool new_front = false; - Vehicle *new_v = NULL; - char vehicle_name[32]; - CargoID replacement_cargo_type; - - new_engine_type = EngineReplacementForPlayer(p, old_v->engine_type); - if (new_engine_type == INVALID_ENGINE) new_engine_type = old_v->engine_type; - - replacement_cargo_type = GetNewCargoTypeForReplace(old_v, new_engine_type); - - /* check if we can't refit to the needed type, so no replace takes place to prevent the vehicle from altering cargo type */ - if (replacement_cargo_type == CT_INVALID) return 0; - - sell_value = DoCommand(0, old_v->index, 0, DC_QUERY_COST, GetCmdSellVeh(old_v)); - - /* We give the player a loan of the same amount as the sell value. - * This is needed in case he needs the income from the sale to build the new vehicle. - * We take it back if building fails or when we really sell the old engine */ - SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - SubtractMoneyFromPlayer(sell_value); - - cost = DoCommand(old_v->tile, new_engine_type, 3, flags, GetCmdBuildVeh(old_v)); - if (CmdFailed(cost)) { - SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - SubtractMoneyFromPlayer(-sell_value); // Take back the money we just gave the player - return cost; - } - - if (replacement_cargo_type != CT_NO_REFIT) cost += GetRefitCost(new_engine_type); // add refit cost - - if (flags & DC_EXEC) { - new_v = GetVehicle(_new_vehicle_id); - *w = new_v; //we changed the vehicle, so MaybeReplaceVehicle needs to work on the new one. Now we tell it what the new one is - - /* refit if needed */ - if (replacement_cargo_type != CT_NO_REFIT) { - if (CmdFailed(DoCommand(0, new_v->index, replacement_cargo_type, DC_EXEC, GetCmdRefitVeh(new_v)))) { - /* Being here shows a failure, which most likely is in GetNewCargoTypeForReplace() or incorrect estimation costs */ - error("Autoreplace failed to refit. Replace engine %d to %d and refit to cargo %d", old_v->engine_type, new_v->engine_type, replacement_cargo_type); - } - } - - if (new_v->type == VEH_Train && HASBIT(old_v->u.rail.flags, VRF_REVERSE_DIRECTION) && !IsMultiheaded(new_v) && !(new_v->next != NULL && IsArticulatedPart(new_v->next))) { - // we are autorenewing to a single engine, so we will turn it as the old one was turned as well - SETBIT(new_v->u.rail.flags, VRF_REVERSE_DIRECTION); - } - - if (old_v->type == VEH_Train && !IsFrontEngine(old_v)) { - /* this is a railcar. We need to move the car into the train - * We add the new engine after the old one instead of replacing it. It will give the same result anyway when we - * sell the old engine in a moment - */ - DoCommand(0, (GetPrevVehicleInChain(old_v)->index << 16) | new_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); - /* Now we move the old one out of the train */ - DoCommand(0, (INVALID_VEHICLE << 16) | old_v->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); - } else { - // copy/clone the orders - DoCommand(0, (old_v->index << 16) | new_v->index, IsOrderListShared(old_v) ? CO_SHARE : CO_COPY, DC_EXEC, CMD_CLONE_ORDER); - new_v->cur_order_index = old_v->cur_order_index; - ChangeVehicleViewWindow(old_v, new_v); - new_v->profit_this_year = old_v->profit_this_year; - new_v->profit_last_year = old_v->profit_last_year; - new_v->service_interval = old_v->service_interval; - new_front = true; - new_v->unitnumber = old_v->unitnumber; // use the same unit number - - new_v->current_order = old_v->current_order; - if (old_v->type == VEH_Train && GetNextVehicle(old_v) != NULL){ - Vehicle *temp_v = GetNextVehicle(old_v); - - // move the entire train to the new engine, excluding the old engine - if (IsMultiheaded(old_v) && temp_v == old_v->u.rail.other_multiheaded_part) { - // we got front and rear of a multiheaded engine right after each other. We should work with the next in line instead - temp_v = GetNextVehicle(temp_v); - } - - if (temp_v != NULL) { - DoCommand(0, (new_v->index << 16) | temp_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); - } - } - } - /* We are done setting up the new vehicle. Now we move the cargo from the old one to the new one */ - MoveVehicleCargo(new_v->type == VEH_Train ? GetFirstVehicleInChain(new_v) : new_v, old_v); - - // Get the name of the old vehicle if it has a custom name. - if (!IsCustomName(old_v->string_id)) { - vehicle_name[0] = '\0'; - } else { - GetName(vehicle_name, old_v->string_id & 0x7FF, lastof(vehicle_name)); - } - } else { // flags & DC_EXEC not set - /* Ensure that the player will not end up having negative money while autoreplacing - * This is needed because the only other check is done after the income from selling the old vehicle is substracted from the cost */ - if (p->money64 < (cost + total_cost)) { - SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - SubtractMoneyFromPlayer(-sell_value); // Pay back the loan - return CMD_ERROR; - } - } - - /* Take back the money we just gave the player just before building the vehicle - * The player will get the same amount now that the sale actually takes place */ - SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - SubtractMoneyFromPlayer(-sell_value); - - /* sell the engine/ find out how much you get for the old engine (income is returned as negative cost) */ - cost += DoCommand(0, old_v->index, 0, flags, GetCmdSellVeh(old_v)); - - if (new_front) { - /* now we assign the old unitnumber to the new vehicle */ - new_v->unitnumber = cached_unitnumber; - } - - /* Transfer the name of the old vehicle */ - if ((flags & DC_EXEC) && vehicle_name[0] != '\0') { - _cmd_text = vehicle_name; - DoCommand(0, new_v->index, 0, DC_EXEC, CMD_NAME_VEHICLE); - } - - return cost; -} - -/** replaces a vehicle if it's set for autoreplace or is too old - * (used to be called autorenew) - * @param v The vehicle to replace - * if the vehicle is a train, v needs to be the front engine - * @param check Checks if the replace is valid. No action is done at all - * @param display_costs If set, a cost animation is shown (only if check is false) - * @return CMD_ERROR if something went wrong. Otherwise the price of the replace - */ -static int32 MaybeReplaceVehicle(Vehicle *v, bool check, bool display_costs) -{ - Vehicle *w; - const Player *p = GetPlayer(v->owner); - byte flags = 0; - int32 cost, temp_cost = 0; - bool stopped; - - /* Remember the length in case we need to trim train later on - * If it's not a train, the value is unused - * round up to the length of the tiles used for the train instead of the train length instead - * Useful when newGRF uses custom length */ - uint16 old_total_length = (v->type == VEH_Train ? - (v->u.rail.cached_total_length + TILE_SIZE - 1) / TILE_SIZE * TILE_SIZE : - -1 - ); - - - _current_player = v->owner; - - assert(IsPlayerBuildableVehicleType(v)); - - assert(v->vehstatus & VS_STOPPED); // the vehicle should have been stopped in VehicleEnteredDepotThisTick() if needed - - /* Remember the flag v->leave_depot_instantly because if we replace the vehicle, the vehicle holding this flag will be sold - * If it is set, then we only stopped the vehicle to replace it (if needed) and we will need to start it again. - * We also need to reset the flag since it should remain false except from when the vehicle enters a depot until autoreplace is handled in the same tick */ - stopped = v->leave_depot_instantly; - v->leave_depot_instantly = false; - - for (;;) { - cost = 0; - w = v; - do { - if (w->type == VEH_Train && IsMultiheaded(w) && !IsTrainEngine(w)) { - /* we build the rear ends of multiheaded trains with the front ones */ - continue; - } - - // check if the vehicle should be replaced - if (!p->engine_renew || - w->age - w->max_age < (p->engine_renew_months * 30) || // replace if engine is too old - w->max_age == 0) { // rail cars got a max age of 0 - if (!EngineHasReplacementForPlayer(p, w->engine_type)) // updates to a new model - continue; - } - - /* Now replace the vehicle */ - temp_cost = ReplaceVehicle(&w, flags, cost); - - if (flags & DC_EXEC && - (w->type != VEH_Train || w->u.rail.first_engine == INVALID_ENGINE)) { - /* now we bought a new engine and sold the old one. We need to fix the - * pointers in order to avoid pointing to the old one for trains: these - * pointers should point to the front engine and not the cars - */ - v = w; - } - - if (!CmdFailed(temp_cost)) { - cost += temp_cost; - } - } while (w->type == VEH_Train && (w = GetNextVehicle(w)) != NULL); - - if (!(flags & DC_EXEC) && (p->money64 < (int32)(cost + p->engine_renew_money) || cost == 0)) { - if (!check && p->money64 < (int32)(cost + p->engine_renew_money) && ( _local_player == v->owner ) && cost != 0) { - StringID message; - SetDParam(0, v->unitnumber); - switch (v->type) { - case VEH_Train: message = STR_TRAIN_AUTORENEW_FAILED; break; - case VEH_Road: message = STR_ROADVEHICLE_AUTORENEW_FAILED; break; - case VEH_Ship: message = STR_SHIP_AUTORENEW_FAILED; break; - case VEH_Aircraft: message = STR_AIRCRAFT_AUTORENEW_FAILED; break; - // This should never happen - default: NOT_REACHED(); message = 0; break; - } - - AddNewsItem(message, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0); - } - if (stopped) v->vehstatus &= ~VS_STOPPED; - if (display_costs) _current_player = OWNER_NONE; - return CMD_ERROR; - } - - if (flags & DC_EXEC) { - break; // we are done replacing since the loop ran once with DC_EXEC - } else if (check) { - /* It's a test only and we know that we can do this - * NOTE: payment for wagon removal is NOT included in this price */ - return cost; - } - // now we redo the loop, but this time we actually do stuff since we know that we can do it - flags |= DC_EXEC; - } - - /* If setting is on to try not to exceed the old length of the train with the replacement */ - if (v->type == VEH_Train && p->renew_keep_length) { - Vehicle *temp; - w = v; - - while (v->u.rail.cached_total_length > old_total_length) { - // the train is too long. We will remove cars one by one from the start of the train until it's short enough - while (w != NULL && RailVehInfo(w->engine_type)->railveh_type != RAILVEH_WAGON) { - w = GetNextVehicle(w); - } - if (w == NULL) { - // we failed to make the train short enough - SetDParam(0, v->unitnumber); - AddNewsItem(STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0); - break; - } - temp = w; - w = GetNextVehicle(w); - DoCommand(0, (INVALID_VEHICLE << 16) | temp->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); - MoveVehicleCargo(v, temp); - cost += DoCommand(0, temp->index, 0, DC_EXEC, CMD_SELL_RAIL_WAGON); - } - } - - if (stopped) v->vehstatus &= ~VS_STOPPED; - if (display_costs) { - if (IsLocalPlayer()) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost); - _current_player = OWNER_NONE; - } - return cost; -} /* Extend the list size for BuildDepotVehicleList() */ static inline void ExtendVehicleListSize(const Vehicle ***engine_list, uint16 *engine_list_length, uint16 step_size) @@ -2307,8 +1911,8 @@ Vehicle *v; /* This function should never be called without an array to store results */ - assert(!(engine_list == NULL && type != VEH_Train)); - assert(!(type == VEH_Train && engine_list == NULL && wagon_list == NULL)); + assert(!(engine_list == NULL && type != VEH_TRAIN)); + assert(!(type == VEH_TRAIN && engine_list == NULL && wagon_list == NULL)); /* Both array and the length should either be NULL to disable the list or both should not be NULL */ assert((engine_list == NULL && engine_list_length == NULL) || (engine_list != NULL && engine_list_length != NULL)); @@ -2321,9 +1925,9 @@ if (wagon_count != NULL) *wagon_count = 0; switch (type) { - case VEH_Train: + case VEH_TRAIN: FOR_ALL_VEHICLES(v) { - if (v->tile == tile && v->type == VEH_Train && v->u.rail.track == TRACK_BIT_DEPOT) { + if (v->tile == tile && v->type == VEH_TRAIN && v->u.rail.track == TRACK_BIT_DEPOT) { if (IsFrontEngine(v)) { if (engine_list == NULL) continue; if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); @@ -2337,28 +1941,28 @@ } break; - case VEH_Road: + case VEH_ROAD: FOR_ALL_VEHICLES(v) { - if (v->tile == tile && v->type == VEH_Road && IsRoadVehInDepot(v)) { + if (v->tile == tile && v->type == VEH_ROAD && IsRoadVehInDepot(v)) { if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); (*engine_list)[(*engine_count)++] = v; } } break; - case VEH_Ship: + case VEH_SHIP: FOR_ALL_VEHICLES(v) { - if (v->tile == tile && v->type == VEH_Ship && IsShipInDepot(v)) { + if (v->tile == tile && v->type == VEH_SHIP && IsShipInDepot(v)) { if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); (*engine_list)[(*engine_count)++] = v; } } break; - case VEH_Aircraft: + case VEH_AIRCRAFT: FOR_ALL_VEHICLES(v) { if (v->tile == tile && - v->type == VEH_Aircraft && IsNormalAircraft(v) && + v->type == VEH_AIRCRAFT && IsNormalAircraft(v) && v->vehstatus & VS_HIDDEN) { if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); (*engine_list)[(*engine_count)++] = v; @@ -2385,7 +1989,7 @@ */ uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, byte type, PlayerID owner, uint32 index, uint16 window_type) { - const byte subtype = (type != VEH_Aircraft) ? (byte)Train_Front : (byte)AIR_AIRCRAFT; + const byte subtype = (type != VEH_AIRCRAFT) ? (byte)Train_Front : (byte)AIR_AIRCRAFT; uint n = 0; const Vehicle *v; @@ -2393,8 +1997,8 @@ case VLW_STATION_LIST: { FOR_ALL_VEHICLES(v) { if (v->type == type && ( - (type == VEH_Train && IsFrontEngine(v)) || - (type != VEH_Train && v->subtype <= subtype))) { + (type == VEH_TRAIN && IsFrontEngine(v)) || + (type != VEH_TRAIN && v->subtype <= subtype))) { const Order *order; FOR_VEHICLE_ORDERS(v, order) { @@ -2428,8 +2032,8 @@ case VLW_STANDARD: { FOR_ALL_VEHICLES(v) { if (v->type == type && v->owner == owner && ( - (type == VEH_Train && IsFrontEngine(v)) || - (type != VEH_Train && v->subtype <= subtype))) { + (type == VEH_TRAIN && IsFrontEngine(v)) || + (type != VEH_TRAIN && v->subtype <= subtype))) { /* TODO find a better estimate on the total number of vehicles for current player */ if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles()/4); (*sort_list)[n++] = v; @@ -2441,8 +2045,8 @@ case VLW_DEPOT_LIST: { FOR_ALL_VEHICLES(v) { if (v->type == type && ( - (type == VEH_Train && IsFrontEngine(v)) || - (type != VEH_Train && v->subtype <= subtype))) { + (type == VEH_TRAIN && IsFrontEngine(v)) || + (type != VEH_TRAIN && v->subtype <= subtype))) { const Order *order; FOR_VEHICLE_ORDERS(v, order) { @@ -2510,10 +2114,10 @@ bool IsVehicleInDepot(const Vehicle *v) { switch (v->type) { - case VEH_Train: return CheckTrainInDepot(v, false) != -1; - case VEH_Road: return IsRoadVehInDepot(v); - case VEH_Ship: return IsShipInDepot(v); - case VEH_Aircraft: return IsAircraftInHangar(v); + case VEH_TRAIN: return CheckTrainInDepot(v, false) != -1; + case VEH_ROAD: return IsRoadVehInDepot(v); + case VEH_SHIP: return IsShipInDepot(v); + case VEH_AIRCRAFT: return IsAircraftInHangar(v); default: NOT_REACHED(); } return false; @@ -2522,32 +2126,32 @@ void VehicleEnterDepot(Vehicle *v) { switch (v->type) { - case VEH_Train: + case VEH_TRAIN: InvalidateWindowClasses(WC_TRAINS_LIST); if (!IsFrontEngine(v)) v = GetFirstVehicleInChain(v); UpdateSignalsOnSegment(v->tile, GetRailDepotDirection(v->tile)); v->load_unload_time_rem = 0; break; - case VEH_Road: + case VEH_ROAD: InvalidateWindowClasses(WC_ROADVEH_LIST); v->u.road.state = RVSB_IN_DEPOT; break; - case VEH_Ship: + case VEH_SHIP: InvalidateWindowClasses(WC_SHIPS_LIST); v->u.ship.state = TRACK_BIT_DEPOT; RecalcShipStuff(v); break; - case VEH_Aircraft: + case VEH_AIRCRAFT: InvalidateWindowClasses(WC_AIRCRAFT_LIST); HandleAircraftEnterHangar(v); break; default: NOT_REACHED(); } - if (v->type != VEH_Train) { + if (v->type != VEH_TRAIN) { /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters. * We only increase the number of vehicles when the first one enters, so we will not need to search for more vehicles in the depot */ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); @@ -2591,7 +2195,7 @@ if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) { /* Part of orders */ - if (v->type == VEH_Train) v->u.rail.days_since_order_progr = 0; + if (v->type == VEH_TRAIN) v->u.rail.days_since_order_progr = 0; v->cur_order_index++; } else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) { /* Force depot visit */ @@ -2600,10 +2204,10 @@ StringID string; switch (v->type) { - case VEH_Train: string = STR_8814_TRAIN_IS_WAITING_IN_DEPOT; break; - case VEH_Road: string = STR_9016_ROAD_VEHICLE_IS_WAITING; break; - case VEH_Ship: string = STR_981C_SHIP_IS_WAITING_IN_DEPOT; break; - case VEH_Aircraft: string = STR_A014_AIRCRAFT_IS_WAITING_IN; break; + case VEH_TRAIN: string = STR_8814_TRAIN_IS_WAITING_IN_DEPOT; break; + case VEH_ROAD: string = STR_9016_ROAD_VEHICLE_IS_WAITING; break; + case VEH_SHIP: string = STR_981C_SHIP_IS_WAITING_IN_DEPOT; break; + case VEH_AIRCRAFT: string = STR_A014_AIRCRAFT_IS_WAITING_IN; break; default: NOT_REACHED(); string = STR_EMPTY; // Set the string to something to avoid a compiler warning } @@ -2744,7 +2348,7 @@ if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR; switch (v->type) { - case VEH_Train: + case VEH_TRAIN: if (v->u.rail.track == TRACK_BIT_DEPOT) /* We'll assume the train is facing outwards */ return DiagdirToDiagTrackdir(GetRailDepotDirection(v->tile)); /* Train in depot */ @@ -2753,14 +2357,14 @@ return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction); - case VEH_Ship: + case VEH_SHIP: if (IsShipInDepot(v)) /* We'll assume the ship is facing outwards */ return DiagdirToDiagTrackdir(GetShipDepotDirection(v->tile)); return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction); - case VEH_Road: + case VEH_ROAD: if (IsRoadVehInDepot(v)) /* We'll assume the road vehicle is facing outwards */ return DiagdirToDiagTrackdir(GetRoadDepotDirection(v->tile)); @@ -2775,7 +2379,7 @@ /* Vehicle is turning around, get the direction from vehicle's direction */ return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); - /* case VEH_Aircraft: case VEH_Special: case VEH_Disaster: */ + /* case VEH_AIRCRAFT: case VEH_SPECIAL: case VEH_DISASTER: */ default: return INVALID_TRACKDIR; } } @@ -2797,10 +2401,10 @@ static UnitID gmax = 0; switch (type) { - case VEH_Train: max = _patches.max_trains; break; - case VEH_Road: max = _patches.max_roadveh; break; - case VEH_Ship: max = _patches.max_ships; break; - case VEH_Aircraft: max = _patches.max_aircraft; break; + case VEH_TRAIN: max = _patches.max_trains; break; + case VEH_ROAD: max = _patches.max_roadveh; break; + case VEH_SHIP: max = _patches.max_ships; break; + case VEH_AIRCRAFT: max = _patches.max_aircraft; break; default: NOT_REACHED(); } @@ -2860,7 +2464,7 @@ if (p->livery[LS_DEFAULT].in_use && (_patches.liveries == 2 || (_patches.liveries == 1 && player == _local_player))) { /* Determine the livery scheme to use */ switch (GetEngine(engine_type)->type) { - case VEH_Train: { + case VEH_TRAIN: { const RailVehicleInfo *rvi = RailVehInfo(engine_type); switch (rvi->railtype) { @@ -2901,21 +2505,21 @@ break; } - case VEH_Road: { + case VEH_ROAD: { const RoadVehicleInfo *rvi = RoadVehInfo(engine_type); if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type; - scheme = (cargo_type == CT_PASSENGERS) ? LS_BUS : LS_TRUCK; + scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK; break; } - case VEH_Ship: { + case VEH_SHIP: { const ShipVehicleInfo *svi = ShipVehInfo(engine_type); if (cargo_type == CT_INVALID) cargo_type = svi->cargo_type; - scheme = (cargo_type == CT_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP; + scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP; break; } - case VEH_Aircraft: { + case VEH_AIRCRAFT: { const AircraftVehicleInfo *avi = AircraftVehInfo(engine_type); if (cargo_type == CT_INVALID) cargo_type = CT_PASSENGERS; switch (avi->subtype) { @@ -2948,7 +2552,7 @@ SpriteID GetVehiclePalette(const Vehicle *v) { - if (v->type == VEH_Train) { + if (v->type == VEH_TRAIN) { return GetEngineColourMap( (v->u.rail.first_engine != INVALID_ENGINE && (IsArticulatedPart(v) || UsesWagonOverride(v))) ? v->u.rail.first_engine : v->engine_type, @@ -3071,7 +2675,7 @@ static const SaveLoad _train_desc[] = { - SLE_WRITEBYTE(Vehicle, type, VEH_Train, 0), // Train type. VEH_Train in mem, 0 in file. + SLE_WRITEBYTE(Vehicle, type, VEH_TRAIN, 0), // Train type. VEH_TRAIN in mem, 0 in file. SLE_INCLUDEX(0, INC_VEHICLE_COMMON), SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRail, crash_anim_pos), SLE_UINT16), SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRail, force_proceed), SLE_UINT8), @@ -3089,7 +2693,7 @@ }; static const SaveLoad _roadveh_desc[] = { - SLE_WRITEBYTE(Vehicle, type, VEH_Road, 1), // Road type. VEH_Road in mem, 1 in file. + SLE_WRITEBYTE(Vehicle, type, VEH_ROAD, 1), // Road type. VEH_ROAD in mem, 1 in file. SLE_INCLUDEX(0, INC_VEHICLE_COMMON), SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, state), SLE_UINT8), SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, frame), SLE_UINT8), @@ -3109,7 +2713,7 @@ }; static const SaveLoad _ship_desc[] = { - SLE_WRITEBYTE(Vehicle, type, VEH_Ship, 2), // Ship type. VEH_Ship in mem, 2 in file. + SLE_WRITEBYTE(Vehicle, type, VEH_SHIP, 2), // Ship type. VEH_SHIP in mem, 2 in file. SLE_INCLUDEX(0, INC_VEHICLE_COMMON), SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleShip, state), SLE_UINT8), @@ -3120,7 +2724,7 @@ }; static const SaveLoad _aircraft_desc[] = { - SLE_WRITEBYTE(Vehicle, type, VEH_Aircraft, 3), // Aircraft type. VEH_Aircraft in mem, 3 in file. + SLE_WRITEBYTE(Vehicle, type, VEH_AIRCRAFT, 3), // Aircraft type. VEH_AIRCRAFT in mem, 3 in file. SLE_INCLUDEX(0, INC_VEHICLE_COMMON), SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, crashed_counter), SLE_UINT16), SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, pos), SLE_UINT8), @@ -3139,7 +2743,7 @@ }; static const SaveLoad _special_desc[] = { - SLE_WRITEBYTE(Vehicle,type,VEH_Special, 4), + SLE_WRITEBYTE(Vehicle,type,VEH_SPECIAL, 4), SLE_VAR(Vehicle, subtype, SLE_UINT8), @@ -3171,7 +2775,7 @@ }; static const SaveLoad _disaster_desc[] = { - SLE_WRITEBYTE(Vehicle, type, VEH_Disaster, 5), + SLE_WRITEBYTE(Vehicle, type, VEH_DISASTER, 5), SLE_REF(Vehicle, next, REF_VEHICLE_OLD), @@ -3223,7 +2827,7 @@ }; // Will be called when the vehicles need to be saved. -static void Save_VEHS(void) +static void Save_VEHS() { Vehicle *v; // Write the vehicles @@ -3234,7 +2838,7 @@ } // Will be called when vehicles need to be loaded. -static void Load_VEHS(void) +static void Load_VEHS() { int index; Vehicle *v; @@ -3284,13 +2888,13 @@ void Vehicle::BeginLoading() { - assert(IsTileType(tile, MP_STATION) || type == VEH_Ship); + assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP); current_order.type = OT_LOADING; } void Vehicle::LeaveStation() { - assert(IsTileType(tile, MP_STATION) || type == VEH_Ship); + assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP); assert(current_order.type == OT_LOADING); current_order.type = OT_LEAVESTATION; current_order.flags = 0;