diff options
-rw-r--r-- | assets/opensb/binds/opensb.binds | 14 | ||||
-rw-r--r-- | assets/opensb/interface/building/collisionblock.png | bin | 0 -> 219 bytes | |||
-rw-r--r-- | assets/opensb/interface/building/collisionempty.png | bin | 0 -> 176 bytes | |||
-rw-r--r-- | assets/opensb/interface/building/collisionplatform.png | bin | 0 -> 178 bytes | |||
-rw-r--r-- | assets/opensb/sfx/tools/cyclematcollision.ogg | bin | 0 -> 4995 bytes | |||
-rw-r--r-- | source/game/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/game/StarCollisionBlock.hpp | 6 | ||||
-rw-r--r-- | source/game/StarToolUser.cpp | 15 | ||||
-rw-r--r-- | source/game/interfaces/StarRenderableItem.hpp | 19 | ||||
-rw-r--r-- | source/game/items/StarMaterialItem.cpp | 113 | ||||
-rw-r--r-- | source/game/items/StarMaterialItem.hpp | 18 | ||||
-rw-r--r-- | source/game/scripting/StarWorldLuaBindings.cpp | 4 |
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 Binary files differnew file mode 100644 index 0000000..b1d5f9d --- /dev/null +++ b/assets/opensb/interface/building/collisionblock.png diff --git a/assets/opensb/interface/building/collisionempty.png b/assets/opensb/interface/building/collisionempty.png Binary files differnew file mode 100644 index 0000000..6289ba1 --- /dev/null +++ b/assets/opensb/interface/building/collisionempty.png diff --git a/assets/opensb/interface/building/collisionplatform.png b/assets/opensb/interface/building/collisionplatform.png Binary files differnew file mode 100644 index 0000000..b8b2b65 --- /dev/null +++ b/assets/opensb/interface/building/collisionplatform.png diff --git a/assets/opensb/sfx/tools/cyclematcollision.ogg b/assets/opensb/sfx/tools/cyclematcollision.ogg Binary files differnew file mode 100644 index 0000000..3a35ee3 --- /dev/null +++ b/assets/opensb/sfx/tools/cyclematcollision.ogg 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 |