diff --git a/CONTRIBUTORS b/CONTRIBUTORS index e2179adb9..f5ee91b89 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -17,6 +17,7 @@ Bond_009 changyongGuo Cocosushi6 derouinw +dImrich (Damian Imrich) Diusrex Duralex Earboxer (Zach DeCook) diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index cbefc764c..143993dad 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -146,6 +146,8 @@ public: esFireworkExploding = 17, // Passive mob is in "love mode" esMobInLove = 18, + // Plays totem of undying animation and sound + esTotemOfUndying = 35, } ; static const int FIRE_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in fire diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp index 35efe05ce..6f33a5eca 100644 --- a/src/Entities/Pawn.cpp +++ b/src/Entities/Pawn.cpp @@ -111,6 +111,20 @@ void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) void cPawn::KilledBy(TakeDamageInfo & a_TDI) { ClearEntityEffects(); + + // Is death eligible for totem reanimation? + if (DeductTotem(a_TDI.DamageType)) + { + m_World->BroadcastEntityStatus(*this, esTotemOfUndying); + + AddEntityEffect(cEntityEffect::effAbsorption, 100, 1); + AddEntityEffect(cEntityEffect::effRegeneration, 900, 1); + AddEntityEffect(cEntityEffect::effFireResistance, 800, 0); + + m_Health = 1; + return; + } + Super::KilledBy(a_TDI); } @@ -490,3 +504,38 @@ void cPawn::ResetPosition(Vector3d a_NewPosition) Super::ResetPosition(a_NewPosition); m_LastGroundHeight = GetPosY(); } + + + + + +bool cPawn::DeductTotem(const eDamageType a_DamageType) +{ + if ((a_DamageType == dtAdmin) || (a_DamageType == dtInVoid)) + { + // Beyond saving: + return false; + } + + if (!IsPlayer()) + { + // TODO: implement when mobs will be able to pick up items based on CanPickUpLoot attribute: + return false; + } + + // If the player is holding a totem of undying in their off-hand or + // main-hand slot and receives otherwise fatal damage, the totem saves the player from death. + + auto & inv = static_cast(this)->GetInventory(); + if (inv.GetEquippedItem().m_ItemType == E_ITEM_TOTEM_OF_UNDYING) + { + inv.SetEquippedItem({}); + return true; + } + if (inv.GetShieldSlot().m_ItemType == E_ITEM_TOTEM_OF_UNDYING) + { + inv.SetShieldSlot({}); + return true; + } + return false; +} diff --git a/src/Entities/Pawn.h b/src/Entities/Pawn.h index 1a9285b77..ab8d66a58 100644 --- a/src/Entities/Pawn.h +++ b/src/Entities/Pawn.h @@ -71,6 +71,7 @@ public: cEntityEffect * GetEntityEffect(cEntityEffect::eType a_EffectType) const; protected: + typedef std::map> tEffectMap; tEffectMap m_EntityEffects; @@ -83,4 +84,8 @@ private: /** A list of all monsters that are targeting this pawn. */ std::vector m_TargetingMe; + + /** Attempt to activate a Totem of Undying. + If activation for the given type of damage was successful, consumes the totem and returns true. */ + bool DeductTotem(eDamageType a_DamageType); } ; // tolua_export