diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp index 95d1b113e..1d2542d58 100644 --- a/src/Entities/Pawn.cpp +++ b/src/Entities/Pawn.cpp @@ -24,6 +24,9 @@ void cPawn::Tick(float a_Dt, cChunk & a_Chunk) iter != m_EntityEffects.end(); ++iter) { + // Apply entity effect + HandleEntityEffects(iter->first, iter->second); + // Reduce the effect's duration iter->second.m_Ticks--; @@ -58,3 +61,95 @@ void cPawn::RemoveEntityEffect(cEntityEffect::eType a_EffectType) m_EntityEffects.erase(a_EffectType); //m_World->BroadcastRemoveEntityEffect(*this, a_EffectType); } + + + + + +void cPawn::HandleEntityEffects(cEntityEffect::eType a_EffectType, cEntityEffect a_Effect) +{ + switch (a_EffectType) + { + // Default effect behaviors + case cEntityEffect::efInstantHealth: + { + // Base heal = 6, doubles for every increase in intensity + Heal(6 * std::pow(2, a_Effect.GetIntensity())); + + // TODO: Harms undead + return; + } + case cEntityEffect::efInstantDamage: + { + // Base damage = 6, doubles for every increase in intensity + int damage = 6 * std::pow(2, a_Effect.GetIntensity()); + TakeDamage(dtPotionOfHarming, a_Effect.GetUser(), damage, 0); + + // TODO: Heals undead + return; + } + case cEntityEffect::efStrength: + { + // TODO: Implement me! + return; + } + case cEntityEffect::efWeakness: + { + // Damage reduction = 0.5 damage, multiplied by potion level (Weakness II = 1 damage) + //double dmg_reduc = 0.5 * (a_Effect.GetIntensity() + 1); + + // TODO: Implement me! + // TODO: Weakened villager zombies can be turned back to villagers with the god apple + return; + } + case cEntityEffect::efRegeneration: + { + // Regen frequency = 50 ticks, divided by potion level (Regen II = 25 ticks) + int frequency = std::floor(50.0 / (double)(a_Effect.GetIntensity() + 1)); + + static short counter = 0; + if (++counter >= frequency) + { + Heal(1); + counter = 0; + } + + // TODO: Doesn't effect undead + return; + } + case cEntityEffect::efPoison: + { + // Poison frequency = 25 ticks, divided by potion level (Poison II = 25 ticks) + int frequency = std::floor(25.0 / (double)(a_Effect.GetIntensity() + 1)); + + static short counter = 0; + if (++counter >= frequency) + { + // Cannot take poison damage when health is at 1 + if (GetHealth() > 1) + { + TakeDamage(dtPoisoning, a_Effect.GetUser(), 1, 0); + } + counter = 0; + } + + // TODO: Doesn't effect undead or spiders + return; + } + case cEntityEffect::efFireResistance: + { + // TODO: Implement me! + return; + } + case cEntityEffect::efSpeed: + { + // TODO: Implement me! + return; + } + case cEntityEffect::efSlowness: + { + // TODO: Implement me! + return; + } + } +} diff --git a/src/Entities/Pawn.h b/src/Entities/Pawn.h index a954f4a70..f7d7213ff 100644 --- a/src/Entities/Pawn.h +++ b/src/Entities/Pawn.h @@ -27,6 +27,8 @@ public: protected: std::map m_EntityEffects; + + virtual void HandleEntityEffects(cEntityEffect::eType a_EffectType, cEntityEffect a_Effect); } ; // tolua_export diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 035973a16..95ee8b39d 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -584,12 +584,11 @@ void cPlayer::FoodPoison(int a_NumTicks) m_FoodPoisonedTicksRemaining = std::max(m_FoodPoisonedTicksRemaining, a_NumTicks); if (!HasBeenFoodPoisoned) { - m_World->BroadcastRemoveEntityEffect(*this, cEntityEffect::efHunger); SendHealth(); } else { - m_World->BroadcastEntityEffect(*this, cEntityEffect::efHunger, 0, 400); // Give the player the "Hunger" effect for 20 seconds. + AddEntityEffect(cEntityEffect::efHunger, cEntityEffect(0, 400)); // Give the player the "Hunger" effect for 20 seconds. } } @@ -1887,6 +1886,43 @@ void cPlayer::TickBurning(cChunk & a_Chunk) +void cPlayer::HandleEntityEffects(cEntityEffect::eType a_EffectType, cEntityEffect a_Effect) +{ + switch (a_EffectType) + { + // Effects whose behaviors are overridden + case cEntityEffect::efMiningFatigue: + { + // TODO: Implement me! + return; + } + case cEntityEffect::efHunger: + { + m_FoodExhaustionLevel += 0.025; // 0.5 per second = 0.025 per tick + return; + } + case cEntityEffect::efSaturation: + { + // Increase saturation 1 per tick, adds 1 for every increase in level + m_FoodSaturationLevel += (1 + a_Effect.GetIntensity()); + return; + } + + // Client-side-only effects + case cEntityEffect::efNausia: + case cEntityEffect::efNightVision: + { + return; + } + } + + super::HandleEntityEffects(a_EffectType, a_Effect); +} + + + + + void cPlayer::HandleFood(void) { // Ref.: http://www.minecraftwiki.net/wiki/Hunger @@ -1921,17 +1957,6 @@ void cPlayer::HandleFood(void) } } } - - // Apply food poisoning food exhaustion: - if (m_FoodPoisonedTicksRemaining > 0) - { - m_FoodPoisonedTicksRemaining--; - m_FoodExhaustionLevel += 0.025; // 0.5 per second = 0.025 per tick - } - else - { - m_World->BroadcastRemoveEntityEffect(*this, cEntityEffect::efHunger); // Remove the "Hunger" effect. - } // Apply food exhaustion that has accumulated: if (m_FoodExhaustionLevel >= 4) diff --git a/src/Entities/Player.h b/src/Entities/Player.h index b2142a18b..88f732096 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -526,6 +526,9 @@ protected: /** Stops players from burning in creative mode */ virtual void TickBurning(cChunk & a_Chunk) override; + /** Called each tick to handle entity effects*/ + virtual void HandleEntityEffects(cEntityEffect::eType a_EffectType, cEntityEffect a_Effect) override; + /** Called in each tick to handle food-related processing */ void HandleFood(void);