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

summaryrefslogtreecommitdiff
path: root/source/game/items/StarMaterialItem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/game/items/StarMaterialItem.cpp')
-rw-r--r--source/game/items/StarMaterialItem.cpp113
1 files changed, 79 insertions, 34 deletions
diff --git a/source/game/items/StarMaterialItem.cpp b/source/game/items/StarMaterialItem.cpp
index e7b83da..acfe805 100644
--- a/source/game/items/StarMaterialItem.cpp
+++ b/source/game/items/StarMaterialItem.cpp
@@ -7,6 +7,7 @@
#include "StarWorld.hpp"
#include "StarWorldClient.hpp"
#include "StarWorldTemplate.hpp"
+#include "StarInput.hpp"
namespace Star {
@@ -47,6 +48,8 @@ MaterialItem::MaterialItem(Json const& config, String const& directory, Json con
m_placeSounds.append(materialDatabase->defaultFootstepSound());
}
m_shifting = false;
+ m_lastTileAreaRadiusCache = 0.0f;
+ m_collisionOverride = TileCollisionOverride::None;
}
ItemPtr MaterialItem::clone() const {
@@ -56,7 +59,7 @@ ItemPtr MaterialItem::clone() const {
void MaterialItem::init(ToolUserEntity* owner, ToolHand hand) {
FireableItem::init(owner, hand);
BeamItem::init(owner, hand);
- owner->addSound(Random::randValueFrom(m_placeSounds), 0.8f, 2.0f);
+ owner->addSound(Random::randValueFrom(m_placeSounds), 1.0f, 2.0f);
}
void MaterialItem::uninit() {
@@ -71,6 +74,44 @@ void MaterialItem::update(float dt, FireMode fireMode, bool shifting, HashSet<Mo
else
setEnd(BeamItem::EndType::TileGroup);
m_shifting = shifting;
+
+ if (auto presses = Input::singleton().bindDown("opensb", "materialCycleCollision")) {
+ CollisionKind baseKind = Root::singleton().materialDatabase()->materialCollisionKind(m_material);
+ for (size_t i = 0; i != *presses; ++i) {
+ constexpr auto limit = (uint8_t)TileCollisionOverride::Block + 1;
+ while (true) {
+ m_collisionOverride = (TileCollisionOverride)(((uint8_t)m_collisionOverride + 1) % limit);
+ if (collisionKindFromOverride(m_collisionOverride) != baseKind)
+ break;
+ }
+ }
+ owner()->addSound("/sfx/tools/cyclematcollision.ogg", 1.0f, Random::randf(0.9f, 1.1f));
+ }
+}
+
+void MaterialItem::render(RenderCallback* renderCallback, EntityRenderLayer renderLayer) {
+ if (m_collisionOverride != TileCollisionOverride::None) {
+ float pulseLevel = 1.f - 0.3f * 0.5f * ((float)sin(2 * Constants::pi * 4.0 * Time::monotonicTime()) + 1.f);
+ Color color = Color::rgba(owner()->favoriteColor()).mix(Color::White);
+ color.setAlphaF(color.alphaF() * pulseLevel * 0.95f);
+ auto addIndicator = [&](String const& path) {
+ Vec2F basePosition = Vec2F(0.5f, 0.5f);
+ auto indicator = Drawable::makeImage(path, 1.0f / TilePixels, true, basePosition);
+ indicator.fullbright = true;
+ indicator.color = color;
+ for (auto& tilePos : tileArea(calcRadius(m_shifting))) {
+ indicator.position = basePosition + Vec2F(tilePos);
+ renderCallback->addDrawable(indicator, RenderLayerForegroundTile);
+ }
+ };
+
+ if (m_collisionOverride == TileCollisionOverride::Empty)
+ addIndicator("/interface/building/collisionempty.png");
+ else if (m_collisionOverride == TileCollisionOverride::Platform)
+ addIndicator("/interface/building/collisionplatform.png");
+ else if (m_collisionOverride == TileCollisionOverride::Block)
+ addIndicator("/interface/building/collisionblock.png");
+ }
}
List<Drawable> MaterialItem::nonRotatedDrawables() const {
@@ -84,18 +125,12 @@ void MaterialItem::fire(FireMode mode, bool shifting, bool edgeTriggered) {
auto layer = (mode == FireMode::Primary || !twoHanded() ? TileLayer::Foreground : TileLayer::Background);
TileModificationList modifications;
- float radius;
-
- if (!shifting)
- radius = m_blockRadius;
- else
- radius = m_altBlockRadius;
-
- if (!multiplaceEnabled())
- radius = 1;
+ float radius = calcRadius(shifting);
auto geo = world()->geometry();
auto aimPosition = owner()->aimPosition();
+ auto& tilePositions = tileArea(radius);
+
if (!m_lastAimPosition)
m_lastAimPosition = aimPosition;
@@ -106,7 +141,7 @@ void MaterialItem::fire(FireMode mode, bool shifting, bool edgeTriggered) {
float magnitude = diff.magnitude();
float limit = max(4.f, 64.f / radius);
if (magnitude > limit) {
- m_lastAimPosition = aimPosition + diff.normalized() * limit;
+ diff = diff.normalized() * limit;
magnitude = limit;
}
@@ -116,8 +151,8 @@ void MaterialItem::fire(FireMode mode, bool shifting, bool edgeTriggered) {
size_t total = 0;
for (int i = 0; i != steps; ++i) {
auto placementOrigin = aimPosition + diff * (1.0f - ((float)i / steps));
- for (Vec2I pos : tileAreaBrush(radius, placementOrigin, true))
- modifications.append({ pos, PlaceMaterial{layer, materialId(), placementHueShift(pos)} });
+ for (Vec2I& pos : tilePositions)
+ modifications.append({ pos, PlaceMaterial{layer, materialId(), placementHueShift(pos), m_collisionOverride} });
// Make sure not to make any more modifications than we have consumables.
if (modifications.size() > count())
@@ -147,6 +182,22 @@ MaterialId MaterialItem::materialId() const {
return m_material;
}
+float MaterialItem::calcRadius(bool shifting) const {
+ if (!multiplaceEnabled())
+ return 1;
+ else
+ return !shifting ? m_blockRadius : m_altBlockRadius;
+}
+
+List<Vec2I>& MaterialItem::tileArea(float radius) const {
+ auto aimPosition = owner()->aimPosition();
+ if (!m_lastAimPosition || *m_lastAimPosition != aimPosition || m_lastTileAreaRadiusCache != radius) {
+ m_lastTileAreaRadiusCache = radius;
+ m_tileAreasCache = tileAreaBrush(radius, owner()->aimPosition(), true);
+ }
+ return m_tileAreasCache;
+}
+
MaterialHue MaterialItem::materialHueShift() const {
return m_materialHueShift;
}
@@ -155,16 +206,9 @@ bool MaterialItem::canPlace(bool shifting) const {
if (initialized()) {
MaterialId material = materialId();
- float radius;
- if (!shifting)
- radius = m_blockRadius;
- else
- radius = m_altBlockRadius;
-
- if (!multiplaceEnabled())
- radius = 1;
+ float radius = calcRadius(shifting);
- for (auto pos : tileAreaBrush(radius, owner()->aimPosition(), true)) {
+ for (auto& pos : tileArea(radius)) {
MaterialHue hueShift = placementHueShift(pos);
if (world()->canModifyTile(pos, PlaceMaterial{TileLayer::Foreground, material, hueShift}, false)
|| world()->canModifyTile(pos, PlaceMaterial{TileLayer::Background, material, hueShift}, false))
@@ -178,6 +222,18 @@ bool MaterialItem::multiplaceEnabled() const {
return m_multiplace && count() > 1;
}
+float& MaterialItem::blockRadius() {
+ return m_blockRadius;
+}
+
+float& MaterialItem::altBlockRadius() {
+ return m_altBlockRadius;
+}
+
+TileCollisionOverride& MaterialItem::collisionOverride() {
+ return m_collisionOverride;
+}
+
List<PreviewTile> MaterialItem::preview(bool shifting) const {
List<PreviewTile> result;
if (initialized()) {
@@ -187,19 +243,8 @@ List<PreviewTile> MaterialItem::preview(bool shifting) const {
auto material = materialId();
auto color = DefaultMaterialColorVariant;
- float radius;
-
- if (!shifting)
- radius = m_blockRadius;
- else
- radius = m_altBlockRadius;
-
- if (!multiplaceEnabled())
- radius = 1;
-
size_t c = 0;
-
- for (auto pos : tileAreaBrush(radius, owner()->aimPosition(), true)) {
+ for (auto& pos : tileArea(calcRadius(shifting))) {
MaterialHue hueShift = placementHueShift(pos);
if (c >= count())
break;