diff options
author | chililisoup <rebot333gaming@gmail.com> | 2025-03-20 15:48:46 -0600 |
---|---|---|
committer | chililisoup <rebot333gaming@gmail.com> | 2025-03-20 15:48:46 -0600 |
commit | 3130381b1c23e42af6fc14e9de951638f5c275b1 (patch) | |
tree | 7a0b7696ad29d594a84d76f3a190a26ffed65ba1 /source/game/items/StarMaterialItem.cpp | |
parent | 3f761123e939ece5c8805c165dc625756b950f8b (diff) |
block swapping
Diffstat (limited to 'source/game/items/StarMaterialItem.cpp')
-rw-r--r-- | source/game/items/StarMaterialItem.cpp | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/source/game/items/StarMaterialItem.cpp b/source/game/items/StarMaterialItem.cpp index bd42bac..6d862ff 100644 --- a/source/game/items/StarMaterialItem.cpp +++ b/source/game/items/StarMaterialItem.cpp @@ -10,6 +10,7 @@ #include "StarInput.hpp" #include "StarTileDrawer.hpp" #include "StarPlayer.hpp" +#include "StarTools.hpp" namespace Star { @@ -17,6 +18,7 @@ constexpr int BlockRadiusLimit = 16; const String BlockRadiusPropertyKey = "building.blockRadius"; const String AltBlockRadiusPropertyKey = "building.altBlockRadius"; const String CollisionOverridePropertyKey = "building.collisionOverride"; +const String BlockSwapPropertyKey = "building.blockSwap"; MaterialItem::MaterialItem(Json const& config, String const& directory, Json const& settings) : Item(config, directory, settings), FireableItem(config), BeamItem(config) { @@ -42,6 +44,7 @@ MaterialItem::MaterialItem(Json const& config, String const& directory, Json con m_blockRadius = config.getFloat("blockRadius", defaultParameters.getFloat("blockRadius")); m_altBlockRadius = config.getFloat("altBlockRadius", defaultParameters.getFloat("altBlockRadius")); m_collisionOverride = TileCollisionOverrideNames.maybeLeft(config.getString("collisionOverride", "None")).value(TileCollisionOverride::None); + m_blockSwap = false; m_multiplace = config.getBool("allowMultiplace", BlockCollisionSet.contains(materialDatabase->materialCollisionKind(m_material))); m_placeSounds = jsonToStringList(config.get("placeSounds", JsonArray())); @@ -114,6 +117,13 @@ void MaterialItem::update(float dt, FireMode fireMode, bool shifting, HashSet<Mo player->setSecretProperty(BlockRadiusPropertyKey, m_blockRadius); owner()->addSound("/sfx/tools/buildradiusshrink.wav", 1.0f, 1.0f + m_blockRadius / BlockRadiusLimit); } + + if (auto presses = input.bindDown("opensb", "blockSwapToggle")) { + if (*presses % 2 != 0) + m_blockSwap = !m_blockSwap; + player->setSecretProperty(BlockSwapPropertyKey, m_blockSwap); + owner()->addSound(m_blockSwap ? "/sfx/interface/button/click.wav" : "/sfx/interface/button/release.wav", 1.0f, Random::randf(0.9f, 1.1f)); + } } else updatePropertiesFromPlayer(player); @@ -190,6 +200,9 @@ void MaterialItem::fire(FireMode mode, bool shifting, bool edgeTriggered) { ? collisionKindFromOverride(m_collisionOverride) : Root::singleton().materialDatabase()->materialCollisionKind(m_material); + if (m_blockSwap && owner()->inToolRange(aimPosition)) + blockSwap(radius, layer); + size_t total = 0; for (unsigned i = 0; i != steps; ++i) { auto placementOrigin = aimPosition + diff * (1.0f - (static_cast<float>(i) / steps)); @@ -223,6 +236,90 @@ void MaterialItem::endFire(FireMode, bool) { m_lastAimPosition.reset(); } +void MaterialItem::blockSwap(float radius, TileLayer layer) { + Player* player = as<Player>(owner()); + if (!player) + return; + + ItemPtr beamAxePtr = player->essentialItem(EssentialItem::BeamAxe); + if (!beamAxePtr) + return; + + Item* beamAxe = beamAxePtr.get(); + BeamMiningTool* tool = as<BeamMiningTool>(beamAxe); + if (!tool) + return; + + List<Vec2I> swapPositions; + for (Vec2I& pos : tileArea(radius, owner()->aimPosition())) { + if (!world()->isTileConnectable(pos, layer, true)) + continue; + if (world()->material(pos, layer) == materialId()) + continue; + swapPositions.append(pos); + } + + if (swapPositions.empty()) + return; + + auto materialDatabase = Root::singleton().materialDatabase(); + auto assets = Root::singleton().assets(); + String blockSound; + + for (auto pos : swapPositions) { + blockSound = materialDatabase->miningSound(world()->material(pos, layer), world()->mod(pos, layer)); + if (!blockSound.empty()) + break; + } + if (blockSound.empty()) { + for (auto pos : swapPositions) { + blockSound = materialDatabase->footstepSound(world()->material(pos, layer), world()->mod(pos, layer)); + if (!blockSound.empty() + && blockSound != assets->json("/client.config:defaultFootstepSound").toString()) + break; + } + } + + TileDamage damage; + damage.type = TileDamageType::Beamish; + damage.amount = beamAxe->instanceValue("tileDamage", 1.0f).toFloat(); + damage.harvestLevel = beamAxe->instanceValue("harvestLevel", 1).toUInt(); + + TileModificationList toSwap; + List<Vec2I> toDamage; + for (auto pos : swapPositions) { + if (world()->damageWouldDestroy(pos, layer, damage)) + toSwap.emplaceAppend(pos, PlaceMaterial{layer, materialId(), placementHueShift(pos), m_collisionOverride}); + else + toDamage.append(pos); + } + + if (toSwap.size() > count()) + toSwap.resize(count()); + if (toDamage.size() + toSwap.size() > count()) + toDamage.resize(count() - toSwap.size()); + + size_t failed = world()->replaceTiles(toSwap).size(); + if (failed < toSwap.size()) + consume(toSwap.size() - failed); + + auto damageResult = world()->damageTiles(toDamage, layer, owner()->position(), damage, owner()->entityId()); + + if (damageResult == TileDamageResult::None) + return; + + if (damageResult == TileDamageResult::Protected) { + blockSound = assets->json("/client.config:defaultDingSound").toString(); + } + + owner()->addSound( + Random::randValueFrom(jsonToStringList(beamAxe->instanceValue("strikeSounds"))), + assets->json("/sfx.config:miningToolVolume").toFloat() + ); + owner()->addSound(blockSound, assets->json("/sfx.config:miningBlockVolume").toFloat()); + setFireTimer(tool->windupTime() + tool->cooldownTime()); +} + MaterialId MaterialItem::materialId() const { return m_material; } @@ -280,6 +377,10 @@ void MaterialItem::updatePropertiesFromPlayer(Player* player) { auto collisionOverride = player->getSecretProperty(CollisionOverridePropertyKey); if (collisionOverride.isType(Json::Type::String)) m_collisionOverride = TileCollisionOverrideNames.maybeLeft(collisionOverride.toString()).value(TileCollisionOverride::None); + + auto blockSwap = player->getSecretProperty(BlockSwapPropertyKey); + if (blockSwap.isType(Json::Type::Bool)) + m_blockSwap = blockSwap.toBool(); } float MaterialItem::calcRadius(bool shifting) const { |