(svn r610) -newgrf: Support for some basic deterministical spritegroups regarding stations. Waypoints look changes based on year now :^) (pasky).
authordarkvater
Sun, 14 Nov 2004 20:50:38 +0000
changeset 413 36f14a6d63d7
parent 412 3b10a6e44e7e
child 414 4629d4bf7f14
(svn r610) -newgrf: Support for some basic deterministical spritegroups regarding stations. Waypoints look changes based on year now :^) (pasky).
Jamfile.next
Makefile
grfspecial.c
rail_cmd.c
sprite.c
sprite.h
station_cmd.c
ttd.vcproj
--- a/Jamfile.next	Sun Nov 14 20:25:07 2004 +0000
+++ b/Jamfile.next	Sun Nov 14 20:50:38 2004 +0000
@@ -13,7 +13,7 @@
 	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;
--- a/Makefile	Sun Nov 14 20:25:07 2004 +0000
+++ b/Makefile	Sun Nov 14 20:50:38 2004 +0000
@@ -504,7 +504,7 @@
 	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 \
--- a/grfspecial.c	Sun Nov 14 20:25:07 2004 +0000
+++ b/grfspecial.c	Sun Nov 14 20:50:38 2004 +0000
@@ -1112,8 +1112,8 @@
 			/* 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));
--- a/rail_cmd.c	Sun Nov 14 20:25:07 2004 +0000
+++ b/rail_cmd.c	Sun Nov 14 20:50:38 2004 +0000
@@ -744,6 +744,7 @@
 
 		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 @@
 	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 @@
 				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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sprite.c	Sun Nov 14 20:50:38 2004 +0000
@@ -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;
+	}
+}
--- a/sprite.h	Sun Nov 14 20:25:07 2004 +0000
+++ b/sprite.h	Sun Nov 14 20:50:38 2004 +0000
@@ -76,7 +76,7 @@
 	
 	// 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 @@
 	} 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);
 
 
 
--- a/station_cmd.c	Sun Nov 14 20:25:07 2004 +0000
+++ b/station_cmd.c	Sun Nov 14 20:50:38 2004 +0000
@@ -1006,15 +1006,81 @@
 	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) {
--- a/ttd.vcproj	Sun Nov 14 20:25:07 2004 +0000
+++ b/ttd.vcproj	Sun Nov 14 20:50:38 2004 +0000
@@ -753,6 +753,9 @@
 				</FileConfiguration>
 			</File>
 			<File
+				RelativePath=".\sprite.c">
+			</File>
+			<File
 				RelativePath="spritecache.c">
 				<FileConfiguration
 					Name="Release|Win32">