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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/opensb/binds/opensb.binds14
-rw-r--r--assets/opensb/interface/building/collisionblock.pngbin0 -> 219 bytes
-rw-r--r--assets/opensb/interface/building/collisionempty.pngbin0 -> 176 bytes
-rw-r--r--assets/opensb/interface/building/collisionplatform.pngbin0 -> 178 bytes
-rw-r--r--assets/opensb/sfx/tools/cyclematcollision.oggbin0 -> 4995 bytes
-rw-r--r--source/game/CMakeLists.txt1
-rw-r--r--source/game/StarCollisionBlock.hpp6
-rw-r--r--source/game/StarToolUser.cpp15
-rw-r--r--source/game/interfaces/StarRenderableItem.hpp19
-rw-r--r--source/game/items/StarMaterialItem.cpp113
-rw-r--r--source/game/items/StarMaterialItem.hpp18
-rw-r--r--source/game/scripting/StarWorldLuaBindings.cpp4
12 files changed, 134 insertions, 56 deletions
diff --git a/assets/opensb/binds/opensb.binds b/assets/opensb/binds/opensb.binds
index 2f84e37..43493e8 100644
--- a/assets/opensb/binds/opensb.binds
+++ b/assets/opensb/binds/opensb.binds
@@ -2,7 +2,8 @@
"opensb": {
"groups": {
"camera": { "name": "Camera" },
- "voice": { "name": "Voice" }
+ "voice": { "name": "Voice" },
+ "building": { "name": "Building" }
},
"name": "Open^#ebd74a;Starbound",
"binds": {
@@ -11,7 +12,7 @@
"type": "key",
"value": "="
}],
- "group" : "camera",
+ "group": "camera",
"name": "Zoom In"
},
"zoomOut": {
@@ -19,13 +20,18 @@
"type": "key",
"value": "-"
}],
- "group" : "camera",
+ "group": "camera",
"name": "Zoom Out"
},
"pushToTalk": {
"default": [],
- "group" : "voice",
+ "group": "voice",
"name": "Push To Talk"
+ },
+ "materialCycleCollision": {
+ "default": [],
+ "group": "building",
+ "name": "Cycle Material Collision"
}
}
}
diff --git a/assets/opensb/interface/building/collisionblock.png b/assets/opensb/interface/building/collisionblock.png
new file mode 100644
index 0000000..b1d5f9d
--- /dev/null
+++ b/assets/opensb/interface/building/collisionblock.png
Binary files differ
diff --git a/assets/opensb/interface/building/collisionempty.png b/assets/opensb/interface/building/collisionempty.png
new file mode 100644
index 0000000..6289ba1
--- /dev/null
+++ b/assets/opensb/interface/building/collisionempty.png
Binary files differ
diff --git a/assets/opensb/interface/building/collisionplatform.png b/assets/opensb/interface/building/collisionplatform.png
new file mode 100644
index 0000000..b8b2b65
--- /dev/null
+++ b/assets/opensb/interface/building/collisionplatform.png
Binary files differ
diff --git a/assets/opensb/sfx/tools/cyclematcollision.ogg b/assets/opensb/sfx/tools/cyclematcollision.ogg
new file mode 100644
index 0000000..3a35ee3
--- /dev/null
+++ b/assets/opensb/sfx/tools/cyclematcollision.ogg
Binary files differ
diff --git a/source/game/CMakeLists.txt b/source/game/CMakeLists.txt
index 120e9e8..c229000 100644
--- a/source/game/CMakeLists.txt
+++ b/source/game/CMakeLists.txt
@@ -196,6 +196,7 @@ SET (star_game_HEADERS
interfaces/StarPointableItem.hpp
interfaces/StarPortraitEntity.hpp
interfaces/StarPreviewableItem.hpp
+ interfaces/StarRenderableItem.hpp
interfaces/StarScriptedEntity.hpp
interfaces/StarStatusEffectEntity.hpp
interfaces/StarStatusEffectItem.hpp
diff --git a/source/game/StarCollisionBlock.hpp b/source/game/StarCollisionBlock.hpp
index 7346fc6..c37ccd0 100644
--- a/source/game/StarCollisionBlock.hpp
+++ b/source/game/StarCollisionBlock.hpp
@@ -22,7 +22,7 @@ enum class TileCollisionOverride : uint8_t {
None,
Empty,
Platform,
- Dynamic
+ Block
};
inline CollisionKind collisionKindFromOverride(TileCollisionOverride const& over) {
@@ -31,8 +31,8 @@ inline CollisionKind collisionKindFromOverride(TileCollisionOverride const& over
return CollisionKind::None;
case TileCollisionOverride::Platform:
return CollisionKind::Platform;
- case TileCollisionOverride::Dynamic:
- return CollisionKind::Dynamic;
+ case TileCollisionOverride::Block:
+ return CollisionKind::Block;
default:
return CollisionKind::Null;
}
diff --git a/source/game/StarToolUser.cpp b/source/game/StarToolUser.cpp
index e0e32a8..7208c6e 100644
--- a/source/game/StarToolUser.cpp
+++ b/source/game/StarToolUser.cpp
@@ -535,21 +535,16 @@ void ToolUser::render(RenderCallback* renderCallback, bool inToolRange, bool shi
return;
}
- // FIXME: Why isn't material item a PreviewTileTool, why is inToolRange
- // passed in again, what is the difference here between the owner's tool
- // range, can't MaterialItem figure this out?
- if (inToolRange) {
- if (auto materialItem = as<MaterialItem>(m_primaryHandItem.get()))
- renderCallback->addTilePreviews(materialItem->preview(shifting));
- else if (auto liquidItem = as<LiquidItem>(m_primaryHandItem.get()))
- renderCallback->addTilePreviews(liquidItem->preview(shifting));
- }
-
if (auto pri = as<PreviewTileTool>(m_primaryHandItem.get()))
renderCallback->addTilePreviews(pri->preview(shifting));
else if (auto alt = as<PreviewTileTool>(m_altHandItem.get()))
renderCallback->addTilePreviews(alt->preview(shifting));
+ if (auto ren = as<RenderableItem>(m_primaryHandItem.get()))
+ ren->render(renderCallback, renderLayer);
+ if (auto ren = as<RenderableItem>(m_altHandItem.get()))
+ ren->render(renderCallback, renderLayer);
+
for (auto item : {m_primaryHandItem.get(), m_altHandItem.get()}) {
if (auto activeItem = as<ActiveItem>(item)) {
for (auto drawablePair : activeItem->entityDrawables())
diff --git a/source/game/interfaces/StarRenderableItem.hpp b/source/game/interfaces/StarRenderableItem.hpp
new file mode 100644
index 0000000..9b02763
--- /dev/null
+++ b/source/game/interfaces/StarRenderableItem.hpp
@@ -0,0 +1,19 @@
+#ifndef STAR_RENDERABLE_ITEM_HPP
+#define STAR_RENDERABLE_ITEM_HPP
+
+#include "StarEntityRendering.hpp"
+
+namespace Star {
+
+ STAR_CLASS(RenderableItem);
+
+ class RenderableItem {
+ public:
+ virtual ~RenderableItem() {}
+
+ virtual void render(RenderCallback* renderCallback, EntityRenderLayer renderLayer) = 0;
+ };
+
+}
+
+#endif
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;
diff --git a/source/game/items/StarMaterialItem.hpp b/source/game/items/StarMaterialItem.hpp
index ca345eb..e5b1f01 100644
--- a/source/game/items/StarMaterialItem.hpp
+++ b/source/game/items/StarMaterialItem.hpp
@@ -5,12 +5,15 @@
#include "StarFireableItem.hpp"
#include "StarBeamItem.hpp"
#include "StarEntityRendering.hpp"
+#include "StarPreviewTileTool.hpp"
+#include "StarRenderableItem.hpp"
+#include "StarCollisionBlock.hpp"
namespace Star {
STAR_CLASS(MaterialItem);
-class MaterialItem : public Item, public FireableItem, public BeamItem {
+class MaterialItem : public Item, public FireableItem, public PreviewTileTool, public RenderableItem, public BeamItem {
public:
MaterialItem(Json const& config, String const& directory, Json const& settings);
virtual ~MaterialItem() {}
@@ -20,6 +23,7 @@ public:
void init(ToolUserEntity* owner, ToolHand hand) override;
void uninit() override;
void update(float dt, FireMode fireMode, bool shifting, HashSet<MoveControlType> const& moves) override;
+ void render(RenderCallback* renderCallback, EntityRenderLayer renderLayer) override;
List<Drawable> nonRotatedDrawables() const override;
@@ -32,10 +36,14 @@ public:
bool canPlace(bool shifting) const;
bool multiplaceEnabled() const;
- // FIXME: Why isn't this a PreviewTileTool then??
- List<PreviewTile> preview(bool shifting) const;
+ float& blockRadius();
+ float& altBlockRadius();
+ TileCollisionOverride& collisionOverride();
+ List<PreviewTile> preview(bool shifting) const override;
private:
+ float calcRadius(bool shifting) const;
+ List<Vec2I>& tileArea(float radius) const;
MaterialHue placementHueShift(Vec2I const& position) const;
MaterialId m_material;
@@ -47,6 +55,10 @@ private:
bool m_multiplace;
StringList m_placeSounds;
Maybe<Vec2F> m_lastAimPosition;
+ TileCollisionOverride m_collisionOverride;
+
+ mutable float m_lastTileAreaRadiusCache;
+ mutable List<Vec2I> m_tileAreasCache;
};
}
diff --git a/source/game/scripting/StarWorldLuaBindings.cpp b/source/game/scripting/StarWorldLuaBindings.cpp
index e1c8822..dc1c5be 100644
--- a/source/game/scripting/StarWorldLuaBindings.cpp
+++ b/source/game/scripting/StarWorldLuaBindings.cpp
@@ -1949,8 +1949,8 @@ namespace LuaBindings {
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 == "block")
+ placeMaterial.collisionOverride = TileCollisionOverride::Block;
else if (overrideName == "platform")
placeMaterial.collisionOverride = TileCollisionOverride::Platform;
else