Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/items/StarMaterialItem.cpp
diff options
context:
space:
mode:
authorchililisoup <rebot333gaming@gmail.com>2025-03-20 15:48:46 -0600
committerchililisoup <rebot333gaming@gmail.com>2025-03-20 15:48:46 -0600
commit3130381b1c23e42af6fc14e9de951638f5c275b1 (patch)
tree7a0b7696ad29d594a84d76f3a190a26ffed65ba1 /source/game/items/StarMaterialItem.cpp
parent3f761123e939ece5c8805c165dc625756b950f8b (diff)
block swapping
Diffstat (limited to 'source/game/items/StarMaterialItem.cpp')
-rw-r--r--source/game/items/StarMaterialItem.cpp101
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 {