# HG changeset patch # User peter1138 # Date 2007-05-06 18:14:33 # Node ID 63b4cb964287f037b708c92eb6c5261fc5b1b589 # Parent 0b46f6cf62fa567d75dc24c3306b38d4062d929c (svn r9797) -Feature: [NewGRF] Add action 1, 2 and 3 support for canals. diff --git a/projects/openttd.vcproj b/projects/openttd.vcproj --- a/projects/openttd.vcproj +++ b/projects/openttd.vcproj @@ -513,6 +513,9 @@ RelativePath=".\..\src\newgrf_callbacks.h"> + + + + + + @@ -1468,6 +1472,10 @@ > + + diff --git a/source.list b/source.list --- a/source.list +++ b/source.list @@ -138,6 +138,7 @@ network/network_server.h network/network_udp.h newgrf.h newgrf_callbacks.h +newgrf_canal.h newgrf_cargo.h newgrf_config.h newgrf_engine.h @@ -282,6 +283,7 @@ ai/trolly/trolly.cpp # NewGRF newgrf.cpp +newgrf_canal.cpp newgrf_cargo.cpp newgrf_config.cpp newgrf_engine.cpp diff --git a/src/newgrf.cpp b/src/newgrf.cpp --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -39,6 +39,7 @@ #include "table/town_land.h" #include "cargotype.h" #include "industry.h" +#include "newgrf_canal.h" /* TTDPatch extended GRF format codec * (c) Petr Baudis 2004 (GPL'd) @@ -2244,6 +2245,7 @@ static void NewSpriteGroup(byte *buf, in case GSF_SHIP: case GSF_AIRCRAFT: case GSF_STATION: + case GSF_CANAL: case GSF_CARGOS: { byte sprites = _cur_grffile->spriteset_numents; @@ -2513,6 +2515,30 @@ static void VehicleMapSpriteGroup(byte * } +static void CanalMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount) +{ + byte *bp = &buf[4 + idcount + cidcount * 3]; + uint16 groupid = grf_load_word(&bp); + + if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) { + grfmsg(1, "CanalMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.", + groupid, _cur_grffile->spritegroups_count); + return; + } + + for (uint i = 0; i < idcount; i++) { + CanalFeature cf = (CanalFeature)buf[3 + i]; + + if (cf >= CF_END) { + grfmsg(1, "CanalMapSpriteGroup: Canal subset %d out of range, skipping", cf); + continue; + } + + _canal_sg[cf] = _cur_grffile->spritegroups[groupid]; + } +} + + static void StationMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount) { for (uint i = 0; i < idcount; i++) { @@ -2661,6 +2687,10 @@ static void FeatureMapSpriteGroup(byte * VehicleMapSpriteGroup(buf, feature, idcount, cidcount, wagover); return; + case GSF_CANAL: + CanalMapSpriteGroup(buf, idcount, cidcount); + return; + case GSF_STATION: StationMapSpriteGroup(buf, idcount, cidcount); return; @@ -4315,6 +4345,9 @@ static void ResetNewGRFData() ResetStationClasses(); ResetCustomStations(); + /* Reset canal sprite groups */ + memset(_canal_sg, 0, sizeof(_canal_sg)); + /* Reset the snowline table. */ ClearSnowLine(); diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp new file mode 100644 --- /dev/null +++ b/src/newgrf_canal.cpp @@ -0,0 +1,96 @@ +/* $Id$ */ + +#include "stdafx.h" +#include "openttd.h" +#include "variables.h" +#include "landscape.h" +#include "debug.h" +#include "newgrf.h" +#include "newgrf_callbacks.h" +#include "newgrf_spritegroup.h" +#include "newgrf_canal.h" + + +/** Table of canal 'feature' sprite groups */ +const SpriteGroup *_canal_sg[CF_END]; + + +/* Random bits and triggers are not supported for canals, so the following + * three functions are stubs. */ +static uint32 CanalGetRandomBits(const ResolverObject *object) +{ + return 0; +} + + +static uint32 CanalGetTriggers(const ResolverObject *object) +{ + return 0; +} + + +static void CanalSetTriggers(const ResolverObject *object, int triggers) +{ + return; +} + + +static uint32 CanalGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) +{ + TileIndex tile = object->u.canal.tile; + + switch (variable) { + case 0x80: + return TileHeight(tile); + + case 0x81: + return ((_opt.landscape == LT_ARCTIC && GetTileZ(tile) > GetSnowLine()) ? 4 : 0) | + (_opt.landscape == LT_TROPIC ? GetTropicZone(tile) : 0); + } + + DEBUG(grf, 1, "Unhandled canal property 0x%02X", variable); + + *available = false; + return 0; +} + + +static const SpriteGroup *CanalResolveReal(const ResolverObject *object, const SpriteGroup *group) +{ + if (group->g.real.num_loaded == 0) return NULL; + + return group->g.real.loaded[0]; +} + + +static void NewCanalResolver(ResolverObject *res, TileIndex tile) +{ + res->GetRandomBits = &CanalGetRandomBits; + res->GetTriggers = &CanalGetTriggers; + res->SetTriggers = &CanalSetTriggers; + res->GetVariable = &CanalGetVariable; + res->ResolveReal = &CanalResolveReal; + + res->u.canal.tile = tile; + + res->callback = 0; + res->callback_param1 = 0; + res->callback_param2 = 0; + res->last_value = 0; + res->trigger = 0; + res->reseed = 0; +} + + +SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile) +{ + ResolverObject object; + const SpriteGroup *group; + + NewCanalResolver(&object, tile); + + group = Resolve(_canal_sg[feature], &object); + if (group == NULL || group->type != SGT_RESULT) return 0; + + return group->g.result.sprite; +} diff --git a/src/newgrf_canal.h b/src/newgrf_canal.h new file mode 100644 --- /dev/null +++ b/src/newgrf_canal.h @@ -0,0 +1,29 @@ +/* $Id$ */ + +#ifndef NEWGRF_CANAL_H +#define NEWGRF_CANAL_H + +/** List of different canal 'features'. + * Each feature gets an entry in the canal spritegroup table */ +enum CanalFeature { + CF_WATERSLOPE, + CF_LOCKS, + CF_DIKES, + CF_ICON, + CF_DOCKS, + CF_END, +}; + + +/** Table of canal 'feature' sprite groups */ +extern const SpriteGroup *_canal_sg[CF_END]; + + +/** Lookup the base sprite to use for a canal. + * @param feature Which canal feature we want. + * @param tile Tile index of canal, if appropriate. + * @return Base sprite returned by GRF, or 0 if none. + */ +SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile); + +#endif /* NEWGRF_CANAL_H */ diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -184,6 +184,9 @@ struct ResolverObject { } vehicle; struct { TileIndex tile; + } canal; + struct { + TileIndex tile; const struct Station *st; const struct StationSpec *statspec; CargoID cargo_type; diff --git a/src/table/water_land.h b/src/table/water_land.h --- a/src/table/water_land.h +++ b/src/table/water_land.h @@ -47,86 +47,86 @@ static const WaterDrawTileStruct* const }; static const WaterDrawTileStruct _shiplift_display_seq_0[] = { - BEGIN(SPR_CANALS_BASE + 6), - { 0, 0, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 0 + 1 }, - { 0, 0xF, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 4 + 1 }, + BEGIN(1), + { 0, 0, 0, 0x10, 1, 0x14, 0 + 1 }, + { 0, 0xF, 0, 0x10, 1, 0x14, 4 + 1 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_1[] = { - BEGIN(SPR_CANALS_BASE + 5), - { 0, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 0 }, - { 0xF, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 4 }, + BEGIN(0), + { 0, 0, 0, 1, 0x10, 0x14, 0 }, + { 0xF, 0, 0, 1, 0x10, 0x14, 4 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_2[] = { - BEGIN(SPR_CANALS_BASE + 7), - { 0, 0, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 0 + 2 }, - { 0, 0xF, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 4 + 2 }, + BEGIN(2), + { 0, 0, 0, 0x10, 1, 0x14, 0 + 2 }, + { 0, 0xF, 0, 0x10, 1, 0x14, 4 + 2 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_3[] = { - BEGIN(SPR_CANALS_BASE + 8), - { 0, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 0 + 3 }, - { 0xF, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 4 + 3 }, + BEGIN(3), + { 0, 0, 0, 1, 0x10, 0x14, 0 + 3 }, + { 0xF, 0, 0, 1, 0x10, 0x14, 4 + 3 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_0b[] = { BEGIN(0xFDD), - { 0, 0, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 8 + 1 }, - { 0, 0xF, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 12 + 1 }, + { 0, 0, 0, 0x10, 1, 0x14, 8 + 1 }, + { 0, 0xF, 0, 0x10, 1, 0x14, 12 + 1 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_1b[] = { BEGIN(0xFDD), - { 0, 0, 0, 0x1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 8 }, - { 0xF, 0, 0, 0x1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 12 }, + { 0, 0, 0, 0x1, 0x10, 0x14, 8 }, + { 0xF, 0, 0, 0x1, 0x10, 0x14, 12 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_2b[] = { BEGIN(0xFDD), - { 0, 0, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 8 + 2 }, - { 0, 0xF, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 12 + 2 }, + { 0, 0, 0, 0x10, 1, 0x14, 8 + 2 }, + { 0, 0xF, 0, 0x10, 1, 0x14, 12 + 2 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_3b[] = { BEGIN(0xFDD), - { 0, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 8 + 3 }, - { 0xF, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 12 + 3 }, + { 0, 0, 0, 1, 0x10, 0x14, 8 + 3 }, + { 0xF, 0, 0, 1, 0x10, 0x14, 12 + 3 }, END(0) }; static const WaterDrawTileStruct _shiplift_display_seq_0t[] = { BEGIN(0xFDD), - { 0, 0, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 16 + 1 }, - { 0, 0xF, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 20 + 1 }, + { 0, 0, 0, 0x10, 1, 0x14, 16 + 1 }, + { 0, 0xF, 0, 0x10, 1, 0x14, 20 + 1 }, END(8) }; static const WaterDrawTileStruct _shiplift_display_seq_1t[] = { BEGIN(0xFDD), - { 0, 0, 0, 0x1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 16 }, - { 0xF, 0, 0, 0x1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 20 }, + { 0, 0, 0, 0x1, 0x10, 0x14, 16 }, + { 0xF, 0, 0, 0x1, 0x10, 0x14, 20 }, END(8) }; static const WaterDrawTileStruct _shiplift_display_seq_2t[] = { BEGIN(0xFDD), - { 0, 0, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 16 + 2 }, - { 0, 0xF, 0, 0x10, 1, 0x14, SPR_CANALS_BASE + 9 + 20 + 2 }, + { 0, 0, 0, 0x10, 1, 0x14, 16 + 2 }, + { 0, 0xF, 0, 0x10, 1, 0x14, 20 + 2 }, END(8) }; static const WaterDrawTileStruct _shiplift_display_seq_3t[] = { BEGIN(0xFDD), - { 0, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 16 + 3 }, - { 0xF, 0, 0, 1, 0x10, 0x14, SPR_CANALS_BASE + 9 + 20 + 3 }, + { 0, 0, 0, 1, 0x10, 0x14, 16 + 3 }, + { 0xF, 0, 0, 1, 0x10, 0x14, 20 + 3 }, END(8) }; diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -25,6 +25,7 @@ #include "train.h" #include "water_map.h" #include "newgrf.h" +#include "newgrf_canal.h" static const SpriteID _water_shore_sprites[] = { 0, @@ -373,39 +374,43 @@ void DrawCanalWater(TileIndex tile) { uint wa; + /* Test for custom graphics, else use the default */ + SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile); + if (dikes_base == 0) dikes_base = SPR_CANALS_BASE + 57; + /* determine the edges around with water. */ wa = IsWateredTile(TILE_ADDXY(tile, -1, 0)) << 0; wa += IsWateredTile(TILE_ADDXY(tile, 0, 1)) << 1; wa += IsWateredTile(TILE_ADDXY(tile, 1, 0)) << 2; wa += IsWateredTile(TILE_ADDXY(tile, 0, -1)) << 3; - if (!(wa & 1)) DrawGroundSprite(SPR_CANALS_BASE + 57, PAL_NONE); - if (!(wa & 2)) DrawGroundSprite(SPR_CANALS_BASE + 58, PAL_NONE); - if (!(wa & 4)) DrawGroundSprite(SPR_CANALS_BASE + 59, PAL_NONE); - if (!(wa & 8)) DrawGroundSprite(SPR_CANALS_BASE + 60, PAL_NONE); + if (!(wa & 1)) DrawGroundSprite(dikes_base, PAL_NONE); + if (!(wa & 2)) DrawGroundSprite(dikes_base + 1, PAL_NONE); + if (!(wa & 4)) DrawGroundSprite(dikes_base + 2, PAL_NONE); + if (!(wa & 8)) DrawGroundSprite(dikes_base + 3, PAL_NONE); /* right corner */ switch (wa & 0x03) { - case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 4, PAL_NONE); break; - case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 8, PAL_NONE); break; + case 0: DrawGroundSprite(dikes_base + 4, PAL_NONE); break; + case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(dikes_base + 8, PAL_NONE); break; } /* bottom corner */ switch (wa & 0x06) { - case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 5, PAL_NONE); break; - case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 9, PAL_NONE); break; + case 0: DrawGroundSprite(dikes_base + 5, PAL_NONE); break; + case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(dikes_base + 9, PAL_NONE); break; } /* left corner */ switch (wa & 0x0C) { - case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 6, PAL_NONE); break; - case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 10, PAL_NONE); break; + case 0: DrawGroundSprite(dikes_base + 6, PAL_NONE); break; + case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(dikes_base + 10, PAL_NONE); break; } /* upper corner */ switch (wa & 0x09) { - case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 7, PAL_NONE); break; - case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 11, PAL_NONE); break; + case 0: DrawGroundSprite(dikes_base + 7, PAL_NONE); break; + case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(dikes_base + 11, PAL_NONE); break; } } @@ -421,12 +426,30 @@ static void DrawWaterStuff(const TileInf SpriteID palette, uint base ) { - DrawGroundSprite(wdts++->image, PAL_NONE); + SpriteID image; + SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile); + SpriteID locks_base = GetCanalSprite(CF_LOCKS, ti->tile); + + /* If no custom graphics, use defaults */ + if (water_base == 0) water_base = SPR_CANALS_BASE + 5; + if (locks_base == 0) { + locks_base = SPR_CANALS_BASE + 9; + } else { + /* If using custom graphics, ignore the variation on height */ + base = 0; + } + + image = wdts++->image; + if (image < 4) image += water_base; + DrawGroundSprite(image, PAL_NONE); for (; wdts->delta_x != 0x80; wdts++) { - SpriteID image = wdts->image + base; + SpriteID image = wdts->image; SpriteID pal; + if (image < 24) image += locks_base; + image += base; + if (HASBIT(_transparent_opt, TO_BUILDINGS)) { SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); pal = PALETTE_TO_TRANSPARENT;