Add support for road stop animation, availability callback
Add animation, callback mask, general flags properties Add animation frame variables
This commit is contained in:
@@ -80,15 +80,16 @@ 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.
|
||||
CargoTypes cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask
|
||||
CargoTypes roadstop_cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask for road stops
|
||||
uint8 cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
|
||||
uint8 cached_roadstop_anim_triggers; ///< 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
|
||||
CargoTypes cached_roadstop_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask for road stops
|
||||
|
||||
TileArea train_station; ///< Tile area the train 'station' part covers
|
||||
StationRect rect; ///< NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions
|
||||
|
||||
std::vector<TileIndex> custom_road_stop_tiles; ///< List of custom road stop tiles
|
||||
std::vector<byte> custom_road_stop_random_bits; ///< Custom road stop random bits in same order as custom_road_stop_tiles
|
||||
std::vector<uint16> custom_road_stop_data; ///< Custom road stop random bits (low) and animation byte (high) in same order as custom_road_stop_tiles
|
||||
|
||||
/**
|
||||
* Initialize the base station.
|
||||
@@ -193,16 +194,31 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
|
||||
return (this->facilities & facilities) != 0;
|
||||
}
|
||||
|
||||
inline byte GetRoadStopRandomBits(TileIndex tile) const
|
||||
inline uint GetRoadStopData(TileIndex tile) const
|
||||
{
|
||||
for (size_t i = 0; i < this->custom_road_stop_tiles.size(); i++) {
|
||||
if (this->custom_road_stop_tiles[i] == tile) return this->custom_road_stop_random_bits[i];
|
||||
if (this->custom_road_stop_tiles[i] == tile) return this->custom_road_stop_data[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetRoadStopRandomBits(TileIndex tile, byte random_bits);
|
||||
void RemoveRoadStopRandomBits(TileIndex tile);
|
||||
inline byte GetRoadStopRandomBits(TileIndex tile) const
|
||||
{
|
||||
return GB(this->GetRoadStopData(tile), 0, 8);
|
||||
}
|
||||
|
||||
inline byte GetRoadStopAnimationFrame(TileIndex tile) const
|
||||
{
|
||||
return GB(this->GetRoadStopData(tile), 8, 8);
|
||||
}
|
||||
|
||||
private:
|
||||
void SetRoadStopTileData(TileIndex tile, byte data, byte offset);
|
||||
|
||||
public:
|
||||
inline void SetRoadStopRandomBits(TileIndex tile, byte random_bits) { this->SetRoadStopTileData(tile, random_bits, 0); }
|
||||
inline void SetRoadStopAnimationFrame(TileIndex tile, byte frame) { this->SetRoadStopTileData(tile, random_bits, 8); }
|
||||
void RemoveRoadStopTileData(TileIndex tile);
|
||||
|
||||
static void PostDestructor(size_t index);
|
||||
|
||||
|
@@ -2147,6 +2147,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
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);
|
||||
TriggerRoadStopAnimation(st, st->xy, SAT_NEW_CARGO, v->cargo_type);
|
||||
TriggerRoadStopRandomisation(st, st->xy, RSRT_CARGO_TAKEN, v->cargo_type);
|
||||
}
|
||||
|
||||
@@ -2170,6 +2171,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
TriggerStationAnimation(st, station_tile, SAT_TRAIN_LOADS);
|
||||
} else if (front->type == VEH_ROAD) {
|
||||
TriggerRoadStopRandomisation(st, station_tile, RSRT_VEH_LOADS);
|
||||
TriggerRoadStopAnimation(st, station_tile, SAT_TRAIN_LOADS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4995,7 +4995,7 @@ static ChangeInfoResult RoadStopChangeInfo(uint id, int numinfo, int prop, const
|
||||
}
|
||||
|
||||
case A0RPI_ROADSTOP_STOP_TYPE:
|
||||
if (MappedPropertyLengthMismatch(buf, 4, mapping_entry)) break;
|
||||
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
|
||||
FALLTHROUGH;
|
||||
case 0x09: // Road stop type
|
||||
rs->stop_type = (RoadStopAvailabilityType)buf->ReadByte();
|
||||
@@ -5029,6 +5029,42 @@ static ChangeInfoResult RoadStopChangeInfo(uint id, int numinfo, int prop, const
|
||||
rs->cargo_triggers = TranslateRefitMask(buf->ReadDWord());
|
||||
break;
|
||||
|
||||
case A0RPI_ROADSTOP_ANIMATION_INFO:
|
||||
if (MappedPropertyLengthMismatch(buf, 2, mapping_entry)) break;
|
||||
FALLTHROUGH;
|
||||
case 0x0E: // Animation info
|
||||
rs->animation.frames = buf->ReadByte();
|
||||
rs->animation.status = buf->ReadByte();
|
||||
break;
|
||||
|
||||
case A0RPI_ROADSTOP_ANIMATION_SPEED:
|
||||
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
|
||||
FALLTHROUGH;
|
||||
case 0x0F: // Animation speed
|
||||
rs->animation.speed = buf->ReadByte();
|
||||
break;
|
||||
|
||||
case A0RPI_ROADSTOP_ANIMATION_TRIGGERS:
|
||||
if (MappedPropertyLengthMismatch(buf, 2, mapping_entry)) break;
|
||||
FALLTHROUGH;
|
||||
case 0x10: // Animation triggers
|
||||
rs->animation.triggers = buf->ReadWord();
|
||||
break;
|
||||
|
||||
case A0RPI_ROADSTOP_CALLBACK_MASK:
|
||||
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
|
||||
FALLTHROUGH;
|
||||
case 0x11: // Callback mask
|
||||
rs->callback_mask = buf->ReadByte();
|
||||
break;
|
||||
|
||||
case A0RPI_ROADSTOP_GENERAL_FLAGS:
|
||||
if (MappedPropertyLengthMismatch(buf, 4, mapping_entry)) break;
|
||||
FALLTHROUGH;
|
||||
case 0x12: // General flags
|
||||
rs->flags = (uint8)buf->ReadDWord(); // Future-proofing, size this as 4 bytes, but we only need one byte's worth of flags at present
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = CIR_UNKNOWN;
|
||||
break;
|
||||
|
@@ -279,7 +279,7 @@ bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const Airport
|
||||
}
|
||||
|
||||
/** Helper class for animation control. */
|
||||
struct AirportTileAnimationBase : public AnimationBase<AirportTileAnimationBase, AirportTileSpec, Station, int, GetAirportTileCallback> {
|
||||
struct AirportTileAnimationBase : public AnimationBase<AirportTileAnimationBase, AirportTileSpec, Station, int, GetAirportTileCallback, TileAnimationFrameAnimationHelper<Station> > {
|
||||
static const CallbackID cb_animation_speed = CBID_AIRPTILE_ANIMATION_SPEED;
|
||||
static const CallbackID cb_animation_next_frame = CBID_AIRPTILE_ANIM_NEXT_FRAME;
|
||||
|
||||
|
@@ -17,6 +17,12 @@
|
||||
#include "newgrf_callbacks.h"
|
||||
#include "tile_map.h"
|
||||
|
||||
template <typename Tobj>
|
||||
struct TileAnimationFrameAnimationHelper {
|
||||
static byte Get(Tobj *obj, TileIndex tile) { return GetAnimationFrame(tile); }
|
||||
static void Set(Tobj *obj, TileIndex tile, byte frame) { SetAnimationFrame(tile, frame); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class for a unified approach to NewGRF animation.
|
||||
* @tparam Tbase Instantiation of this class.
|
||||
@@ -24,8 +30,9 @@
|
||||
* @tparam Tobj Object related to the animated tile.
|
||||
* @tparam Textra Custom extra callback data.
|
||||
* @tparam GetCallback The callback function pointer.
|
||||
* @tparam Tframehelper The animation frame get/set helper.
|
||||
*/
|
||||
template <typename Tbase, typename Tspec, typename Tobj, typename Textra, uint16 (*GetCallback)(CallbackID callback, uint32 param1, uint32 param2, const Tspec *statspec, Tobj *st, TileIndex tile, Textra extra_data)>
|
||||
template <typename Tbase, typename Tspec, typename Tobj, typename Textra, uint16 (*GetCallback)(CallbackID callback, uint32 param1, uint32 param2, const Tspec *statspec, Tobj *st, TileIndex tile, Textra extra_data), typename Tframehelper>
|
||||
struct AnimationBase {
|
||||
/**
|
||||
* Animate a single tile.
|
||||
@@ -55,7 +62,7 @@ struct AnimationBase {
|
||||
* maximum, corresponding to around 33 minutes. */
|
||||
if (_scaled_tick_counter % (1 << animation_speed) != 0) return;
|
||||
|
||||
uint8 frame = GetAnimationFrame(tile);
|
||||
uint8 frame = Tframehelper::Get(obj, tile);
|
||||
uint8 num_frames = spec->animation.frames;
|
||||
|
||||
bool frame_set_by_callback = false;
|
||||
@@ -98,7 +105,7 @@ struct AnimationBase {
|
||||
}
|
||||
}
|
||||
|
||||
SetAnimationFrame(tile, frame);
|
||||
Tframehelper::Set(obj, tile, frame);
|
||||
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
|
||||
}
|
||||
|
||||
@@ -124,7 +131,7 @@ struct AnimationBase {
|
||||
case 0xFE: AddAnimatedTile(tile); break;
|
||||
case 0xFF: DeleteAnimatedTile(tile); break;
|
||||
default:
|
||||
SetAnimationFrame(tile, callback);
|
||||
Tframehelper::Set(obj, tile, callback);
|
||||
AddAnimatedTile(tile);
|
||||
break;
|
||||
}
|
||||
|
@@ -307,6 +307,15 @@ enum StationCallbackMask {
|
||||
CBM_STATION_SLOPE_CHECK = 4, ///< Check slope of new station tiles
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback masks for road stops.
|
||||
*/
|
||||
enum RoadStopCallbackMask {
|
||||
CBM_ROAD_STOP_AVAIL = 0, ///< Availability of road stop in construction window
|
||||
CBM_ROAD_STOP_ANIMATION_NEXT_FRAME = 1, ///< Use a custom next frame callback
|
||||
CBM_ROAD_STOP_ANIMATION_SPEED = 2, ///< Customize the animation speed of the road stop
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback masks for houses.
|
||||
*/
|
||||
|
@@ -95,7 +95,12 @@ extern const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_STOP_NAME, "roadstop_stop_name"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_CLASS_NAME, "roadstop_class_name"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_DRAW_MODE, "roadstop_draw_mode"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_TRIGGER_CARGOES, "roadstop_trigger_cargoes"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_TRIGGER_CARGOES, "roadstop_random_trigger_cargoes"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_ANIMATION_INFO, "roadstop_animation_info"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_ANIMATION_SPEED, "roadstop_animation_speed"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_ANIMATION_TRIGGERS, "roadstop_animation_triggers"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_CALLBACK_MASK, "roadstop_callback_mask"),
|
||||
GRFPropertyMapDefinition(GSF_ROADSTOPS, A0RPI_ROADSTOP_GENERAL_FLAGS, "roadstop_general_flags"),
|
||||
GRFPropertyMapDefinition(),
|
||||
};
|
||||
|
||||
|
@@ -45,6 +45,11 @@ enum Action0RemapPropertyIds {
|
||||
A0RPI_ROADSTOP_CLASS_NAME,
|
||||
A0RPI_ROADSTOP_DRAW_MODE,
|
||||
A0RPI_ROADSTOP_TRIGGER_CARGOES,
|
||||
A0RPI_ROADSTOP_ANIMATION_INFO,
|
||||
A0RPI_ROADSTOP_ANIMATION_SPEED,
|
||||
A0RPI_ROADSTOP_ANIMATION_TRIGGERS,
|
||||
A0RPI_ROADSTOP_CALLBACK_MASK,
|
||||
A0RPI_ROADSTOP_GENERAL_FLAGS,
|
||||
};
|
||||
|
||||
|
||||
|
@@ -637,7 +637,7 @@ uint16 GetSimpleHouseCallback(CallbackID callback, uint32 param1, uint32 param2,
|
||||
}
|
||||
|
||||
/** Helper class for animation control. */
|
||||
struct HouseAnimationBase : public AnimationBase<HouseAnimationBase, HouseSpec, Town, CargoTypes, GetSimpleHouseCallback> {
|
||||
struct HouseAnimationBase : public AnimationBase<HouseAnimationBase, HouseSpec, Town, CargoTypes, GetSimpleHouseCallback, TileAnimationFrameAnimationHelper<Town> > {
|
||||
static const CallbackID cb_animation_speed = CBID_HOUSE_ANIMATION_SPEED;
|
||||
static const CallbackID cb_animation_next_frame = CBID_HOUSE_ANIMATION_NEXT_FRAME;
|
||||
|
||||
|
@@ -257,7 +257,7 @@ uint16 GetSimpleIndustryCallback(CallbackID callback, uint32 param1, uint32 para
|
||||
}
|
||||
|
||||
/** Helper class for animation control. */
|
||||
struct IndustryAnimationBase : public AnimationBase<IndustryAnimationBase, IndustryTileSpec, Industry, int, GetSimpleIndustryCallback> {
|
||||
struct IndustryAnimationBase : public AnimationBase<IndustryAnimationBase, IndustryTileSpec, Industry, int, GetSimpleIndustryCallback, TileAnimationFrameAnimationHelper<Industry> > {
|
||||
static const CallbackID cb_animation_speed = CBID_INDTILE_ANIMATION_SPEED;
|
||||
static const CallbackID cb_animation_next_frame = CBID_INDTILE_ANIM_NEXT_FRAME;
|
||||
|
||||
|
@@ -558,7 +558,7 @@ uint16 StubGetObjectCallback(CallbackID callback, uint32 param1, uint32 param2,
|
||||
}
|
||||
|
||||
/** Helper class for animation control. */
|
||||
struct ObjectAnimationBase : public AnimationBase<ObjectAnimationBase, ObjectSpec, Object, int, StubGetObjectCallback> {
|
||||
struct ObjectAnimationBase : public AnimationBase<ObjectAnimationBase, ObjectSpec, Object, int, StubGetObjectCallback, TileAnimationFrameAnimationHelper<Object> > {
|
||||
static const CallbackID cb_animation_speed = CBID_OBJECT_ANIMATION_SPEED;
|
||||
static const CallbackID cb_animation_next_frame = CBID_OBJECT_ANIMATION_NEXT_FRAME;
|
||||
|
||||
|
@@ -22,6 +22,8 @@
|
||||
#include "date_func.h"
|
||||
#include "town.h"
|
||||
#include "viewport_func.h"
|
||||
#include "newgrf_animation_base.h"
|
||||
#include "newgrf_sound.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
@@ -102,11 +104,23 @@ uint32 RoadStopScopeResolver::GetVariable(uint16 variable, uint32 parameter, Get
|
||||
/* Company information */
|
||||
case 0x47: return GetCompanyInfo(this->st == nullptr ? _current_company : this->st->owner);
|
||||
|
||||
/* Animation frame */
|
||||
case 0x49: return this->tile == INVALID_TILE ? 0 : this->st->GetRoadStopAnimationFrame(this->tile);
|
||||
|
||||
/* Variables which use the parameter */
|
||||
/* Variables 0x60 to 0x65 and 0x69 are handled separately below */
|
||||
|
||||
/* Animation frame of nearby tile */
|
||||
case 0x66: {
|
||||
if (this->tile == INVALID_TILE) return UINT_MAX;
|
||||
TileIndex tile = this->tile;
|
||||
if (parameter != 0) tile = GetNearbyTile(parameter, tile);
|
||||
return (IsAnyRoadStopTile(tile) && GetStationIndex(tile) == this->st->index) ? this->st->GetRoadStopAnimationFrame(tile) : UINT_MAX;
|
||||
}
|
||||
|
||||
/* Land info of nearby tile */
|
||||
case 0x67: {
|
||||
if (this->tile == INVALID_TILE) return 0;
|
||||
TileIndex tile = this->tile;
|
||||
if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required
|
||||
return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8);
|
||||
@@ -114,6 +128,7 @@ uint32 RoadStopScopeResolver::GetVariable(uint16 variable, uint32 parameter, Get
|
||||
|
||||
/* Road stop info of nearby tiles */
|
||||
case 0x68: {
|
||||
if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
|
||||
TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
|
||||
|
||||
if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
|
||||
@@ -132,6 +147,7 @@ uint32 RoadStopScopeResolver::GetVariable(uint16 variable, uint32 parameter, Get
|
||||
|
||||
/* GRFID of nearby road stop tiles */
|
||||
case 0x6A: {
|
||||
if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
|
||||
TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
|
||||
|
||||
if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
|
||||
@@ -212,6 +228,12 @@ TownScopeResolver* RoadStopResolverObject::GetTown()
|
||||
return this->town_scope;
|
||||
}
|
||||
|
||||
uint16 GetRoadStopCallback(CallbackID callback, uint32 param1, uint32 param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, const RoadTypeInfo *rti, StationType type, uint8 view)
|
||||
{
|
||||
RoadStopResolverObject object(roadstopspec, st, tile, rti, type, view, callback, param1, param2);
|
||||
return object.ResolveCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw representation of a road stop tile for GUI purposes.
|
||||
* @param x position x of image.
|
||||
@@ -272,6 +294,74 @@ void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec,
|
||||
DrawCommonTileSeqInGUI(x, y, dts, 0, 0, palette, true);
|
||||
}
|
||||
|
||||
/** Wrapper for animation control, see GetRoadStopCallback. */
|
||||
uint16 GetAnimRoadStopCallback(CallbackID callback, uint32 param1, uint32 param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, int extra_data)
|
||||
{
|
||||
return GetRoadStopCallback(callback, param1, param2, roadstopspec, st, tile, nullptr, GetStationType(tile), GetStationGfx(tile));
|
||||
}
|
||||
|
||||
struct RoadStopAnimationFrameAnimationHelper {
|
||||
static byte Get(BaseStation *st, TileIndex tile) { return st->GetRoadStopAnimationFrame(tile); }
|
||||
static void Set(BaseStation *st, TileIndex tile, byte frame) { st->SetRoadStopAnimationFrame(tile, frame); }
|
||||
};
|
||||
|
||||
/** Helper class for animation control. */
|
||||
struct RoadStopAnimationBase : public AnimationBase<RoadStopAnimationBase, RoadStopSpec, BaseStation, int, GetAnimRoadStopCallback, RoadStopAnimationFrameAnimationHelper> {
|
||||
static const CallbackID cb_animation_speed = CBID_STATION_ANIMATION_SPEED;
|
||||
static const CallbackID cb_animation_next_frame = CBID_STATION_ANIM_NEXT_FRAME;
|
||||
|
||||
static const RoadStopCallbackMask cbm_animation_speed = CBM_ROAD_STOP_ANIMATION_SPEED;
|
||||
static const RoadStopCallbackMask cbm_animation_next_frame = CBM_ROAD_STOP_ANIMATION_NEXT_FRAME;
|
||||
};
|
||||
|
||||
void AnimateRoadStopTile(TileIndex tile)
|
||||
{
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(tile);
|
||||
if (ss == nullptr) return;
|
||||
|
||||
RoadStopAnimationBase::AnimateTile(ss, BaseStation::GetByTile(tile), tile, HasBit(ss->flags, RSF_CB141_RANDOM_BITS));
|
||||
}
|
||||
|
||||
uint8 GetRoadStopTileAnimationSpeed(TileIndex tile)
|
||||
{
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(tile);
|
||||
if (ss == nullptr) return 0;
|
||||
|
||||
return RoadStopAnimationBase::GetAnimationSpeed(ss);
|
||||
}
|
||||
|
||||
void TriggerRoadStopAnimation(BaseStation *st, TileIndex trigger_tile, StationAnimationTrigger trigger, CargoID cargo_type)
|
||||
{
|
||||
/* Get Station if it wasn't supplied */
|
||||
if (st == nullptr) st = BaseStation::GetByTile(trigger_tile);
|
||||
|
||||
/* Check the cached animation trigger bitmask to see if we need
|
||||
* to bother with any further processing. */
|
||||
if (!HasBit(st->cached_roadstop_anim_triggers, trigger)) return;
|
||||
|
||||
uint16 random_bits = Random();
|
||||
auto process_tile = [&](TileIndex cur_tile) {
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
|
||||
if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) {
|
||||
CargoID cargo;
|
||||
if (cargo_type == CT_INVALID) {
|
||||
cargo = CT_INVALID;
|
||||
} else {
|
||||
cargo = ss->grf_prop.grffile->cargo_map[cargo_type];
|
||||
}
|
||||
RoadStopAnimationBase::ChangeAnimationFrame(CBID_STATION_ANIM_START_STOP, ss, st, cur_tile, (random_bits << 16) | Random(), (uint8)trigger | (cargo << 8));
|
||||
}
|
||||
};
|
||||
|
||||
if (trigger == SAT_NEW_CARGO || trigger == SAT_CARGO_TAKEN || trigger == SAT_250_TICKS) {
|
||||
for (TileIndex cur_tile : st->custom_road_stop_tiles) {
|
||||
process_tile(cur_tile);
|
||||
}
|
||||
} else {
|
||||
process_tile(trigger_tile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger road stop randomisation
|
||||
*
|
||||
@@ -286,8 +376,8 @@ void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTri
|
||||
|
||||
/* Check the cached cargo trigger bitmask to see if we need
|
||||
* to bother with any further processing. */
|
||||
if (st->roadstop_cached_cargo_triggers == 0) return;
|
||||
if (cargo_type != CT_INVALID && !HasBit(st->roadstop_cached_cargo_triggers, cargo_type)) return;
|
||||
if (st->cached_roadstop_cargo_triggers == 0) return;
|
||||
if (cargo_type != CT_INVALID && !HasBit(st->cached_roadstop_cargo_triggers, cargo_type)) return;
|
||||
|
||||
SetBit(st->waiting_triggers, trigger);
|
||||
|
||||
@@ -305,7 +395,7 @@ void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTri
|
||||
|
||||
uint32 used_triggers = 0;
|
||||
auto process_tile = [&](TileIndex cur_tile) {
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(tile);
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
|
||||
if (ss == nullptr) return;
|
||||
|
||||
/* Cargo taken "will only be triggered if all of those
|
||||
@@ -315,10 +405,7 @@ void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTri
|
||||
}
|
||||
|
||||
if (cargo_type == CT_INVALID || HasBit(ss->cargo_triggers, cargo_type)) {
|
||||
int dir = GetRoadStopDir(cur_tile);
|
||||
if (IsDriveThroughStopTile(cur_tile)) dir += 4;
|
||||
|
||||
RoadStopResolverObject object(ss, st, cur_tile, nullptr, GetStationType(cur_tile), dir);
|
||||
RoadStopResolverObject object(ss, st, cur_tile, nullptr, GetStationType(cur_tile), GetStationGfx(cur_tile));
|
||||
object.waiting_triggers = st->waiting_triggers;
|
||||
|
||||
const SpriteGroup *group = object.Resolve();
|
||||
@@ -487,7 +574,8 @@ void DeallocateRoadStopSpecFromStation(BaseStation *st, byte specindex)
|
||||
free(st->roadstop_speclist);
|
||||
st->num_roadstop_specs = 0;
|
||||
st->roadstop_speclist = nullptr;
|
||||
st->roadstop_cached_cargo_triggers = 0;
|
||||
st->cached_roadstop_anim_triggers = 0;
|
||||
st->cached_roadstop_cargo_triggers = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -501,14 +589,16 @@ void DeallocateRoadStopSpecFromStation(BaseStation *st, byte specindex)
|
||||
*/
|
||||
void StationUpdateRoadStopCachedTriggers(BaseStation *st)
|
||||
{
|
||||
st->roadstop_cached_cargo_triggers = 0;
|
||||
st->cached_roadstop_anim_triggers = 0;
|
||||
st->cached_roadstop_cargo_triggers = 0;
|
||||
|
||||
/* Combine animation trigger bitmask for all road stop specs
|
||||
* of this station. */
|
||||
for (uint i = 0; i < st->num_roadstop_specs; i++) {
|
||||
const RoadStopSpec *ss = st->roadstop_speclist[i].spec;
|
||||
if (ss != nullptr) {
|
||||
st->roadstop_cached_cargo_triggers |= ss->cargo_triggers;
|
||||
st->cached_roadstop_anim_triggers |= ss->animation.triggers;
|
||||
st->cached_roadstop_cargo_triggers |= ss->cargo_triggers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,6 +35,8 @@ DECLARE_POSTFIX_INCREMENT(RoadStopClassID)
|
||||
enum RoadStopRandomTrigger {
|
||||
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.
|
||||
};
|
||||
|
||||
@@ -61,6 +63,10 @@ enum RoadStopDrawMode : byte {
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(RoadStopDrawMode)
|
||||
|
||||
enum RoadStopSpecFlags {
|
||||
RSF_CB141_RANDOM_BITS, ///< Callback 141 needs random bits.
|
||||
};
|
||||
|
||||
/** Scope resolver for road stops. */
|
||||
struct RoadStopScopeResolver : public ScopeResolver {
|
||||
TileIndex tile; ///< %Tile of the station.
|
||||
@@ -123,9 +129,13 @@ struct RoadStopSpec {
|
||||
|
||||
RoadStopAvailabilityType stop_type = ROADSTOPTYPE_ALL;
|
||||
RoadStopDrawMode draw_mode = ROADSTOP_DRAW_MODE_ROAD | ROADSTOP_DRAW_MODE_OVERLAY;
|
||||
uint8 callback_mask = 0;
|
||||
uint8 flags = 0;
|
||||
|
||||
CargoTypes cargo_triggers = 0; ///< Bitmask of cargo types which cause trigger re-randomizing
|
||||
|
||||
AnimationInfo animation;
|
||||
|
||||
static const RoadStopSpec *Get(uint16 index);
|
||||
};
|
||||
|
||||
@@ -136,6 +146,11 @@ typedef NewGRFClass<RoadStopSpec, RoadStopClassID, ROADSTOP_CLASS_MAX> RoadStopC
|
||||
|
||||
void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec, StationType type, int view);
|
||||
|
||||
uint16 GetRoadStopCallback(CallbackID callback, uint32 param1, uint32 param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, const RoadTypeInfo *rti, StationType type, uint8 view);
|
||||
|
||||
void AnimateRoadStopTile(TileIndex tile);
|
||||
uint8 GetRoadStopTileAnimationSpeed(TileIndex tile);
|
||||
void TriggerRoadStopAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
|
||||
void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoID cargo_type = CT_INVALID);
|
||||
|
||||
bool GetIfNewStopsByType(RoadStopType rs);
|
||||
|
@@ -906,7 +906,7 @@ uint16 GetAnimStationCallback(CallbackID callback, uint32 param1, uint32 param2,
|
||||
}
|
||||
|
||||
/** Helper class for animation control. */
|
||||
struct StationAnimationBase : public AnimationBase<StationAnimationBase, StationSpec, BaseStation, int, GetAnimStationCallback> {
|
||||
struct StationAnimationBase : public AnimationBase<StationAnimationBase, StationSpec, BaseStation, int, GetAnimStationCallback, TileAnimationFrameAnimationHelper<BaseStation> > {
|
||||
static const CallbackID cb_animation_speed = CBID_STATION_ANIMATION_SPEED;
|
||||
static const CallbackID cb_animation_next_frame = CBID_STATION_ANIM_NEXT_FRAME;
|
||||
|
||||
|
@@ -89,6 +89,20 @@ static RoadFlags _place_road_flag;
|
||||
static RoadType _cur_roadtype;
|
||||
|
||||
|
||||
/**
|
||||
* Check whether a road stop type can be built.
|
||||
* @return true if building is allowed.
|
||||
*/
|
||||
static bool IsRoadStopAvailable(const RoadStopSpec *roadstopspec, StationType type)
|
||||
{
|
||||
if (roadstopspec == nullptr || !HasBit(roadstopspec->callback_mask, CBM_ROAD_STOP_AVAIL)) return true;
|
||||
|
||||
uint16 cb_res = GetRoadStopCallback(CBID_STATION_AVAILABILITY, 0, 0, roadstopspec, nullptr, INVALID_TILE, GetRoadTypeInfo(_cur_roadtype), type, 0);
|
||||
if (cb_res == CALLBACK_FAILED) return true;
|
||||
|
||||
return Convert8bitBooleanCallback(roadstopspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res);
|
||||
}
|
||||
|
||||
void CcPlaySound_CONSTRUCTION_OTHER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
|
||||
{
|
||||
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
|
||||
@@ -1488,6 +1502,13 @@ public:
|
||||
byte type = GB(widget, 16, 16);
|
||||
assert(type < _roadstop_gui_settings.roadstop_count);
|
||||
|
||||
const RoadStopSpec *spec = RoadStopClass::Get(_roadstop_gui_settings.roadstop_class)->GetSpec(type);
|
||||
StationType st = GetRoadStationTypeByWindowClass(this->window_class);
|
||||
|
||||
if (!IsRoadStopAvailable(spec, st)) {
|
||||
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK, FILLRECT_CHECKER);
|
||||
}
|
||||
|
||||
// Set up a clipping area for the sprite preview.
|
||||
if (FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.right - r.left + 1, r.bottom - r.top + 1)) {
|
||||
DrawPixelInfo *old_dpi = _cur_dpi;
|
||||
@@ -1495,8 +1516,6 @@ public:
|
||||
int x = ScaleGUITrad(31) + 1;
|
||||
int y = r.bottom - r.top - ScaleGUITrad(31);
|
||||
// Instead of "5" (5th view), pass the orientation clicked in the selection.
|
||||
const RoadStopSpec *spec = RoadStopClass::Get(_roadstop_gui_settings.roadstop_class)->GetSpec(type);
|
||||
StationType st = GetRoadStationTypeByWindowClass(this->window_class);
|
||||
if (spec == nullptr) {
|
||||
StationPickerDrawSprite(r.left + 1 + ScaleGUITrad(31), r.bottom - ScaleGUITrad(31), st, INVALID_RAILTYPE, _cur_roadtype, _roadstop_gui_settings.orientation);
|
||||
} else {
|
||||
@@ -1573,6 +1592,11 @@ public:
|
||||
int y = GB(widget, 16, 16);
|
||||
if (y >= _roadstop_gui_settings.roadstop_count) return;
|
||||
|
||||
const RoadStopSpec *spec = RoadStopClass::Get(_roadstop_gui_settings.roadstop_class)->GetSpec(y);
|
||||
StationType st = GetRoadStationTypeByWindowClass(this->window_class);
|
||||
|
||||
if (!IsRoadStopAvailable(spec, st)) return;
|
||||
|
||||
/* Check station availability callback */
|
||||
_roadstop_gui_settings.roadstop_type = y;
|
||||
|
||||
@@ -1830,6 +1854,9 @@ struct BuildRoadWaypointWindow : PickerWindowBase {
|
||||
} else {
|
||||
DrawRoadStopTile(r.left + 1 + ScaleGUITrad(31), r.bottom - ScaleGUITrad(31), _cur_roadtype, spec, STATION_ROADWAYPOINT, 4);
|
||||
}
|
||||
if (!IsRoadStopAvailable(spec, STATION_ROADWAYPOINT)) {
|
||||
GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK, FILLRECT_CHECKER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1839,6 +1866,10 @@ struct BuildRoadWaypointWindow : PickerWindowBase {
|
||||
switch (GB(widget, 0, 16)) {
|
||||
case WID_BROW_WAYPOINT: {
|
||||
uint type = GB(widget, 16, 16);
|
||||
|
||||
const RoadStopSpec *spec = RoadStopClass::Get(ROADSTOP_CLASS_WAYP)->GetSpec(type);
|
||||
if (!IsRoadStopAvailable(spec, STATION_ROADWAYPOINT)) return;
|
||||
|
||||
this->GetWidget<NWidgetMatrix>(WID_BROW_WAYPOINT_MATRIX)->SetClicked(_cur_waypoint_type);
|
||||
|
||||
_cur_waypoint_type = type;
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "scope_info.h"
|
||||
#include "string_func.h"
|
||||
#include "core/checksum_func.hpp"
|
||||
#include "newgrf_roadstop.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
@@ -1950,6 +1951,8 @@ again:
|
||||
v->last_station_visited = st->index;
|
||||
RoadVehArrivesAt(v, st);
|
||||
v->BeginLoading();
|
||||
TriggerRoadStopRandomisation(st, v->tile, RSRT_VEH_ARRIVES);
|
||||
TriggerRoadStopAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2012,6 +2015,8 @@ 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);
|
||||
TriggerRoadStopAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@@ -411,7 +411,7 @@ static const SaveLoad _base_station_desc[] = {
|
||||
SLE_VAR(BaseStation, num_specs, SLE_UINT8),
|
||||
SLE_CONDVAR_X(BaseStation, num_roadstop_specs, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_GRF_ROADSTOPS)),
|
||||
SLE_CONDVARVEC_X(BaseStation, custom_road_stop_tiles, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_GRF_ROADSTOPS)),
|
||||
SLE_CONDVARVEC_X(BaseStation, custom_road_stop_random_bits, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_GRF_ROADSTOPS)),
|
||||
SLE_CONDVARVEC_X(BaseStation, custom_road_stop_data, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_GRF_ROADSTOPS)),
|
||||
};
|
||||
|
||||
static OldPersistentStorage _old_st_persistent_storage;
|
||||
|
@@ -185,26 +185,26 @@ void BaseStation::PostDestructor(size_t index)
|
||||
InvalidateWindowData(WC_SELECT_STATION, 0, 0);
|
||||
}
|
||||
|
||||
void BaseStation::SetRoadStopRandomBits(TileIndex tile, byte random_bits)
|
||||
void BaseStation::SetRoadStopTileData(TileIndex tile, byte data, byte offset)
|
||||
{
|
||||
for (size_t i = 0; i < this->custom_road_stop_tiles.size(); i++) {
|
||||
if (this->custom_road_stop_tiles[i] == tile) {
|
||||
this->custom_road_stop_random_bits[i] = random_bits;
|
||||
SB(this->custom_road_stop_data[i], offset, 8, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->custom_road_stop_tiles.push_back(tile);
|
||||
this->custom_road_stop_random_bits.push_back(random_bits);
|
||||
this->custom_road_stop_data.push_back(((uint)data) << offset);
|
||||
}
|
||||
|
||||
void BaseStation::RemoveRoadStopRandomBits(TileIndex tile)
|
||||
void BaseStation::RemoveRoadStopTileData(TileIndex tile)
|
||||
{
|
||||
for (size_t i = 0; i < this->custom_road_stop_tiles.size(); i++) {
|
||||
if (this->custom_road_stop_tiles[i] == tile) {
|
||||
this->custom_road_stop_tiles[i] = this->custom_road_stop_tiles.back();
|
||||
this->custom_road_stop_random_bits[i] = this->custom_road_stop_random_bits.back();
|
||||
this->custom_road_stop_data[i] = this->custom_road_stop_data.back();
|
||||
this->custom_road_stop_tiles.pop_back();
|
||||
this->custom_road_stop_random_bits.pop_back();
|
||||
this->custom_road_stop_data.pop_back();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -2132,6 +2132,16 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
int specindex = AllocateRoadStopSpecToStation(roadstopspec, st, (flags & DC_EXEC) != 0);
|
||||
if (specindex == -1) return_cmd_error(STR_ERROR_TOO_MANY_STATION_SPECS);
|
||||
|
||||
if (roadstopspec != nullptr) {
|
||||
/* Perform NewGRF checks */
|
||||
|
||||
/* Check if the road stop is buildable */
|
||||
if (HasBit(roadstopspec->callback_mask, CBM_ROAD_STOP_AVAIL)) {
|
||||
uint16 cb_res = GetRoadStopCallback(CBID_STATION_AVAILABILITY, 0, 0, roadstopspec, nullptr, INVALID_TILE, GetRoadTypeInfo(rt), type ? STATION_TRUCK : STATION_BUS, 0);
|
||||
if (cb_res != CALLBACK_FAILED && !Convert8bitBooleanCallback(roadstopspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res)) return CMD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* Check every tile in the area. */
|
||||
for (TileIndex cur_tile : roadstop_area) {
|
||||
@@ -2146,6 +2156,12 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
RemoveRoadStop(cur_tile, flags);
|
||||
}
|
||||
|
||||
if (roadstopspec != nullptr) {
|
||||
/* Include this road stop spec's animation trigger bitmask
|
||||
* in the station's cached copy. */
|
||||
st->cached_roadstop_anim_triggers |= roadstopspec->animation.triggers;
|
||||
}
|
||||
|
||||
RoadStop *road_stop = new RoadStop(cur_tile);
|
||||
/* Insert into linked list of RoadStops. */
|
||||
RoadStop **currstop = FindRoadStopSpot(type, st);
|
||||
@@ -2190,7 +2206,10 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
Company::Get(st->owner)->infrastructure.station++;
|
||||
|
||||
SetCustomRoadStopSpecIndex(cur_tile, specindex);
|
||||
if (roadstopspec != nullptr) st->SetRoadStopRandomBits(cur_tile, GB(Random(), 0, 4));
|
||||
if (roadstopspec != nullptr) {
|
||||
st->SetRoadStopRandomBits(cur_tile, GB(Random(), 0, 4));
|
||||
TriggerRoadStopAnimation(st, cur_tile, SAT_BUILT);
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(cur_tile);
|
||||
UpdateRoadCachedOneWayStatesAroundTile(cur_tile);
|
||||
@@ -2245,6 +2264,8 @@ CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlag flags)
|
||||
Company::Get(wp->owner)->infrastructure.station--;
|
||||
DirtyCompanyInfrastructureWindows(wp->owner);
|
||||
|
||||
DeleteAnimatedTile(tile);
|
||||
|
||||
uint specindex = GetCustomRoadStopSpecIndex(tile);
|
||||
|
||||
DeleteNewGRFInspectWindow(GSF_ROADSTOPS, tile);
|
||||
@@ -2253,7 +2274,7 @@ CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlag flags)
|
||||
|
||||
wp->rect.AfterRemoveTile(wp, tile);
|
||||
|
||||
wp->RemoveRoadStopRandomBits(tile);
|
||||
wp->RemoveRoadStopTileData(tile);
|
||||
DeallocateRoadStopSpecFromStation(wp, specindex);
|
||||
|
||||
MakeRoadWaypointStationAreaSmaller(wp, wp->road_waypoint_area);
|
||||
@@ -2341,6 +2362,8 @@ CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||
Company::Get(st->owner)->infrastructure.station--;
|
||||
DirtyCompanyInfrastructureWindows(st->owner);
|
||||
|
||||
DeleteAnimatedTile(tile);
|
||||
|
||||
uint specindex = GetCustomRoadStopSpecIndex(tile);
|
||||
|
||||
DeleteNewGRFInspectWindow(GSF_ROADSTOPS, tile);
|
||||
@@ -2366,7 +2389,7 @@ CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||
|
||||
st->AfterStationTileSetChange(false, is_truck ? STATION_TRUCK: STATION_BUS);
|
||||
|
||||
st->RemoveRoadStopRandomBits(tile);
|
||||
st->RemoveRoadStopTileData(tile);
|
||||
DeallocateRoadStopSpecFromStation(st, specindex);
|
||||
|
||||
/* Update the tile area of the truck/bus stop */
|
||||
@@ -3788,6 +3811,12 @@ void AnimateTile_Station(TileIndex tile)
|
||||
|
||||
if (IsAirport(tile)) {
|
||||
AnimateAirportTile(tile);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsAnyRoadStopTile(tile)) {
|
||||
AnimateRoadStopTile(tile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3800,6 +3829,10 @@ uint8 GetAnimatedTileSpeed_Station(TileIndex tile)
|
||||
if (IsAirport(tile)) {
|
||||
return GetAirportTileAnimationSpeed(tile);
|
||||
}
|
||||
|
||||
if (IsAnyRoadStopTile(tile)) {
|
||||
return GetRoadStopTileAnimationSpeed(tile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4485,6 +4518,7 @@ void OnTick_Station()
|
||||
/* Stop processing this station if it was deleted */
|
||||
if (!StationHandleBigTick(st)) continue;
|
||||
TriggerStationAnimation(st, st->xy, SAT_250_TICKS);
|
||||
TriggerRoadStopAnimation(st, st->xy, SAT_250_TICKS);
|
||||
if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_TICKS);
|
||||
}
|
||||
}
|
||||
@@ -4569,6 +4603,7 @@ static uint UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceT
|
||||
TriggerStationRandomisation(st, st->xy, SRT_NEW_CARGO, type);
|
||||
TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, type);
|
||||
AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type);
|
||||
TriggerRoadStopAnimation(st, st->xy, SAT_NEW_CARGO, type);
|
||||
TriggerRoadStopRandomisation(st, st->xy, RSRT_NEW_CARGO, type);
|
||||
|
||||
SetWindowDirty(WC_STATION_VIEW, st->index);
|
||||
|
@@ -1371,6 +1371,15 @@ static const NIFeature _nif_roadtype = {
|
||||
new NIHRoadType(),
|
||||
};
|
||||
|
||||
#define NICRS(cb_id, bit) NIC(cb_id, RoadStopSpec, callback_mask, bit)
|
||||
static const NICallback _nic_roadstops[] = {
|
||||
NICRS(CBID_STATION_AVAILABILITY, CBM_ROAD_STOP_AVAIL),
|
||||
NICRS(CBID_STATION_ANIM_START_STOP, CBM_NO_BIT),
|
||||
NICRS(CBID_STATION_ANIM_NEXT_FRAME, CBM_ROAD_STOP_ANIMATION_NEXT_FRAME),
|
||||
NICRS(CBID_STATION_ANIMATION_SPEED, CBM_ROAD_STOP_ANIMATION_SPEED),
|
||||
NIC_END()
|
||||
};
|
||||
|
||||
static const NIVariable _nif_roadstops[] = {
|
||||
NIV(0x40, "view/rotation"),
|
||||
NIV(0x41, "stop type"),
|
||||
@@ -1381,12 +1390,14 @@ static const NIVariable _nif_roadstops[] = {
|
||||
NIV(0x46, "square of Euclidean distance of town"),
|
||||
NIV(0x47, "player info"),
|
||||
NIV(0x48, "bitmask of accepted cargoes"),
|
||||
NIV(0x49, "current animation frame"),
|
||||
NIV(0x60, "amount of cargo waiting"),
|
||||
NIV(0x61, "time since last cargo pickup"),
|
||||
NIV(0x62, "rating of cargo"),
|
||||
NIV(0x63, "time spent on route"),
|
||||
NIV(0x64, "information about last vehicle picking cargo up"),
|
||||
NIV(0x65, "amount of cargo acceptance"),
|
||||
NIV(0x66, "animation frame of nearby tile"),
|
||||
NIV(0x67, "land info of nearby tiles"),
|
||||
NIV(0x68, "road stop info of nearby tiles"),
|
||||
NIV(0x69, "information about cargo accepted in the past"),
|
||||
@@ -1420,11 +1431,15 @@ class NIHRoadStop : public NIHelper {
|
||||
uint class_id = RoadStopClass::Get(spec->cls_id)->global_id;
|
||||
seprintf(buffer, lastof(buffer), " class ID: %c%c%c%c, spec ID: %u", class_id >> 24, class_id >> 16, class_id >> 8, class_id, spec->spec_id);
|
||||
output.print(buffer);
|
||||
seprintf(buffer, lastof(buffer), " spec: stop type: %u, draw mode: %u, cargo triggers: 0x" OTTD_PRINTFHEX64, spec->stop_type, spec->draw_mode, spec->cargo_triggers);
|
||||
seprintf(buffer, lastof(buffer), " spec: stop type: %X, draw mode: %X, cargo triggers: " OTTD_PRINTFHEX64, spec->stop_type, spec->draw_mode, spec->cargo_triggers);
|
||||
output.print(buffer);
|
||||
seprintf(buffer, lastof(buffer), " spec: callback mask: %X, flags: %X", spec->callback_mask, spec->flags);
|
||||
output.print(buffer);
|
||||
seprintf(buffer, lastof(buffer), " animation: frames: %u, status: %u, speed: %u, triggers: 0x%X", spec->animation.frames, spec->animation.status, spec->animation.speed, spec->animation.triggers);
|
||||
output.print(buffer);
|
||||
|
||||
const BaseStation *st = BaseStation::GetByTile(index);
|
||||
seprintf(buffer, lastof(buffer), " stop random bits: %02X", st->GetRoadStopRandomBits(index));
|
||||
seprintf(buffer, lastof(buffer), " road stop: random bits: %02X, animation frame: %02X", st->GetRoadStopRandomBits(index), st->GetRoadStopAnimationFrame(index));
|
||||
output.print(buffer);
|
||||
}
|
||||
}
|
||||
@@ -1438,7 +1453,7 @@ class NIHRoadStop : public NIHelper {
|
||||
|
||||
static const NIFeature _nif_roadstop = {
|
||||
nullptr,
|
||||
nullptr,
|
||||
_nic_roadstops,
|
||||
_nif_roadstops,
|
||||
new NIHRoadStop(),
|
||||
};
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include "newgrf_debug.h"
|
||||
#include "newgrf_sound.h"
|
||||
#include "newgrf_station.h"
|
||||
#include "newgrf_roadstop.h"
|
||||
#include "group_gui.h"
|
||||
#include "strings_func.h"
|
||||
#include "zoom_func.h"
|
||||
@@ -3418,6 +3419,13 @@ void Vehicle::LeaveStation()
|
||||
|
||||
SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
|
||||
}
|
||||
if (this->type == VEH_ROAD && !(this->vehstatus & VS_CRASHED)) {
|
||||
/* Trigger road stop animation */
|
||||
if (IsAnyRoadStopTile(this->tile)) {
|
||||
TriggerRoadStopRandomisation(st, this->tile, RSRT_VEH_DEPARTS);
|
||||
TriggerRoadStopAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->cur_real_order_index < this->GetNumOrders()) {
|
||||
Order *real_current_order = this->GetOrder(this->cur_real_order_index);
|
||||
|
@@ -420,6 +420,12 @@ CommandCost CmdBuildRoadWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
||||
|
||||
wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY);
|
||||
|
||||
if (spec != nullptr) {
|
||||
/* Include this road stop spec's animation trigger bitmask
|
||||
* in the station's cached copy. */
|
||||
wp->cached_roadstop_anim_triggers |= spec->animation.triggers;
|
||||
}
|
||||
|
||||
wp->delete_ctr = 0;
|
||||
wp->facilities |= FACIL_BUS_STOP | FACIL_TRUCK_STOP;
|
||||
wp->build_date = _date;
|
||||
|
Reference in New Issue
Block a user