git repos / saland

commit ef2a612a

Poul Sander · 2026-05-09 10:58
ef2a612a737b2ec74588537d9656f607dc0d394a patch · browse files
parent bb79d939d88427e743f31e97d9b71355169e8854

Started to make the tile ids more generic

Changed files

M data/maps/desert.tmx before
M data/maps/sample_dungeon.tmx before
M data/maps/template_forrest.tmx before
M data/maps/template_forrest2.tmx before
M data/maps/template_start.tmx before
M data/saland/spells/base_spells.json before
M src/sagotmx/tmx_struct.h before
M src/saland/Game.cpp before
M src/saland/GameRegion.cpp before
M src/saland/GameRegion.hpp before
M src/saland/GameSpellState.cpp before
M src/saland/model/spells.cpp before
M src/saland/model/spells.hpp before
M src/terrain/WaterHandler.cpp before
M src/terrain/WaterHandler.hpp before
diff --git a/data/maps/desert.tmx b/data/maps/desert.tmx index a95218e..986240b 100644 --- a/data/maps/desert.tmx +++ b/data/maps/desert.tmx
@@ -2,6 +2,7 @@
<map version="1.2" tiledversion="1.3.2" orientation="orthogonal" renderorder="right-down" compressionlevel="0" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="12">
<tileset firstgid="1" source="terrain.tsx"/>
<tileset firstgid="1025" source="city_outside.tsx"/>
+ <tileset firstgid="2049" source="tiles_dungeon.tsx"/>
<layer id="1" name="ground_1" width="100" height="100">
<data encoding="base64" compression="zlib">
eAHt2DsOgCAQQMG9/y3kpGhHyErHJ2EKE8VC3TdaWCKi2MyAAQYYYIABBhhggAEGGGCAAQYYYIABBjYZeN7r9pt/lvv+2/YtsmN91vbJGmRruqzrks1/tKbN/Daj+f+d00WXmw2078U3h/Y42795Vic8uybzv1cndHYPOjPAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAAD5xmocwy5Ow==
diff --git a/data/maps/sample_dungeon.tmx b/data/maps/sample_dungeon.tmx index 9fc34f5..efb7fb8 100644 --- a/data/maps/sample_dungeon.tmx +++ b/data/maps/sample_dungeon.tmx
@@ -2,6 +2,7 @@
<map version="1.8" tiledversion="1.8.0" orientation="orthogonal" renderorder="right-down" compressionlevel="0" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="6" nextobjectid="13">
<tileset firstgid="1" source="terrain.tsx"/>
<tileset firstgid="1025" source="city_outside.tsx"/>
+ <tileset firstgid="2049" source="tiles_dungeon.tsx"/>
<layer id="1" name="ground_1" width="100" height="100">
<data encoding="base64" compression="zlib">
eAHt3TERAAAIA7HiFWv4RAYMGWqgl/0nyZgPGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhg4MBAl26CbgQDDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMDAPwMLiAQuiA==
diff --git a/data/maps/template_forrest.tmx b/data/maps/template_forrest.tmx index 5d2b790..7125fb9 100644 --- a/data/maps/template_forrest.tmx +++ b/data/maps/template_forrest.tmx
@@ -2,6 +2,7 @@
<map version="1.2" tiledversion="1.3.2" orientation="orthogonal" renderorder="right-down" compressionlevel="0" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="12">
<tileset firstgid="1" source="terrain.tsx"/>
<tileset firstgid="1025" source="city_outside.tsx"/>
+ <tileset firstgid="2049" source="tiles_dungeon.tsx"/>
<layer id="1" name="ground_1" width="100" height="100">
<data encoding="base64" compression="zlib">
eAHt2zEKACAIAEB7q/3/DfUAxwSDG1wcJOIGBc0VkcIfMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMXAObAw4YYIABBhhggIHvDVQ9XZVzY+zOmgEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBqYYsOPE4hSL3sEiAwwwwAADDDDAAAMMdBswAzPWbUx9xhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggIG3Bg4x3kMn
diff --git a/data/maps/template_forrest2.tmx b/data/maps/template_forrest2.tmx index e627692..56756f1 100644 --- a/data/maps/template_forrest2.tmx +++ b/data/maps/template_forrest2.tmx
@@ -2,6 +2,7 @@
<map version="1.4" tiledversion="1.4.2" orientation="orthogonal" renderorder="right-down" compressionlevel="0" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="7" nextobjectid="12">
<tileset firstgid="1" source="terrain.tsx"/>
<tileset firstgid="1025" source="city_outside.tsx"/>
+ <tileset firstgid="2049" source="tiles_dungeon.tsx"/>
<layer id="1" name="ground_1" width="100" height="100">
<data encoding="base64" compression="zlib">
eAHt2zEKACAIAEB7q/3/DfUAxwSDG1wcJOIGBc0VkcIfMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMXAObAw4YYIABBhhggIHvDVQ9XZVzY+zOmgEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBqYYsOPE4hSL3sEiAwwwwAADDDDAAAMMdBswAzPWbUx9xhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggIG3Bg4x3kMn
diff --git a/data/maps/template_start.tmx b/data/maps/template_start.tmx index 57f2dc6..fe182cf 100644 --- a/data/maps/template_start.tmx +++ b/data/maps/template_start.tmx
@@ -2,6 +2,7 @@
<map version="1.2" tiledversion="1.3.2" orientation="orthogonal" renderorder="right-down" compressionlevel="0" width="100" height="100" tilewidth="32" tileheight="32" infinite="0" nextlayerid="6" nextobjectid="13">
<tileset firstgid="1" source="terrain.tsx"/>
<tileset firstgid="1025" source="city_outside.tsx"/>
+ <tileset firstgid="2049" source="tiles_dungeon.tsx"/>
<layer id="1" name="ground_1" width="100" height="100">
<data encoding="base64" compression="zlib">
eAHt2zEKACAIAMB6TC+z/7+hHuCYYHBDi0OI3iJozDHCUwMGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggAEGGGCAAQYYYIABBhhggIFrYHPAAQMMMMAAAwww8L2BlfQwi7kxdmfNAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADXQzYZWexi0V5sMgAAwwwwAADDDDAAAPVBszAjFUb8z9jDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAAAMMMMAAAwwwwAADDDDAwFsDB/P6Qqk=
diff --git a/data/saland/spells/base_spells.json b/data/saland/spells/base_spells.json index cc323ec..9ad49cc 100644 --- a/data/saland/spells/base_spells.json +++ b/data/saland/spells/base_spells.json
@@ -21,24 +21,34 @@
}
,{
"name": "spell_create_block",
- "tile": 607,
+ "tile": 606,
+ "tileset": "terrain",
"type": "tile"
}
,{
"icon": "",
"name" : "spell_create_block",
- "tile" : 28,
+ "tile" : 27,
+ "tileset": "terrain",
"type" : "tile"
}
,{
"icon" : "",
"name" : "spell_create_block",
- "tile" : 16,
+ "tile" : 15,
+ "tileset": "terrain",
"type" : "tile"
}
,{
"name" : "spell_create_ground",
- "tile" : 1,
+ "tile" : 0,
+ "tileset": "terrain",
+ "type" : "tile"
+ }
+ ,{
+ "name" : "spell_create_dungeon",
+ "tile" : 0,
+ "tileset": "tiles_dungeon",
"type" : "tile"
}
,{
diff --git a/src/sagotmx/tmx_struct.h b/src/sagotmx/tmx_struct.h index 9dc3a56..99fb545 100644 --- a/src/sagotmx/tmx_struct.h +++ b/src/sagotmx/tmx_struct.h
@@ -695,6 +695,64 @@ inline void setTileOnLayerNumber(TileMap& m, int layer_number, int x, int y, uin
*dp = tile;
}
+/**
+ * Returns the firstgid of the tileset whose source filename (without path and extension)
+ * matches short_name. For example, pass "terrain" to find the tileset loaded from "terrain.tsx".
+ * Returns 0 and prints a warning if not found.
+ */
+inline uint32_t getFirstGidForTilesetSource(const TileMap& tm, const std::string& short_name) {
+ for (const auto& ts : tm.tileset) {
+ if (!ts.source.empty()) {
+ std::string basename = ts.source;
+ size_t slash = basename.find_last_of("/\\");
+ if (slash != std::string::npos) {
+ basename = basename.substr(slash + 1);
+ }
+ size_t dot = basename.rfind('.');
+ if (dot != std::string::npos) {
+ basename = basename.substr(0, dot);
+ }
+ if (basename == short_name) {
+ return static_cast<uint32_t>(ts.firstgid);
+ }
+ }
+ }
+ std::cerr << "Warning: tileset '" << short_name << "' not found in TileMap\n";
+ return 0;
+}
+
+/**
+ * Returns the number of tile columns in the tileset identified by short_name.
+ * Computed as image.width / tilewidth from the loaded tileset data.
+ * Returns 32 as fallback if not found or image data is unavailable.
+ */
+inline int getTilesetColumns(const TileMap& tm, const std::string& short_name) {
+ for (const auto& ts : tm.tileset) {
+ if (!ts.source.empty()) {
+ std::string basename = ts.source;
+ size_t slash = basename.find_last_of("/\\");
+ if (slash != std::string::npos) {
+ basename = basename.substr(slash + 1);
+ }
+ size_t dot = basename.rfind('.');
+ if (dot != std::string::npos) {
+ basename = basename.substr(0, dot);
+ }
+ if (basename == short_name) {
+ const TileSet* effective = &ts;
+ while (effective->alternativeSource) {
+ effective = effective->alternativeSource;
+ }
+ if (effective->tilewidth > 0 && effective->image.width > 0) {
+ return effective->image.width / effective->tilewidth;
+ }
+ return 32;
+ }
+ }
+ }
+ return 32;
+}
+
} //tiled
} //sago
diff --git a/src/saland/Game.cpp b/src/saland/Game.cpp index 377a000..6373280 100644 --- a/src/saland/Game.cpp +++ b/src/saland/Game.cpp
@@ -368,10 +368,10 @@ Game::Game() {
data->spell_holder->init();
data->spell_holder->slot_spell.at(0) = data->spell_holder->get_spell_by_name("spell_fireball");
data->spell_holder->slot_spell.at(1) = data->spell_holder->get_spell_by_name("weapon_slash_long_knife");
- data->spell_holder->slot_spell.at(2) = data->spell_holder->get_spell_by_name("spell_create_block:607");
- data->spell_holder->slot_spell.at(3) = data->spell_holder->get_spell_by_name("spell_create_block:28");
- data->spell_holder->slot_spell.at(4) = data->spell_holder->get_spell_by_name("spell_create_block:16");
- data->spell_holder->slot_spell.at(5) = data->spell_holder->get_spell_by_name("spell_create_ground:1");
+ data->spell_holder->slot_spell.at(2) = data->spell_holder->get_spell_by_name("spell_create_block:terrain:606");
+ data->spell_holder->slot_spell.at(3) = data->spell_holder->get_spell_by_name("spell_create_block:terrain:27");
+ data->spell_holder->slot_spell.at(4) = data->spell_holder->get_spell_by_name("spell_create_block:terrain:15");
+ data->spell_holder->slot_spell.at(5) = data->spell_holder->get_spell_by_name("spell_create_ground:terrain:0");
data->spell_holder->slot_spell.at(6) = data->spell_holder->get_spell_by_name("spell_spawn_item:food_potato");
data->spell_holder->slot_spell.at(7) = data->spell_holder->get_spell_by_name("spell_spawn_item:barrel");
data->spell_holder->slot_spell.at(8) = data->spell_holder->get_spell_by_name("spell_spawn_item:tree_palm");
@@ -1118,7 +1118,7 @@ void Game::Update() {
data->human->animation = "spellcast";
int base_tile_x = data->world_mouse_x/32;
int base_tile_y = data->world_mouse_y/32;
- int tile = data->spell_holder->slot_spell.at(data->spell_holder->slot_selected).tile;
+ uint32_t tile = resolveSpellTileGID(data->spell_holder->slot_spell.at(data->spell_holder->slot_selected), data->gameRegion.world.tm);
int layer_number = data->gameRegion.world.ground2Layer;
if (layer_number >= 0) {
for (int dy = 0; dy < data->brushSize; ++dy) {
@@ -1141,7 +1141,7 @@ void Game::Update() {
data->human->animation = "spellcast";
int base_tile_x = data->world_mouse_x/32;
int base_tile_y = data->world_mouse_y/32;
- int tile = data->spell_holder->slot_spell.at(data->spell_holder->slot_selected).tile;
+ uint32_t tile = resolveSpellTileGID(data->spell_holder->slot_spell.at(data->spell_holder->slot_selected), data->gameRegion.world.tm);
int layer_number = data->gameRegion.world.blockingLayer;
bool anyTileChanged = false;
for (int dy = 0; dy < data->brushSize; ++dy) {
@@ -1153,6 +1153,7 @@ void Game::Update() {
sago::tiled::setTileOnLayerNumber(data->gameRegion.world.tm, layer_number, tile_x, tile_y, tile);
data->gameRegion.liqudHandler["water"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
data->gameRegion.liqudHandler["lava"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
+ data->gameRegion.liqudHandler["dungeon"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
anyTileChanged = true;
}
}
@@ -1180,6 +1181,35 @@ void Game::Update() {
sago::tiled::setTileOnLayerNumber(data->gameRegion.world.tm, layer_number, tile_x, tile_y, tile);
data->gameRegion.liqudHandler["water"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
data->gameRegion.liqudHandler["lava"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
+ data->gameRegion.liqudHandler["dungeon"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
+ anyTileChanged = true;
+ }
+ }
+ }
+ if (anyTileChanged) {
+ data->gameRegion.world.init_physics(data->gameRegion.physicsBox);
+ }
+ }
+ }
+ if (data->spell_holder->slot_spell.at(data->spell_holder->slot_selected).name == "spell_create_dungeon") {
+ if (data->human->castTimeRemaining == 0) {
+ data->human->castTimeRemaining = data->human->castTime;
+ data->human->animation = "spellcast";
+ int base_tile_x = data->world_mouse_x/32;
+ int base_tile_y = data->world_mouse_y/32;
+ uint32_t tile = resolveSpellTileGID(data->spell_holder->slot_spell.at(data->spell_holder->slot_selected), data->gameRegion.world.tm);
+ int layer_number = data->gameRegion.world.blockingLayer;
+ bool anyTileChanged = false;
+ for (int dy = 0; dy < data->brushSize; ++dy) {
+ for (int dx = 0; dx < data->brushSize; ++dx) {
+ int tile_x = base_tile_x + dx;
+ int tile_y = base_tile_y + dy;
+ if (sago::tiled::tileInBound(data->gameRegion.world.tm, tile_x, tile_y)
+ && !(data->gameRegion.world.tile_protected(tile_x, tile_y)) ) {
+ sago::tiled::setTileOnLayerNumber(data->gameRegion.world.tm, layer_number, tile_x, tile_y, tile);
+ data->gameRegion.liqudHandler["dungeon"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
+ data->gameRegion.liqudHandler["water"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
+ data->gameRegion.liqudHandler["lava"].updateFirstTile(data->gameRegion.world.tm, tile_x, tile_y);
anyTileChanged = true;
}
}
diff --git a/src/saland/GameRegion.cpp b/src/saland/GameRegion.cpp index 7bf6624..9a2da40 100644 --- a/src/saland/GameRegion.cpp +++ b/src/saland/GameRegion.cpp
@@ -279,7 +279,7 @@ void GameRegion::CreateLake(World& world, int tile_x, int tile_y)
continue;
}
int layer_number = world.blockingLayer;
- uint32_t tile = 28;
+ uint32_t tile = liqudHandler["water"].default_tile;
sago::tiled::setTileOnLayerNumber(world.tm, layer_number, tile_x + i, tile_y + j, tile);
liqudHandler["water"].updateFirstTile(world.tm, tile_x + i, tile_y + j);
}
@@ -321,22 +321,42 @@ void GameRegion::InitCommon() {
placeables.clear();
physicsBox.reset(new b2World(b2Vec2(0.0f, 0.0f)));
world.managed_bodies.clear();
+}
+
+void GameRegion::InitLiquidHandlers() {
+ liqudHandler.clear();
+
+ uint32_t terrain_firstgid = sago::tiled::getFirstGidForTilesetSource(world.tm, "terrain");
+ if (terrain_firstgid == 0) {
+ terrain_firstgid = 1; // fallback for maps without a named terrain tileset
+ }
+ int terrain_cols = sago::tiled::getTilesetColumns(world.tm, "terrain");
liqudHandler["water"].blockingLayer = world.blockingLayer;
liqudHandler["water"].blockingLayer_overlay_1 = world.blockingLayer_overlay_1;
- liqudHandler["water"].setupTiles(28);
+ liqudHandler["water"].setupTiles(terrain_firstgid + 27, terrain_cols);
+
liqudHandler["lava"].blockingLayer = world.blockingLayer;
liqudHandler["lava"].blockingLayer_overlay_1 = world.blockingLayer_overlay_1;
- liqudHandler["lava"].setupTiles(16);
+ liqudHandler["lava"].setupTiles(terrain_firstgid + 15, terrain_cols);
+
liqudHandler["ground"].blockingLayer = world.ground2Layer;
liqudHandler["ground"].blockingLayer_overlay_1 = world.ground2OverlayLayer;
- liqudHandler["ground"].setupTiles(1);
-
+ liqudHandler["ground"].setupTiles(terrain_firstgid + 0, terrain_cols);
+
+ uint32_t dungeon_firstgid = sago::tiled::getFirstGidForTilesetSource(world.tm, "tiles_dungeon");
+ if (dungeon_firstgid > 0) {
+ int dungeon_cols = sago::tiled::getTilesetColumns(world.tm, "tiles_dungeon");
+ liqudHandler["dungeon"].blockingLayer = world.blockingLayer;
+ liqudHandler["dungeon"].blockingLayer_overlay_1 = world.blockingLayer_overlay_1;
+ liqudHandler["dungeon"].setupTiles(dungeon_firstgid, dungeon_cols);
+ }
}
void GameRegion::InitDungeon(const std::string& dungeonName, const std::string& dungeonType, bool forceResetWorld) {
InitCommon();
world.init(physicsBox, "maps/"+dungeonName+".tmx");
+ InitLiquidHandlers();
}
@@ -354,6 +374,7 @@ void GameRegion::Init(int x, int y, const std::string& worldName, bool forceRese
InitCommon();
ScanPrefabs("prefabs01");
world.init(physicsBox, loadMap);
+ InitLiquidHandlers();
const std::vector<sago::tiled::TileObjectGroup>& object_groups = world.tm.object_groups;
diff --git a/src/saland/GameRegion.hpp b/src/saland/GameRegion.hpp index 2d3a534..bcf2f66 100644 --- a/src/saland/GameRegion.hpp +++ b/src/saland/GameRegion.hpp
@@ -75,6 +75,7 @@ private:
int region_y = 0;
std::string mapFileName = "maps/sample1.tmx";
void InitCommon();
+ void InitLiquidHandlers();
};
#endif /* GAMEREGION_HPP */
diff --git a/src/saland/GameSpellState.cpp b/src/saland/GameSpellState.cpp index 654a7c8..283d785 100644 --- a/src/saland/GameSpellState.cpp +++ b/src/saland/GameSpellState.cpp
@@ -72,8 +72,12 @@ void GameSpellState::GameSpellState::Draw(SDL_Renderer* target) {
if (current_spell.icon.length() > 0) {
globalData.spriteHolder.get()->GetSprite(current_spell.icon).Draw(target, SDL_GetTicks(), 36+i*56, 36, resize);
}
- if (current_spell.tile > 0) {
- DrawTile(target, globalData.spriteHolder.get(), *tm, current_spell.tile, 20+i*BOX_SPACING, 20, resize);
+ bool hasTile = (current_spell.tile > 0) || (!current_spell.tileset_name.empty());
+ if (hasTile && tm != nullptr) {
+ uint32_t gid = resolveSpellTileGID(current_spell, *tm);
+ if (gid > 0) {
+ DrawTile(target, globalData.spriteHolder.get(), *tm, gid, 20+i*BOX_SPACING, 20, resize);
+ }
}
}
if (!data->spellSelectActive) {
@@ -87,8 +91,12 @@ void GameSpellState::GameSpellState::Draw(SDL_Renderer* target) {
if (current_spell.icon.length() > 0) {
globalData.spriteHolder.get()->GetSprite(current_spell.icon).Draw(target, SDL_GetTicks(), x+BOX_SIZE/2, y+BOX_SIZE/2, resize);
}
- if (current_spell.tile > 0) {
- DrawTile(target, globalData.spriteHolder.get(), *tm, current_spell.tile, x+10, y+10, resize);
+ bool hasTile = (current_spell.tile > 0) || (!current_spell.tileset_name.empty());
+ if (hasTile && tm != nullptr) {
+ uint32_t gid = resolveSpellTileGID(current_spell, *tm);
+ if (gid > 0) {
+ DrawTile(target, globalData.spriteHolder.get(), *tm, gid, x+10, y+10, resize);
+ }
}
}
}
diff --git a/src/saland/model/spells.cpp b/src/saland/model/spells.cpp index 256f452..cc993e9 100644 --- a/src/saland/model/spells.cpp +++ b/src/saland/model/spells.cpp
@@ -33,7 +33,9 @@ void SpellHolder::add_spell(const Spell& spell) {
if (spell.item_name[0]) {
name = name + ":" + spell.item_name;
}
- if (spell.tile) {
+ if (!spell.tileset_name.empty()) {
+ name = name + ":" + spell.tileset_name + ":" + std::to_string(spell.tile);
+ } else if (spell.tile) {
name = name + ":" + std::to_string(spell.tile);
}
spellIndex[name] = spells.size() - 1;
@@ -68,6 +70,9 @@ void SpellHolder::ReadSpellFile(const std::string& filename) {
if (member.name == "item_name") {
spell.item_name = member.value.GetString();
}
+ if (member.name == "tileset") {
+ spell.tileset_name = member.value.GetString();
+ }
if (member.name == "tile") {
spell.tile = member.value.GetInt64();
}
@@ -132,3 +137,14 @@ const Spell& SpellHolder::get_spell_by_name(const std::string& spell_name) const
const Spell& SpellHolder::get_spell_clear_tile() const {
return clearTileSpell;
}
+
+uint32_t resolveSpellTileGID(const Spell& spell, const sago::tiled::TileMap& tm) {
+ if (spell.tileset_name.empty()) {
+ return static_cast<uint32_t>(spell.tile);
+ }
+ uint32_t firstgid = sago::tiled::getFirstGidForTilesetSource(tm, spell.tileset_name);
+ if (firstgid == 0) {
+ return static_cast<uint32_t>(spell.tile);
+ }
+ return firstgid + static_cast<uint32_t>(spell.tile);
+}
diff --git a/src/saland/model/spells.hpp b/src/saland/model/spells.hpp index c112d2b..f8ec794 100644 --- a/src/saland/model/spells.hpp +++ b/src/saland/model/spells.hpp
@@ -28,6 +28,7 @@ https://github.com/sago007/saland
#include <vector>
#include <array>
#include <map>
+#include "../../sagotmx/tmx_struct.h"
enum class SpellCursorType { dot = 0, tile=1, shpere = 2 };
@@ -35,7 +36,8 @@ struct Spell {
std::string name;
std::string icon;
std::string item_name;
- int tile = 0; //Number reference to a tile, we might also need a tileset at some point
+ int tile = 0; //Local (0-indexed) tile offset within the named tileset, or raw GID when tileset_name is empty
+ std::string tileset_name; //Short name of the tileset source (e.g. "terrain", "tiles_dungeon"). Empty = raw GID in tile field.
SpellCursorType type = SpellCursorType::dot;
};
@@ -58,4 +60,10 @@ public:
void ReadSpellFile(const std::string& filename);
};
+/**
+ * Resolves the GID for a spell's tile. If tileset_name is set, returns firstgid + tile (local offset).
+ * If tileset_name is empty, returns tile directly as a raw GID (backward compatibility).
+ */
+uint32_t resolveSpellTileGID(const Spell& spell, const sago::tiled::TileMap& tm);
+
#endif //MODEL_SPELLS_HPP
diff --git a/src/terrain/WaterHandler.cpp b/src/terrain/WaterHandler.cpp index b395443..1196ecd 100644 --- a/src/terrain/WaterHandler.cpp +++ b/src/terrain/WaterHandler.cpp
@@ -29,9 +29,8 @@ WaterHandler::WaterHandler() {
setupTiles(default_tile);
}
-void WaterHandler::setupTiles(uint32_t start_tile) {
+void WaterHandler::setupTiles(uint32_t start_tile, int tile_count_width) {
default_tile = start_tile;
- int tile_count_width = 32;
tile_map["11111110"] = start_tile+1;
tile_map["11111011"] = start_tile+2;
tile_map["11011111"] = start_tile+tile_count_width+1;
@@ -53,10 +52,12 @@ void WaterHandler::setupTiles(uint32_t start_tile) {
tile_map["11111111b"] = start_tile+tile_count_width*5+1;
tile_map["11111111c"] = start_tile+tile_count_width*5+2;
- tiles = {start_tile, start_tile+1, start_tile+2, start_tile+33, start_tile+34,
- start_tile+35, start_tile+64, start_tile+65, start_tile+66, start_tile+96,
- start_tile+97, start_tile+98, start_tile+128, start_tile+129, start_tile+130,
- start_tile+160, start_tile+161, start_tile+162
+ tiles = {start_tile, start_tile+1, start_tile+2,
+ start_tile+tile_count_width+1, start_tile+tile_count_width+2, start_tile+tile_count_width+3,
+ start_tile+tile_count_width*2, start_tile+tile_count_width*2+1, start_tile+tile_count_width*2+2,
+ start_tile+tile_count_width*3, start_tile+tile_count_width*3+1, start_tile+tile_count_width*3+2,
+ start_tile+tile_count_width*4, start_tile+tile_count_width*4+1, start_tile+tile_count_width*4+2,
+ start_tile+tile_count_width*5, start_tile+tile_count_width*5+1, start_tile+tile_count_width*5+2
};
}
diff --git a/src/terrain/WaterHandler.hpp b/src/terrain/WaterHandler.hpp index 3780df6..aa798f9 100644 --- a/src/terrain/WaterHandler.hpp +++ b/src/terrain/WaterHandler.hpp
@@ -36,7 +36,7 @@ struct WaterHandler {
WaterHandler();
- void setupTiles(uint32_t start_tile);
+ void setupTiles(uint32_t start_tile, int tile_count_width = 32);
uint32_t getTile(sago::tiled::TileMap& tm, int x, int y, uint32_t& overlay_tile);