mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r24905) -Feature(ish): Implement station randomisation triggers.
This commit is contained in:
parent
4ebbfc3de4
commit
c00a400cc7
|
@ -71,6 +71,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
|
|||
uint16 random_bits; ///< Random bits assigned to this station
|
||||
byte waiting_triggers; ///< Waiting triggers (NewGRF) for this station
|
||||
uint8 cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
|
||||
uint32 cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask
|
||||
|
||||
TileArea train_station; ///< Tile area the train 'station' part covers
|
||||
StationRect rect; ///< NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions
|
||||
|
|
|
@ -1535,6 +1535,7 @@ static void LoadUnloadVehicle(Vehicle *front, int *cargo_left)
|
|||
st->last_vehicle_type = v->type;
|
||||
|
||||
if (ge->cargo.Empty()) {
|
||||
TriggerStationRandomisation(st, st->xy, SRT_CARGO_TAKEN, v->cargo_type);
|
||||
TriggerStationAnimation(st, st->xy, SAT_CARGO_TAKEN, v->cargo_type);
|
||||
AirportAnimationTrigger(st, AAT_STATION_CARGO_TAKEN, v->cargo_type);
|
||||
}
|
||||
|
@ -1552,7 +1553,10 @@ static void LoadUnloadVehicle(Vehicle *front, int *cargo_left)
|
|||
}
|
||||
|
||||
if (anything_loaded || anything_unloaded) {
|
||||
if (front->type == VEH_TRAIN) TriggerStationAnimation(st, front->tile, SAT_TRAIN_LOADS);
|
||||
if (front->type == VEH_TRAIN) {
|
||||
TriggerStationRandomisation(st, front->tile, SRT_TRAIN_LOADS);
|
||||
TriggerStationAnimation(st, front->tile, SAT_TRAIN_LOADS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Only set completely_emptied, if we just unloaded all remaining cargo */
|
||||
|
|
|
@ -1908,6 +1908,9 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
|||
|
||||
case 0x12: // Cargo types for random triggers
|
||||
statspec->cargo_triggers = buf->ReadDWord();
|
||||
if (_cur.grffile->grf_version >= 7) {
|
||||
statspec->cargo_triggers = TranslateRefitMask(statspec->cargo_triggers);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x13: // General flags
|
||||
|
|
|
@ -731,7 +731,7 @@ int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exe
|
|||
st->speclist[i].grfid = statspec->grf_prop.grffile->grfid;
|
||||
st->speclist[i].localidx = statspec->grf_prop.local_id;
|
||||
|
||||
StationUpdateAnimTriggers(st);
|
||||
StationUpdateCachedTriggers(st);
|
||||
}
|
||||
|
||||
return i;
|
||||
|
@ -773,11 +773,12 @@ void DeallocateSpecFromStation(BaseStation *st, byte specindex)
|
|||
st->num_specs = 0;
|
||||
st->speclist = NULL;
|
||||
st->cached_anim_triggers = 0;
|
||||
st->cached_cargo_triggers = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StationUpdateAnimTriggers(st);
|
||||
StationUpdateCachedTriggers(st);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -968,19 +969,104 @@ void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTr
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger station randomisation
|
||||
* @param st station being triggered
|
||||
* @param tile specific tile of platform to trigger
|
||||
* @param trigger trigger type
|
||||
* @param cargo_type cargo type causing trigger
|
||||
*/
|
||||
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type)
|
||||
{
|
||||
/* List of coverage areas for each animation trigger */
|
||||
static const TriggerArea tas[] = {
|
||||
TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM
|
||||
};
|
||||
|
||||
/* Get Station if it wasn't supplied */
|
||||
if (st == NULL) st = Station::GetByTile(tile);
|
||||
|
||||
/* Check the cached cargo trigger bitmask to see if we need
|
||||
* to bother with any further processing. */
|
||||
if (st->cached_cargo_triggers == 0) return;
|
||||
if (cargo_type != CT_INVALID && !HasBit(st->cached_cargo_triggers, cargo_type)) return;
|
||||
|
||||
uint32 whole_reseed = 0;
|
||||
ETileArea area = ETileArea(st, tile, tas[trigger]);
|
||||
|
||||
uint32 empty_mask = 0;
|
||||
if (trigger == SRT_CARGO_TAKEN) {
|
||||
/* Create a bitmask of completely empty cargo types to be matched */
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
if (st->goods[i].cargo.Empty()) {
|
||||
SetBit(empty_mask, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert trigger to bit */
|
||||
uint8 trigger_bit = 1 << trigger;
|
||||
|
||||
/* Check all tiles over the station to check if the specindex is still in use */
|
||||
TILE_AREA_LOOP(tile, area) {
|
||||
if (st->TileBelongsToRailStation(tile)) {
|
||||
const StationSpec *ss = GetStationSpec(tile);
|
||||
if (ss == NULL) continue;
|
||||
|
||||
/* Cargo taken "will only be triggered if all of those
|
||||
* cargo types have no more cargo waiting." */
|
||||
if (trigger == SRT_CARGO_TAKEN) {
|
||||
if ((ss->cargo_triggers & ~empty_mask) != 0) continue;
|
||||
}
|
||||
|
||||
if (cargo_type == CT_INVALID || HasBit(ss->cargo_triggers, cargo_type)) {
|
||||
StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
|
||||
object.trigger = trigger_bit;
|
||||
|
||||
const SpriteGroup *group = ResolveStation(&object);
|
||||
if (group == NULL) continue;
|
||||
|
||||
uint32 reseed = object.GetReseedSum();
|
||||
if (reseed != 0) {
|
||||
whole_reseed |= reseed;
|
||||
reseed >>= 16;
|
||||
|
||||
/* Set individual tile random bits */
|
||||
uint8 random_bits = GetStationTileRandomBits(tile);
|
||||
random_bits &= ~reseed;
|
||||
random_bits |= Random() & reseed;
|
||||
SetStationTileRandomBits(tile, random_bits);
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update whole station random bits */
|
||||
if ((whole_reseed & 0xFFFF) != 0) {
|
||||
st->random_bits &= ~whole_reseed;
|
||||
st->random_bits |= Random() & whole_reseed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cached animation trigger bitmask for a station.
|
||||
* @param st Station to update.
|
||||
*/
|
||||
void StationUpdateAnimTriggers(BaseStation *st)
|
||||
void StationUpdateCachedTriggers(BaseStation *st)
|
||||
{
|
||||
st->cached_anim_triggers = 0;
|
||||
st->cached_cargo_triggers = 0;
|
||||
|
||||
/* Combine animation trigger bitmask for all station specs
|
||||
* of this station. */
|
||||
for (uint i = 0; i < st->num_specs; i++) {
|
||||
const StationSpec *ss = st->speclist[i].spec;
|
||||
if (ss != NULL) st->cached_anim_triggers |= ss->animation.triggers;
|
||||
if (ss != NULL) {
|
||||
st->cached_anim_triggers |= ss->animation.triggers;
|
||||
st->cached_cargo_triggers |= ss->cargo_triggers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,16 @@ enum StationSpecFlags {
|
|||
SSF_EXTENDED_FOUNDATIONS, ///< Extended foundation block instead of simple.
|
||||
};
|
||||
|
||||
/** Randomisation triggers for stations */
|
||||
enum StationRandomTrigger {
|
||||
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 layout for given dimensions - it is a two-dimensional array
|
||||
* where index is computed as (x * platforms) + platform. */
|
||||
typedef byte *StationLayout;
|
||||
|
@ -176,6 +186,7 @@ bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID
|
|||
|
||||
void AnimateStationTile(TileIndex tile);
|
||||
void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
|
||||
void StationUpdateAnimTriggers(BaseStation *st);
|
||||
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type = CT_INVALID);
|
||||
void StationUpdateCachedTriggers(BaseStation *st);
|
||||
|
||||
#endif /* NEWGRF_STATION_H */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "yapf_costrail.hpp"
|
||||
#include "yapf_destrail.hpp"
|
||||
#include "../../viewport_func.h"
|
||||
#include "../../newgrf_station.h"
|
||||
|
||||
#define DEBUG_YAPF_CACHE 0
|
||||
|
||||
|
@ -83,6 +84,8 @@ private:
|
|||
tile = TILE_ADD(tile, diff);
|
||||
} while (IsCompatibleTrainStationTile(tile, start) && tile != m_origin_tile);
|
||||
|
||||
TriggerStationRandomisation(NULL, start, SRT_PATH_RESERVATION);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "viewport_func.h"
|
||||
#include "vehicle_func.h"
|
||||
#include "newgrf_station.h"
|
||||
#include "pathfinder/follow_track.hpp"
|
||||
|
||||
/**
|
||||
|
@ -72,10 +73,11 @@ void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool
|
|||
* Try to reserve a specific track on a tile
|
||||
* @param tile the tile
|
||||
* @param t the track
|
||||
* @param trigger_stations whether to call station randomisation trigger
|
||||
* @return \c true if reservation was successful, i.e. the track was
|
||||
* free and didn't cross any other reserved tracks.
|
||||
*/
|
||||
bool TryReserveRailTrack(TileIndex tile, Track t)
|
||||
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
|
||||
{
|
||||
assert((GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & TrackToTrackBits(t)) != 0);
|
||||
|
||||
|
@ -108,6 +110,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t)
|
|||
case MP_STATION:
|
||||
if (HasStationRail(tile) && !HasStationReservation(tile)) {
|
||||
SetRailStationReservation(tile, true);
|
||||
if (trigger_stations) TriggerStationRandomisation(NULL, tile, SRT_PATH_RESERVATION);
|
||||
MarkTileDirtyByTile(tile); // some GRFs need redraw after reserving track
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ TrackBits GetReservedTrackbits(TileIndex t);
|
|||
|
||||
void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool b);
|
||||
|
||||
bool TryReserveRailTrack(TileIndex tile, Track t);
|
||||
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations = true);
|
||||
void UnreserveRailTrack(TileIndex tile, Track t);
|
||||
|
||||
/** This struct contains information about the end of a reserved path. */
|
||||
|
|
|
@ -123,7 +123,7 @@ void AfterLoadStations()
|
|||
for (const RoadStop *rs = sta->truck_stops; rs != NULL; rs = rs->next) sta->truck_station.Add(rs->xy);
|
||||
}
|
||||
|
||||
StationUpdateAnimTriggers(st);
|
||||
StationUpdateCachedTriggers(st);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3380,6 +3380,7 @@ static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceT
|
|||
SetBit(ge.acceptance_pickup, GoodsEntry::GES_PICKUP);
|
||||
}
|
||||
|
||||
TriggerStationRandomisation(st, st->xy, SRT_NEW_CARGO, type);
|
||||
TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, type);
|
||||
AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type);
|
||||
|
||||
|
|
|
@ -2810,6 +2810,7 @@ static void TrainEnterStation(Train *v, StationID station)
|
|||
|
||||
v->BeginLoading();
|
||||
|
||||
TriggerStationRandomisation(st, v->tile, SRT_TRAIN_ARRIVES);
|
||||
TriggerStationAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
|
||||
}
|
||||
|
||||
|
@ -3184,7 +3185,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
|||
}
|
||||
goto reverse_train_direction;
|
||||
} else {
|
||||
TryReserveRailTrack(gp.new_tile, TrackBitsToTrack(chosen_track));
|
||||
TryReserveRailTrack(gp.new_tile, TrackBitsToTrack(chosen_track), false);
|
||||
}
|
||||
} else {
|
||||
/* The wagon is active, simply follow the prev vehicle. */
|
||||
|
|
|
@ -2001,7 +2001,10 @@ void Vehicle::LeaveStation()
|
|||
|
||||
if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
|
||||
/* Trigger station animation (trains only) */
|
||||
if (IsTileType(this->tile, MP_STATION)) TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
|
||||
if (IsTileType(this->tile, MP_STATION)) {
|
||||
TriggerStationRandomisation(st, this->tile, SRT_TRAIN_DEPARTS);
|
||||
TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
|
||||
}
|
||||
|
||||
SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue