mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2026-07-25 08:22:17 +00:00
@@ -74,6 +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
|
||||
std::unordered_map<TileIndex, StationRandomTriggers> tile_waiting_random_triggers;
|
||||
StationRandomTriggers waiting_random_triggers; ///< Waiting triggers (NewGRF), shared by all station parts/tiles, road stops, ... essentially useless and broken by design.
|
||||
StationAnimationTriggers cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
|
||||
StationAnimationTriggers cached_roadstop_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing should happen.
|
||||
|
||||
+27
-5
@@ -66,7 +66,14 @@ uint32_t RoadStopScopeResolver::GetRandomBits() const
|
||||
|
||||
uint32_t RoadStopScopeResolver::GetRandomTriggers() const
|
||||
{
|
||||
return this->st == nullptr ? 0 : this->st->waiting_random_triggers.base();
|
||||
if (this->st == nullptr) return 0;
|
||||
|
||||
StationRandomTriggers triggers = st->waiting_random_triggers;
|
||||
|
||||
auto it = this->st->tile_waiting_random_triggers.find(this->tile);
|
||||
if (it != std::end(this->st->tile_waiting_random_triggers)) triggers.Set(it->second);
|
||||
|
||||
return triggers.base();
|
||||
}
|
||||
|
||||
uint32_t RoadStopScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const
|
||||
@@ -418,6 +425,17 @@ void TriggerRoadStopAnimation(BaseStation *st, TileIndex trigger_tile, StationAn
|
||||
*/
|
||||
void TriggerRoadStopRandomisation(BaseStation *st, TileIndex tile, StationRandomTrigger trigger, CargoType cargo_type)
|
||||
{
|
||||
enum TriggerArea : uint8_t {
|
||||
TA_TILE,
|
||||
TA_PLATFORM,
|
||||
TA_WHOLE,
|
||||
};
|
||||
|
||||
/* List of coverage areas for each animation trigger */
|
||||
static constexpr TriggerArea tas[] = {
|
||||
TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM
|
||||
};
|
||||
|
||||
assert(st != nullptr);
|
||||
|
||||
/* Check the cached cargo trigger bitmask to see if we need
|
||||
@@ -426,7 +444,9 @@ void TriggerRoadStopRandomisation(BaseStation *st, TileIndex tile, StationRandom
|
||||
if (st->cached_roadstop_cargo_triggers == 0) return;
|
||||
if (IsValidCargoType(cargo_type) && !HasBit(st->cached_roadstop_cargo_triggers, cargo_type)) return;
|
||||
|
||||
st->waiting_random_triggers.Set(trigger);
|
||||
TriggerArea ta = tas[to_underlying(trigger)];
|
||||
if (ta == TA_WHOLE) st->waiting_random_triggers.Set(trigger);
|
||||
StationRandomTriggers used_random_triggers;
|
||||
|
||||
uint32_t whole_reseed = 0;
|
||||
|
||||
@@ -436,11 +456,12 @@ void TriggerRoadStopRandomisation(BaseStation *st, TileIndex tile, StationRandom
|
||||
empty_mask = GetEmptyMask(Station::From(st));
|
||||
}
|
||||
|
||||
StationRandomTriggers used_random_triggers;
|
||||
auto process_tile = [&](TileIndex cur_tile) {
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
|
||||
if (ss == nullptr) return;
|
||||
|
||||
st->tile_waiting_random_triggers[tile].Set(trigger);
|
||||
|
||||
/* Cargo taken "will only be triggered if all of those
|
||||
* cargo types have no more cargo waiting." */
|
||||
if (trigger == StationRandomTrigger::CargoTaken) {
|
||||
@@ -449,10 +470,11 @@ void TriggerRoadStopRandomisation(BaseStation *st, TileIndex tile, StationRandom
|
||||
|
||||
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.SetWaitingRandomTriggers(st->waiting_random_triggers);
|
||||
object.SetWaitingRandomTriggers(st->waiting_random_triggers | st->tile_waiting_random_triggers[tile]);
|
||||
|
||||
object.ResolveRerandomisation();
|
||||
|
||||
st->tile_waiting_random_triggers[tile].Reset(object.GetUsedRandomTriggers());
|
||||
used_random_triggers.Set(object.GetUsedRandomTriggers());
|
||||
|
||||
uint32_t reseed = object.GetReseedSum();
|
||||
@@ -470,7 +492,7 @@ void TriggerRoadStopRandomisation(BaseStation *st, TileIndex tile, StationRandom
|
||||
}
|
||||
}
|
||||
};
|
||||
if (trigger == StationRandomTrigger::NewCargo || trigger == StationRandomTrigger::CargoTaken) {
|
||||
if (ta == TA_WHOLE) {
|
||||
for (const RoadStopTileData &tile_data : st->custom_roadstop_tile_data) {
|
||||
process_tile(tile_data.tile);
|
||||
}
|
||||
|
||||
+17
-5
@@ -244,7 +244,14 @@ static uint32_t GetRailContinuationInfo(TileIndex tile)
|
||||
|
||||
/* virtual */ uint32_t StationScopeResolver::GetRandomTriggers() const
|
||||
{
|
||||
return this->st == nullptr ? 0 : this->st->waiting_random_triggers.base();
|
||||
if (this->st == nullptr) return 0;
|
||||
|
||||
StationRandomTriggers triggers = st->waiting_random_triggers;
|
||||
|
||||
auto it = this->st->tile_waiting_random_triggers.find(this->tile);
|
||||
if (it != std::end(this->st->tile_waiting_random_triggers)) triggers.Set(it->second);
|
||||
|
||||
return triggers.base();
|
||||
}
|
||||
|
||||
|
||||
@@ -949,7 +956,7 @@ void TriggerStationAnimation(BaseStation *st, TileIndex trigger_tile, StationAni
|
||||
void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoType cargo_type)
|
||||
{
|
||||
/* List of coverage areas for each animation trigger */
|
||||
static const TriggerArea tas[] = {
|
||||
static constexpr TriggerArea tas[] = {
|
||||
TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM
|
||||
};
|
||||
|
||||
@@ -970,12 +977,16 @@ void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, Statio
|
||||
}
|
||||
|
||||
/* Store triggers now for var 5F */
|
||||
st->waiting_random_triggers.Set(trigger);
|
||||
TriggerArea ta = tas[to_underlying(trigger)];
|
||||
if (ta == TA_WHOLE) 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 : GetRailTileArea(st, trigger_tile, tas[static_cast<size_t>(trigger)])) {
|
||||
for (TileIndex tile : GetRailTileArea(st, trigger_tile, ta)) {
|
||||
if (st->TileBelongsToRailStation(tile)) {
|
||||
/* Store triggers now for var 5F */
|
||||
st->tile_waiting_random_triggers[tile].Set(trigger);
|
||||
|
||||
const StationSpec *ss = GetStationSpec(tile);
|
||||
if (ss == nullptr) continue;
|
||||
|
||||
@@ -987,10 +998,11 @@ void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, Statio
|
||||
|
||||
if (!IsValidCargoType(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) {
|
||||
StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
|
||||
object.SetWaitingRandomTriggers(st->waiting_random_triggers);
|
||||
object.SetWaitingRandomTriggers(st->waiting_random_triggers | st->tile_waiting_random_triggers[tile]);
|
||||
|
||||
object.ResolveRerandomisation();
|
||||
|
||||
st->tile_waiting_random_triggers[tile].Reset(object.GetUsedRandomTriggers());
|
||||
used_random_triggers.Set(object.GetUsedRandomTriggers());
|
||||
|
||||
uint32_t reseed = object.GetReseedSum();
|
||||
|
||||
@@ -229,6 +229,37 @@ public:
|
||||
template class SlStationSpecList<StationSpec>;
|
||||
template class SlStationSpecList<RoadStopSpec>;
|
||||
|
||||
class SlStationWaitingTriggers : public DefaultSaveLoadHandler<SlStationWaitingTriggers, BaseStation> {
|
||||
public:
|
||||
using StationWaitingTriggersPair = std::pair<const TileIndex, StationRandomTriggers>;
|
||||
|
||||
static inline const SaveLoad description[] = {
|
||||
SLE_VAR(StationWaitingTriggersPair, first, SLE_UINT32),
|
||||
SLE_VAR(StationWaitingTriggersPair, second, SLE_UINT8),
|
||||
};
|
||||
static inline const SaveLoadCompatTable compat_description = _station_cargo_sl_compat;
|
||||
|
||||
void Save(BaseStation *st) const override
|
||||
{
|
||||
SlSetStructListLength(st->tile_waiting_random_triggers.size());
|
||||
for (const auto &pair : st->tile_waiting_random_triggers) {
|
||||
SlObject(const_cast<StationWaitingTriggersPair *>(&pair), this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load(BaseStation *st) const override
|
||||
{
|
||||
size_t num = SlGetStructListLength(UINT32_MAX);
|
||||
if (num == 0) return;
|
||||
|
||||
StationWaitingTriggersPair pair;
|
||||
for (uint j = 0; j < num; ++j) {
|
||||
SlObject(&pair, this->GetLoadDescription());
|
||||
st->tile_waiting_random_triggers.emplace(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlStationCargo : public DefaultSaveLoadHandler<SlStationCargo, GoodsEntry> {
|
||||
public:
|
||||
static inline const SaveLoad description[] = {
|
||||
@@ -563,6 +594,7 @@ public:
|
||||
/* Used by newstations for graphic variations */
|
||||
SLE_VAR(BaseStation, random_bits, SLE_UINT16),
|
||||
SLE_VARNAME(BaseStation, waiting_random_triggers, "waiting_triggers", SLE_UINT8),
|
||||
SLEG_STRUCTLIST("tile_waiting_triggers", SlStationWaitingTriggers),
|
||||
SLEG_CONDVAR("num_specs", SlStationSpecList<StationSpec>::last_num_specs, SLE_UINT8, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
|
||||
};
|
||||
static inline const SaveLoadCompatTable compat_description = _station_base_sl_compat;
|
||||
|
||||
@@ -1806,6 +1806,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector<T *> &affected_st
|
||||
Company::Get(owner)->infrastructure.station--;
|
||||
DirtyCompanyInfrastructureWindows(owner);
|
||||
|
||||
st->tile_waiting_random_triggers.erase(tile);
|
||||
st->rect.AfterRemoveTile(st, tile);
|
||||
AddTrackToSignalBuffer(tile, track, owner);
|
||||
YapfNotifyTrackLayoutChange(tile, track);
|
||||
@@ -2329,6 +2330,7 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlags flags, int repl
|
||||
|
||||
if (replacement_spec_index < 0) st->AfterStationTileSetChange(false, is_truck ? StationType::Truck: StationType::Bus);
|
||||
|
||||
st->tile_waiting_random_triggers.erase(tile);
|
||||
st->RemoveRoadStopTileData(tile);
|
||||
if ((int)specindex != replacement_spec_index) DeallocateSpecFromRoadStop(st, specindex);
|
||||
|
||||
@@ -2388,6 +2390,7 @@ CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlags flags, int rep
|
||||
|
||||
wp->rect.AfterRemoveTile(wp, tile);
|
||||
|
||||
wp->tile_waiting_random_triggers.erase(tile);
|
||||
wp->RemoveRoadStopTileData(tile);
|
||||
if ((int)specindex != replacement_spec_index) DeallocateSpecFromRoadStop(wp, specindex);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user