1
0

Implement invisibility effect

This commit is contained in:
peterbell10 2017-08-01 18:51:43 +01:00 committed by Lukas Pioch
parent 759618b035
commit 79eb4c3aed
5 changed files with 91 additions and 44 deletions

View File

@ -1,8 +1,9 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "EntityEffect.h" #include "EntityEffect.h"
#include "../Mobs/Monster.h"
#include "Player.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> cEntityEffect::CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier)
{ {
switch (a_EffectType) switch (a_EffectType)
{ {
case cEntityEffect::effNoEffect: return new cEntityEffect (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effNoEffect: return cpp14::make_unique<cEntityEffect >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effAbsorption: return new cEntityEffectAbsorption (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effAbsorption: return cpp14::make_unique<cEntityEffectAbsorption >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effBlindness: return new cEntityEffectBlindness (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effBlindness: return cpp14::make_unique<cEntityEffectBlindness >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effFireResistance: return new cEntityEffectFireResistance(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effFireResistance: return cpp14::make_unique<cEntityEffectFireResistance>(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effHaste: return new cEntityEffectHaste (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effHaste: return cpp14::make_unique<cEntityEffectHaste >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effHealthBoost: return new cEntityEffectHealthBoost (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effHealthBoost: return cpp14::make_unique<cEntityEffectHealthBoost >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effHunger: return new cEntityEffectHunger (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effHunger: return cpp14::make_unique<cEntityEffectHunger >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effInstantDamage: return new cEntityEffectInstantDamage (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effInstantDamage: return cpp14::make_unique<cEntityEffectInstantDamage >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effInstantHealth: return new cEntityEffectInstantHealth (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effInstantHealth: return cpp14::make_unique<cEntityEffectInstantHealth >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effInvisibility: return new cEntityEffectInvisibility (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effInvisibility: return cpp14::make_unique<cEntityEffectInvisibility >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effJumpBoost: return new cEntityEffectJumpBoost (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effJumpBoost: return cpp14::make_unique<cEntityEffectJumpBoost >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effMiningFatigue: return new cEntityEffectMiningFatigue (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effMiningFatigue: return cpp14::make_unique<cEntityEffectMiningFatigue >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effNausea: return new cEntityEffectNausea (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effNausea: return cpp14::make_unique<cEntityEffectNausea >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effNightVision: return new cEntityEffectNightVision (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effNightVision: return cpp14::make_unique<cEntityEffectNightVision >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effPoison: return new cEntityEffectPoison (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effPoison: return cpp14::make_unique<cEntityEffectPoison >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effRegeneration: return new cEntityEffectRegeneration (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effRegeneration: return cpp14::make_unique<cEntityEffectRegeneration >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effResistance: return new cEntityEffectResistance (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effResistance: return cpp14::make_unique<cEntityEffectResistance >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effSaturation: return new cEntityEffectSaturation (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effSaturation: return cpp14::make_unique<cEntityEffectSaturation >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effSlowness: return new cEntityEffectSlowness (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effSlowness: return cpp14::make_unique<cEntityEffectSlowness >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effSpeed: return new cEntityEffectSpeed (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effSpeed: return cpp14::make_unique<cEntityEffectSpeed >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effStrength: return new cEntityEffectStrength (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effStrength: return cpp14::make_unique<cEntityEffectStrength >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effWaterBreathing: return new cEntityEffectWaterBreathing(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effWaterBreathing: return cpp14::make_unique<cEntityEffectWaterBreathing>(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effWeakness: return new cEntityEffectWeakness (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effWeakness: return cpp14::make_unique<cEntityEffectWeakness >(a_Duration, a_Intensity, a_DistanceModifier);
case cEntityEffect::effWither: return new cEntityEffectWither (a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effWither: return cpp14::make_unique<cEntityEffectWither >(a_Duration, a_Intensity, a_DistanceModifier);
} }
ASSERT(!"Unhandled entity effect type!"); ASSERT(!"Unhandled entity effect type!");
#ifndef __clang__ #ifndef __clang__
return nullptr; return {};
#endif #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: // cEntityEffectWeakness:

View File

@ -81,7 +81,7 @@ public:
@param a_Duration How long this effect will last, in ticks @param a_Duration How long this effect will last, in ticks
@param a_Intensity How strong the effect will be applied @param a_Intensity How strong the effect will be applied
@param a_DistanceModifier The distance modifier for affecting potency, defaults to 1 */ @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<cEntityEffect> CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier);
/** Returns how many ticks this effect has been active for */ /** Returns how many ticks this effect has been active for */
int GetTicks(void) const { return m_Ticks; } int GetTicks(void) const { return m_Ticks; }
@ -346,6 +346,12 @@ public:
super(a_Duration, a_Intensity, a_DistanceModifier) 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);
}; };

View File

@ -55,7 +55,7 @@ void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{ {
// Copies values to prevent pesky wrong accesses and erasures // Copies values to prevent pesky wrong accesses and erasures
cEntityEffect::eType EffectType = iter->first; cEntityEffect::eType EffectType = iter->first;
cEntityEffect * Effect = iter->second; cEntityEffect * Effect = iter->second.get();
// Iterates (must be called before any possible erasure) // Iterates (must be called before any possible erasure)
++iter; ++iter;
@ -157,6 +157,15 @@ bool cPawn::IsFireproof(void) const
bool cPawn::IsInvisible() const
{
return HasEntityEffect(cEntityEffect::effInvisibility);
}
void cPawn::HandleAir(void) void cPawn::HandleAir(void)
{ {
if (IsSubmerged() && HasEntityEffect(cEntityEffect::effWaterBreathing)) if (IsSubmerged() && HasEntityEffect(cEntityEffect::effWaterBreathing))
@ -188,9 +197,10 @@ void cPawn::AddEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, s
} }
a_Duration = static_cast<int>(a_Duration * a_DistanceModifier); a_Duration = static_cast<int>(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<short>(a_Duration)); m_World->BroadcastEntityEffect(*this, a_EffectType, a_Intensity, static_cast<short>(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) void cPawn::RemoveEntityEffect(cEntityEffect::eType a_EffectType)
{ {
m_World->BroadcastRemoveEntityEffect(*this, a_EffectType); m_World->BroadcastRemoveEntityEffect(*this, a_EffectType);
m_EntityEffects[a_EffectType]->OnDeactivate(*this); auto itr = m_EntityEffects.find(a_EffectType);
delete m_EntityEffects[a_EffectType]; if (itr != m_EntityEffects.end())
m_EntityEffects.erase(a_EffectType); {
// 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<cEntityEffect::eType, cEntityEffect *> cPawn::GetEntityEffects() std::map<cEntityEffect::eType, cEntityEffect *> cPawn::GetEntityEffects()
{ {
return m_EntityEffects; std::map<cEntityEffect::eType, cEntityEffect *> 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;
} }

View File

@ -29,6 +29,7 @@ public:
virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override;
virtual bool IsFireproof(void) const override; virtual bool IsFireproof(void) const override;
virtual bool IsInvisible() const override;
virtual void HandleAir(void) override; virtual void HandleAir(void) override;
virtual void HandleFalling(void); virtual void HandleFalling(void);
@ -66,11 +67,11 @@ public:
/** Returns all entity effects */ /** Returns all entity effects */
std::map<cEntityEffect::eType, cEntityEffect *> GetEntityEffects(); std::map<cEntityEffect::eType, cEntityEffect *> GetEntityEffects();
/** Returns the entity effect, if it is currently applied. */ /** Returns the entity effect, if it is currently applied or nullptr if not. */
cEntityEffect *GetEntityEffect(cEntityEffect::eType a_EffectType); cEntityEffect * GetEntityEffect(cEntityEffect::eType a_EffectType);
protected: protected:
typedef std::map<cEntityEffect::eType, cEntityEffect *> tEffectMap; typedef std::map<cEntityEffect::eType, std::unique_ptr<cEntityEffect>> tEffectMap;
tEffectMap m_EntityEffects; tEffectMap m_EntityEffects;
double m_LastGroundHeight; double m_LastGroundHeight;

View File

@ -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); 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) switch (intensity)
{ {
case 0: f *= 0.3f; break; case 0: f *= 0.3f; break;