diff options
Diffstat (limited to 'src')
33 files changed, 416 insertions, 374 deletions
diff --git a/src/ai/api/ai_vehicle.cpp b/src/ai/api/ai_vehicle.cpp index fa324200a..baeeaefa5 100644 --- a/src/ai/api/ai_vehicle.cpp +++ b/src/ai/api/ai_vehicle.cpp @@ -29,7 +29,7 @@ int num = 1; if (::Vehicle::Get(vehicle_id)->type == VEH_TRAIN) { - const Vehicle *v = ::Vehicle::Get(vehicle_id); + const Train *v = (Train *)::Vehicle::Get(vehicle_id); while ((v = GetNextUnit(v)) != NULL) num++; } @@ -85,11 +85,11 @@ EnforcePrecondition(false, ::Vehicle::Get(source_vehicle_id)->type == VEH_TRAIN); EnforcePrecondition(false, dest_vehicle_id == -1 || ::Vehicle::Get(dest_vehicle_id)->type == VEH_TRAIN); - const Vehicle *v = ::Vehicle::Get(source_vehicle_id); + const Train *v = (Train *)::Vehicle::Get(source_vehicle_id); while (source_wagon-- > 0) v = GetNextUnit(v); - const Vehicle *w = NULL; + const Train *w = NULL; if (dest_vehicle_id != -1) { - w = ::Vehicle::Get(dest_vehicle_id); + w = (Train *)::Vehicle::Get(dest_vehicle_id); while (dest_wagon-- > 0) w = GetNextUnit(w); } @@ -136,7 +136,7 @@ EnforcePrecondition(false, IsValidVehicle(vehicle_id) && wagon < GetNumWagons(vehicle_id)); EnforcePrecondition(false, ::Vehicle::Get(vehicle_id)->type == VEH_TRAIN); - const Vehicle *v = ::Vehicle::Get(vehicle_id); + const Train *v = (Train *)::Vehicle::Get(vehicle_id); while (wagon-- > 0) v = GetNextUnit(v); return AIObject::DoCommand(0, v->index, sell_attached_wagons ? 1 : 0, CMD_SELL_RAIL_WAGON); @@ -243,7 +243,7 @@ const Vehicle *v = ::Vehicle::Get(vehicle_id); if (v->type == VEH_TRAIN) { - while (wagon-- > 0) v = GetNextUnit(v); + while (wagon-- > 0) v = GetNextUnit((Train *)v); } return v->engine_type; } @@ -281,7 +281,7 @@ const Vehicle *v = ::Vehicle::Get(vehicle_id); if (v->type == VEH_TRAIN) { - while (wagon-- > 0) v = GetNextUnit(v); + while (wagon-- > 0) v = GetNextUnit((Train *)v); } return v->age; } diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index 33259ebb4..2de9bac0f 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -208,7 +208,7 @@ bool IsArticulatedVehicleCarryingDifferentCargos(const Vehicle *v, CargoID *carg switch (v->type) { case VEH_TRAIN: - v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL); + v = (EngineHasArticPart((Train *)v) ? GetNextArticPart((Train *)v) : NULL); break; case VEH_ROAD: @@ -256,7 +256,7 @@ void CheckConsistencyOfArticulatedVehicle(const Vehicle *v) switch (v->type) { case VEH_TRAIN: - v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL); + v = (EngineHasArticPart((Train *)v) ? GetNextArticPart((Train *)v) : NULL); break; case VEH_ROAD: @@ -307,25 +307,27 @@ void AddArticulatedParts(Vehicle *first, VehicleType type) switch (type) { default: NOT_REACHED(); - case VEH_TRAIN: - u = new Train(); - u->subtype = 0; - previous->SetNext(u); - u->u.rail.track = v->u.rail.track; - u->u.rail.railtype = v->u.rail.railtype; - u->u.rail.first_engine = v->engine_type; + case VEH_TRAIN: { + Train *front = (Train *)v; + Train *t = new Train(); + t->subtype = 0; + previous->SetNext(t); + t->u.rail.track = front->u.rail.track; + t->u.rail.railtype = front->u.rail.railtype; + t->u.rail.first_engine = front->engine_type; - u->spritenum = e_artic->u.rail.image_index; + t->spritenum = e_artic->u.rail.image_index; if (e_artic->CanCarryCargo()) { - u->cargo_type = e_artic->GetDefaultCargoType(); - u->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished + t->cargo_type = e_artic->GetDefaultCargoType(); + t->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished } else { - u->cargo_type = v->cargo_type; // Needed for livery selection - u->cargo_cap = 0; + t->cargo_type = front->cargo_type; // Needed for livery selection + t->cargo_cap = 0; } - SetArticulatedPart(u); - break; + SetArticulatedPart(t); + u = t; + } break; case VEH_ROAD: { RoadVehicle *front = (RoadVehicle *)v; diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 2b035cbfa..25bc39ea3 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -92,18 +92,18 @@ static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chai assert(!part_of_chain || new_head->IsPrimaryVehicle()); /* Loop through source parts */ for (Vehicle *src = old_veh; src != NULL; src = src->Next()) { - if (!part_of_chain && src->type == VEH_TRAIN && src != old_veh && src != old_veh->u.rail.other_multiheaded_part && !IsArticulatedPart(src)) { + if (!part_of_chain && src->type == VEH_TRAIN && src != old_veh && src != ((Train *)old_veh)->u.rail.other_multiheaded_part && !IsArticulatedPart(src)) { /* Skip vehicles, which do not belong to old_veh */ - src = GetLastEnginePart(src); + src = GetLastEnginePart((Train *)src); continue; } if (src->cargo_type >= NUM_CARGO || src->cargo.Count() == 0) continue; /* Find free space in the new chain */ for (Vehicle *dest = new_head; dest != NULL && src->cargo.Count() > 0; dest = dest->Next()) { - if (!part_of_chain && dest->type == VEH_TRAIN && dest != new_head && dest != new_head->u.rail.other_multiheaded_part && !IsArticulatedPart(dest)) { + if (!part_of_chain && dest->type == VEH_TRAIN && dest != new_head && dest != ((Train *)new_head)->u.rail.other_multiheaded_part && !IsArticulatedPart(dest)) { /* Skip vehicles, which do not belong to new_head */ - dest = GetLastEnginePart(dest); + dest = GetLastEnginePart((Train *)dest); continue; } if (dest->cargo_type != src->cargo_type) continue; @@ -116,7 +116,7 @@ static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chai } /* Update train weight etc., the old vehicle will be sold anyway */ - if (part_of_chain && new_head->type == VEH_TRAIN) TrainConsistChanged(new_head, true); + if (part_of_chain && new_head->type == VEH_TRAIN) TrainConsistChanged((Train *)new_head, true); } /** @@ -269,7 +269,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic } /* Try to reverse the vehicle, but do not care if it fails as the new type might not be reversible */ - if (new_veh->type == VEH_TRAIN && HasBit(old_veh->u.rail.flags, VRF_REVERSE_DIRECTION)) { + if (new_veh->type == VEH_TRAIN && HasBit(((Train *)old_veh)->u.rail.flags, VRF_REVERSE_DIRECTION)) { DoCommand(0, new_veh->index, true, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION); } @@ -406,33 +406,33 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon uint16 old_total_length = (old_head->u.rail.cached_total_length + TILE_SIZE - 1) / TILE_SIZE * TILE_SIZE; int num_units = 0; ///< Number of units in the chain - for (Vehicle *w = old_head; w != NULL; w = GetNextUnit(w)) num_units++; + for (Train *w = (Train *)old_head; w != NULL; w = GetNextUnit(w)) num_units++; - Vehicle **old_vehs = CallocT<Vehicle *>(num_units); ///< Will store vehicles of the old chain in their order - Vehicle **new_vehs = CallocT<Vehicle *>(num_units); ///< New vehicles corresponding to old_vehs or NULL if no replacement - Money *new_costs = MallocT<Money>(num_units); ///< Costs for buying and refitting the new vehicles + Train **old_vehs = CallocT<Train *>(num_units); ///< Will store vehicles of the old chain in their order + Train **new_vehs = CallocT<Train *>(num_units); ///< New vehicles corresponding to old_vehs or NULL if no replacement + Money *new_costs = MallocT<Money>(num_units); ///< Costs for buying and refitting the new vehicles /* Collect vehicles and build replacements * Note: The replacement vehicles can only successfully build as long as the old vehicles are still in their chain */ int i; - Vehicle *w; - for (w = old_head, i = 0; w != NULL; w = GetNextUnit(w), i++) { + Train *w; + for (w = (Train *)old_head, i = 0; w != NULL; w = GetNextUnit(w), i++) { assert(i < num_units); old_vehs[i] = w; - CommandCost ret = BuildReplacementVehicle(old_vehs[i], &new_vehs[i], true); + CommandCost ret = BuildReplacementVehicle(old_vehs[i], (Vehicle**)&new_vehs[i], true); cost.AddCost(ret); if (cost.Failed()) break; new_costs[i] = ret.GetCost(); if (new_vehs[i] != NULL) *nothing_to_do = false; } - Vehicle *new_head = (new_vehs[0] != NULL ? new_vehs[0] : old_vehs[0]); + Train *new_head = (new_vehs[0] != NULL ? new_vehs[0] : old_vehs[0]); /* Note: When autoreplace has already failed here, old_vehs[] is not completely initialized. But it is also not needed. */ if (cost.Succeeded()) { /* Separate the head, so we can start constructing the new chain */ - Vehicle *second = GetNextUnit(old_head); + Train *second = GetNextUnit((Train *)old_head); if (second != NULL) cost.AddCost(MoveVehicle(second, NULL, DC_EXEC | DC_AUTOREPLACE, true)); assert(GetNextUnit(new_head) == NULL); @@ -440,10 +440,10 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon /* Append engines to the new chain * We do this from back to front, so that the head of the temporary vehicle chain does not change all the time. * OTOH the vehicle attach callback is more expensive this way :s */ - Vehicle *last_engine = NULL; ///< Shall store the last engine unit after this step + Train *last_engine = NULL; ///< Shall store the last engine unit after this step if (cost.Succeeded()) { for (int i = num_units - 1; i > 0; i--) { - Vehicle *append = (new_vehs[i] != NULL ? new_vehs[i] : old_vehs[i]); + Train *append = (new_vehs[i] != NULL ? new_vehs[i] : old_vehs[i]); if (RailVehInfo(append->engine_type)->railveh_type == RAILVEH_WAGON) continue; @@ -538,10 +538,10 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon * Note: The vehicle attach callback is disabled here :) */ if ((flags & DC_EXEC) == 0) { /* Separate the head, so we can reattach the old vehicles */ - Vehicle *second = GetNextUnit(old_head); + Train *second = GetNextUnit((Train *)old_head); if (second != NULL) MoveVehicle(second, NULL, DC_EXEC | DC_AUTOREPLACE, true); - assert(GetNextUnit(old_head) == NULL); + assert(GetNextUnit((Train *)old_head) == NULL); for (int i = num_units - 1; i > 0; i--) { CommandCost ret = MoveVehicle(old_vehs[i], old_head, DC_EXEC | DC_AUTOREPLACE, false); @@ -632,7 +632,7 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1 bool any_replacements = false; while (w != NULL && !any_replacements) { any_replacements = (GetNewEngineType(w, c) != INVALID_ENGINE); - w = (!free_wagon && w->type == VEH_TRAIN ? GetNextUnit(w) : NULL); + w = (!free_wagon && w->type == VEH_TRAIN ? GetNextUnit((Train *)w) : NULL); } if (any_replacements) { diff --git a/src/elrail.cpp b/src/elrail.cpp index 81ee510e4..78ee3c8a8 100644 --- a/src/elrail.cpp +++ b/src/elrail.cpp @@ -555,12 +555,15 @@ bool SettingsDisableElrail(int32 p1) * normal rail too */ if (disable) { FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN && v->u.rail.railtype == RAILTYPE_ELECTRIC) { + if (v->type != VEH_TRAIN) continue; + + Train *t = (Train *)v; + if (t->u.rail.railtype == RAILTYPE_ELECTRIC) { /* this railroad vehicle is now compatible only with elrail, * so add there also normal rail compatibility */ - v->u.rail.compatible_railtypes |= RAILTYPES_RAIL; - v->u.rail.railtype = RAILTYPE_RAIL; - SetBit(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL); + t->u.rail.compatible_railtypes |= RAILTYPES_RAIL; + t->u.rail.railtype = RAILTYPE_RAIL; + SetBit(t->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL); } } } @@ -569,8 +572,9 @@ bool SettingsDisableElrail(int32 p1) FOR_ALL_VEHICLES(v) { /* power and acceleration is cached only for front engines */ if (v->type == VEH_TRAIN && IsFrontEngine(v)) { - TrainPowerChanged(v); - UpdateTrainAcceleration(v); + Train *t = (Train *)v; + TrainPowerChanged(t); + UpdateTrainAcceleration(t); } } diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index cc7a6d4ad..dd971f7f1 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -668,7 +668,8 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by uint16 modflags = 0; if (v->type == VEH_TRAIN) { - const Vehicle *u = IsTrainWagon(v) && HasBit(v->vehicle_flags, VRF_POWEREDWAGON) ? v->First() : v; + const Train *t = (const Train *)v; + const Train *u = IsTrainWagon(v) && HasBit(v->vehicle_flags, VRF_POWEREDWAGON) ? t->First() : t; RailType railtype = GetRailType(v->tile); bool powered = IsTrainEngine(v) || (IsTrainWagon(v) && HasBit(v->vehicle_flags, VRF_POWEREDWAGON)); bool has_power = powered && HasPowerOnRail(u->u.rail.railtype, railtype); @@ -676,7 +677,7 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by if (has_power) SetBit(modflags, 5); if (is_electric && !has_power) SetBit(modflags, 6); - if (HasBit(v->u.rail.flags, VRF_TOGGLE_REVERSE)) SetBit(modflags, 8); + if (HasBit(t->u.rail.flags, VRF_TOGGLE_REVERSE)) SetBit(modflags, 8); } if (HasBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE)) SetBit(modflags, 10); @@ -735,7 +736,7 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by case 0x47: return GB(Engine::Get(v->engine_type)->internal_id, 8, 8); case 0x48: if (v->type != VEH_TRAIN || v->spritenum != 0xFD) return v->spritenum; - return HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION) ? 0xFE : 0xFD; + return HasBit(((Train *)v)->u.rail.flags, VRF_REVERSE_DIRECTION) ? 0xFE : 0xFD; case 0x49: return v->day_counter; case 0x4A: return v->breakdowns_since_last_service; @@ -766,20 +767,21 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by /* Vehicle specific properties */ switch (v->type) { - case VEH_TRAIN: + case VEH_TRAIN: { + Train *t = (Train *)v; switch (variable - 0x80) { - case 0x62: return v->u.rail.track; - case 0x66: return v->u.rail.railtype; - case 0x73: return v->u.rail.cached_veh_length; - case 0x74: return v->u.rail.cached_power; - case 0x75: return GB(v->u.rail.cached_power, 8, 24); - case 0x76: return GB(v->u.rail.cached_power, 16, 16); - case 0x77: return GB(v->u.rail.cached_power, 24, 8); - case 0x7C: return v->First()->index; - case 0x7D: return GB(v->First()->index, 8, 8); + case 0x62: return t->u.rail.track; + case 0x66: return t->u.rail.railtype; + case 0x73: return t->u.rail.cached_veh_length; + case 0x74: return t->u.rail.cached_power; + case 0x75: return GB(t->u.rail.cached_power, 8, 24); + case 0x76: return GB(t->u.rail.cached_power, 16, 16); + case 0x77: return GB(t->u.rail.cached_power, 24, 8); + case 0x7C: return t->First()->index; + case 0x7D: return GB(t->First()->index, 8, 8); case 0x7F: return 0; // Used for vehicle reversing hack in TTDP } - break; + } break; case VEH_ROAD: { RoadVehicle *rv = (RoadVehicle *)v; diff --git a/src/npf.cpp b/src/npf.cpp index 27d71ab81..5502b2206 100644 --- a/src/npf.cpp +++ b/src/npf.cpp @@ -16,6 +16,7 @@ #include "pbs.h" #include "settings_type.h" #include "pathfind.h" +#include "train.h" static AyStar _npf_aystar; @@ -424,7 +425,7 @@ static int32 NPFFindDepot(AyStar *as, OpenListNode *current) /** Find any safe and free tile. */ static int32 NPFFindSafeTile(AyStar *as, OpenListNode *current) { - const Vehicle *v = ((NPFFindStationOrTileData*)as->user_target)->v; + const Train *v = (Train *)((NPFFindStationOrTileData*)as->user_target)->v; return IsSafeWaitingPosition(v, current->path.node.tile, current->path.node.direction, true, _settings_game.pf.forbid_90_deg) && @@ -458,7 +459,7 @@ static int32 NPFFindStationOrTile(AyStar *as, OpenListNode *current) * the second signal is returnd. If no suitable signal is present, the * last node of the path is returned. */ -static const PathNode *FindSafePosition(PathNode *path, const Vehicle *v) +static const PathNode *FindSafePosition(PathNode *path, const Train *v) { /* If there is no signal, reserve the whole path. */ PathNode *sig = path; @@ -505,7 +506,7 @@ static void NPFSaveTargetData(AyStar *as, OpenListNode *current) if (as->user_target != NULL && ((NPFFindStationOrTileData*)as->user_target)->reserve_path && as->user_data[NPF_TYPE] == TRANSPORT_RAIL) { /* Path reservation is requested. */ - const Vehicle *v = ((NPFFindStationOrTileData*)as->user_target)->v; + const Train *v = (Train *)((NPFFindStationOrTileData*)as->user_target)->v; const PathNode *target = FindSafePosition(¤t->path, v); ftd->node = target->node; @@ -1053,7 +1054,7 @@ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, return best_result; } -NPFFoundTargetData NPFRouteToSafeTile(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool override_railtype) +NPFFoundTargetData NPFRouteToSafeTile(const Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype) { assert(v->type == VEH_TRAIN); @@ -115,7 +115,7 @@ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, /** * Search for any safe tile using a breadth first search and try to reserve a path. */ -NPFFoundTargetData NPFRouteToSafeTile(const Vehicle *v, TileIndex tile, Trackdir trackdir,bool override_railtype); +NPFFoundTargetData NPFRouteToSafeTile(const struct Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype); void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, Vehicle *v, bool reserve_path = false); diff --git a/src/openttd.cpp b/src/openttd.cpp index db4f56f4d..90404cae3 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -31,6 +31,7 @@ #include "fios.h" #include "aircraft.h" #include "roadveh.h" +#include "train.h" #include "console_func.h" #include "screenshot.h" #include "network/network.h" @@ -1132,7 +1133,7 @@ void StateGameLoop() length = 0; for (Vehicle *u = v; u != NULL; u = u->Next()) wagons[length++] = u->u.rail; - TrainConsistChanged(v, true); + TrainConsistChanged((Train *)v, true); length = 0; for (Vehicle *u = v; u != NULL; u = u->Next()) { diff --git a/src/pbs.cpp b/src/pbs.cpp index 213d1c051..26a586516 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -222,7 +222,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra */ struct FindTrainOnTrackInfo { PBSTileInfo res; ///< Information about the track. - Vehicle *best; ///< The currently "best" vehicle we have found. + Train *best; ///< The currently "best" vehicle we have found. /** Init the best location to NULL always! */ FindTrainOnTrackInfo() : best(NULL) {} @@ -233,12 +233,15 @@ static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data) { FindTrainOnTrackInfo *info = (FindTrainOnTrackInfo *)data; - if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info->res.trackdir))) { - v = v->First(); + if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return NULL; + + Train *t = (Train *)v; + if (HasBit((TrackBits)t->u.rail.track, TrackdirToTrack(info->res.trackdir))) { + t = t->First(); /* ALWAYS return the lowest ID (anti-desync!) */ - if (info->best == NULL || v->index < info->best->index) info->best = v; - return v; + if (info->best == NULL || t->index < info->best->index) info->best = t; + return t; } return NULL; @@ -251,7 +254,7 @@ static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data) * @param train_on_res Is set to a train we might encounter * @returns The last tile of the reservation or the current train tile if no reservation present. */ -PBSTileInfo FollowTrainReservation(const Vehicle *v, bool *train_on_res) +PBSTileInfo FollowTrainReservation(const Train *v, bool *train_on_res) { assert(v->type == VEH_TRAIN); @@ -274,7 +277,7 @@ PBSTileInfo FollowTrainReservation(const Vehicle *v, bool *train_on_res) * @param track A reserved track on the tile. * @return The vehicle holding the reservation or NULL if the path is stray. */ -Vehicle *GetTrainForReservation(TileIndex tile, Track track) +Train *GetTrainForReservation(TileIndex tile, Track track) { assert(HasReservedTracks(tile, TrackToTrackBits(track))); Trackdir trackdir = TrackToTrackdir(track); @@ -320,7 +323,7 @@ Vehicle *GetTrainForReservation(TileIndex tile, Track track) * @param forbid_90def Don't allow trains to make 90 degree turns * @return True if it is a safe position */ -bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg) +bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg) { if (IsRailDepotTile(tile)) return true; @@ -360,7 +363,7 @@ bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, * @param forbid_90def Don't allow trains to make 90 degree turns * @return True if the position is free */ -bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg) +bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg) { Track track = TrackdirToTrack(trackdir); TrackBits reserved = GetReservedTrackbits(tile); @@ -27,11 +27,11 @@ struct PBSTileInfo { PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {} }; -PBSTileInfo FollowTrainReservation(const Vehicle *v, bool *train_on_res = NULL); -bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false); -bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false); +PBSTileInfo FollowTrainReservation(const Train *v, bool *train_on_res = NULL); +bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false); +bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false); -Vehicle *GetTrainForReservation(TileIndex tile, Track track); +Train *GetTrainForReservation(TileIndex tile, Track track); /** * Check whether some of tracks is reserved on a tile. diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index eb0c137a8..6e9ecc37e 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -92,7 +92,8 @@ Vehicle *EnsureNoTrainOnTrackProc(Vehicle *v, void *data) if (v->type != VEH_TRAIN) return NULL; - if ((v->u.rail.track != rail_bits) && !TracksOverlap(v->u.rail.track | rail_bits)) return NULL; + Train *t = (Train *)v; + if ((t->u.rail.track != rail_bits) && !TracksOverlap(t->u.rail.track | rail_bits)) return NULL; _error_message = VehicleInTheWayErrMsg(v); return v; @@ -456,7 +457,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, * so do not call GetTileOwner(tile) in any case here */ Owner owner = INVALID_OWNER; - Vehicle *v = NULL; + Train *v = NULL; switch (GetTileType(tile)) { case MP_ROAD: { @@ -877,7 +878,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, } if (flags & DC_EXEC) { - Vehicle *v = NULL; + Train *v = NULL; /* The new/changed signal could block our path. As this can lead to * stale reservations, we clear the path reservation here and try * to redo it later on. */ @@ -1184,7 +1185,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1 /* Do it? */ if (flags & DC_EXEC) { - Vehicle *v = NULL; + Train *v = NULL; if (HasReservedTracks(tile, TrackToTrackBits(track))) { v = GetTrainForReservation(tile, track); } @@ -1234,7 +1235,7 @@ Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data) if (v->type == VEH_TRAIN && !IsArticulatedPart(v)) { const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); - if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First()); + if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged((Train *)v->First()); } return NULL; @@ -1296,7 +1297,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 /* Trying to convert other's rail */ if (!CheckTileOwnership(tile)) continue; - SmallVector<Vehicle*, 2> vehicles_affected; + SmallVector<Train *, 2> vehicles_affected; /* Vehicle on the tile when not converting Rail <-> ElRail * Tunnels and bridges have special check later */ @@ -1306,7 +1307,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 TrackBits reserved = GetReservedTrackbits(tile); Track track; while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) { - Vehicle *v = GetTrainForReservation(tile, track); + Train *v = GetTrainForReservation(tile, track); if (v != NULL && !HasPowerOnRail(v->u.rail.railtype, totype)) { /* No power on new rail type, reroute. */ FreeTrainTrackReservation(v); @@ -1372,7 +1373,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (flags & DC_EXEC) { Track track = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile)); if (GetTunnelBridgeReservation(tile)) { - Vehicle *v = GetTrainForReservation(tile, track); + Train *v = GetTrainForReservation(tile, track); if (v != NULL && !HasPowerOnRail(v->u.rail.railtype, totype)) { /* No power on new rail type, reroute. */ FreeTrainTrackReservation(v); @@ -1432,7 +1433,7 @@ static CommandCost RemoveTrainDepot(TileIndex tile, DoCommandFlag flags) /* read variables before the depot is removed */ DiagDirection dir = GetRailDepotDirection(tile); Owner owner = GetTileOwner(tile); - Vehicle *v = NULL; + Train *v = NULL; if (GetDepotWaypointReservation(tile)) { v = GetTrainForReservation(tile, DiagDirToDiagTrack(dir)); @@ -2450,7 +2451,7 @@ int TicksToLeaveDepot(const Vehicle *v) /** Tile callback routine when vehicle enters tile * @see vehicle_enter_tile_proc */ -static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y) +static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *u, TileIndex tile, int x, int y) { byte fract_coord; byte fract_coord_leave; @@ -2458,7 +2459,9 @@ static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *v, TileIndex tile, int int length; /* this routine applies only to trains in depot tiles */ - if (v->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE; + if (u->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE; + + Train *v = (Train *)u; /* depot direction */ dir = GetRailDepotDirection(tile); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 088aef84f..3e0309ac1 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -912,7 +912,7 @@ bool AfterLoadGame() continue; } if (v->type == VEH_TRAIN) { - v->u.rail.track = TRACK_BIT_WORMHOLE; + ((Train *)v)->u.rail.track = TRACK_BIT_WORMHOLE; } else { ((RoadVehicle *)v)->state = RVSB_WORMHOLE; } @@ -928,7 +928,7 @@ bool AfterLoadGame() if (v->type == VEH_TRAIN) { RailType rt = RailVehInfo(v->engine_type)->railtype; - v->u.rail.railtype = rt; + ((Train *)v)->u.rail.railtype = rt; if (rt == RAILTYPE_ELECTRIC) min_rail = RAILTYPE_RAIL; } } @@ -964,7 +964,7 @@ bool AfterLoadGame() } FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v, true); + if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged((Train *)v, true); } } @@ -1700,9 +1700,10 @@ bool AfterLoadGame() /* Reserve all tracks trains are currently on. */ if (CheckSavegameVersion(101)) { - Vehicle *v; - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN) { + Vehicle *u; + FOR_ALL_VEHICLES(u) { + if (u->type == VEH_TRAIN) { + Train *v = (Train *)u; if ((v->u.rail.track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) { TryReserveRailTrack(v->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(v->tile))); } else if ((v->u.rail.track & TRACK_BIT_MASK) != TRACK_BIT_NONE) { diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 842db05df..e95748807 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -1315,7 +1315,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num) }; if (v->spritenum / 2 >= lengthof(spriteset_rail)) return false; v->spritenum = spriteset_rail[v->spritenum / 2]; // adjust railway sprite set offset - v->u.rail.railtype = type == 0x25 ? 1 : 0; // monorail / rail + ((Train *)v)->u.rail.railtype = type == 0x25 ? 1 : 0; // monorail / rail break; } diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 10b7f3614..6901bef4f 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -24,7 +24,7 @@ void ConnectMultiheadedTrains() FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN) { - v->u.rail.other_multiheaded_part = NULL; + ((Train *)v)->u.rail.other_multiheaded_part = NULL; } } @@ -45,7 +45,7 @@ void ConnectMultiheadedTrains() bool sequential_matching = IsFrontEngine(v); - for (Vehicle *u = v; u != NULL; u = GetNextVehicle(u)) { + for (Train *u = (Train *)v; u != NULL; u = (Train *)GetNextVehicle(u)) { if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one if (IsMultiheaded(u)) { @@ -57,7 +57,7 @@ void ConnectMultiheadedTrains() /* Find a matching back part */ EngineID eid = u->engine_type; - Vehicle *w; + Train *w; if (sequential_matching) { for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) { if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue; @@ -318,8 +318,8 @@ void AfterLoadVehicles(bool part_of_load) assert(v->first != NULL); if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) { - if (IsFrontEngine(v)) v->u.rail.last_speed = v->cur_speed; // update displayed train speed - TrainConsistChanged(v, false); + if (IsFrontEngine(v)) ((Train *)v)->u.rail.last_speed = v->cur_speed; // update displayed train speed + TrainConsistChanged((Train *)v, false); } else if (v->type == VEH_ROAD && IsRoadVehFront(v)) { RoadVehUpdateCache((RoadVehicle *)v); } diff --git a/src/settings.cpp b/src/settings.cpp index f3e5fb9ad..b5fc8db82 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -697,7 +697,7 @@ static bool UpdateConsists(int32 p1) Vehicle *v; FOR_ALL_VEHICLES(v) { /* Update the consist of all trains so the maximum speed is set correctly. */ - if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v, true); + if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged((Train *)v, true); } return true; } @@ -747,7 +747,7 @@ static bool TrainAccelerationModelChanged(int32 p1) Vehicle *v; FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN && IsFrontEngine(v)) UpdateTrainAcceleration(v); + if (v->type == VEH_TRAIN && IsFrontEngine(v)) UpdateTrainAcceleration((Train *)v); } return true; diff --git a/src/signal.cpp b/src/signal.cpp index 947e71a9f..4226a4446 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -7,8 +7,8 @@ #include "station_map.h" #include "tunnelbridge_map.h" #include "vehicle_func.h" -#include "vehicle_base.h" #include "functions.h" +#include "train.h" /** these are the maximums used for updating signal blocks */ @@ -185,7 +185,7 @@ static SmallSet<DiagDirection, SIG_GLOB_SIZE> _globset("_globset"); ///< set of /** Check whether there is a train on rail, not in a depot */ static Vehicle *TrainOnTileEnum(Vehicle *v, void *) { - if (v->type != VEH_TRAIN || v->u.rail.track == TRACK_BIT_DEPOT) return NULL; + if (v->type != VEH_TRAIN || ((Train *)v)->u.rail.track == TRACK_BIT_DEPOT) return NULL; return v; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 7c7e712f7..9a0f5f187 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1015,7 +1015,7 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, DoCommandFlag flags, uin numtracks_orig = numtracks; - SmallVector<Vehicle*, 4> affected_vehicles; + SmallVector<Train*, 4> affected_vehicles; do { TileIndex tile = tile_org; int w = plat_len; @@ -1023,7 +1023,7 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, DoCommandFlag flags, uin byte layout = *layout_ptr++; if (IsRailwayStationTile(tile) && GetRailwayStationReservation(tile)) { /* Check for trains having a reservation for this tile. */ - Vehicle *v = GetTrainForReservation(tile, AxisToTrack(GetRailStationAxis(tile))); + Train *v = GetTrainForReservation(tile, AxisToTrack(GetRailStationAxis(tile))); if (v != NULL) { FreeTrainTrackReservation(v); *affected_vehicles.Append() = v; @@ -1063,7 +1063,7 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, DoCommandFlag flags, uin for (uint i = 0; i < affected_vehicles.Length(); ++i) { /* Restore reservations of trains. */ - Vehicle *v = affected_vehicles[i]; + Train *v = affected_vehicles[i]; if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), true); TryPathReserve(v, true, true); for (; v->Next() != NULL; v = v->Next()) ; @@ -1196,7 +1196,7 @@ CommandCost CmdRemoveFromRailroadStation(TileIndex tile, DoCommandFlag flags, ui uint specindex = GetCustomStationSpecIndex(tile2); Track track = GetRailStationTrack(tile2); Owner owner = GetTileOwner(tile2); - Vehicle *v = NULL; + Train *v = NULL; if (GetRailwayStationReservation(tile2)) { v = GetTrainForReservation(tile2, track); @@ -1280,7 +1280,7 @@ static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, DoCommandF /* read variables before the station tile is removed */ Track track = GetRailStationTrack(tile); Owner owner = GetTileOwner(tile); // _current_company can be OWNER_WATER - Vehicle *v = NULL; + Train *v = NULL; if (GetRailwayStationReservation(tile)) { v = GetTrainForReservation(tile, track); if (v != NULL) FreeTrainTrackReservation(v); @@ -2621,7 +2621,7 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i int station_ahead; int station_length; - int stop = GetTrainStopLocation(station_id, tile, v, &station_ahead, &station_length); + int stop = GetTrainStopLocation(station_id, tile, (Train *)v, &station_ahead, &station_length); /* Stop whenever that amount of station ahead + the distance from the * begin of the platform to the stop location is longer than the length diff --git a/src/train.h b/src/train.h index 4fa431d90..86c8c8a21 100644 --- a/src/train.h +++ b/src/train.h @@ -9,6 +9,7 @@ #include "core/bitmath_func.hpp" #include "vehicle_base.h" +struct Train; /** enum to handle train subtypes * Do not access it directly unless you have to. Use the access functions below @@ -202,12 +203,81 @@ static inline bool EngineHasArticPart(const Vehicle *v) return (v->Next() != NULL && IsArticulatedPart(v->Next())); } +/** Tell if we are dealing with the rear end of a multiheaded engine. + * @param v Vehicle. + * @return True if the engine is the rear part of a dualheaded engine. + */ +static inline bool IsRearDualheaded(const Vehicle *v) +{ + assert(v->type == VEH_TRAIN); + return (IsMultiheaded(v) && !IsTrainEngine(v)); +} + +void CcBuildLoco(bool success, TileIndex tile, uint32 p1, uint32 p2); +void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2); + +byte FreightWagonMult(CargoID cargo); + +int CheckTrainInDepot(const Train *v, bool needs_to_be_stopped); +int CheckTrainStoppedInDepot(const Train *v); +void UpdateTrainAcceleration(Train *v); +void CheckTrainsLengths(); + +void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR); +bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false); + +int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length); + +void TrainConsistChanged(Train *v, bool same_length); +void TrainPowerChanged(Train *v); +Money GetTrainRunningCost(const Train *v); + +/** + * This class 'wraps' Vehicle; you do not actually instantiate this class. + * You create a Vehicle using AllocateVehicle, so it is added to the pool + * and you reinitialize that to a Train using: + * v = new (v) Train(); + * + * As side-effect the vehicle type is set correctly. + */ +struct Train : public Vehicle { + /** Initializes the Vehicle to a train */ + Train() { this->type = VEH_TRAIN; } + + /** We want to 'destruct' the right class. */ + virtual ~Train() { this->PreDestructor(); } + + const char *GetTypeString() const { return "train"; } + void MarkDirty(); + void UpdateDeltaXY(Direction direction); + ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; } + void PlayLeaveStationSound() const; + bool IsPrimaryVehicle() const { return IsFrontEngine(this); } + SpriteID GetImage(Direction direction) const; + int GetDisplaySpeed() const { return this->u.rail.last_speed; } + int GetDisplayMaxSpeed() const { return this->u.rail.cached_max_speed; } + Money GetRunningCost() const; + bool IsInDepot() const { return CheckTrainInDepot(this, false) != -1; } + bool IsStoppedInDepot() const { return CheckTrainStoppedInDepot(this) >= 0; } + bool Tick(); + void OnNewDay(); + Trackdir GetVehicleTrackdir() const; + TileIndex GetOrderStationLocation(StationID station); + bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse); + Train *First() { return (Train *)this->Vehicle::First(); } + Train *First() const { return (Train *)this->Vehicle::First(); } + Train *Next() { return (Train *)this->Vehicle::Next(); } + Train *Next() const { return (Train *)this->Vehicle::Next(); } + Train *Previous() { return (Train *)this->Vehicle::Previous(); } + Train *Previous() const { return (Train *)this->Vehicle::Previous(); } +}; + /** * Get the next part of a multi-part engine. * Will only work on a multi-part engine (EngineHasArticPart(v) == true), * Result is undefined for normal engine. */ -static inline Vehicle *GetNextArticPart(const Vehicle *v) +static inline Train *GetNextArticPart(const Train *v) { assert(EngineHasArticPart(v)); return v->Next(); @@ -217,28 +287,18 @@ static inline Vehicle *GetNextArticPart(const Vehicle *v) * @param v Vehicle. * @return Last part of the engine. */ -static inline Vehicle *GetLastEnginePart(Vehicle *v) +static inline Train *GetLastEnginePart(Train *v) { assert(v->type == VEH_TRAIN); while (EngineHasArticPart(v)) v = GetNextArticPart(v); return v; } -/** Tell if we are dealing with the rear end of a multiheaded engine. - * @param v Vehicle. - * @return True if the engine is the rear part of a dualheaded engine. - */ -static inline bool IsRearDualheaded(const Vehicle *v) -{ - assert(v->type == VEH_TRAIN); - return (IsMultiheaded(v) && !IsTrainEngine(v)); -} - /** Get the next real (non-articulated part) vehicle in the consist. * @param v Vehicle. * @return Next vehicle in the consist. */ -static inline Vehicle *GetNextVehicle(const Vehicle *v) +static inline Train *GetNextVehicle(const Train *v) { assert(v->type == VEH_TRAIN); while (EngineHasArticPart(v)) v = GetNextArticPart(v); @@ -251,11 +311,11 @@ static inline Vehicle *GetNextVehicle(const Vehicle *v) * @param w Vehicle. * @return Previous vehicle in the consist. */ -static inline Vehicle *GetPrevVehicle(const Vehicle *w) +static inline Train *GetPrevVehicle(const Train *w) { assert(w->type == VEH_TRAIN); - Vehicle *v = w->Previous(); + Train *v = w->Previous(); while (v != NULL && IsArticulatedPart(v)) v = v->Previous(); return v; @@ -265,10 +325,10 @@ static inline Vehicle *GetPrevVehicle(const Vehicle *w) * @param v Vehicle. * @return Next vehicle in the consist. */ -static inline Vehicle *GetNextUnit(const Vehicle *v) +static inline Train *GetNextUnit(const Train *v) { assert(v->type == VEH_TRAIN); - Vehicle *w = GetNextVehicle(v); + Train *w = GetNextVehicle(v); if (w != NULL && IsRearDualheaded(w)) w = GetNextVehicle(w); return w; @@ -278,62 +338,13 @@ static inline Vehicle *GetNextUnit(const Vehicle *v) * @param v Vehicle. * @return Previous vehicle in the consist. */ -static inline Vehicle *GetPrevUnit(const Vehicle *v) +static inline Train *GetPrevUnit(const Train *v) { assert(v->type == VEH_TRAIN); - Vehicle *w = GetPrevVehicle(v); + Train *w = GetPrevVehicle(v); if (w != NULL && IsRearDualheaded(w)) w = GetPrevVehicle(w); return w; } -void CcBuildLoco(bool success, TileIndex tile, uint32 p1, uint32 p2); -void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2); - -byte FreightWagonMult(CargoID cargo); - -int CheckTrainInDepot(const Vehicle *v, bool needs_to_be_stopped); -int CheckTrainStoppedInDepot(const Vehicle *v); -void UpdateTrainAcceleration(Vehicle *v); -void CheckTrainsLengths(); - -void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR); -bool TryPathReserve(Vehicle *v, bool mark_as_stuck = false, bool first_tile_okay = false); - -int GetTrainStopLocation(StationID station_id, TileIndex tile, const Vehicle *v, int *station_ahead, int *station_length); - -/** - * This class 'wraps' Vehicle; you do not actually instantiate this class. - * You create a Vehicle using AllocateVehicle, so it is added to the pool - * and you reinitialize that to a Train using: - * v = new (v) Train(); - * - * As side-effect the vehicle type is set correctly. - */ -struct Train : public Vehicle { - /** Initializes the Vehicle to a train */ - Train() { this->type = VEH_TRAIN; } - - /** We want to 'destruct' the right class. */ - virtual ~Train() { this->PreDestructor(); } - - const char *GetTypeString() const { return "train"; } - void MarkDirty(); - void UpdateDeltaXY(Direction direction); - ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; } - void PlayLeaveStationSound() const; - bool IsPrimaryVehicle() const { return IsFrontEngine(this); } - SpriteID GetImage(Direction direction) const; - int GetDisplaySpeed() const { return this->u.rail.last_speed; } - int GetDisplayMaxSpeed() const { return this->u.rail.cached_max_speed; } - Money GetRunningCost() const; - bool IsInDepot() const { return CheckTrainInDepot(this, false) != -1; } - bool IsStoppedInDepot() const { return CheckTrainStoppedInDepot(this) >= 0; } - bool Tick(); - void OnNewDay(); - Trackdir GetVehicleTrackdir() const; - TileIndex GetOrderStationLocation(StationID station); - bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse); -}; - #endif /* TRAIN_H */ diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 49754a070..31a7d7b26 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -37,12 +37,12 @@ #include "table/strings.h" #include "table/train_cmd.h" -static Track ChooseTrainTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck); -static bool TrainCheckIfLineEnds(Vehicle *v); -static void TrainController(Vehicle *v, Vehicle *nomove); -static TileIndex TrainApproachingCrossingTile(const Vehicle *v); -static void CheckIfTrainNeedsService(Vehicle *v); -static void CheckNextTrainTile(Vehicle *v); +static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck); +static bool TrainCheckIfLineEnds(Train *v); +static void TrainController(Train *v, Vehicle *nomove); +static TileIndex TrainApproachingCrossingTile(const Train *v); +static void CheckIfTrainNeedsService(Train *v); +static void CheckNextTrainTile(Train *v); static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8}; static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10}; @@ -85,12 +85,12 @@ byte FreightWagonMult(CargoID cargo) * Recalculates the cached total power of a train. Should be called when the consist is changed * @param v First vehicle of the consist. */ -void TrainPowerChanged(Vehicle *v) +void TrainPowerChanged(Train *v) { uint32 total_power = 0; uint32 max_te = 0; - for (const Vehicle *u = v; u != NULL; u = u->Next()) { + for (const Train *u = v; u != NULL; u = u->Next()) { RailType railtype = GetRailType(u->tile); /* Power is not added for articulated parts */ @@ -134,11 +134,11 @@ void TrainPowerChanged(Vehicle *v) * the consist changes. * @param v First vehicle of the consist. */ -static void TrainCargoChanged(Vehicle *v) +static void TrainCargoChanged(Train *v) { uint32 weight = 0; - for (Vehicle *u = v; u != NULL; u = u->Next()) { + for (Train *u = v; u != NULL; u = u->Next()) { uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo.Count() * FreightWagonMult(u->cargo_type) / 16; /* Vehicle weight is not added for articulated parts. */ @@ -171,7 +171,7 @@ static void TrainCargoChanged(Vehicle *v) * is for the first time this happened. * @param u first vehicle of chain */ -static void RailVehicleLengthChanged(const Vehicle *u) +static void RailVehicleLengthChanged(const Train *u) { /* show a warning once for each engine in whole game and once for each GRF after each game load */ const Engine *engine = Engine::Get(u->engine_type); @@ -189,7 +189,7 @@ void CheckTrainsLengths() FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN && v->First() == v && !(v->vehstatus & VS_CRASHED)) { - for (const Vehicle *u = v, *w = v->Next(); w != NULL; u = w, w = w->Next()) { + for (const Train *u = (Train *)v, *w = (Train *)v->Next(); w != NULL; u = w, w = w->Next()) { if (u->u.rail.track != TRACK_BIT_DEPOT) { if ((w->u.rail.track != TRACK_BIT_DEPOT && max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->u.rail.cached_veh_length) || @@ -213,7 +213,7 @@ void CheckTrainsLengths() * @param v First vehicle of the chain. * @param same_length should length of vehicles stay the same? */ -void TrainConsistChanged(Vehicle *v, bool same_length) +void TrainConsistChanged(Train *v, bool same_length) { uint16 max_speed = UINT16_MAX; @@ -227,7 +227,7 @@ void TrainConsistChanged(Vehicle *v, bool same_length) bool train_can_tilt = true; - for (Vehicle *u = v; u != NULL; u = u->Next()) { + for (Train *u = v; u != NULL; u = u->Next()) { const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); /* Check the v->first cache. */ @@ -244,13 +244,13 @@ void TrainConsistChanged(Vehicle *v, bool same_length) u->cache_valid = 0; } - for (Vehicle *u = v; u != NULL; u = u->Next()) { + for (Train *u = v; u != NULL; u = u->Next()) { /* Update user defined data (must be done before other properties) */ u->u.rail.user_def_data = GetVehicleProperty(u, 0x25, u->u.rail.user_def_data); u->cache_valid = 0; } - for (Vehicle *u = v; u != NULL; u = u->Next()) { + for (Train *u = v; u != NULL; u = u->Next()) { const Engine *e_u = Engine::Get(u->engine_type); const RailVehicleInfo *rvi_u = &e_u->u.rail; @@ -364,7 +364,7 @@ enum AccelType { * @param station_length 'return' the station length in 1/16th tiles * @return the location, calculated from the begin of the station to stop at. */ -int GetTrainStopLocation(StationID station_id, TileIndex tile, const Vehicle *v, int *station_ahead, int *station_length) +int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length) { const Station *st = Station::Get(station_id); *station_ahead = st->GetPlatformLength(tile, DirToDiagDir(v->direction)) * TILE_SIZE; @@ -404,7 +404,7 @@ int GetTrainStopLocation(StationID station_id, TileIndex tile, const Vehicle *v, } /** new acceleration*/ -static int GetTrainAcceleration(Vehicle *v, bool mode) +static int GetTrainAcceleration(Train *v, bool mode) { static const int absolute_max_speed = UINT16_MAX; int max_speed = absolute_max_speed; @@ -496,7 +496,7 @@ static int GetTrainAcceleration(Vehicle *v, bool mode) int num = 0; // number of vehicles, change this into the number of axles later int incl = 0; int drag_coeff = 20; //[1e-4] - for (const Vehicle *u = v; u != NULL; u = u->Next()) { + for (const Train *u = v; u != NULL; u = u->Next()) { num++; drag_coeff += 3; @@ -556,7 +556,7 @@ static int GetTrainAcceleration(Vehicle *v, bool mode) } } -void UpdateTrainAcceleration(Vehicle *v) +void UpdateTrainAcceleration(Train *v) { assert(IsFrontEngine(v)); @@ -660,7 +660,7 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandF } } - Vehicle *v = new Train(); + Train *v = new Train(); v->spritenum = rvi->image_index; v->engine_type = engine; @@ -725,14 +725,14 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandF } /** Move all free vehicles in the depot to the train */ -static void NormalizeTrainVehInDepot(const Vehicle *u) +static void NormalizeTrainVehInDepot(const Train *u) { const Vehicle *v; FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN && IsFreeWagon(v) && v->tile == u->tile && - v->u.rail.track == TRACK_BIT_DEPOT) { + ((Train *)v)->u.rail.track == TRACK_BIT_DEPOT) { if (CmdFailed(DoCommand(0, v->index | (u->index << 16), 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE))) break; @@ -740,9 +740,9 @@ static void NormalizeTrainVehInDepot(const Vehicle *u) } } -static void AddRearEngineToMultiheadedTrain(Vehicle *v) +static void AddRearEngineToMultiheadedTrain(Train *v) { - Vehicle *u = new Train(); + Train *u = new Train(); v->value >>= 1; u->value = v->value; u->direction = v->direction; @@ -823,7 +823,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir]; int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir]; - Vehicle *v = new Train(); + Train *v = new Train(); v->unitnumber = unit_num; v->direction = DiagDirToDir(dir); v->tile = tile; @@ -901,7 +901,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, /* Check if all the wagons of the given train are in a depot, returns the * number of cars (including loco) then. If not it returns -1 */ -int CheckTrainInDepot(const Vehicle *v, bool needs_to_be_stopped) +int CheckTrainInDepot(const Train *v, bool needs_to_be_stopped) { TileIndex tile = v->tile; @@ -926,13 +926,13 @@ int CheckTrainInDepot(const Vehicle *v, bool needs_to_be_stopped) } /* Used to check if the train is inside the depot and verifying that the VS_STOPPED flag is set */ -int CheckTrainStoppedInDepot(const Vehicle *v) +int CheckTrainStoppedInDepot(const Train *v) { return CheckTrainInDepot(v, true); } /* Used to check if the train is inside the depot, but not checking the VS_STOPPED flag */ -inline bool CheckTrainIsInsideDepot(const Vehicle *v) +inline bool CheckTrainIsInsideDepot(const Train *v) { return CheckTrainInDepot(v, false) > 0; } @@ -943,7 +943,7 @@ inline bool CheckTrainIsInsideDepot(const Vehicle *v) * @param first The first vehicle of the consist. * @return The first vehicle of the consist. */ -static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first) +static Train *UnlinkWagon(Train *v, Train *first) { /* unlinking the first vehicle of the chain? */ if (v == first) { @@ -960,13 +960,13 @@ static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first) return v; } - Vehicle *u; + Train *u; for (u = first; GetNextVehicle(u) != v; u = GetNextVehicle(u)) {} GetLastEnginePart(u)->SetNext(GetNextVehicle(v)); return first; } -static Vehicle *FindGoodVehiclePos(const Vehicle *src) +static Train *FindGoodVehiclePos(const Train *src) { Vehicle *dst; EngineID eng = src->engine_type; @@ -979,7 +979,7 @@ static Vehicle *FindGoodVehiclePos(const Vehicle *src) while (v->engine_type == eng) { v = v->Next(); - if (v == NULL) return dst; + if (v == NULL) return (Train *)dst; } } } @@ -991,12 +991,12 @@ static Vehicle *FindGoodVehiclePos(const Vehicle *src) * add a vehicle v behind vehicle dest * use this function since it sets flags as needed */ -static void AddWagonToConsist(Vehicle *v, Vehicle *dest) +static void AddWagonToConsist(Train *v, Train *dest) { UnlinkWagon(v, v->First()); if (dest == NULL) return; - Vehicle *next = dest->Next(); + Train *next = dest->Next(); v->SetNext(NULL); dest->SetNext(v); v->SetNext(next); @@ -1008,7 +1008,7 @@ static void AddWagonToConsist(Vehicle *v, Vehicle *dest) * move around on the train so rear engines are placed correctly according to the other engines * always call with the front engine */ -static void NormaliseTrainConsist(Vehicle *v) +static void NormaliseTrainConsist(Train *v) { if (IsFreeWagon(v)) return; @@ -1018,7 +1018,7 @@ static void NormaliseTrainConsist(Vehicle *v) if (!IsMultiheaded(v) || !IsTrainEngine(v)) continue; /* make sure that there are no free cars before next engine */ - Vehicle *u; + Train *u; for (u = v; u->Next() != NULL && !IsTrainEngine(u->Next()); u = u->Next()) {} if (u == v->u.rail.other_multiheaded_part) continue; @@ -1040,22 +1040,25 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u VehicleID s = GB(p1, 0, 16); VehicleID d = GB(p1, 16, 16); - Vehicle *src = Vehicle::GetIfValid(s); - if (src == NULL || src->type != VEH_TRAIN || !CheckOwnership(src->owner)) return CMD_ERROR; + Vehicle *src_v = Vehicle::GetIfValid(s); + if (src_v == NULL || src_v->type != VEH_TRAIN || !CheckOwnership(src_v->owner)) return CMD_ERROR; /* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */ - if (HASBITS(src->vehstatus, VS_CRASHED)) return CMD_ERROR; + if (HASBITS(src_v->vehstatus, VS_CRASHED)) return CMD_ERROR; + + Train *src = (Train *)src_v; /* if nothing is selected as destination, try and find a matching vehicle to drag to. */ - Vehicle *dst; + Train *dst; if (d == INVALID_VEHICLE) { dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src); } else { - dst = Vehicle::GetIfValid(d); - if (dst == NULL || dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR; + Vehicle *dst_v = Vehicle::GetIfValid(d); + if (dst_v == NULL || dst_v->type != VEH_TRAIN || !CheckOwnership(dst_v->owner)) return CMD_ERROR; /* Do not allow appending to crashed vehicles, too */ - if (HASBITS(dst->vehstatus, VS_CRASHED)) return CMD_ERROR; + if (HASBITS(dst_v->vehstatus, VS_CRASHED)) return CMD_ERROR; + dst = (Train *)dst_v; } /* if an articulated part is being handled, deal with its parent vehicle */ @@ -1068,8 +1071,8 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (src == dst) return CommandCost(); /* locate the head of the two chains */ - Vehicle *src_head = src->First(); - Vehicle *dst_head; + Train *src_head = src->First(); + Train *dst_head; if (dst != NULL) { dst_head = dst->First(); if (dst_head->tile != src_head->tile) return CMD_ERROR; @@ -1105,7 +1108,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u /* We are moving between rows, so only count the wagons from the source * row that are being moved. */ if (HasBit(p2, 0)) { - const Vehicle *u; + const Train *u; for (u = src_head; u != src && u != NULL; u = GetNextVehicle(u)) src_len--; } else { @@ -1151,7 +1154,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u * v->Next()->Previous() == v holds (assuming v->Next() != NULL). */ bool src_in_dst = false; - for (Vehicle *v = dst_head; !src_in_dst && v != NULL; v = v->Next()) src_in_dst = v == src; + for (Train *v = dst_head; !src_in_dst && v != NULL; v = v->Next()) src_in_dst = v == src; /* * If the source chain is in the destination chain then the user is @@ -1171,12 +1174,12 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u * attaching fails or succeeds because we are not 'only' doing this * in the DC_EXEC state. */ - Vehicle *dst_tail = dst_head; + Train *dst_tail = dst_head; while (dst_tail->Next() != NULL) dst_tail = dst_tail->Next(); - Vehicle *orig_tail = dst_tail; - Vehicle *next_to_attach = src; - Vehicle *src_previous = src->Previous(); + Train *orig_tail = dst_tail; + Train *next_to_attach = src; + Train *src_previous = src->Previous(); while (next_to_attach != NULL) { /* Don't check callback for articulated or rear dual headed parts */ @@ -1224,7 +1227,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u * to the next wagon. Then add that to the tail of the destination * train and update the tail with the new vehicle. */ - Vehicle *to_add = next_to_attach; + Train *to_add = next_to_attach; next_to_attach = next_to_attach->Next(); to_add->SetNext(NULL); @@ -1259,7 +1262,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u if (HasBit(p2, 0)) { /* unlink ALL wagons */ if (src != src_head) { - Vehicle *v = src_head; + Train *v = src_head; while (GetNextVehicle(v) != src) v = GetNextVehicle(v); GetLastEnginePart(v)->SetNext(NULL); } else { @@ -1318,7 +1321,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u /* link in the wagon(s) in the chain. */ { - Vehicle *v; + Train *v; for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v)) {} GetLastEnginePart(v)->SetNext(dst->Next()); @@ -1391,14 +1394,15 @@ CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* Check if we deleted a vehicle window */ Window *w = NULL; - Vehicle *v = Vehicle::GetIfValid(p1); - if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR; + Vehicle *vt = Vehicle::GetIfValid(p1); + if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR; if (p2 > 1) return CMD_ERROR; - if (HASBITS(v->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE); + if (HASBITS(vt->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE); + Train *v = (Train *)vt; while (IsArticulatedPart(v)) v = v->Previous(); - Vehicle *first = v->First(); + Train *first = v->First(); /* make sure the vehicle is stopped in the depot */ if (CheckTrainStoppedInDepot(first) < 0) { @@ -1426,7 +1430,7 @@ CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* 1. Delete the engine, if it is dualheaded also delete the matching * rear engine of the loco (from the point of deletion onwards) */ - Vehicle *rear = (IsMultiheaded(v) && + Train *rear = (IsMultiheaded(v) && IsTrainEngine(v)) ? v->u.rail.other_multiheaded_part : NULL; if (rear != NULL) { @@ -1440,7 +1444,7 @@ CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* 2. We are selling the front vehicle, some special action might be required * here, so take attention */ if (v == first) { - Vehicle *new_f = GetNextVehicle(first); + Train *new_f = GetNextVehicle(first); /* 2.2 If there are wagons present after the deleted front engine, check * if the second wagon (which will be first) is an engine. If it is one, @@ -1500,13 +1504,13 @@ CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* Start deleting every vehicle after the selected one * If we encounter a matching rear-engine to a front-engine * earlier in the chain (before deletion), leave it alone */ - for (Vehicle *tmp; v != NULL; v = tmp) { + for (Train *tmp; v != NULL; v = tmp) { tmp = GetNextVehicle(v); if (IsMultiheaded(v)) { if (IsTrainEngine(v)) { /* We got a front engine of a multiheaded set. Now we will sell the rear end too */ - Vehicle *rear = v->u.rail.other_multiheaded_part; + Train *rear = v->u.rail.other_multiheaded_part; if (rear != NULL) { cost.AddCost(-rear->value); @@ -1572,14 +1576,14 @@ void Train::UpdateDeltaXY(Direction direction) this->z_extent = 6; } -static void UpdateVarsAfterSwap(Vehicle *v) +static void UpdateVarsAfterSwap(Train *v) { v->UpdateDeltaXY(v->direction); v->cur_image = v->GetImage(v->direction); VehicleMove(v, true); } -static inline void SetLastSpeed(Vehicle *v, int spd) +static inline void SetLastSpeed(Train *v, int spd) { int old = v->u.rail.last_speed; if (spd != old) { @@ -1591,7 +1595,7 @@ static inline void SetLastSpeed(Vehicle *v, int spd) } /** Mark a train as stuck and stop it if it isn't stopped right now. */ -static void MarkTrainAsStuck(Vehicle *v) +static void MarkTrainAsStuck(Train *v) { if (!HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) { /* It is the first time the problem occured, set the "train stuck" flag. */ @@ -1631,9 +1635,9 @@ static void SwapTrainFlags(uint16 *swap_flag1, uint16 *swap_flag2) } } -static void ReverseTrainSwapVeh(Vehicle *v, int l, int r) +static void ReverseTrainSwapVeh(Train *v, int l, int r) { - Vehicle *a, *b; + Train *a, *b; /* locate vehicles to swap */ for (a = v; l != 0; l--) a = a->Next(); @@ -1704,7 +1708,7 @@ static Vehicle *TrainApproachingCrossingEnum(Vehicle *v, void *data) TileIndex tile = *(TileIndex*)data; - if (TrainApproachingCrossingTile(v) != tile) return NULL; + if (TrainApproachingCrossingTile((Train *)v) != tile) return NULL; return v; } @@ -1775,11 +1779,11 @@ static inline void MaybeBarCrossingWithSound(TileIndex tile) * This one is called before the train is reversed. * @param v First vehicle in chain */ -static void AdvanceWagonsBeforeSwap(Vehicle *v) +static void AdvanceWagonsBeforeSwap(Train *v) { - Vehicle *base = v; - Vehicle *first = base; // first vehicle to move - Vehicle *last = GetLastVehicleInChain(v); // last vehicle to move + Train *base = v; + Train *first = base; // first vehicle to move + Train *last = (Train *)GetLastVehicleInChain(v); // last vehicle to move uint length = CountVehiclesInChain(v); while (length > 2) { @@ -1803,15 +1807,15 @@ static void AdvanceWagonsBeforeSwap(Vehicle *v) * This one is called after the train is reversed. * @param v First vehicle in chain */ -static void AdvanceWagonsAfterSwap(Vehicle *v) +static void AdvanceWagonsAfterSwap(Train *v) { /* first of all, fix the situation when the train was entering a depot */ - Vehicle *dep = v; // last vehicle in front of just left depot + Train *dep = v; // last vehicle in front of just left depot while (dep->Next() != NULL && (dep->u.rail.track == TRACK_BIT_DEPOT || dep->Next()->u.rail.track != TRACK_BIT_DEPOT)) { dep = dep->Next(); // find first vehicle outside of a depot, with next vehicle inside a depot } - Vehicle *leave = dep->Next(); // first vehicle in a depot we are leaving now + Train *leave = dep->Next(); // first vehicle in a depot we are leaving now if (leave != NULL) { /* 'pull' next wagon out of the depot, so we won't miss it (it could stay in depot forever) */ @@ -1826,9 +1830,9 @@ static void AdvanceWagonsAfterSwap(Vehicle *v) dep = NULL; // no vehicle in a depot, so no vehicle leaving a depot } - Vehicle *base = v; - Vehicle *first = base; // first vehicle to move - Vehicle *last = GetLastVehicleInChain(v); // last vehicle to move + Train *base = v; + Train *first = base; // first vehicle to move + Train *last = (Train *)GetLastVehicleInChain(v); // last vehicle to move uint length = CountVehiclesInChain(v); /* we have to make sure all wagons that leave a depot because of train reversing are moved coorectly @@ -1857,7 +1861,7 @@ static void AdvanceWagonsAfterSwap(Vehicle *v) } -static void ReverseTrainDirection(Vehicle *v) +static void ReverseTrainDirection(Train *v) { if (IsRailDepotTile(v->tile)) { InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); @@ -1946,8 +1950,10 @@ static void ReverseTrainDirection(Vehicle *v) */ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Vehicle *v = Vehicle::GetIfValid(p1); - if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR; + Vehicle *vt = Vehicle::GetIfValid(p1); + if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR; + + Train *v = (Train *)vt; if (p2 != 0) { /* turn a single unit around */ @@ -1956,7 +1962,7 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT); } - Vehicle *front = v->First(); + Train *front = v->First(); /* make sure the vehicle is stopped in the depot */ if (CheckTrainStoppedInDepot(front) < 0) { return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT); @@ -2007,7 +2013,7 @@ CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, Vehicle *v = Vehicle::GetIfValid(p1); if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR; - if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50; + if (flags & DC_EXEC) ((Train *)v)->u.rail.force_proceed = 0x50; return CommandCost(); } @@ -2028,8 +2034,10 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, byte new_subtype = GB(p2, 8, 8); bool only_this = HasBit(p2, 16); - Vehicle *v = Vehicle::GetIfValid(p1); - if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR; + Vehicle *vt = Vehicle::GetIfValid(p1); + if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR; + + Train *v = (Train *)vt; if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED); if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_CAN_T_REFIT_DESTROYED_VEHICLE); @@ -2103,7 +2111,7 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, _returned_refit_capacity = num; /* Update the train's cached variables */ - if (flags & DC_EXEC) TrainConsistChanged(Vehicle::Get(p1)->First(), false); + if (flags & DC_EXEC) TrainConsistChanged((Train *)Vehicle::Get(p1)->First(), false); return cost; } @@ -2135,7 +2143,7 @@ static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int trac /** returns the tile of a depot to goto to. The given vehicle must not be * crashed! */ -static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance) +static TrainFindDepotData FindClosestTrainDepot(Train *v, int max_distance) { assert(!(v->vehstatus & VS_CRASHED)); @@ -2247,7 +2255,7 @@ static const int8 _vehicle_smoke_pos[8] = { 1, 1, 1, 0, -1, -1, -1, 0 }; -static void HandleLocomotiveSmokeCloud(const Vehicle *v) +static void HandleLocomotiveSmokeCloud(const Train *v) { bool sound = false; @@ -2255,7 +2263,7 @@ static void HandleLocomotiveSmokeCloud(const Vehicle *v) return; } - const Vehicle *u = v; + const Train *u = v; do { const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); @@ -2341,7 +2349,7 @@ void Train::PlayLeaveStationSound() const } /** Check if the train is on the last reserved tile and try to extend the path then. */ -static void CheckNextTrainTile(Vehicle *v) +static void CheckNextTrainTile(Train *v) { /* Don't do any look-ahead if path_backoff_interval is 255. */ if (_settings_game.pf.path_backoff_interval == 255) return; @@ -2378,10 +2386,10 @@ static void CheckNextTrainTile(Vehicle *v) } } -static bool CheckTrainStayInDepot(Vehicle *v) +static bool CheckTrainStayInDepot(Train *v) { /* bail out if not all wagons are in the same depot or not in a depot at all */ - for (const Vehicle *u = v; u != NULL; u = u->Next()) { + for (const Train *u = v; u != NULL; u = u->Next()) { if (u->u.rail.track != TRACK_BIT_DEPOT || u->tile != v->tile) return false; } @@ -2454,7 +2462,7 @@ static bool CheckTrainStayInDepot(Vehicle *v) } /** Clear the reservation of a tile that was just left by a wagon on track_dir. */ -static void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir track_dir) +static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir) { DiagDirection dir = TrackdirToExitdir(track_dir); @@ -2488,7 +2496,7 @@ static void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir trac } /** Free the reserved path in front of a vehicle. */ -void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin, Trackdir orig_td) +void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_td) { assert(IsFrontEngine(v)); @@ -2613,7 +2621,7 @@ static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0}; * @param dest [out] State and destination of the requested path * @return The best track the train should follow */ -static Track DoTrainPathfind(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation, PBSTileInfo *dest) +static Track DoTrainPathfind(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation, PBSTileInfo *dest) { Track best_track; @@ -2714,7 +2722,7 @@ static Track DoTrainPathfind(Vehicle *v, TileIndex tile, DiagDirection enterdir, * another reservation or a track choice. * @return INVALID_TILE indicates that the reservation failed. */ -static PBSTileInfo ExtendTrainReservation(const Vehicle *v, TrackBits *new_tracks, DiagDirection *enterdir) +static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, DiagDirection *enterdir) { bool no_90deg_turns = _settings_game.pf.pathfinder_for_trains != VPF_NTP && _settings_game.pf.forbid_90_deg; PBSTileInfo origin = FollowTrainReservation(v); @@ -2807,7 +2815,7 @@ static PBSTileInfo ExtendTrainReservation(const Vehicle *v, TrackBits *new_track * @param override_tailtype Whether all physically compatible railtypes should be followed. * @return True if a path to a safe stopping tile could be reserved. */ -static bool TryReserveSafeTrack(const Vehicle *v, TileIndex tile, Trackdir td, bool override_tailtype) +static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_tailtype) { if (_settings_game.pf.pathfinder_for_trains == VPF_YAPF) { return YapfRailFindNearestSafeTile(v, tile, td, override_tailtype); @@ -2896,7 +2904,7 @@ public: }; /* choose a track */ -static Track ChooseTrainTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck) +static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck) { Track best_track = INVALID_TRACK; bool do_track_reservation = _settings_game.pf.reserve_paths || force_res; @@ -3075,7 +3083,7 @@ static Track ChooseTrainTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir * @param first_tile_okay True if no path should be reserved if the current tile is a safe position. * @return True if a path could be reserved. */ -bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay) +bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay) { assert(v->type == VEH_TRAIN && IsFrontEngine(v)); @@ -3155,7 +3163,7 @@ bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay) } -static bool CheckReverseTrain(Vehicle *v) +static bool CheckReverseTrain(Train *v) { if (_settings_game.difficulty.line_reverse_mode != 0 || v->u.rail.track == TRACK_BIT_DEPOT || v->u.rail.track == TRACK_BIT_WORMHOLE || @@ -3295,7 +3303,7 @@ void Train::MarkDirty() * @param v The vehicle to update the speed of. * @return distance to drive. */ -static int UpdateTrainSpeed(Vehicle *v) +static int UpdateTrainSpeed(Train *v) { uint accel; @@ -3340,7 +3348,7 @@ static int UpdateTrainSpeed(Vehicle *v) return scaled_spd; } -static void TrainEnterStation(Vehicle *v, StationID station) +static void TrainEnterStation(Train *v, StationID station) { v->last_station_visited = station; @@ -3363,7 +3371,7 @@ static void TrainEnterStation(Vehicle *v, StationID station) StationAnimationTrigger(st, v->tile, STAT_ANIM_TRAIN_ARRIVES); } -static byte AfterSetTrainPos(Vehicle *v, bool new_tile) +static byte AfterSetTrainPos(Train *v, bool new_tile) { byte old_z = v->z_pos; v->z_pos = GetSlopeZ(v->x_pos, v->y_pos); @@ -3396,7 +3404,7 @@ static byte AfterSetTrainPos(Vehicle *v, bool new_tile) } /* Check if the vehicle is compatible with the specified tile */ -static inline bool CheckCompatibleRail(const Vehicle *v, TileIndex tile) +static inline bool CheckCompatibleRail(const Train *v, TileIndex tile) { return IsTileOwner(tile, v->owner) && ( @@ -3420,7 +3428,7 @@ static const RailtypeSlowdownParams _railtype_slowdown[] = { }; /** Modify the speed of the vehicle due to a turn */ -static inline void AffectSpeedByDirChange(Vehicle *v, Direction new_dir) +static inline void AffectSpeedByDirChange(Train *v, Direction new_dir) { if (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL) return; @@ -3432,7 +3440,7 @@ static inline void AffectSpeedByDirChange(Vehicle *v, Direction new_dir) } /** Modify the speed of the vehicle due to a change in altitude */ -static inline void AffectSpeedByZChange(Vehicle *v, byte old_z) +static inline void AffectSpeedByZChange(Train *v, byte old_z) { if (old_z == v->z_pos || _settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL) return; @@ -3461,7 +3469,7 @@ static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir) } -static void SetVehicleCrashed(Vehicle *v) +static void SetVehicleCrashed(Train *v) { if (v->u.rail.crash_anim_pos != 0) return; @@ -3470,7 +3478,7 @@ static void SetVehicleCrashed(Vehicle *v) /* Remove all reservations, also the ones currently under the train * and any railway station paltform reservation. */ FreeTrainTrackReservation(v); - for (const Vehicle *u = v; u != NULL; u = u->Next()) { + for (const Train *u = v; u != NULL; u = u->Next()) { ClearPathReservation(u, u->tile, u->GetVehicleTrackdir()); if (IsTileType(u->tile, MP_TUNNELBRIDGE)) { /* ClearPathReservation will not free the wormhole exit @@ -3503,7 +3511,7 @@ static void SetVehicleCrashed(Vehicle *v) if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing); } -static uint CountPassengersInTrain(const Vehicle *v) +static uint CountPassengersInTrain(const Train *v) { uint num = 0; @@ -3520,7 +3528,7 @@ static uint CountPassengersInTrain(const Vehicle *v) * @param v first vehicle of chain * @return number of victims (including 2 drivers; zero if train was already crashed) */ -static uint TrainCrashed(Vehicle *v) +static uint TrainCrashed(Train *v) { /* do not crash train twice */ if (v->vehstatus & VS_CRASHED) return 0; @@ -3549,7 +3557,7 @@ static Vehicle *FindTrainCollideEnum(Vehicle *v, void *data) Vehicle *coll = v->First(); /* can't collide with own wagons && can't crash in depot && the same height level */ - if (coll != tcc->v && v->u.rail.track != TRACK_BIT_DEPOT && abs(v->z_pos - tcc->v->z_pos) < 6) { + if (coll != tcc->v && ((Train *)v)->u.rail.track != TRACK_BIT_DEPOT && abs(v->z_pos - tcc->v->z_pos) < 6) { int x_diff = v->x_pos - tcc->v->x_pos; int y_diff = v->y_pos - tcc->v->y_pos; @@ -3557,15 +3565,15 @@ static Vehicle *FindTrainCollideEnum(Vehicle *v, void *data) if (x_diff * x_diff + y_diff * y_diff > 25) return NULL; /* crash both trains */ - tcc->num += TrainCrashed(tcc->v); - tcc->num += TrainCrashed(coll); + tcc->num += TrainCrashed((Train *)tcc->v); + tcc->num += TrainCrashed((Train *)coll); /* Try to reserve all tiles directly under the crashed trains. * As there might be more than two trains involved, we have to do that for all vehicles */ const Vehicle *u; FOR_ALL_VEHICLES(u) { - if (u->type == VEH_TRAIN && HASBITS(u->vehstatus, VS_CRASHED) && (u->u.rail.track & TRACK_BIT_DEPOT) == TRACK_BIT_NONE) { - TrackBits trackbits = u->u.rail.track; + if (u->type == VEH_TRAIN && HASBITS(u->vehstatus, VS_CRASHED) && (((Train *)u)->u.rail.track & TRACK_BIT_DEPOT) == TRACK_BIT_NONE) { + TrackBits trackbits = ((Train *)u)->u.rail.track; if ((trackbits & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) { /* Vehicle is inside a wormhole, v->u.rail.track contains no useful value then. */ trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(u->tile)); @@ -3584,7 +3592,7 @@ static Vehicle *FindTrainCollideEnum(Vehicle *v, void *data) * Reports the incident in a flashy news item, modifies station ratings and * plays a sound. */ -static bool CheckTrainCollision(Vehicle *v) +static bool CheckTrainCollision(Train *v) { /* can't collide in depot */ if (v->u.rail.track == TRACK_BIT_DEPOT) return false; @@ -3623,16 +3631,16 @@ static Vehicle *CheckVehicleAtSignal(Vehicle *v, void *data) DiagDirection exitdir = *(DiagDirection *)data; /* front engine of a train, not inside wormhole or depot, not crashed */ - if (v->type == VEH_TRAIN && IsFrontEngine(v) && (v->u.rail.track & TRACK_BIT_MASK) != 0 && !(v->vehstatus & VS_CRASHED)) { - if (v->cur_speed <= 5 && TrainExitDir(v->direction, v->u.rail.track) == exitdir) return v; + if (v->type == VEH_TRAIN && IsFrontEngine(v) && (((Train *)v)->u.rail.track & TRACK_BIT_MASK) != 0 && !(v->vehstatus & VS_CRASHED)) { + if (v->cur_speed <= 5 && TrainExitDir(v->direction, ((Train *)v)->u.rail.track) == exitdir) return v; } return NULL; } -static void TrainController(Vehicle *v, Vehicle *nomove) +static void TrainController(Train *v, Vehicle *nomove) { - Vehicle *prev; + Train *prev; /* For every vehicle after and including the given vehicle */ for (prev = v->Previous(); v != nomove; prev = v, v = v->Next()) { @@ -3922,11 +3930,11 @@ static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data) TrackBits *trackbits = (TrackBits *)data; if (v->type == VEH_TRAIN && (v->vehstatus & VS_CRASHED) != 0) { - if ((v->u.rail.track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) { + if ((((Train *)v)->u.rail.track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) { /* Vehicle is inside a wormhole, v->u.rail.track contains no useful value then. */ *trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(v->tile)); } else { - *trackbits |= v->u.rail.track; + *trackbits |= ((Train *)v)->u.rail.track; } } @@ -3940,14 +3948,14 @@ static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data) * or inside a tunnel/bridge, recalculate the signals as they might need updating * @param v the Vehicle of which last wagon is to be removed */ -static void DeleteLastWagon(Vehicle *v) +static void DeleteLastWagon(Train *v) { - Vehicle *first = v->First(); + Train *first = v->First(); /* Go to the last wagon and delete the link pointing there * *u is then the one-before-last wagon, and *v the last * one which will physicially be removed */ - Vehicle *u = v; + Train *u = v; for (; v->Next() != NULL; v = v->Next()) u = v; u->SetNext(NULL); @@ -4002,7 +4010,7 @@ static void DeleteLastWagon(Vehicle *v) } } -static void ChangeTrainDirRandomly(Vehicle *v) +static void ChangeTrainDirRandomly(Train *v) { static const DirDiff delta[] = { DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT @@ -4022,7 +4030,7 @@ static void ChangeTrainDirRandomly(Vehicle *v) } while ((v = v->Next()) != NULL); } -static bool HandleCrashedTrain(Vehicle *v) +static bool HandleCrashedTrain(Train *v) { int state = ++v->u.rail.crash_anim_pos; @@ -4061,7 +4069,7 @@ static bool HandleCrashedTrain(Vehicle *v) return true; } -static void HandleBrokenTrain(Vehicle *v) +static void HandleBrokenTrain(Train *v) { if (v->breakdown_ctr != 1) { v->breakdown_ctr = 1; @@ -4105,7 +4113,7 @@ static const uint16 _breakdown_speeds[16] = { * @param signal not line end, just a red signal * @return true iff we did NOT have to reverse */ -static bool TrainApproachingLineEnd(Vehicle *v, bool signal) +static bool TrainApproachingLineEnd(Train *v, bool signal) { /* Calc position within the current tile */ uint x = v->x_pos & 0xF; @@ -4146,7 +4154,7 @@ static bool TrainApproachingLineEnd(Vehicle *v, bool signal) * @param v train to test * @return true iff vehicle is NOT entering or inside a depot or tunnel/bridge */ -static bool TrainCanLeaveTile(const Vehicle *v) +static bool TrainCanLeaveTile(const Train *v) { /* Exit if inside a tunnel/bridge or a depot */ if (v->u.rail.track == TRACK_BIT_WORMHOLE || v->u.rail.track == TRACK_BIT_DEPOT) return false; @@ -4176,7 +4184,7 @@ static bool TrainCanLeaveTile(const Vehicle *v) * @return TileIndex of crossing the train is approaching, else INVALID_TILE * @pre v in non-crashed front engine */ -static TileIndex TrainApproachingCrossingTile(const Vehicle *v) +static TileIndex TrainApproachingCrossingTile(const Train *v) { assert(IsFrontEngine(v)); assert(!(v->vehstatus & VS_CRASHED)); @@ -4202,7 +4210,7 @@ static TileIndex TrainApproachingCrossingTile(const Vehicle *v) * @param v vehicle we are checking * @return true iff we did NOT have to reverse */ -static bool TrainCheckIfLineEnds(Vehicle *v) +static bool TrainCheckIfLineEnds(Train *v) { /* First, handle broken down train */ @@ -4253,7 +4261,7 @@ static bool TrainCheckIfLineEnds(Vehicle *v) } -static bool TrainLocoHandler(Vehicle *v, bool mode) +static bool TrainLocoHandler(Train *v, bool mode) { /* train has crashed? */ if (v->vehstatus & VS_CRASHED) { @@ -4381,7 +4389,7 @@ static bool TrainLocoHandler(Vehicle *v, bool mode) SetLastSpeed(v, v->cur_speed); } - for (Vehicle *u = v; u != NULL; u = u->Next()) { + for (Train *u = v; u != NULL; u = u->Next()) { if ((u->vehstatus & VS_HIDDEN) != 0) continue; uint16 old_image = u->cur_image; @@ -4399,7 +4407,7 @@ static bool TrainLocoHandler(Vehicle *v, bool mode) Money Train::GetRunningCost() const { Money cost = 0; - const Vehicle *v = this; + const Train *v = this; do { const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); @@ -4448,7 +4456,7 @@ bool Train::Tick() return true; } -static void CheckIfTrainNeedsService(Vehicle *v) +static void CheckIfTrainNeedsService(Train *v) { static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16; diff --git a/src/train_gui.cpp b/src/train_gui.cpp index 7ffeac6aa..1f16bbd15 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -28,7 +28,7 @@ void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2) FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN && IsFrontEngine(v) && v->tile == tile && - v->u.rail.track == TRACK_BIT_DEPOT) { + ((Train *)v)->u.rail.track == TRACK_BIT_DEPOT) { if (found != NULL) return; // must be exactly one. found = v; } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 9a20e31cb..4cd0d2e5a 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -647,7 +647,7 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) Track track = DiagDirToDiagTrack(dir); Owner owner = GetTileOwner(tile); - Vehicle *v = NULL; + Train *v = NULL; if (GetTunnelBridgeReservation(tile)) { v = GetTrainForReservation(tile, track); if (v != NULL) FreeTrainTrackReservation(v); @@ -711,7 +711,7 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags) bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL; Owner owner = GetTileOwner(tile); uint height = GetBridgeHeight(tile); - Vehicle *v = NULL; + Train *v = NULL; if (rail && GetTunnelBridgeReservation(tile)) { v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction)); @@ -1385,31 +1385,32 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti DiagDirection vdir; if (v->type == VEH_TRAIN) { + Train *t = (Train *)v; fc = (x & 0xF) + (y << 4); - vdir = DirToDiagDir(v->direction); + vdir = DirToDiagDir(t->direction); - if (v->u.rail.track != TRACK_BIT_WORMHOLE && dir == vdir) { - if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) { - if (!PlayVehicleSound(v, VSE_TUNNEL) && RailVehInfo(v->engine_type)->engclass == 0) { + if (t->u.rail.track != TRACK_BIT_WORMHOLE && dir == vdir) { + if (IsFrontEngine(t) && fc == _tunnel_fractcoord_1[dir]) { + if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) { SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v); } return VETSB_CONTINUE; } if (fc == _tunnel_fractcoord_2[dir]) { - v->tile = tile; - v->u.rail.track = TRACK_BIT_WORMHOLE; - v->vehstatus |= VS_HIDDEN; + t->tile = tile; + t->u.rail.track = TRACK_BIT_WORMHOLE; + t->vehstatus |= VS_HIDDEN; return VETSB_ENTERED_WORMHOLE; } } if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) { /* We're at the tunnel exit ?? */ - v->tile = tile; - v->u.rail.track = (TrackBits)_exit_tunnel_track[dir]; - assert(v->u.rail.track); - v->vehstatus &= ~VS_HIDDEN; + t->tile = tile; + t->u.rail.track = (TrackBits)_exit_tunnel_track[dir]; + assert(t->u.rail.track); + t->vehstatus &= ~VS_HIDDEN; return VETSB_ENTERED_WORMHOLE; } } else if (v->type == VEH_ROAD) { @@ -1462,11 +1463,12 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti case DIAGDIR_NW: if ((y & 0xF) != 0) return VETSB_CONTINUE; break; } switch (v->type) { - case VEH_TRAIN: - v->u.rail.track = TRACK_BIT_WORMHOLE; - ClrBit(v->u.rail.flags, VRF_GOINGUP); - ClrBit(v->u.rail.flags, VRF_GOINGDOWN); - break; + case VEH_TRAIN: { + Train *t = (Train *)v; + t->u.rail.track = TRACK_BIT_WORMHOLE; + ClrBit(t->u.rail.flags, VRF_GOINGUP); + ClrBit(t->u.rail.flags, VRF_GOINGDOWN); + } break; case VEH_ROAD: ((RoadVehicle *)v)->state = RVSB_WORMHOLE; @@ -1482,12 +1484,13 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) { v->tile = tile; switch (v->type) { - case VEH_TRAIN: - if (v->u.rail.track == TRACK_BIT_WORMHOLE) { - v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); + case VEH_TRAIN: { + Train *t = (Train *)v; + if (t->u.rail.track == TRACK_BIT_WORMHOLE) { + t->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); return VETSB_ENTERED_WORMHOLE; } - break; + } break; case VEH_ROAD: { RoadVehicle *rv = (RoadVehicle *)v; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index fc936d555..5cfb253bb 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -982,8 +982,8 @@ void VehicleEnterDepot(Vehicle *v) if (!IsFrontEngine(v)) v = v->First(); UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner); v->load_unload_time_rem = 0; - ClrBit(v->u.rail.flags, VRF_TOGGLE_REVERSE); - TrainConsistChanged(v, true); + ClrBit(((Train *)v)->u.rail.flags, VRF_TOGGLE_REVERSE); + TrainConsistChanged((Train *)v, true); break; case VEH_ROAD: @@ -1488,7 +1488,7 @@ void Vehicle::LeaveStation() * might not be marked as wanting a reservation, e.g. * when an overlength train gets turned around in a station. */ if (UpdateSignalsOnSegment(this->tile, TrackdirToExitdir(this->GetVehicleTrackdir()), this->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) { - TryPathReserve(this, true, true); + TryPathReserve((Train *)this, true, true); } } } diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 7217f3f30..cb18d2b69 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -46,7 +46,7 @@ enum VehicleFlags { struct VehicleRail { /* Link between the two ends of a multiheaded engine */ - Vehicle *other_multiheaded_part; + Train *other_multiheaded_part; /* Cached wagon override spritegroup */ const struct SpriteGroup *cached_override; diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 6dd38a346..dc21d1000 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -152,7 +152,7 @@ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 if (!vehicle_list_window) { if (vehicle_type == VEH_TRAIN) { - if (CheckTrainInDepot(v, false) == -1) continue; + if (CheckTrainInDepot((Train *)v, false) == -1) continue; } else { if (!(v->vehstatus & VS_HIDDEN)) continue; } @@ -381,8 +381,8 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (flags & DC_EXEC) { w = Vehicle::Get(_new_vehicle_id); - 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 && HasBit(((Train *)v)->u.rail.flags, VRF_REVERSE_DIRECTION)) { + SetBit(((Train *)w)->u.rail.flags, VRF_REVERSE_DIRECTION); } if (v->type == VEH_TRAIN && !IsFrontEngine(v)) { @@ -403,7 +403,7 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint } 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); + } while (v->type == VEH_TRAIN && (v = GetNextVehicle((Train *)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 */ @@ -437,7 +437,7 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint } if (w->type == VEH_TRAIN && EngineHasArticPart(w)) { - w = GetNextArticPart(w); + w = GetNextArticPart((Train *)w); } else if (w->type == VEH_ROAD && RoadVehHasArticPart(w)) { w = w->Next(); } else { @@ -453,7 +453,7 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint } if (v->type == VEH_TRAIN && EngineHasArticPart(v)) { - v = GetNextArticPart(v); + v = GetNextArticPart((Train *)v); } else if (v->type == VEH_ROAD && RoadVehHasArticPart(v)) { v = v->Next(); } else { @@ -461,8 +461,8 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint } } while (v != NULL); - if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w); - } while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL); + if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle((Train *)w); + } while (v->type == VEH_TRAIN && (v = GetNextVehicle((Train *)v)) != NULL); if (flags & DC_EXEC) { /* diff --git a/src/vehicle_func.h b/src/vehicle_func.h index f10050d1c..f7827112e 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -59,10 +59,6 @@ void MarkSingleVehicleDirty(const Vehicle *v); UnitID GetFreeUnitNumber(VehicleType type); -void TrainConsistChanged(Vehicle *v, bool same_length); -void TrainPowerChanged(Vehicle *v); -Money GetTrainRunningCost(const Vehicle *v); - CommandCost SendAllVehiclesToDepot(VehicleType type, DoCommandFlag flags, bool service, Owner owner, uint16 vlw_flag, uint32 id); void VehicleEnterDepot(Vehicle *v); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 725382077..6a6ee6bb3 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -18,6 +18,7 @@ #include "newgrf_text.h" #include "station_map.h" #include "roadveh.h" +#include "train.h" #include "depot_base.h" #include "group_gui.h" #include "strings_func.h" @@ -1468,7 +1469,7 @@ struct VehicleDetailsWindow : Window { SetDParam(1, v->u.rail.cached_power); SetDParam(0, v->u.rail.cached_weight); SetDParam(3, v->u.rail.cached_max_te / 1000); - DrawString(2, this->width - 2, 25, (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL && v->u.rail.railtype != RAILTYPE_MAGLEV) ? + DrawString(2, this->width - 2, 25, (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL && ((Train *)v)->u.rail.railtype != RAILTYPE_MAGLEV) ? STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE : STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED); break; @@ -1948,7 +1949,7 @@ struct VehicleViewWindow : Window { } else { // no train str = STR_VEHICLE_STATUS_STOPPED; } - } else if (v->type == VEH_TRAIN && HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) { + } else if (v->type == VEH_TRAIN && HasBit(((Train *)v)->u.rail.flags, VRF_TRAIN_STUCK)) { str = STR_TRAIN_STUCK; } else { // vehicle is in a "normal" state, show current order switch (v->current_order.GetType()) { diff --git a/src/vehicle_type.h b/src/vehicle_type.h index d1152ace3..1bba8defa 100644 --- a/src/vehicle_type.h +++ b/src/vehicle_type.h @@ -24,6 +24,10 @@ template <> struct EnumPropsT<VehicleType> : MakeEnumPropsT<VehicleType, byte, V typedef TinyEnumT<VehicleType> VehicleTypeByte; struct Vehicle; +struct Train; +struct RoadVehicle; +struct Ship; +struct Aircraft; struct BaseVehicle { diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp index b72882b73..ab57da1e4 100644 --- a/src/vehiclelist.cpp +++ b/src/vehiclelist.cpp @@ -29,7 +29,7 @@ void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine switch (type) { case VEH_TRAIN: if (IsArticulatedPart(v) || IsRearDualheaded(v)) continue; - if (v->u.rail.track != TRACK_BIT_DEPOT) continue; + if (((Train *)v)->u.rail.track != TRACK_BIT_DEPOT) continue; if (wagons != NULL && IsFreeWagon(v->First())) { if (individual_wagons || IsFreeWagon(v)) *wagons->Append() = v; continue; diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 4f157aa55..2ba7dd8d5 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -813,7 +813,7 @@ static void FloodVehicle(Vehicle *v) /* FreeTrainTrackReservation() calls GetVehicleTrackdir() that doesn't like crashed vehicles. * In this case, v->direction matches v->u.rail.track, so we can do this (it wasn't crashed before) */ v->vehstatus &= ~VS_CRASHED; - FreeTrainTrackReservation(v); + FreeTrainTrackReservation((Train *)v); v->vehstatus |= VS_CRASHED; } v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index ae3980edf..bac5417c3 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -258,7 +258,7 @@ CommandCost RemoveTrainWaypoint(TileIndex tile, DoCommandFlag flags, bool justre wp->deleted = 30; // let it live for this many days before we do the actual deletion. RedrawWaypointSign(wp); - Vehicle *v = NULL; + Train *v = NULL; if (justremove) { TrackBits tracks = GetRailWaypointBits(tile); bool reserved = GetDepotWaypointReservation(tile); diff --git a/src/yapf/follow_track.hpp b/src/yapf/follow_track.hpp index f69e4c190..a0f9dc37c 100644 --- a/src/yapf/follow_track.hpp +++ b/src/yapf/follow_track.hpp @@ -8,6 +8,7 @@ #include "yapf.hpp" #include "../depot_map.h" #include "../roadveh.h" +#include "../train.h" /** Track follower helper template class (can serve pathfinders and vehicle * controllers). See 6 different typedefs below for 3 different transport @@ -54,7 +55,7 @@ struct CFollowTrackT { assert(!IsRailTT() || (v != NULL && v->type == VEH_TRAIN)); m_veh = v; - Init(v != NULL ? v->owner : INVALID_OWNER, railtype_override == INVALID_RAILTYPES ? v->u.rail.compatible_railtypes : railtype_override, pPerf); + Init(v != NULL ? v->owner : INVALID_OWNER, railtype_override == INVALID_RAILTYPES ? ((Train *)v)->u.rail.compatible_railtypes : railtype_override, pPerf); } FORCEINLINE void Init(Owner o, RailTypes railtype_override, CPerformanceTimer *pPerf) @@ -105,7 +106,7 @@ struct CFollowTrackT m_old_tile = old_tile; m_old_td = old_td; m_err = EC_NONE; - assert(((TrackStatusToTrackdirBits(GetTileTrackStatus(m_old_tile, TT(), m_veh ? m_veh->u.road.compatible_roadtypes : 0)) & TrackdirToTrackdirBits(m_old_td)) != 0) || + assert(((TrackStatusToTrackdirBits(GetTileTrackStatus(m_old_tile, TT(), m_veh ? ((RoadVehicle *)m_veh)->compatible_roadtypes : 0)) & TrackdirToTrackdirBits(m_old_td)) != 0) || (IsTram() && GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR)); // Disable the assertion for single tram bits m_exitdir = TrackdirToExitdir(m_old_td); if (ForcedReverse()) return true; diff --git a/src/yapf/yapf_destrail.hpp b/src/yapf/yapf_destrail.hpp index 7fb41d653..fbdac4a71 100644 --- a/src/yapf/yapf_destrail.hpp +++ b/src/yapf/yapf_destrail.hpp @@ -91,8 +91,8 @@ public: FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td) { return - IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns()) && - IsWaitingPositionFree(Yapf().GetVehicle(), tile, td, !TrackFollower::Allow90degTurns()); + IsSafeWaitingPosition((Train *)Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns()) && + IsWaitingPositionFree((Train *)Yapf().GetVehicle(), tile, td, !TrackFollower::Allow90degTurns()); } /** Called by YAPF to calculate cost estimate. Calculates distance to the destination diff --git a/src/yapf/yapf_rail.cpp b/src/yapf/yapf_rail.cpp index 8d530bf52..2c05c68ff 100644 --- a/src/yapf/yapf_rail.cpp +++ b/src/yapf/yapf_rail.cpp @@ -54,7 +54,7 @@ private: bool FindSafePositionProc(TileIndex tile, Trackdir td) { - if (IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) { + if (IsSafeWaitingPosition((Train *)Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) { m_res_dest = tile; m_res_dest_td = td; return false; // Stop iterating segment @@ -149,7 +149,7 @@ public: } /* Don't bother if the target is reserved. */ - if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false; + if (!IsWaitingPositionFree((Train *)Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false; for (Node *node = m_res_node; node->m_parent != NULL; node = node->m_parent) { node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack); @@ -411,7 +411,7 @@ public: if (target != NULL) target->tile = INVALID_TILE; /* set origin and destination nodes */ - PBSTileInfo origin = FollowTrainReservation(v); + PBSTileInfo origin = FollowTrainReservation((Train *)v); Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, INVALID_TRACKDIR, 1, true); Yapf().SetDestination(v); @@ -534,10 +534,11 @@ Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection ent return td_ret; } -bool YapfCheckReverseTrain(const Vehicle *v) +bool YapfCheckReverseTrain(const Vehicle *vt) { + Train *v = (Train *)vt; /* last wagon */ - const Vehicle *last_veh = GetLastVehicleInChain(v); + const Train *last_veh = (Train *)GetLastVehicleInChain(v); /* get trackdirs of both ends */ Trackdir td = v->GetVehicleTrackdir(); @@ -601,7 +602,7 @@ bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reve const Vehicle *last_veh = GetLastVehicleInChain(v); - PBSTileInfo origin = FollowTrainReservation(v); + PBSTileInfo origin = FollowTrainReservation((Train *)v); TileIndex last_tile = last_veh->tile; Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir()); |