From 79eb4c3aed59edce58d2529bf9c6334f7fe6fbad Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Tue, 1 Aug 2017 18:51:43 +0100 Subject: Implement invisibility effect --- src/Entities/EntityEffect.cpp | 73 ++++++++++++++++++++++++++----------------- src/Entities/EntityEffect.h | 8 ++++- src/Entities/Pawn.cpp | 39 +++++++++++++++++------ src/Entities/Pawn.h | 7 +++-- src/Entities/Player.cpp | 10 +++--- 5 files changed, 92 insertions(+), 45 deletions(-) diff --git a/src/Entities/EntityEffect.cpp b/src/Entities/EntityEffect.cpp index 620be395b..cc9aaca5a 100644 --- a/src/Entities/EntityEffect.cpp +++ b/src/Entities/EntityEffect.cpp @@ -1,8 +1,9 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EntityEffect.h" -#include "../Mobs/Monster.h" #include "Player.h" +#include "../Chunk.h" +#include "../Mobs/Monster.h" @@ -185,40 +186,40 @@ cEntityEffect & cEntityEffect::operator =(cEntityEffect a_OtherEffect) -cEntityEffect * cEntityEffect::CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier) +std::unique_ptr cEntityEffect::CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier) { switch (a_EffectType) { - case cEntityEffect::effNoEffect: return new cEntityEffect (a_Duration, a_Intensity, a_DistanceModifier); - - case cEntityEffect::effAbsorption: return new cEntityEffectAbsorption (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effBlindness: return new cEntityEffectBlindness (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effFireResistance: return new cEntityEffectFireResistance(a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effHaste: return new cEntityEffectHaste (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effHealthBoost: return new cEntityEffectHealthBoost (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effHunger: return new cEntityEffectHunger (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effInstantDamage: return new cEntityEffectInstantDamage (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effInstantHealth: return new cEntityEffectInstantHealth (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effInvisibility: return new cEntityEffectInvisibility (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effJumpBoost: return new cEntityEffectJumpBoost (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effMiningFatigue: return new cEntityEffectMiningFatigue (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effNausea: return new cEntityEffectNausea (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effNightVision: return new cEntityEffectNightVision (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effPoison: return new cEntityEffectPoison (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effRegeneration: return new cEntityEffectRegeneration (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effResistance: return new cEntityEffectResistance (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effSaturation: return new cEntityEffectSaturation (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effSlowness: return new cEntityEffectSlowness (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effSpeed: return new cEntityEffectSpeed (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effStrength: return new cEntityEffectStrength (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effWaterBreathing: return new cEntityEffectWaterBreathing(a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effWeakness: return new cEntityEffectWeakness (a_Duration, a_Intensity, a_DistanceModifier); - case cEntityEffect::effWither: return new cEntityEffectWither (a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effNoEffect: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + + case cEntityEffect::effAbsorption: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effBlindness: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effFireResistance: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effHaste: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effHealthBoost: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effHunger: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effInstantDamage: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effInstantHealth: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effInvisibility: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effJumpBoost: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effMiningFatigue: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effNausea: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effNightVision: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effPoison: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effRegeneration: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effResistance: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effSaturation: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effSlowness: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effSpeed: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effStrength: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effWaterBreathing: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effWeakness: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); + case cEntityEffect::effWither: return cpp14::make_unique(a_Duration, a_Intensity, a_DistanceModifier); } ASSERT(!"Unhandled entity effect type!"); #ifndef __clang__ - return nullptr; + return {}; #endif } @@ -407,6 +408,22 @@ void cEntityEffectHunger::OnTick(cPawn & a_Target) +//////////////////////////////////////////////////////////////////////////////// +// cEntityEffectInvisibility: + +void cEntityEffectInvisibility::BroadcastMetadata(cPawn & a_Target) +{ + auto ParentChunk = a_Target.GetParentChunk(); + if (ParentChunk != nullptr) + { + ParentChunk->BroadcastEntityMetadata(a_Target); + } +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cEntityEffectWeakness: diff --git a/src/Entities/EntityEffect.h b/src/Entities/EntityEffect.h index aa18b500e..dd126c20d 100644 --- a/src/Entities/EntityEffect.h +++ b/src/Entities/EntityEffect.h @@ -81,7 +81,7 @@ public: @param a_Duration How long this effect will last, in ticks @param a_Intensity How strong the effect will be applied @param a_DistanceModifier The distance modifier for affecting potency, defaults to 1 */ - static cEntityEffect * CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier); + static std::unique_ptr CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier); /** Returns how many ticks this effect has been active for */ int GetTicks(void) const { return m_Ticks; } @@ -346,6 +346,12 @@ public: super(a_Duration, a_Intensity, a_DistanceModifier) { } + + virtual void OnActivate (cPawn & a_Target) override { BroadcastMetadata(a_Target); } + virtual void OnDeactivate(cPawn & a_Target) override { BroadcastMetadata(a_Target); } + +private: + static void BroadcastMetadata(cPawn & a_Target); }; diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp index 0a9abcdc1..a0095a8a4 100644 --- a/src/Entities/Pawn.cpp +++ b/src/Entities/Pawn.cpp @@ -55,7 +55,7 @@ void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { // Copies values to prevent pesky wrong accesses and erasures cEntityEffect::eType EffectType = iter->first; - cEntityEffect * Effect = iter->second; + cEntityEffect * Effect = iter->second.get(); // Iterates (must be called before any possible erasure) ++iter; @@ -157,6 +157,15 @@ bool cPawn::IsFireproof(void) const +bool cPawn::IsInvisible() const +{ + return HasEntityEffect(cEntityEffect::effInvisibility); +} + + + + + void cPawn::HandleAir(void) { if (IsSubmerged() && HasEntityEffect(cEntityEffect::effWaterBreathing)) @@ -188,9 +197,10 @@ void cPawn::AddEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, s } a_Duration = static_cast(a_Duration * a_DistanceModifier); - m_EntityEffects[a_EffectType] = cEntityEffect::CreateEntityEffect(a_EffectType, a_Duration, a_Intensity, a_DistanceModifier); + auto Res = m_EntityEffects.emplace(a_EffectType, cEntityEffect::CreateEntityEffect(a_EffectType, a_Duration, a_Intensity, a_DistanceModifier)); m_World->BroadcastEntityEffect(*this, a_EffectType, a_Intensity, static_cast(a_Duration)); - m_EntityEffects[a_EffectType]->OnActivate(*this); + cEntityEffect * Effect = Res.first->second.get(); + Effect->OnActivate(*this); } @@ -200,9 +210,14 @@ void cPawn::AddEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, s void cPawn::RemoveEntityEffect(cEntityEffect::eType a_EffectType) { m_World->BroadcastRemoveEntityEffect(*this, a_EffectType); - m_EntityEffects[a_EffectType]->OnDeactivate(*this); - delete m_EntityEffects[a_EffectType]; - m_EntityEffects.erase(a_EffectType); + auto itr = m_EntityEffects.find(a_EffectType); + if (itr != m_EntityEffects.end()) + { + // Erase from effect map before calling OnDeactivate to allow metadata broadcasts (e.g. for invisibility effect) + auto Effect = std::move(itr->second); + m_EntityEffects.erase(itr); + Effect->OnDeactivate(*this); + } } @@ -459,16 +474,22 @@ void cPawn::StopEveryoneFromTargetingMe() std::map cPawn::GetEntityEffects() { - return m_EntityEffects; + std::map Effects; + for (auto & Effect : m_EntityEffects) + { + Effects.insert({ Effect.first, Effect.second.get() }); + } + return Effects; } -cEntityEffect *cPawn::GetEntityEffect(cEntityEffect::eType a_EffectType) +cEntityEffect * cPawn::GetEntityEffect(cEntityEffect::eType a_EffectType) { - return m_EntityEffects.at(a_EffectType); + auto itr = m_EntityEffects.find(a_EffectType); + return (itr != m_EntityEffects.end()) ? itr->second.get() : nullptr; } diff --git a/src/Entities/Pawn.h b/src/Entities/Pawn.h index e6aae4f49..480b523ea 100644 --- a/src/Entities/Pawn.h +++ b/src/Entities/Pawn.h @@ -29,6 +29,7 @@ public: virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual bool IsFireproof(void) const override; + virtual bool IsInvisible() const override; virtual void HandleAir(void) override; virtual void HandleFalling(void); @@ -66,11 +67,11 @@ public: /** Returns all entity effects */ std::map GetEntityEffects(); - /** Returns the entity effect, if it is currently applied. */ - cEntityEffect *GetEntityEffect(cEntityEffect::eType a_EffectType); + /** Returns the entity effect, if it is currently applied or nullptr if not. */ + cEntityEffect * GetEntityEffect(cEntityEffect::eType a_EffectType); protected: - typedef std::map tEffectMap; + typedef std::map> tEffectMap; tEffectMap m_EntityEffects; double m_LastGroundHeight; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index b07f23958..3bbe334fb 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -2963,15 +2963,17 @@ float cPlayer::GetDigSpeed(BLOCKTYPE a_Block) } } - if (HasEntityEffect(cEntityEffect::effHaste)) + auto Haste = GetEntityEffect(cEntityEffect::effHaste); + if (Haste != nullptr) { - int intensity = GetEntityEffect(cEntityEffect::effHaste)->GetIntensity() + 1; + int intensity = Haste->GetIntensity() + 1; f *= 1.0f + (intensity * 0.2f); } - if (HasEntityEffect(cEntityEffect::effMiningFatigue)) + auto MiningFatigue = GetEntityEffect(cEntityEffect::effMiningFatigue); + if (MiningFatigue != nullptr) { - int intensity = GetEntityEffect(cEntityEffect::effMiningFatigue)->GetIntensity(); + int intensity = MiningFatigue->GetIntensity(); switch (intensity) { case 0: f *= 0.3f; break; -- cgit v1.2.3