diff --git a/source/game/StarCollisionBlock.hpp b/source/game/StarCollisionBlock.hpp index 40234c9..7346fc6 100644 --- a/source/game/StarCollisionBlock.hpp +++ b/source/game/StarCollisionBlock.hpp @@ -18,6 +18,26 @@ enum class CollisionKind : uint8_t { Block }; +enum class TileCollisionOverride : uint8_t { + None, + Empty, + Platform, + Dynamic +}; + +inline CollisionKind collisionKindFromOverride(TileCollisionOverride const& over) { + switch (over) { + case TileCollisionOverride::Empty: + return CollisionKind::None; + case TileCollisionOverride::Platform: + return CollisionKind::Platform; + case TileCollisionOverride::Dynamic: + return CollisionKind::Dynamic; + default: + return CollisionKind::Null; + } +} + class CollisionSet { public: CollisionSet(); diff --git a/source/game/StarTileModification.cpp b/source/game/StarTileModification.cpp index a20ae1e..0bcb4dc 100644 --- a/source/game/StarTileModification.cpp +++ b/source/game/StarTileModification.cpp @@ -4,7 +4,17 @@ namespace Star { DataStream& operator>>(DataStream& ds, PlaceMaterial& tileMaterialPlacement) { - ds.read(tileMaterialPlacement.layer); + uint8_t layer; + ds.read(layer); + if (layer > 1) { + tileMaterialPlacement.layer = TileLayer::Foreground; + tileMaterialPlacement.collisionOverride = (TileCollisionOverride)(layer - 1); + } + else { + tileMaterialPlacement.layer = (TileLayer)layer; + tileMaterialPlacement.collisionOverride = TileCollisionOverride::None; + } + ds.read(tileMaterialPlacement.material); ds.read(tileMaterialPlacement.materialHueShift); @@ -12,7 +22,14 @@ DataStream& operator>>(DataStream& ds, PlaceMaterial& tileMaterialPlacement) { } DataStream& operator<<(DataStream& ds, PlaceMaterial const& tileMaterialPlacement) { - ds.write(tileMaterialPlacement.layer); + if (tileMaterialPlacement.collisionOverride != TileCollisionOverride::None + && tileMaterialPlacement.layer == TileLayer::Foreground) { + uint8_t layer = (uint8_t)tileMaterialPlacement.collisionOverride; + ds.write(++layer); + } + else + ds.write(tileMaterialPlacement.layer); + ds.write(tileMaterialPlacement.material); ds.write(tileMaterialPlacement.materialHueShift); diff --git a/source/game/StarTileModification.hpp b/source/game/StarTileModification.hpp index bd30386..311a529 100644 --- a/source/game/StarTileModification.hpp +++ b/source/game/StarTileModification.hpp @@ -4,16 +4,17 @@ #include "StarDataStream.hpp" #include "StarVariant.hpp" #include "StarGameTypes.hpp" +#include "StarCollisionBlock.hpp" namespace Star { struct PlaceMaterial { TileLayer layer; MaterialId material; - // If the material hue shift is not set it will get the natural hue shift for // the environment. Maybe materialHueShift; + TileCollisionOverride collisionOverride = TileCollisionOverride::None; }; DataStream& operator>>(DataStream& ds, PlaceMaterial& tileMaterialPlacement); DataStream& operator<<(DataStream& ds, PlaceMaterial const& tileMaterialPlacement); diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp index cfc0827..753cbd5 100644 --- a/source/game/StarWorldClient.cpp +++ b/source/game/StarWorldClient.cpp @@ -2224,7 +2224,10 @@ void WorldClient::informTilePrediction(Vec2I const& pos, TileModification const& if (placeMaterial->layer == TileLayer::Foreground) { p.foreground = placeMaterial->material; p.foregroundHueShift = placeMaterial->materialHueShift; - p.collision = Root::singleton().materialDatabase()->materialCollisionKind(placeMaterial->material); + if (placeMaterial->collisionOverride != TileCollisionOverride::None) + p.collision = collisionKindFromOverride(placeMaterial->collisionOverride); + else + p.collision = Root::singleton().materialDatabase()->materialCollisionKind(placeMaterial->material); dirtyCollision(RectI::withSize(pos, { 1, 1 })); } else { p.background = placeMaterial->material; diff --git a/source/game/StarWorldServer.cpp b/source/game/StarWorldServer.cpp index 492ea81..6579c91 100644 --- a/source/game/StarWorldServer.cpp +++ b/source/game/StarWorldServer.cpp @@ -1378,7 +1378,10 @@ TileModificationList WorldServer::doApplyTileModifications(TileModificationList tile->foregroundHueShift = m_worldTemplate->biomeMaterialHueShift(tile->blockBiomeIndex, placeMaterial->material); tile->foregroundColorVariant = DefaultMaterialColorVariant; - tile->updateCollision(materialDatabase->materialCollisionKind(tile->foreground)); + if (placeMaterial->collisionOverride != TileCollisionOverride::None) + tile->updateCollision(collisionKindFromOverride(placeMaterial->collisionOverride)); + else + tile->updateCollision(materialDatabase->materialCollisionKind(tile->foreground)); if (tile->foreground == EmptyMaterialId) { // Remove the foreground mod if removing the foreground. tile->foregroundMod = NoModId; diff --git a/source/game/scripting/StarWorldLuaBindings.cpp b/source/game/scripting/StarWorldLuaBindings.cpp index 4645eb7..e1c8822 100644 --- a/source/game/scripting/StarWorldLuaBindings.cpp +++ b/source/game/scripting/StarWorldLuaBindings.cpp @@ -1912,7 +1912,7 @@ namespace LuaBindings { } else if (layerName == "background") { layer = TileLayer::Background; } else { - throw StarException(strf("Unsupported damageTile layer {}", layerName)); + throw StarException(strf("Unsupported tile layer {}", layerName)); } unsigned harvestLevel = 999; @@ -1942,15 +1942,28 @@ namespace LuaBindings { PlaceMaterial placeMaterial; - auto layerName = arg2; - if (layerName == "foreground") { - placeMaterial.layer = TileLayer::Foreground; - } else if (layerName == "background") { - placeMaterial.layer = TileLayer::Background; - } else { - throw StarException(strf("Unsupported damageTile layer {}", layerName)); + std::string layerName = arg2.utf8(); + auto split = layerName.find_first_of('+'); + if (split != NPos) { + auto overrideName = layerName.substr(split + 1); + layerName = layerName.substr(0, split); + if (overrideName == "empty" || overrideName == "none") + placeMaterial.collisionOverride = TileCollisionOverride::Empty; + else if (overrideName == "dynamic" || overrideName == "block") + placeMaterial.collisionOverride = TileCollisionOverride::Dynamic; + else if (overrideName == "platform") + placeMaterial.collisionOverride = TileCollisionOverride::Platform; + else + throw StarException(strf("Unsupported collision override {}", overrideName)); } + if (layerName == "foreground") + placeMaterial.layer = TileLayer::Foreground; + else if (layerName == "background") + placeMaterial.layer = TileLayer::Background; + else + throw StarException(strf("Unsupported tile layer {}", layerName)); + auto materialName = arg3; auto materialDatabase = Root::singleton().materialDatabase(); if (!materialDatabase->materialNames().contains(materialName)) @@ -1976,7 +1989,7 @@ namespace LuaBindings { } else if (layerName == "background") { placeMod.layer = TileLayer::Background; } else { - throw StarException(strf("Unsupported damageTile layer {}", layerName)); + throw StarException(strf("Unsupported tile layer {}", layerName)); } auto modName = arg3;