diff --git a/src/base_station_base.h b/src/base_station_base.h index 0adf7a358a..12036085a3 100644 --- a/src/base_station_base.h +++ b/src/base_station_base.h @@ -74,7 +74,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> { TimerGameCalendar::Date build_date{}; ///< Date of construction uint16_t random_bits = 0; ///< Random bits assigned to this station - uint8_t waiting_random_triggers = 0; ///< Waiting triggers (NewGRF) for this station + StationRandomTriggers waiting_random_triggers; ///< Waiting triggers (NewGRF), shared by all station parts/tiles, road stops, ... essentially useless and broken by design. uint8_t cached_anim_triggers = 0; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen. uint8_t cached_roadstop_anim_triggers = 0; ///< NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing should happen. CargoTypes cached_cargo_triggers{}; ///< NOSAVE: Combined cargo trigger bitmask diff --git a/src/economy.cpp b/src/economy.cpp index 689ac489d2..01896c9ba7 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1167,7 +1167,7 @@ static void TriggerIndustryProduction(Industry *i) } } - TriggerIndustryRandomisation(i, INDUSTRY_TRIGGER_RECEIVED_CARGO); + TriggerIndustryRandomisation(i, IndustryRandomTrigger::CargoReceived); TriggerIndustryAnimation(i, IAT_INDUSTRY_RECEIVED_CARGO); } @@ -1779,7 +1779,7 @@ static void LoadUnloadVehicle(Vehicle *front) /* If there's goods waiting at the station, and the vehicle * has capacity for it, load it on the vehicle. */ if ((v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0 || (ge->HasData() && ge->GetData().cargo.AvailableCount() > 0)) && MayLoadUnderExclusiveRights(st, v)) { - if (v->cargo.StoredCount() == 0) TriggerVehicleRandomisation(v, VEHICLE_TRIGGER_NEW_CARGO); + if (v->cargo.StoredCount() == 0) TriggerVehicleRandomisation(v, VehicleRandomTrigger::NewCargo); if (_settings_game.order.gradual_loading) cap_left = std::min(cap_left, GetLoadAmount(v)); uint loaded = ge->GetOrCreateData().cargo.Load(cap_left, &v->cargo, next_station, v->GetCargoTile()); @@ -1811,10 +1811,10 @@ static void LoadUnloadVehicle(Vehicle *front) st->last_vehicle_type = v->type; if (ge->GetData().cargo.TotalCount() == 0) { - TriggerStationRandomisation(st, st->xy, SRT_CARGO_TAKEN, v->cargo_type); + TriggerStationRandomisation(st, st->xy, StationRandomTrigger::CargoTaken, v->cargo_type); TriggerStationAnimation(st, st->xy, SAT_CARGO_TAKEN, v->cargo_type); TriggerAirportAnimation(st, AAT_STATION_CARGO_TAKEN, v->cargo_type); - TriggerRoadStopRandomisation(st, st->xy, RSRT_CARGO_TAKEN, v->cargo_type); + TriggerRoadStopRandomisation(st, st->xy, StationRandomTrigger::CargoTaken, v->cargo_type); TriggerRoadStopAnimation(st, st->xy, SAT_CARGO_TAKEN, v->cargo_type); } @@ -1834,10 +1834,10 @@ static void LoadUnloadVehicle(Vehicle *front) if (anything_loaded || anything_unloaded) { if (front->type == VEH_TRAIN) { - TriggerStationRandomisation(st, front->tile, SRT_TRAIN_LOADS); + TriggerStationRandomisation(st, front->tile, StationRandomTrigger::VehicleLoads); TriggerStationAnimation(st, front->tile, SAT_TRAIN_LOADS); } else if (front->type == VEH_ROAD) { - TriggerRoadStopRandomisation(st, front->tile, RSRT_VEH_LOADS); + TriggerRoadStopRandomisation(st, front->tile, StationRandomTrigger::VehicleLoads); TriggerRoadStopAnimation(st, front->tile, SAT_TRAIN_LOADS); } } @@ -1910,7 +1910,7 @@ static void LoadUnloadVehicle(Vehicle *front) /* Make sure the vehicle is marked dirty, since we need to update the NewGRF * properties such as weight, power and TE whenever the trigger runs. */ dirty_vehicle = true; - TriggerVehicleRandomisation(front, VEHICLE_TRIGGER_EMPTY); + TriggerVehicleRandomisation(front, VehicleRandomTrigger::Empty); } if (dirty_vehicle) { diff --git a/src/house_type.h b/src/house_type.h index 6c5f4d136f..bac5d01712 100644 --- a/src/house_type.h +++ b/src/house_type.h @@ -15,4 +15,16 @@ typedef uint16_t HouseClassID; ///< Classes of houses. struct HouseSpec; +/** Randomisation triggers for houses */ +enum class HouseRandomTrigger : uint8_t { + /* The tile of the house has been triggered during the tileloop. */ + TileLoop, + /* + * The top tile of a (multitile) building has been triggered during and all + * the tileloop other tiles of the same building get the same random value. + */ + TileLoopNorth, +}; +using HouseRandomTriggers = EnumBitSet; + #endif /* HOUSE_TYPE_H */ diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 1d274b1a60..5c3cb2d57f 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -844,7 +844,7 @@ static void TileLoop_Industry(TileIndex tile) * returning from TileLoop_Water. */ if (!IsTileType(tile, MP_INDUSTRY)) return; - TriggerIndustryTileRandomisation(tile, INDTILE_TRIGGER_TILE_LOOP); + TriggerIndustryTileRandomisation(tile, IndustryRandomTrigger::TileLoop); if (!IsIndustryCompleted(tile)) { MakeIndustryTileBigger(tile); @@ -1222,7 +1222,7 @@ static void ProduceIndustryGoods(Industry *i) if (cut) ChopLumberMillTrees(i); } - TriggerIndustryRandomisation(i, INDUSTRY_TRIGGER_INDUSTRY_TICK); + TriggerIndustryRandomisation(i, IndustryRandomTrigger::IndustryTick); TriggerIndustryAnimation(i, IAT_INDUSTRY_TICK); } } diff --git a/src/industry_map.h b/src/industry_map.h index 404b345276..700d33f4da 100644 --- a/src/industry_map.h +++ b/src/industry_map.h @@ -247,10 +247,10 @@ inline void SetIndustryRandomBits(Tile tile, uint8_t bits) * @pre IsTileType(tile, MP_INDUSTRY) * @return requested triggers */ -inline uint8_t GetIndustryRandomTriggers(Tile tile) +inline IndustryRandomTriggers GetIndustryRandomTriggers(Tile tile) { assert(IsTileType(tile, MP_INDUSTRY)); - return GB(tile.m6(), 3, 3); + return static_cast(GB(tile.m6(), 3, 3)); } @@ -261,10 +261,10 @@ inline uint8_t GetIndustryRandomTriggers(Tile tile) * @param triggers the triggers to set * @pre IsTileType(tile, MP_INDUSTRY) */ -inline void SetIndustryRandomTriggers(Tile tile, uint8_t triggers) +inline void SetIndustryRandomTriggers(Tile tile, IndustryRandomTriggers triggers) { assert(IsTileType(tile, MP_INDUSTRY)); - SB(tile.m6(), 3, 3, triggers); + SB(tile.m6(), 3, 3, triggers.base()); } /** @@ -283,7 +283,7 @@ inline void MakeIndustry(Tile t, IndustryID index, IndustryGfx gfx, uint8_t rand SetIndustryRandomBits(t, random); // m3 t.m4() = 0; SetIndustryGfx(t, gfx); // m5, part of m6 - SetIndustryRandomTriggers(t, 0); // rest of m6 + SetIndustryRandomTriggers(t, {}); // rest of m6 SetWaterClass(t, wc); t.m7() = 0; } diff --git a/src/industry_type.h b/src/industry_type.h index 76514a19e1..33db310ed5 100644 --- a/src/industry_type.h +++ b/src/industry_type.h @@ -21,6 +21,14 @@ struct Industry; struct IndustrySpec; struct IndustryTileSpec; +/** Available industry random triggers. */ +enum class IndustryRandomTrigger : uint8_t { + TileLoop, ///< The tile of the industry has been triggered during the tileloop. + IndustryTick, ///< The industry has been triggered via its tick. + CargoReceived, ///< Cargo has been delivered. +}; +using IndustryRandomTriggers = EnumBitSet; + static const IndustryType NUM_INDUSTRYTYPES_PER_GRF = 128; ///< maximum number of industry types per NewGRF; limited to 128 because bit 7 has a special meaning in some variables/callbacks (see MapNewGRFIndustryType). static const IndustryType NEW_INDUSTRYOFFSET = 37; ///< original number of industry types diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 1a52dd2ee7..5bb85806bb 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -311,7 +311,7 @@ static uint8_t MapAircraftMovementAction(const Aircraft *v) /* virtual */ uint32_t VehicleScopeResolver::GetRandomTriggers() const { - return this->v == nullptr ? 0 : this->v->waiting_random_triggers; + return this->v == nullptr ? 0 : this->v->waiting_random_triggers.base(); } @@ -626,7 +626,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec if (parameter == 0x5F) { /* This seems to be the only variable that makes sense to access via var 61, but is not handled by VehicleGetVariable */ - return (u->random_bits << 8) | u->waiting_random_triggers; + return (u->random_bits << 8) | u->waiting_random_triggers.base(); } else { return VehicleGetVariable(u, object, parameter, GetRegister(0x10E), available); } @@ -891,7 +891,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec case 0x78: break; // not implemented case 0x79: break; // not implemented case 0x7A: return v->random_bits; - case 0x7B: return v->waiting_random_triggers; + case 0x7B: return v->waiting_random_triggers.base(); case 0x7C: break; // vehicle specific, see below case 0x7D: break; // vehicle specific, see below case 0x7E: break; // not implemented @@ -1061,7 +1061,7 @@ static const GRFFile *GetEngineGrfFile(EngineID engine_type) */ VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool rotor_in_gui, CallbackID callback, uint32_t callback_param1, uint32_t callback_param2) - : ResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2), + : SpecializedResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2), self_scope(*this, engine_type, v, rotor_in_gui), parent_scope(*this, engine_type, ((v != nullptr) ? v->First() : v), rotor_in_gui), relative_scope(*this, engine_type, v, rotor_in_gui), @@ -1247,20 +1247,20 @@ bool TestVehicleBuildProbability(Vehicle *v, EngineID engine, BuildProbabilityTy return p + RandomRange(PROBABILITY_RANGE) >= PROBABILITY_RANGE; } -static void DoTriggerVehicleRandomisation(Vehicle *v, VehicleTrigger trigger, uint16_t base_random_bits, bool first) +static void DoTriggerVehicleRandomisation(Vehicle *v, VehicleRandomTrigger trigger, uint16_t base_random_bits, bool first) { /* We can't trigger a non-existent vehicle... */ assert(v != nullptr); VehicleResolverObject object(v->engine_type, v, VehicleResolverObject::WO_CACHED, false, CBID_RANDOM_TRIGGER); - object.waiting_random_triggers = v->waiting_random_triggers | trigger; - v->waiting_random_triggers = object.waiting_random_triggers; // store now for var 5F + v->waiting_random_triggers.Set(trigger); // store now for var 5F + object.SetWaitingRandomTriggers(v->waiting_random_triggers); const SpriteGroup *group = object.Resolve(); if (group == nullptr) return; /* Store remaining triggers. */ - v->waiting_random_triggers = object.GetRemainingRandomTriggers(); + v->waiting_random_triggers.Reset(object.GetUsedRandomTriggers()); /* Rerandomise bits. Scopes other than SELF are invalid for rerandomisation. For bug-to-bug-compatibility with TTDP we ignore the scope. */ uint16_t new_random_bits = Random(); @@ -1269,7 +1269,7 @@ static void DoTriggerVehicleRandomisation(Vehicle *v, VehicleTrigger trigger, ui v->random_bits |= (first ? new_random_bits : base_random_bits) & reseed; switch (trigger) { - case VEHICLE_TRIGGER_NEW_CARGO: + case VehicleRandomTrigger::NewCargo: /* All vehicles in chain get ANY_NEW_CARGO trigger now. * So we call it for the first one and they will recurse. * Indexing part of vehicle random bits needs to be @@ -1278,17 +1278,17 @@ static void DoTriggerVehicleRandomisation(Vehicle *v, VehicleTrigger trigger, ui * i.e.), so we give them all the NEW_CARGO triggered * vehicle's portion of random bits. */ assert(first); - DoTriggerVehicleRandomisation(v->First(), VEHICLE_TRIGGER_ANY_NEW_CARGO, new_random_bits, false); + DoTriggerVehicleRandomisation(v->First(), VehicleRandomTrigger::AnyNewCargo, new_random_bits, false); break; - case VEHICLE_TRIGGER_DEPOT: + case VehicleRandomTrigger::Depot: /* We now trigger the next vehicle in chain recursively. * The random bits portions may be different for each * vehicle in chain. */ if (v->Next() != nullptr) DoTriggerVehicleRandomisation(v->Next(), trigger, 0, true); break; - case VEHICLE_TRIGGER_EMPTY: + case VehicleRandomTrigger::Empty: /* We now trigger the next vehicle in chain * recursively. The random bits portions must be same * for each vehicle in chain, so we give them all @@ -1296,20 +1296,20 @@ static void DoTriggerVehicleRandomisation(Vehicle *v, VehicleTrigger trigger, ui if (v->Next() != nullptr) DoTriggerVehicleRandomisation(v->Next(), trigger, first ? new_random_bits : base_random_bits, false); break; - case VEHICLE_TRIGGER_ANY_NEW_CARGO: + case VehicleRandomTrigger::AnyNewCargo: /* Now pass the trigger recursively to the next vehicle * in chain. */ assert(!first); - if (v->Next() != nullptr) DoTriggerVehicleRandomisation(v->Next(), VEHICLE_TRIGGER_ANY_NEW_CARGO, base_random_bits, false); + if (v->Next() != nullptr) DoTriggerVehicleRandomisation(v->Next(), trigger, base_random_bits, false); break; - case VEHICLE_TRIGGER_CALLBACK_32: + case VehicleRandomTrigger::Callback32: /* Do not do any recursion */ break; } } -void TriggerVehicleRandomisation(Vehicle *v, VehicleTrigger trigger) +void TriggerVehicleRandomisation(Vehicle *v, VehicleRandomTrigger trigger) { v->InvalidateNewGRFCacheOfChain(); DoTriggerVehicleRandomisation(v, trigger, 0, true); diff --git a/src/newgrf_engine.h b/src/newgrf_engine.h index f2373528c5..26ee250884 100644 --- a/src/newgrf_engine.h +++ b/src/newgrf_engine.h @@ -44,7 +44,7 @@ struct VehicleScopeResolver : public ScopeResolver { }; /** Resolver for a vehicle (chain) */ -struct VehicleResolverObject : public ResolverObject { +struct VehicleResolverObject : public SpecializedResolverObject { /** Application of 'wagon overrides'. */ enum WagonOverride : uint8_t { WO_NONE, //!< Resolve no wagon overrides. @@ -107,18 +107,7 @@ enum class BuildProbabilityType : uint8_t { bool TestVehicleBuildProbability(Vehicle *v, EngineID engine, BuildProbabilityType type); -enum VehicleTrigger : uint8_t { - VEHICLE_TRIGGER_NEW_CARGO = 0x01, - /* Externally triggered only for the first vehicle in chain */ - VEHICLE_TRIGGER_DEPOT = 0x02, - /* Externally triggered only for the first vehicle in chain, only if whole chain is empty */ - VEHICLE_TRIGGER_EMPTY = 0x04, - /* Not triggered externally (called for the whole chain if we got NEW_CARGO) */ - VEHICLE_TRIGGER_ANY_NEW_CARGO = 0x08, - /* Externally triggered for each vehicle in chain */ - VEHICLE_TRIGGER_CALLBACK_32 = 0x10, -}; -void TriggerVehicleRandomisation(Vehicle *veh, VehicleTrigger trigger); +void TriggerVehicleRandomisation(Vehicle *veh, VehicleRandomTrigger trigger); void AlterVehicleListOrder(EngineID engine, uint16_t target); void CommitVehicleListOrderChanges(); diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index 56715db47a..68002b1b92 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -107,7 +107,7 @@ void ResetHouses() HouseResolverObject::HouseResolverObject(HouseID house_id, TileIndex tile, Town *town, CallbackID callback, uint32_t param1, uint32_t param2, bool not_yet_constructed, uint8_t initial_random_bits, CargoTypes watched_cargo_triggers, int view) - : ResolverObject(GetHouseSpecGrf(house_id), callback, param1, param2), + : SpecializedResolverObject(GetHouseSpecGrf(house_id), callback, param1, param2), house_scope(*this, house_id, tile, town, not_yet_constructed, initial_random_bits, watched_cargo_triggers, view), town_scope(*this, town, not_yet_constructed) // Don't access StorePSA if house is not yet constructed. { @@ -229,7 +229,7 @@ void DecreaseBuildingCount(Town *t, HouseID house_id) /* virtual */ uint32_t HouseScopeResolver::GetRandomTriggers() const { /* Note: Towns build houses over houses. So during construction checks 'tile' may be a valid but unrelated house. */ - return this->not_yet_constructed ? 0 : GetHouseRandomTriggers(this->tile); + return this->not_yet_constructed ? 0 : GetHouseRandomTriggers(this->tile).base(); } static uint32_t GetNumHouses(HouseID house_id, const Town *town) @@ -591,8 +591,8 @@ bool NewHouseTileLoop(TileIndex tile) return true; } - TriggerHouseRandomisation(tile, HOUSE_TRIGGER_TILE_LOOP); - if (hs->building_flags.Any(BUILDING_HAS_1_TILE)) TriggerHouseRandomisation(tile, HOUSE_TRIGGER_TILE_LOOP_TOP); + TriggerHouseRandomisation(tile, HouseRandomTrigger::TileLoop); + if (hs->building_flags.Any(BUILDING_HAS_1_TILE)) TriggerHouseRandomisation(tile, HouseRandomTrigger::TileLoopNorth); /* Call the unsynchronized tile loop trigger */ TriggerHouseAnimation_TileLoop(tile, false, 0); @@ -620,7 +620,7 @@ bool NewHouseTileLoop(TileIndex tile) return true; } -static void DoTriggerHouseRandomisation(TileIndex tile, HouseTrigger trigger, uint8_t base_random, bool first) +static void DoTriggerHouseRandomisation(TileIndex tile, HouseRandomTrigger trigger, uint8_t base_random, bool first) { /* We can't trigger a non-existent building... */ assert(IsTileType(tile, MP_HOUSE)); @@ -631,14 +631,17 @@ static void DoTriggerHouseRandomisation(TileIndex tile, HouseTrigger trigger, ui if (hs->grf_prop.GetSpriteGroup() == nullptr) return; HouseResolverObject object(hid, tile, Town::GetByTile(tile), CBID_RANDOM_TRIGGER); - object.waiting_random_triggers = GetHouseRandomTriggers(tile) | trigger; - SetHouseRandomTriggers(tile, object.waiting_random_triggers); // store now for var 5F + auto waiting_random_triggers = GetHouseRandomTriggers(tile); + waiting_random_triggers.Set(trigger); + SetHouseRandomTriggers(tile, waiting_random_triggers); // store now for var 5F + object.SetWaitingRandomTriggers(waiting_random_triggers); const SpriteGroup *group = object.Resolve(); if (group == nullptr) return; /* Store remaining triggers. */ - SetHouseRandomTriggers(tile, object.GetRemainingRandomTriggers()); + waiting_random_triggers.Reset(object.GetUsedRandomTriggers()); + SetHouseRandomTriggers(tile, waiting_random_triggers); /* Rerandomise bits. Scopes other than SELF are invalid for houses. For bug-to-bug-compatibility with TTDP we ignore the scope. */ uint8_t new_random_bits = Random(); @@ -649,11 +652,11 @@ static void DoTriggerHouseRandomisation(TileIndex tile, HouseTrigger trigger, ui SetHouseRandomBits(tile, random_bits); switch (trigger) { - case HOUSE_TRIGGER_TILE_LOOP: + case HouseRandomTrigger::TileLoop: /* Random value already set. */ break; - case HOUSE_TRIGGER_TILE_LOOP_TOP: + case HouseRandomTrigger::TileLoopNorth: if (!first) { /* The top tile is marked dirty by the usual TileLoop */ MarkTileDirtyByTile(tile); @@ -667,7 +670,7 @@ static void DoTriggerHouseRandomisation(TileIndex tile, HouseTrigger trigger, ui } } -void TriggerHouseRandomisation(TileIndex t, HouseTrigger trigger) +void TriggerHouseRandomisation(TileIndex t, HouseRandomTrigger trigger) { DoTriggerHouseRandomisation(t, trigger, 0, true); } diff --git a/src/newgrf_house.h b/src/newgrf_house.h index 835fbef852..941a9e611a 100644 --- a/src/newgrf_house.h +++ b/src/newgrf_house.h @@ -49,7 +49,7 @@ struct HouseScopeResolver : public ScopeResolver { }; /** Resolver object to be used for houses (feature 07 spritegroups). */ -struct HouseResolverObject : public ResolverObject { +struct HouseResolverObject : public SpecializedResolverObject { HouseScopeResolver house_scope; TownScopeResolver town_scope; @@ -110,15 +110,6 @@ bool CanDeleteHouse(TileIndex tile); bool NewHouseTileLoop(TileIndex tile); -enum HouseTrigger : uint8_t { - /* The tile of the house has been triggered during the tileloop. */ - HOUSE_TRIGGER_TILE_LOOP = 0x01, - /* - * The top tile of a (multitile) building has been triggered during and all - * the tileloop other tiles of the same building get the same random value. - */ - HOUSE_TRIGGER_TILE_LOOP_TOP = 0x02, -}; -void TriggerHouseRandomisation(TileIndex t, HouseTrigger trigger); +void TriggerHouseRandomisation(TileIndex t, HouseRandomTrigger trigger); #endif /* NEWGRF_HOUSE_H */ diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 9b0ba71c4e..52dd262d4a 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -115,7 +115,7 @@ uint32_t GetRelativePosition(TileIndex tile, TileIndex ind_tile) assert(this->industry != nullptr && IsValidTile(this->tile)); assert(this->industry->index == IndustryID::Invalid() || IsTileType(this->tile, MP_INDUSTRY)); if (this->industry->index == IndustryID::Invalid()) return 0; - return GetIndustryRandomTriggers(this->tile); + return GetIndustryRandomTriggers(this->tile).base(); } /** @@ -140,7 +140,7 @@ static const GRFFile *GetIndTileGrffile(IndustryGfx gfx) */ IndustryTileResolverObject::IndustryTileResolverObject(IndustryGfx gfx, TileIndex tile, Industry *indus, CallbackID callback, uint32_t callback_param1, uint32_t callback_param2) - : ResolverObject(GetIndTileGrffile(gfx), callback, callback_param1, callback_param2), + : SpecializedResolverObject(GetIndTileGrffile(gfx), callback, callback_param1, callback_param2), indtile_scope(*this, indus, tile), ind_scope(*this, tile, indus, indus->type), gfx(gfx) @@ -310,7 +310,7 @@ bool TriggerIndustryAnimation(const Industry *ind, IndustryAnimationTrigger iat) * @param ind Industry of the tile. * @param[in,out] reseed_industry Collects bits to reseed for the industry. */ -static void DoTriggerIndustryTileRandomisation(TileIndex tile, IndustryTileTrigger trigger, Industry *ind, uint32_t &reseed_industry) +static void DoTriggerIndustryTileRandomisation(TileIndex tile, IndustryRandomTrigger trigger, Industry *ind, uint32_t &reseed_industry) { assert(IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY)); @@ -320,14 +320,17 @@ static void DoTriggerIndustryTileRandomisation(TileIndex tile, IndustryTileTrigg if (itspec->grf_prop.GetSpriteGroup() == nullptr) return; IndustryTileResolverObject object(gfx, tile, ind, CBID_RANDOM_TRIGGER); - object.waiting_random_triggers = GetIndustryRandomTriggers(tile) | trigger; - SetIndustryRandomTriggers(tile, object.waiting_random_triggers); // store now for var 5F + auto waiting_random_triggers = GetIndustryRandomTriggers(tile); + waiting_random_triggers.Set(trigger); + SetIndustryRandomTriggers(tile, waiting_random_triggers); // store now for var 5F + object.SetWaitingRandomTriggers(waiting_random_triggers); const SpriteGroup *group = object.Resolve(); if (group == nullptr) return; /* Store remaining triggers. */ - SetIndustryRandomTriggers(tile, object.GetRemainingRandomTriggers()); + waiting_random_triggers.Reset(object.GetUsedRandomTriggers()); + SetIndustryRandomTriggers(tile, waiting_random_triggers); /* Rerandomise tile bits */ uint8_t new_random_bits = Random(); @@ -359,7 +362,7 @@ static void DoReseedIndustry(Industry *ind, uint32_t reseed) * @param tile Industry tile to trigger. * @param trigger Trigger to trigger. */ -void TriggerIndustryTileRandomisation(TileIndex tile, IndustryTileTrigger trigger) +void TriggerIndustryTileRandomisation(TileIndex tile, IndustryRandomTrigger trigger) { uint32_t reseed_industry = 0; Industry *ind = Industry::GetByTile(tile); @@ -372,7 +375,7 @@ void TriggerIndustryTileRandomisation(TileIndex tile, IndustryTileTrigger trigge * @param ind Industry to trigger. * @param trigger Trigger to trigger. */ -void TriggerIndustryRandomisation(Industry *ind, IndustryTileTrigger trigger) +void TriggerIndustryRandomisation(Industry *ind, IndustryRandomTrigger trigger) { uint32_t reseed_industry = 0; for (TileIndex tile : ind->location) { diff --git a/src/newgrf_industrytiles.h b/src/newgrf_industrytiles.h index a13c70bf7f..de39963371 100644 --- a/src/newgrf_industrytiles.h +++ b/src/newgrf_industrytiles.h @@ -36,7 +36,7 @@ struct IndustryTileScopeResolver : public ScopeResolver { }; /** Resolver for industry tiles. */ -struct IndustryTileResolverObject : public ResolverObject { +struct IndustryTileResolverObject : public SpecializedResolverObject { IndustryTileScopeResolver indtile_scope; ///< Scope resolver for the industry tile. IndustriesScopeResolver ind_scope; ///< Scope resolver for the industry owning the tile. IndustryGfx gfx; @@ -65,14 +65,7 @@ void AnimateNewIndustryTile(TileIndex tile); bool TriggerIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32_t random = Random()); bool TriggerIndustryAnimation(const Industry *ind, IndustryAnimationTrigger iat); - -/** Available industry tile triggers. */ -enum IndustryTileTrigger : uint8_t { - INDTILE_TRIGGER_TILE_LOOP = 0x01, ///< The tile of the industry has been triggered during the tileloop. - INDUSTRY_TRIGGER_INDUSTRY_TICK = 0x02, ///< The industry has been triggered via its tick. - INDUSTRY_TRIGGER_RECEIVED_CARGO = 0x04, ///< Cargo has been delivered. -}; -void TriggerIndustryTileRandomisation(TileIndex t, IndustryTileTrigger trigger); -void TriggerIndustryRandomisation(Industry *ind, IndustryTileTrigger trigger); +void TriggerIndustryTileRandomisation(TileIndex t, IndustryRandomTrigger trigger); +void TriggerIndustryRandomisation(Industry *ind, IndustryRandomTrigger trigger); #endif /* NEWGRF_INDUSTRYTILES_H */ diff --git a/src/newgrf_roadstop.cpp b/src/newgrf_roadstop.cpp index 1a14c0f9cc..3096c2d2ea 100644 --- a/src/newgrf_roadstop.cpp +++ b/src/newgrf_roadstop.cpp @@ -65,7 +65,7 @@ uint32_t RoadStopScopeResolver::GetRandomBits() const uint32_t RoadStopScopeResolver::GetRandomTriggers() const { - return this->st == nullptr ? 0 : this->st->waiting_random_triggers; + return this->st == nullptr ? 0 : this->st->waiting_random_triggers.base(); } uint32_t RoadStopScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const @@ -226,7 +226,7 @@ const SpriteGroup *RoadStopResolverObject::ResolveReal(const RealSpriteGroup *gr RoadStopResolverObject::RoadStopResolverObject(const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8_t view, CallbackID callback, uint32_t param1, uint32_t param2) - : ResolverObject(roadstopspec->grf_prop.grffile, callback, param1, param2), roadstop_scope(*this, st, roadstopspec, tile, roadtype, type, view) + : SpecializedResolverObject(roadstopspec->grf_prop.grffile, callback, param1, param2), roadstop_scope(*this, st, roadstopspec, tile, roadtype, type, view) { CargoType ctype = SpriteGroupCargo::SG_DEFAULT_NA; @@ -417,7 +417,7 @@ void TriggerRoadStopAnimation(BaseStation *st, TileIndex trigger_tile, StationAn * @param trigger trigger type * @param cargo_type cargo type causing the trigger */ -void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoType cargo_type) +void TriggerRoadStopRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoType cargo_type) { if (st == nullptr) st = Station::GetByTile(tile); @@ -426,32 +426,32 @@ void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTri if (st->cached_roadstop_cargo_triggers == 0) return; if (IsValidCargoType(cargo_type) && !HasBit(st->cached_roadstop_cargo_triggers, cargo_type)) return; - SetBit(st->waiting_random_triggers, trigger); + st->waiting_random_triggers.Set(trigger); uint32_t whole_reseed = 0; /* Bitmask of completely empty cargo types to be matched. */ - CargoTypes empty_mask = (trigger == RSRT_CARGO_TAKEN) ? GetEmptyMask(st) : 0; + CargoTypes empty_mask = (trigger == StationRandomTrigger::CargoTaken) ? GetEmptyMask(st) : 0; - uint32_t used_random_triggers = 0; + StationRandomTriggers used_random_triggers; auto process_tile = [&](TileIndex cur_tile) { const RoadStopSpec *ss = GetRoadStopSpec(cur_tile); if (ss == nullptr) return; /* Cargo taken "will only be triggered if all of those * cargo types have no more cargo waiting." */ - if (trigger == RSRT_CARGO_TAKEN) { + if (trigger == StationRandomTrigger::CargoTaken) { if ((ss->cargo_triggers & ~empty_mask) != 0) return; } if (!IsValidCargoType(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) { RoadStopResolverObject object(ss, st, cur_tile, INVALID_ROADTYPE, GetStationType(cur_tile), GetStationGfx(cur_tile)); - object.waiting_random_triggers = st->waiting_random_triggers; + object.SetWaitingRandomTriggers(st->waiting_random_triggers); const SpriteGroup *group = object.Resolve(); if (group == nullptr) return; - used_random_triggers |= object.used_random_triggers; + used_random_triggers.Set(object.GetUsedRandomTriggers()); uint32_t reseed = object.GetReseedSum(); if (reseed != 0) { @@ -468,7 +468,7 @@ void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTri } } }; - if (trigger == RSRT_NEW_CARGO || trigger == RSRT_CARGO_TAKEN) { + if (trigger == StationRandomTrigger::NewCargo || trigger == StationRandomTrigger::CargoTaken) { for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) { process_tile(tile_data.tile); } @@ -477,7 +477,7 @@ void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTri } /* Update whole station random bits */ - st->waiting_random_triggers &= ~used_random_triggers; + st->waiting_random_triggers.Reset(used_random_triggers); if ((whole_reseed & 0xFFFF) != 0) { st->random_bits &= ~whole_reseed; st->random_bits |= Random() & whole_reseed; diff --git a/src/newgrf_roadstop.h b/src/newgrf_roadstop.h index 90d02a82e4..7c18e93c6f 100644 --- a/src/newgrf_roadstop.h +++ b/src/newgrf_roadstop.h @@ -35,15 +35,6 @@ enum RoadStopClassID : uint16_t { }; DECLARE_INCREMENT_DECREMENT_OPERATORS(RoadStopClassID) -/* Some Triggers etc. */ -enum RoadStopRandomTrigger : uint8_t { - RSRT_NEW_CARGO, ///< Trigger roadstop on arrival of new cargo. - RSRT_CARGO_TAKEN, ///< Trigger roadstop when cargo is completely taken. - RSRT_VEH_ARRIVES, ///< Trigger roadstop when road vehicle arrives. - RSRT_VEH_DEPARTS, ///< Trigger roadstop when road vehicle leaves. - RSRT_VEH_LOADS, ///< Trigger roadstop when road vehicle loads. -}; - /** * Various different options for availability, restricting * the roadstop to be only for busses or for trucks. @@ -109,7 +100,7 @@ struct RoadStopScopeResolver : public ScopeResolver { }; /** Road stop resolver. */ -struct RoadStopResolverObject : public ResolverObject { +struct RoadStopResolverObject : public SpecializedResolverObject { RoadStopScopeResolver roadstop_scope; ///< The stop scope resolver. std::optional town_scope = std::nullopt; ///< The town scope resolver (created on the first call). @@ -185,7 +176,7 @@ uint16_t GetRoadStopCallback(CallbackID callback, uint32_t param1, uint32_t para void AnimateRoadStopTile(TileIndex tile); uint8_t GetRoadStopTileAnimationSpeed(TileIndex tile); void TriggerRoadStopAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoType cargo_type = INVALID_CARGO); -void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoType cargo_type = INVALID_CARGO); +void TriggerRoadStopRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoType cargo_type = INVALID_CARGO); bool GetIfNewStopsByType(RoadStopType rs, RoadType roadtype); bool GetIfClassHasNewStopsByType(const RoadStopClass *roadstopclass, RoadStopType rs, RoadType roadtype); diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 2b7ea9a055..ce75956f2b 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -258,11 +258,11 @@ const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject &object) const ScopeResolver *scope = object.GetScope(this->var_scope, this->count); if (object.callback == CBID_RANDOM_TRIGGER) { /* Handle triggers */ - uint8_t match = this->triggers & object.waiting_random_triggers; + uint8_t match = this->triggers & object.GetWaitingRandomTriggers(); bool res = (this->cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == this->triggers); if (res) { - object.used_random_triggers |= match; + object.AddUsedRandomTriggers(match); object.reseed[this->var_scope] |= (this->groups.size() - 1) << this->lowest_randbit; } } diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 71b2ac8cb7..2b511cf131 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -318,8 +318,10 @@ struct ResolverObject { uint32_t last_value = 0; ///< Result of most recent DeterministicSpriteGroup (including procedure calls) +protected: uint32_t waiting_random_triggers = 0; ///< Waiting triggers to be used by any rerandomisation. (scope independent) uint32_t used_random_triggers = 0; ///< Subset of cur_triggers, which actually triggered some rerandomisation. (scope independent) +public: std::array reseed; ///< Collects bits to rerandomise while triggering triggers. const GRFFile *grffile = nullptr; ///< GRFFile the resolved SpriteGroup belongs to @@ -349,11 +351,19 @@ struct ResolverObject { virtual ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, uint8_t relative = 0); /** - * Returns the waiting triggers that did not trigger any rerandomisation. + * Used by RandomizedSpriteGroup: Triggers for rerandomisation */ - uint32_t GetRemainingRandomTriggers() const + uint32_t GetWaitingRandomTriggers() const { - return this->waiting_random_triggers & ~this->used_random_triggers; + return this->waiting_random_triggers; + } + + /** + * Used by RandomizedSpriteGroup: Consume triggers. + */ + void AddUsedRandomTriggers(uint32_t triggers) + { + this->used_random_triggers |= triggers; } /** @@ -395,4 +405,30 @@ struct ResolverObject { virtual uint32_t GetDebugID() const { return 0; } }; +/** + * Specialization of ResolverObject with type-safe access to RandomTriggers. + */ +template +struct SpecializedResolverObject : public ResolverObject { + using ResolverObject::ResolverObject; + + /** + * Set waiting triggers for rerandomisation. + * This is scope independent, even though this is broken-by-design in most cases. + */ + void SetWaitingRandomTriggers(RandomTriggers triggers) + { + this->waiting_random_triggers = triggers.base(); + } + + /** + * Get the triggers, which were "consumed" by some rerandomisation. + * This is scope independent, even though this is broken-by-design in most cases. + */ + RandomTriggers GetUsedRandomTriggers() const + { + return static_cast(this->used_random_triggers); + } +}; + #endif /* NEWGRF_SPRITEGROUP_H */ diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 9df9f0032d..8c2bb29cf7 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -246,7 +246,7 @@ static uint32_t GetRailContinuationInfo(TileIndex tile) /* virtual */ uint32_t StationScopeResolver::GetRandomTriggers() const { - return this->st == nullptr ? 0 : this->st->waiting_random_triggers; + return this->st == nullptr ? 0 : this->st->waiting_random_triggers.base(); } @@ -588,7 +588,7 @@ uint32_t StationResolverObject::GetDebugID() const */ StationResolverObject::StationResolverObject(const StationSpec *statspec, BaseStation *base_station, TileIndex tile, CallbackID callback, uint32_t callback_param1, uint32_t callback_param2) - : ResolverObject(statspec->grf_prop.grffile, callback, callback_param1, callback_param2), + : SpecializedResolverObject(statspec->grf_prop.grffile, callback, callback_param1, callback_param2), station_scope(*this, statspec, base_station, tile) { /* Invalidate all cached vars */ @@ -959,14 +959,14 @@ void TriggerStationRandomisation(Station *st, TileIndex trigger_tile, StationRan if (IsValidCargoType(cargo_type) && !HasBit(st->cached_cargo_triggers, cargo_type)) return; uint32_t whole_reseed = 0; - ETileArea area = ETileArea(st, trigger_tile, tas[trigger]); + ETileArea area = ETileArea(st, trigger_tile, tas[static_cast(trigger)]); /* Bitmask of completely empty cargo types to be matched. */ - CargoTypes empty_mask = (trigger == SRT_CARGO_TAKEN) ? GetEmptyMask(st) : 0; + CargoTypes empty_mask = (trigger == StationRandomTrigger::CargoTaken) ? GetEmptyMask(st) : 0; /* Store triggers now for var 5F */ - SetBit(st->waiting_random_triggers, trigger); - uint32_t used_random_triggers = 0; + st->waiting_random_triggers.Set(trigger); + StationRandomTriggers used_random_triggers; /* Check all tiles over the station to check if the specindex is still in use */ for (TileIndex tile : area) { @@ -976,18 +976,18 @@ void TriggerStationRandomisation(Station *st, TileIndex trigger_tile, StationRan /* Cargo taken "will only be triggered if all of those * cargo types have no more cargo waiting." */ - if (trigger == SRT_CARGO_TAKEN) { + if (trigger == StationRandomTrigger::CargoTaken) { if ((ss->cargo_triggers & ~empty_mask) != 0) continue; } if (!IsValidCargoType(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) { StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0); - object.waiting_random_triggers = st->waiting_random_triggers; + object.SetWaitingRandomTriggers(st->waiting_random_triggers); const SpriteGroup *group = object.Resolve(); if (group == nullptr) continue; - used_random_triggers |= object.used_random_triggers; + used_random_triggers.Set(object.GetUsedRandomTriggers()); uint32_t reseed = object.GetReseedSum(); if (reseed != 0) { @@ -1007,7 +1007,7 @@ void TriggerStationRandomisation(Station *st, TileIndex trigger_tile, StationRan } /* Update whole station random bits */ - st->waiting_random_triggers &= ~used_random_triggers; + st->waiting_random_triggers.Reset(used_random_triggers); if ((whole_reseed & 0xFFFF) != 0) { st->random_bits &= ~whole_reseed; st->random_bits |= Random() & whole_reseed; diff --git a/src/newgrf_station.h b/src/newgrf_station.h index e520ae7e6b..fd27dc81e3 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -49,7 +49,7 @@ struct StationScopeResolver : public ScopeResolver { }; /** Station resolver. */ -struct StationResolverObject : public ResolverObject { +struct StationResolverObject : public SpecializedResolverObject { StationScopeResolver station_scope; ///< The station scope resolver. std::optional town_scope = std::nullopt; ///< The town scope resolver (created on the first call). @@ -103,16 +103,6 @@ enum class StationSpecFlag : uint8_t { }; using StationSpecFlags = EnumBitSet; -/** Randomisation triggers for stations */ -enum StationRandomTrigger : uint8_t { - SRT_NEW_CARGO, ///< Trigger station on new cargo arrival. - SRT_CARGO_TAKEN, ///< Trigger station when cargo is completely taken. - SRT_TRAIN_ARRIVES, ///< Trigger platform when train arrives. - SRT_TRAIN_DEPARTS, ///< Trigger platform when train leaves. - SRT_TRAIN_LOADS, ///< Trigger platform when train loads/unloads. - SRT_PATH_RESERVATION, ///< Trigger platform when train reserves path. -}; - /** Station specification. */ struct StationSpec : NewGRFSpecBase { StationSpec() : name(0), diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index 39f6dffd6c..af0725f501 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -80,7 +80,7 @@ private: tile = TileAdd(tile, diff); } while (IsCompatibleTrainStationTile(tile, start) && tile != this->origin_tile); - TriggerStationRandomisation(nullptr, start, SRT_PATH_RESERVATION); + TriggerStationRandomisation(nullptr, start, StationRandomTrigger::PathReservation); return true; } diff --git a/src/pbs.cpp b/src/pbs.cpp index 9e37633a04..ecf570a5d3 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -113,7 +113,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) case MP_STATION: if (HasStationRail(tile) && !HasStationReservation(tile)) { SetRailStationReservation(tile, true); - if (trigger_stations && IsRailStation(tile)) TriggerStationRandomisation(nullptr, tile, SRT_PATH_RESERVATION); + if (trigger_stations && IsRailStation(tile)) TriggerStationRandomisation(nullptr, tile, StationRandomTrigger::PathReservation); MarkTileDirtyByTile(tile); // some GRFs need redraw after reserving track return true; } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 5fbcd51a16..dfc6a7bf6a 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1455,7 +1455,7 @@ again: v->last_station_visited = st->index; RoadVehArrivesAt(v, st); v->BeginLoading(); - TriggerRoadStopRandomisation(st, v->tile, RSRT_VEH_ARRIVES); + TriggerRoadStopRandomisation(st, v->tile, StationRandomTrigger::VehicleArrives); TriggerRoadStopAnimation(st, v->tile, SAT_TRAIN_ARRIVES); } return false; @@ -1519,7 +1519,7 @@ again: if (IsDriveThroughStopTile(v->tile) || (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == st->index)) { RoadVehArrivesAt(v, st); v->BeginLoading(); - TriggerRoadStopRandomisation(st, v->tile, RSRT_VEH_ARRIVES); + TriggerRoadStopRandomisation(st, v->tile, StationRandomTrigger::VehicleArrives); TriggerRoadStopAnimation(st, v->tile, SAT_TRAIN_ARRIVES); return false; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index ba074a004c..0ee5738d64 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -4278,10 +4278,10 @@ static uint UpdateStationWaiting(Station *st, CargoType cargo, uint amount, Sour ge.status.Set(GoodsEntry::State::Rating); } - TriggerStationRandomisation(st, st->xy, SRT_NEW_CARGO, cargo); + TriggerStationRandomisation(st, st->xy, StationRandomTrigger::NewCargo, cargo); TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, cargo); TriggerAirportAnimation(st, AAT_STATION_NEW_CARGO, cargo); - TriggerRoadStopRandomisation(st, st->xy, RSRT_NEW_CARGO, cargo); + TriggerRoadStopRandomisation(st, st->xy, StationRandomTrigger::NewCargo, cargo); TriggerRoadStopAnimation(st, st->xy, SAT_NEW_CARGO, cargo); diff --git a/src/station_type.h b/src/station_type.h index 45943b77e4..25ac176f8e 100644 --- a/src/station_type.h +++ b/src/station_type.h @@ -76,6 +76,17 @@ enum StationHadVehicleOfType : uint8_t { }; DECLARE_ENUM_AS_BIT_SET(StationHadVehicleOfType) +/** Randomisation triggers for stations and roadstops */ +enum class StationRandomTrigger : uint8_t { + NewCargo, ///< Trigger station on new cargo arrival. + CargoTaken, ///< Trigger station when cargo is completely taken. + VehicleArrives, ///< Trigger platform when train arrives. + VehicleDeparts, ///< Trigger platform when train leaves. + VehicleLoads, ///< Trigger platform when train loads/unloads. + PathReservation, ///< Trigger platform when train reserves path. +}; +using StationRandomTriggers = EnumBitSet; + /* The different catchment area sizes. */ static constexpr uint CA_NONE = 0; ///< Catchment when the station has no facilities static constexpr uint CA_BUS = 3; ///< Catchment for bus stops with "modified catchment" enabled diff --git a/src/town_map.h b/src/town_map.h index d408a302ce..1a982bcb82 100644 --- a/src/town_map.h +++ b/src/town_map.h @@ -307,10 +307,10 @@ inline uint8_t GetHouseRandomBits(Tile t) * @param triggers the activated triggers * @pre IsTileType(t, MP_HOUSE) */ -inline void SetHouseRandomTriggers(Tile t, uint8_t triggers) +inline void SetHouseRandomTriggers(Tile t, HouseRandomTriggers triggers) { assert(IsTileType(t, MP_HOUSE)); - SB(t.m3(), 0, 5, triggers); + SB(t.m3(), 0, 5, triggers.base()); } /** @@ -320,10 +320,10 @@ inline void SetHouseRandomTriggers(Tile t, uint8_t triggers) * @pre IsTileType(t, MP_HOUSE) * @return triggers */ -inline uint8_t GetHouseRandomTriggers(Tile t) +inline HouseRandomTriggers GetHouseRandomTriggers(Tile t) { assert(IsTileType(t, MP_HOUSE)); - return GB(t.m3(), 0, 5); + return static_cast(GB(t.m3(), 0, 5)); } /** diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 52c0a3243f..d3e780e657 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3024,7 +3024,7 @@ static void TrainEnterStation(Train *v, StationID station) v->BeginLoading(); - TriggerStationRandomisation(st, v->tile, SRT_TRAIN_ARRIVES); + TriggerStationRandomisation(st, v->tile, StationRandomTrigger::VehicleArrives); TriggerStationAnimation(st, v->tile, SAT_TRAIN_ARRIVES); } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index d292539af9..f3a5e13253 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -972,7 +972,7 @@ static void RunEconomyVehicleDayProc() uint16_t callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v); if (callback != CALLBACK_FAILED) { if (HasBit(callback, 0)) { - TriggerVehicleRandomisation(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10 + TriggerVehicleRandomisation(v, VehicleRandomTrigger::Callback32); // Trigger vehicle trigger 10 } /* After a vehicle trigger, the graphics and properties of the vehicle could change. @@ -1614,7 +1614,7 @@ void VehicleEnterDepot(Vehicle *v) VehicleEnteredDepotThisTick(v); /* After a vehicle trigger, the graphics and properties of the vehicle could change. */ - TriggerVehicleRandomisation(v, VEHICLE_TRIGGER_DEPOT); + TriggerVehicleRandomisation(v, VehicleRandomTrigger::Depot); v->MarkDirty(); InvalidateWindowData(WC_VEHICLE_VIEW, v->index); @@ -2394,7 +2394,7 @@ void Vehicle::LeaveStation() if (this->type == VEH_TRAIN && !this->vehstatus.Test(VehState::Crashed)) { /* Trigger station animation (trains only) */ if (IsTileType(this->tile, MP_STATION)) { - TriggerStationRandomisation(st, this->tile, SRT_TRAIN_DEPARTS); + TriggerStationRandomisation(st, this->tile, StationRandomTrigger::VehicleDeparts); TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS); } @@ -2403,7 +2403,7 @@ void Vehicle::LeaveStation() if (this->type == VEH_ROAD && !this->vehstatus.Test(VehState::Crashed)) { /* Trigger road stop animation */ if (IsStationRoadStopTile(this->tile)) { - TriggerRoadStopRandomisation(st, this->tile, RSRT_VEH_DEPARTS); + TriggerRoadStopRandomisation(st, this->tile, StationRandomTrigger::VehicleDeparts); TriggerRoadStopAnimation(st, this->tile, SAT_TRAIN_DEPARTS); } } diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 946abca731..6595f03d99 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -311,7 +311,7 @@ public: uint32_t motion_counter = 0; ///< counter to occasionally play a vehicle sound. uint8_t progress = 0; ///< The percentage (if divided by 256) this vehicle already crossed the tile unit. - uint8_t waiting_random_triggers = 0; ///< Triggers to be yet matched before rerandomizing the random bits. + VehicleRandomTriggers waiting_random_triggers; ///< Triggers to be yet matched before rerandomizing the random bits. uint16_t random_bits = 0; ///< Bits used for randomized variational spritegroups. StationID last_station_visited = StationID::Invalid(); ///< The last station we stopped at. diff --git a/src/vehicle_type.h b/src/vehicle_type.h index 49028c0eac..09aa86d1a1 100644 --- a/src/vehicle_type.h +++ b/src/vehicle_type.h @@ -80,4 +80,14 @@ enum EngineImageType : uint8_t { EIT_PREVIEW = 0x21, ///< Vehicle drawn in preview window, news, ... }; +/** Randomisation triggers for vehicles */ +enum class VehicleRandomTrigger : uint8_t { + NewCargo, ///< Affected vehicle only: Vehicle is loaded with cargo, after it was empty. + Depot, ///< Front vehicle only: Consist arrived in depot. + Empty, ///< Front vehicle only: Entire consist is empty. + AnyNewCargo, ///< All vehicles in consist: Any vehicle in the consist received new cargo. + Callback32, ///< All vehicles in consist: 32 day callback requested rerandomisation +}; +using VehicleRandomTriggers = EnumBitSet; + #endif /* VEHICLE_TYPE_H */