Add support for road stop animation, availability callback
Add animation, callback mask, general flags properties Add animation frame variables
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user