summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamfile.next2
-rw-r--r--Makefile2
-rw-r--r--grfspecial.c4
-rw-r--r--rail_cmd.c20
-rw-r--r--sprite.c62
-rw-r--r--sprite.h14
-rw-r--r--station_cmd.c72
-rw-r--r--ttd.vcproj3
8 files changed, 166 insertions, 13 deletions
diff --git a/Jamfile.next b/Jamfile.next
index 240b52fdc..1ffd777a5 100644
--- a/Jamfile.next
+++ b/Jamfile.next
@@ -13,7 +13,7 @@ CFILES = ai.c aircraft_cmd.c aircraft_gui.c airport_gui.c
train_cmd.c train_gui.c tree_cmd.c ttd.c
tunnelbridge_cmd.c unmovable_cmd.c vehicle.c
viewport.c water_cmd.c widget.c window.c screenshot.c
- airport.c grfspecial.c terraform_gui.c ;
+ airport.c grfspecial.c terraform_gui.c sprite.c ;
LANGFILES = english.txt swedish.txt french.txt german.txt italian.txt slovak.txt hungarian.txt norwegian.txt danish.txt czech.txt galician.txt polish.txt romanian.txt;
diff --git a/Makefile b/Makefile
index d0ba157d0..52356b888 100644
--- a/Makefile
+++ b/Makefile
@@ -504,7 +504,7 @@ ttd_SOURCES = \
pathfind.c player_gui.c players.c queue.c rail_cmd.c rail_gui.c rev.c \
road_cmd.c road_gui.c roadveh_cmd.c roadveh_gui.c saveload.c \
screenshot.c settings.c settings_gui.c ship_cmd.c ship_gui.c \
- smallmap_gui.c sound.c spritecache.c station_cmd.c station_gui.c \
+ smallmap_gui.c sound.c sprite.c spritecache.c station_cmd.c station_gui.c \
strings.c subsidy_gui.c terraform_gui.c texteff.c town_cmd.c \
town_gui.c train_cmd.c train_gui.c tree_cmd.c ttd.c tunnelbridge_cmd.c \
unmovable_cmd.c vehicle.c vehicle_gui.c viewport.c water_cmd.c widget.c window.c \
diff --git a/grfspecial.c b/grfspecial.c
index 3afda1d81..4498d26fe 100644
--- a/grfspecial.c
+++ b/grfspecial.c
@@ -1112,8 +1112,8 @@ static void NewSpriteGroup(byte *buf, int len)
/* XXX: If multiple surreal sets attach a surreal
* set this way, we are in trouble. */
dg->ranges[i].group = _cur_grffile->spritegroups[setid];
- dg->ranges[i].range_low = grf_load_byte(&buf);
- dg->ranges[i].range_high = grf_load_byte(&buf);
+ dg->ranges[i].low = grf_load_byte(&buf);
+ dg->ranges[i].high = grf_load_byte(&buf);
}
dg->default_group = malloc(sizeof(*dg->default_group));
diff --git a/rail_cmd.c b/rail_cmd.c
index 060e3da89..3c46b8798 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -744,6 +744,7 @@ int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2)
cp->deleted = 0;
cp->xy = tile;
+ cp->build_date = _date;
if (cp->town_or_string == 0) MakeDefaultWaypointName(cp); else RedrawWaypointSign(cp);
UpdateWaypointSign(cp);
@@ -1427,6 +1428,22 @@ static void DrawSpecialBuilding(uint32 image, uint32 tracktype_offs,
AddSortableSpriteToDraw(image, ti->x + x, ti->y + y, xsize, ysize, zsize, ti->z + z);
}
+/* This hacks together some dummy one-shot Station structure for a waypoint. */
+static Station *ComposeWaypointStation(uint tile)
+{
+ Waypoint *waypt = &_waypoints[GetWaypointByTile(tile)];
+ static Station stat;
+
+ stat.train_tile = stat.xy = waypt->xy;
+ /* FIXME - We should always keep town. */
+ stat.town = waypt->town_or_string & 0xC000 ? &_towns[waypt->town_or_string & 0xFF] : NULL;
+ stat.string_id = waypt->town_or_string & 0xC000 ? /* FIXME? */ 0 : waypt->town_or_string;
+ stat.build_date = waypt->build_date;
+ stat.class_id = 6; stat.stat_id = waypt->stat_id;
+
+ return &stat;
+}
+
static void DrawTile_Track(TileInfo *ti)
{
uint32 tracktype_offs, image;
@@ -1551,8 +1568,7 @@ static void DrawTile_Track(TileInfo *ti)
DrawTileSeqStruct const *seq;
// emulate station tile - open with building
DrawTileSprites *cust = &stat->renderdata[2 + (m5 & 0x1)];
- /* FIXME: NULL Station! --pasky */
- uint32 relocation = GetCustomStationRelocation(stat, NULL, 0);
+ uint32 relocation = GetCustomStationRelocation(stat, ComposeWaypointStation(ti->tile), 0);
image = cust->ground_sprite;
if (image & 0x8000) image = (image & 0x7FFF) + tracktype_offs;
diff --git a/sprite.c b/sprite.c
new file mode 100644
index 000000000..f0a130d4e
--- /dev/null
+++ b/sprite.c
@@ -0,0 +1,62 @@
+#include "stdafx.h"
+
+#include <stdarg.h>
+
+#include "ttd.h"
+#include "sprite.h"
+
+
+struct SpriteGroup *EvalDeterministicSpriteGroup(struct DeterministicSpriteGroup *dsg, int value)
+{
+ int i;
+
+ value >>= dsg->shift_num; // This should bring us to the byte range.
+ value &= dsg->and_mask;
+
+ if (dsg->operation != DSG_OP_NONE)
+ value += (signed char) dsg->add_val;
+
+ switch (dsg->operation) {
+ case DSG_OP_DIV:
+ value /= (signed char) dsg->divmod_val;
+ break;
+ case DSG_OP_MOD:
+ value %= (signed char) dsg->divmod_val;
+ break;
+ case DSG_OP_NONE:
+ break;
+ }
+
+ for (i = 0; i < dsg->num_ranges; i++) {
+ struct DeterministicSpriteGroupRange *range = &dsg->ranges[i];
+
+ if (range->low <= value && value <= range->high)
+ return &range->group;
+ }
+
+ return dsg->default_group;
+}
+
+int GetDeterministicSpriteValue(byte var)
+{
+ switch (var) {
+ case 0x00:
+ return _date;
+ case 0x01:
+ return _cur_year;
+ case 0x02:
+ return _cur_month;
+ case 0x03:
+ return _opt.landscape;
+ case 0x09:
+ return _date_fract;
+ case 0x0A:
+ return _tick_counter;
+ case 0x0C:
+ /* If we got here, it means there was no callback or
+ * callbacks aren't supported on our callpath. */
+ return 0;
+ default:
+ return -1;
+ }
+}
diff --git a/sprite.h b/sprite.h
index 13660a7d8..ded9ce6a8 100644
--- a/sprite.h
+++ b/sprite.h
@@ -76,7 +76,7 @@ struct DeterministicSpriteGroup {
// And apply it to this:
byte num_ranges;
- struct DeterministicSpriteGroupRanges *ranges; // Dynamically allocated
+ struct DeterministicSpriteGroupRange *ranges; // Dynamically allocated
// Dynamically allocated, this is the sole owner
struct SpriteGroup *default_group;
@@ -95,16 +95,22 @@ struct SpriteGroup {
} g;
};
-struct DeterministicSpriteGroupRanges {
+struct DeterministicSpriteGroupRange {
struct SpriteGroup group;
- byte range_low;
- byte range_high;
+ byte low;
+ byte high;
};
/* This is a temporary helper for SpriteGroup users not supporting variational
* sprite groups yet - it just traverses those cowardly, always taking the
* default choice until it hits a real sprite group, returning it. */
static struct RealSpriteGroup *TriviallyGetRSG(struct SpriteGroup *sg);
+/* This takes value (probably of the variable specified in the group) and
+ * chooses corresponding SpriteGroup accordingly to the given
+ * DeterministicSpriteGroup. */
+struct SpriteGroup *EvalDeterministicSpriteGroup(struct DeterministicSpriteGroup *dsg, int value);
+/* Get value of a common deterministic SpriteGroup variable. */
+int GetDeterministicSpriteValue(byte var);
diff --git a/station_cmd.c b/station_cmd.c
index da83d893e..d8181610a 100644
--- a/station_cmd.c
+++ b/station_cmd.c
@@ -1006,15 +1006,81 @@ struct StationSpec *GetCustomStation(uint32 classid, byte stid)
return &_waypoint_data[stid];
}
+static struct RealSpriteGroup *
+ResolveStationSpriteGroup(struct SpriteGroup *spritegroup, struct Station *stat)
+{
+ switch (spritegroup->type) {
+ case SGT_REAL:
+ return &spritegroup->g.real;
+
+ case SGT_DETERMINISTIC: {
+ struct DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
+ struct SpriteGroup *target;
+ int value = -1;
+
+ if ((dsg->variable >> 6) == 0) {
+ /* General property */
+ value = GetDeterministicSpriteValue(dsg->variable);
+
+ } else {
+ /* Station-specific property. */
+ if (dsg->var_scope == VSG_SCOPE_PARENT) {
+ /* TODO: Town structure. */
+
+ } else /* VSG_SELF */ {
+ if (dsg->variable == 0x40
+ || dsg->variable == 0x41) {
+ /* FIXME: This is ad hoc only
+ * for waypoints. */
+ value = 0x01010000;
+ } else {
+ /* TODO: Only small fraction done. */
+ // 0x80 + offset - 0x10
+ switch (dsg->variable - 0x70) {
+ case 0x80:
+ if (stat) value = stat->facilities;
+ break;
+ case 0x81:
+ if (stat) value = stat->airport_type;
+ break;
+ case 0x82:
+ if (stat) value = stat->truck_stop_status;
+ break;
+ case 0x83:
+ if (stat) value = stat->bus_stop_status;
+ break;
+ case 0x86:
+ if (stat) value = stat->airport_flags & 0xFFFF;
+ break;
+ case 0x87:
+ if (stat) value = (stat->airport_flags >> 8) & 0xFF;
+ break;
+ case 0x8A:
+ if (stat) value = stat->build_date;
+ break;
+ }
+ }
+ }
+ }
+
+ target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group;
+ return ResolveStationSpriteGroup(target, stat);
+ }
+
+ default:
+ case SGT_RANDOM:
+ error("I don't know how to handle random spritegroups yet!");
+ return NULL;
+ }
+}
+
uint32 GetCustomStationRelocation(struct StationSpec *spec, struct Station *stat, byte ctype)
{
struct RealSpriteGroup *rsg;
assert(spec->classid == 'WAYP');
- /* In the future, variational spritegroups will kick in through this
- * accessor, using @stat. */
- rsg = TriviallyGetRSG(&spec->spritegroup[ctype]);
+ rsg = ResolveStationSpriteGroup(&spec->spritegroup[ctype], stat);
if (rsg->sprites_per_set != 0) {
if (rsg->loading_count != 0) {
diff --git a/ttd.vcproj b/ttd.vcproj
index a6639e1bb..4c34ef4ae 100644
--- a/ttd.vcproj
+++ b/ttd.vcproj
@@ -753,6 +753,9 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\sprite.c">
+ </File>
+ <File
RelativePath="spritecache.c">
<FileConfiguration
Name="Release|Win32">