summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--newgrf_station.c226
-rw-r--r--newgrf_station.h2
2 files changed, 155 insertions, 73 deletions
diff --git a/newgrf_station.c b/newgrf_station.c
index a141f275d..97dd48cb0 100644
--- a/newgrf_station.c
+++ b/newgrf_station.c
@@ -4,12 +4,14 @@
#include "stdafx.h"
#include "openttd.h"
+#include "variables.h"
#include "debug.h"
#include "sprite.h"
#include "table/strings.h"
#include "station.h"
#include "station_map.h"
#include "newgrf_station.h"
+#include "newgrf_spritegroup.h"
static StationClass station_classes[STAT_CLASS_MAX];
@@ -158,87 +160,167 @@ const StationSpec *GetCustomStationSpec(StationClassID sclass, uint station)
return NULL;
}
-static const RealSpriteGroup *ResolveStationSpriteGroup(const SpriteGroup *spg, const Station *st)
+
+/* Station Resolver Functions */
+static uint32 StationGetRandomBits(const ResolverObject *object)
{
- if (spg == NULL) return NULL;
- switch (spg->type) {
- case SGT_REAL:
- return &spg->g.real;
-
- case SGT_DETERMINISTIC: {
- const DeterministicSpriteGroup *dsg = &spg->g.determ;
- SpriteGroup *target;
- int value = -1;
- byte variable = dsg->adjusts[0].variable;
-
- if ((variable >> 6) == 0) {
- /* General property */
- value = GetDeterministicSpriteValue(variable);
- } else {
- if (st == NULL) {
- /* We are in a build dialog of something,
- * and we are checking for something undefined.
- * That means we should get the first target
- * (NOT the default one). */
- if (dsg->num_ranges > 0) {
- target = dsg->ranges[0].group;
- } else {
- target = dsg->default_group;
- }
- return ResolveStationSpriteGroup(target, NULL);
- }
-
- /* Station-specific property. */
- if (dsg->var_scope == VSG_SCOPE_PARENT) {
- /* TODO: Town structure. */
-
- } else /* VSG_SELF */ {
- if (variable == 0x40 || variable == 0x41) {
- /* FIXME: This is ad hoc only
- * for waypoints. */
- value = 0x01010000;
- } else {
- /* TODO: Only small fraction done. */
- // TTDPatch runs on little-endian arch;
- // Variable is 0x70 + offset in the TTD's station structure
- switch (variable - 0x70) {
- case 0x80: value = st->facilities; break;
- case 0x81: value = st->airport_type; break;
- case 0x82: value = st->truck_stops->status; break;
- case 0x83: value = st->bus_stops->status; break;
- case 0x86: value = st->airport_flags & 0xFFFF; break;
- case 0x87: value = st->airport_flags & 0xFF; break;
- case 0x8A: value = st->build_date; break;
- }
- }
- }
+ const Station *st = object->u.station.st;
+ const TileIndex tile = object->u.station.tile;
+ return (st == NULL ? 0 : st->random_bits) | (tile == INVALID_TILE ? 0 : GetStationTileRandomBits(tile) << 16);
+}
+
+
+static uint32 StationGetTriggers(const ResolverObject *object)
+{
+ const Station *st = object->u.station.st;
+ return st == NULL ? 0 : st->waiting_triggers;
+}
+
+
+static void StationSetTriggers(const ResolverObject *object, int triggers)
+{
+ Station *st = (Station*)object->u.station.st;
+ assert(st != NULL);
+ st->waiting_triggers = triggers;
+}
+
+
+static uint32 StationGetVariable(const ResolverObject *object, byte variable, byte parameter)
+{
+ const Station *st = object->u.station.st;
+
+ if (st == NULL) {
+ /* Station does not exist, so we're in a purchase list */
+ switch (variable) {
+ case 0x40:
+ case 0x41:
+ case 0x46:
+ case 0x47:
+ case 0x49: return 0x2110000; /* Platforms, tracks & position */
+ case 0x42: return 0; /* Rail type (XXX Get current type from GUI?) */
+ case 0x43: return _current_player; /* Station owner */
+ case 0xFA: return _date; /* Build date */
+ default: return -1;
+ }
+ }
+
+ switch (variable) {
+ /* Calculated station variables */
+ case 0x43: return st->owner; /* Station owner */
+ case 0x44: return 0; /* PBS status */
+ case 0x48: { /* Accepted cargo types */
+ CargoID cargo_type;
+ uint32 value = 0;
+
+ for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
+ if (HASBIT(st->goods[cargo_type].waiting_acceptance, 15)) SETBIT(value, cargo_type);
}
+ return value;
+ }
+
+ /* Variables which use the parameter */
+ case 0x60: return GB(st->goods[parameter].waiting_acceptance, 0, 12);
+ case 0x61: return st->goods[parameter].days_since_pickup;
+ case 0x62: return st->goods[parameter].rating;
+ case 0x63: return st->goods[parameter].enroute_time;
+ case 0x64: return st->goods[parameter].last_speed | (st->goods[parameter].last_age << 8);
+
+ /* General station properties */
+ case 0x82: return 50;
+ case 0x84: return st->string_id;
+ case 0x86: return 0;
+ case 0x9A: return st->had_vehicle_of_type;
+ case 0xF0: return st->facilities;
+ case 0xF1: return st->airport_type;
+ case 0xF2: return st->truck_stops->status;
+ case 0xF3: return st->bus_stops->status;
+ case 0xF6: return st->airport_flags;
+ case 0xF7: return st->airport_flags & 0xFF;
+ case 0xFA: return st->build_date;
+ }
- target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group;
- return ResolveStationSpriteGroup(target, st);
+ DEBUG(grf, 1)("Unhandled station property 0x%X", variable);
+
+ return -1;
+}
+
+
+static const SpriteGroup *StationResolveReal(const ResolverObject *object, const SpriteGroup *group)
+{
+ const Station *st = object->u.station.st;
+ const StationSpec *statspec = object->u.station.statspec;
+ uint set;
+
+ uint cargo = 0;
+ CargoID cargo_type = CT_INVALID; /* XXX Pick the correct cargo type */
+
+ if (st == NULL || statspec->sclass == STAT_CLASS_WAYP) {
+ return group->g.real.loading[0];
+ }
+
+ if (cargo_type == CT_INVALID) {
+ for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
+ cargo += GB(st->goods[cargo_type].waiting_acceptance, 0, 12);
}
+ } else {
+ cargo = GB(st->goods[cargo_type].waiting_acceptance, 0, 12);
+ }
+
+ if (HASBIT(statspec->flags, 1)) cargo /= (st->trainst_w + st->trainst_h);
+ cargo = min(0xfff, cargo);
- default:
- case SGT_RANDOMIZED:
- DEBUG(grf, 6)("I don't know how to handle random spritegroups yet!");
- return NULL;
+ if (cargo > statspec->cargo_threshold) {
+ if (group->g.real.num_loaded > 0) {
+ set = ((cargo - statspec->cargo_threshold) * group->g.real.num_loaded) / (0xfff - statspec->cargo_threshold);
+ return group->g.real.loaded[set];
+ }
+ } else {
+ if (group->g.real.num_loading > 0) {
+ set = (cargo * group->g.real.num_loading) / statspec->cargo_threshold;
+ return group->g.real.loading[set];
+ }
}
+
+ return group->g.real.loading[0];
+}
+
+
+static void NewStationResolver(ResolverObject *res, const StationSpec *statspec, const Station *st, TileIndex tile)
+{
+ res->GetRandomBits = StationGetRandomBits;
+ res->GetTriggers = StationGetTriggers;
+ res->SetTriggers = StationSetTriggers;
+ res->GetVariable = StationGetVariable;
+ res->ResolveReal = StationResolveReal;
+
+ res->u.station.st = st;
+ res->u.station.statspec = statspec;
+ res->u.station.tile = tile;
+
+ res->callback = 0;
+ res->callback_param1 = 0;
+ res->callback_param2 = 0;
+ res->last_value = 0;
+ res->trigger = 0;
+ res->reseed = 0;
}
-SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *st, TileIndex tile, byte ctype)
+
+SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *st, TileIndex tile, CargoID ctype)
{
- const RealSpriteGroup *rsg = ResolveStationSpriteGroup(statspec->spritegroup[ctype], st);
- if (rsg == NULL) return 0;
-
- if (rsg->num_loading != 0) return rsg->loading[0]->g.result.sprite;
- if (rsg->num_loaded != 0) return rsg->loaded[0]->g.result.sprite;
-
- DEBUG(grf, 6)("Custom station 0x%08x::0x%02x has no sprites associated.",
- statspec->grfid, statspec->localidx);
- /* This is what gets subscribed of dtss->image in newgrf.c,
- * so it's probably kinda "default offset". Try to use it as
- * emergency measure. */
- return 0;
+ const SpriteGroup *group;
+ ResolverObject object;
+
+ NewStationResolver(&object, statspec, st, tile);
+
+ group = Resolve(statspec->spritegroup[ctype], &object);
+ if ((group == NULL || group->type != SGT_RESULT) && ctype != GC_DEFAULT) {
+ group = Resolve(statspec->spritegroup[GC_DEFAULT], &object);
+ }
+
+ if (group == NULL || group->type != SGT_RESULT) return 0;
+
+ return group->g.result.sprite;
}
diff --git a/newgrf_station.h b/newgrf_station.h
index 22dcdd2fb..6680334ac 100644
--- a/newgrf_station.h
+++ b/newgrf_station.h
@@ -98,7 +98,7 @@ const StationSpec *GetCustomStationSpec(StationClassID sclass, uint station);
/* Get sprite offset for a given custom station and station structure (may be
* NULL if ctype is set - that means we are in a build dialog). The station
* structure is used for variational sprite groups. */
-SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *st, TileIndex tile, byte ctype);
+SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *st, TileIndex tile, CargoID ctype);
/* Allocate a StationSpec to a Station. This is called once per build operation. */
int AllocateSpecToStation(const StationSpec *statspec, Station *st, bool exec);