diff options
Diffstat (limited to 'source/game/interfaces/StarFireableItem.cpp')
-rw-r--r-- | source/game/interfaces/StarFireableItem.cpp | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/source/game/interfaces/StarFireableItem.cpp b/source/game/interfaces/StarFireableItem.cpp new file mode 100644 index 0000000..e39d77e --- /dev/null +++ b/source/game/interfaces/StarFireableItem.cpp @@ -0,0 +1,300 @@ +#include "StarFireableItem.hpp" +#include "StarJsonExtra.hpp" +#include "StarWorldLuaBindings.hpp" +#include "StarConfigLuaBindings.hpp" +#include "StarItemLuaBindings.hpp" +#include "StarFireableItemLuaBindings.hpp" +#include "StarItem.hpp" +#include "StarWorld.hpp" + +namespace Star { + +FireableItem::FireableItem() + : m_fireTimer(0), + m_cooldownTime(10), + m_windupTime(0), + m_fireWhenReady(false), + m_startWhenReady(false), + m_cooldown(false), + m_alreadyInit(false), + m_requireEdgeTrigger(false), + m_attemptedFire(false), + m_fireOnRelease(false), + m_timeFiring(0.0f), + m_startTimingFire(false), + m_inUse(false), + m_walkWhileFiring(false), + m_stopWhileFiring(false), + m_mode(FireMode::None) {} + +FireableItem::FireableItem(Json const& params) : FireableItem() { + setParams(params); + m_fireableParams = params; +} + +FireableItem::FireableItem(FireableItem const& rhs) : ToolUserItem(rhs), StatusEffectItem(rhs) { + m_fireTimer = rhs.m_fireTimer; + m_cooldownTime = rhs.m_cooldownTime; + m_windupTime = rhs.m_windupTime; + m_fireWhenReady = rhs.m_fireWhenReady; + m_startWhenReady = rhs.m_startWhenReady; + m_cooldown = rhs.m_cooldown; + m_alreadyInit = rhs.m_alreadyInit; + m_requireEdgeTrigger = rhs.m_requireEdgeTrigger; + m_attemptedFire = rhs.m_attemptedFire; + m_fireOnRelease = rhs.m_fireOnRelease; + m_timeFiring = rhs.m_timeFiring; + m_startTimingFire = rhs.m_startTimingFire; + m_inUse = rhs.m_inUse; + m_walkWhileFiring = rhs.m_walkWhileFiring; + m_stopWhileFiring = rhs.m_stopWhileFiring; + m_fireableParams = rhs.m_fireableParams; + m_handPosition = rhs.m_handPosition; + m_mode = rhs.m_mode; +} + +void FireableItem::init(ToolUserEntity* owner, ToolHand hand) { + ToolUserItem::init(owner, hand); + + m_fireWhenReady = false; + m_startWhenReady = false; + + auto scripts = m_fireableParams.opt("scripts").apply(jsonToStringList); + if (entityMode() == EntityMode::Master && scripts) { + if (!m_scriptComponent) { + m_scriptComponent.emplace(); + m_scriptComponent->setScripts(*scripts); + } + m_scriptComponent->addCallbacks( + "config", LuaBindings::makeConfigCallbacks(bind(&Item::instanceValue, as<Item>(this), _1, _2))); + m_scriptComponent->addCallbacks("fireableItem", LuaBindings::makeFireableItemCallbacks(this)); + m_scriptComponent->addCallbacks("item", LuaBindings::makeItemCallbacks(as<Item>(this))); + m_scriptComponent->init(world()); + } +} + +void FireableItem::uninit() { + if (m_scriptComponent) { + m_scriptComponent->uninit(); + m_scriptComponent->removeCallbacks("config"); + m_scriptComponent->removeCallbacks("fireableItem"); + m_scriptComponent->removeCallbacks("item"); + } + + ToolUserItem::uninit(); +} + +void FireableItem::fire(FireMode mode, bool, bool edgeTriggered) { + m_attemptedFire = true; + if (ready()) { + m_inUse = true; + m_startTimingFire = true; + m_mode = mode; + if (!m_requireEdgeTrigger || edgeTriggered) { + setFireTimer(windupTime() + cooldownTime()); + if (!m_fireOnRelease) { + m_fireWhenReady = true; + m_startWhenReady = true; + } + } + } + + if (m_scriptComponent) + m_scriptComponent->invoke("attemptedFire"); +} + +void FireableItem::endFire(FireMode mode, bool) { + if (m_scriptComponent) + m_scriptComponent->invoke("endFire"); + + m_attemptedFire = false; + if (m_fireOnRelease && m_timeFiring) { + m_mode = mode; + triggerCooldown(); + fireTriggered(); + } +} + +FireMode FireableItem::fireMode() const { + return m_mode; +} + +float FireableItem::cooldownTime() const { + return m_cooldownTime; +} + +void FireableItem::setCooldownTime(float cooldownTime) { + m_cooldownTime = cooldownTime; +} + +float FireableItem::fireTimer() const { + return m_fireTimer; +} + +void FireableItem::setFireTimer(float fireTimer) { + m_fireTimer = fireTimer; +} + +bool FireableItem::ready() const { + return fireTimer() <= 0; +} + +bool FireableItem::firing() const { + return m_timeFiring > 0; +} + +bool FireableItem::inUse() const { + return m_inUse; +} + +bool FireableItem::walkWhileFiring() const { + return m_walkWhileFiring; +} + +bool FireableItem::stopWhileFiring() const { + return m_stopWhileFiring; +} + +bool FireableItem::windup() const { + if (ready()) + return false; + + if (m_scriptComponent) + m_scriptComponent->invoke("triggerWindup"); + + return fireTimer() > cooldownTime(); +} + +void FireableItem::update(FireMode fireMode, bool shifting, HashSet<MoveControlType> const&) { + if (m_scriptComponent) + m_scriptComponent->invoke("update", WorldTimestep, FireModeNames.getRight(fireMode), shifting); + + if (m_attemptedFire) { + if (m_startTimingFire) { + m_timeFiring += WorldTimestep; + if (m_scriptComponent) + m_scriptComponent->invoke("continueFire", WorldTimestep); + } + } else { + m_timeFiring = 0.0f; + m_startTimingFire = false; + } + m_attemptedFire = false; + + if (entityMode() == EntityMode::Master) { + if (fireTimer() > 0.0f) { + setFireTimer(fireTimer() - WorldTimestep); + if (fireTimer() < 0.0f) { + setFireTimer(0.0f); + m_inUse = false; + } + } + if (fireTimer() <= 0) { + m_cooldown = false; + } + if (m_startWhenReady) { + m_startWhenReady = false; + startTriggered(); + } + if (m_fireWhenReady) { + if (fireTimer() <= cooldownTime()) { + m_fireWhenReady = false; + fireTriggered(); + } + } + } +} + +void FireableItem::triggerCooldown() { + setFireTimer(cooldownTime()); + m_cooldown = true; + if (m_scriptComponent) + m_scriptComponent->invoke("triggerCooldown"); +} + +bool FireableItem::coolingDown() const { + return m_cooldown; +} + +void FireableItem::setCoolingDown(bool coolingdown) { + m_cooldown = coolingdown; +} + +float FireableItem::timeFiring() const { + return m_timeFiring; +} + +void FireableItem::setTimeFiring(float timeFiring) { + m_timeFiring = timeFiring; +} + +Vec2F FireableItem::handPosition() const { + return m_handPosition; +} + +Vec2F FireableItem::firePosition() const { + return Vec2F(); +} + +Json FireableItem::fireableParam(String const& key) const { + return m_fireableParams.get(key); +} + +Json FireableItem::fireableParam(String const& key, Json const& defaultVal) const { + return m_fireableParams.get(key, defaultVal); +} + +bool FireableItem::validAimPos(Vec2F const&) { + return true; +} + +void FireableItem::setParams(Json const& params) { + if (!m_alreadyInit) { + // cannot use setWindupTime or setCooldownTime here, because object is not fully constructed + m_windupTime = params.getFloat("windupTime", 0.0f); + m_cooldownTime = params.getFloat("cooldown", params.getFloat("fireTime", 0.15f) - m_windupTime); + if (params.contains("handPosition")) { + m_handPosition = jsonToVec2F(params.get("handPosition")); + } + m_requireEdgeTrigger = params.getBool("edgeTrigger", false); + m_fireOnRelease = params.getBool("fireOnRelease", false); + m_walkWhileFiring = params.getBool("walkWhileFiring", false); + m_stopWhileFiring = params.getBool("stopWhileFiring", false); + m_alreadyInit = true; + } +} + +void FireableItem::setFireableParam(String const& key, Json const& value) { + m_fireableParams = m_fireableParams.set(key, value); +} + +void FireableItem::startTriggered() { + if (m_scriptComponent) + m_scriptComponent->invoke("startTriggered"); +} + +void FireableItem::fireTriggered() { + if (m_scriptComponent) + m_scriptComponent->invoke("fireTriggered"); +} + +Vec2F FireableItem::ownerFirePosition() const { + if (!initialized()) + throw StarException("FireableItem uninitialized in ownerFirePosition"); + + return owner()->handPosition(hand(), (this->firePosition() - handPosition()) / TilePixels); +} + +float FireableItem::windupTime() const { + return m_windupTime; +} + +void FireableItem::setWindupTime(float time) { + m_windupTime = time; +} + +List<PersistentStatusEffect> FireableItem::statusEffects() const { + return {}; +} + +} |