From ec434b208e6e67f98f7795f1a9d6154df888c6b2 Mon Sep 17 00:00:00 2001 From: darkvater Date: Sun, 14 Nov 2004 20:50:38 +0000 Subject: (svn r610) -newgrf: Support for some basic deterministical spritegroups regarding stations. Waypoints look changes based on year now :^) (pasky). --- Jamfile.next | 2 +- Makefile | 2 +- grfspecial.c | 4 ++-- rail_cmd.c | 20 +++++++++++++++-- sprite.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ sprite.h | 14 ++++++++---- station_cmd.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- ttd.vcproj | 3 +++ 8 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 sprite.c 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 + +#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 @@ -752,6 +752,9 @@ BasicRuntimeChecks="3"/> + +