summaryrefslogtreecommitdiffstats
path: root/src/Entities/Entity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities/Entity.cpp')
-rw-r--r--src/Entities/Entity.cpp227
1 files changed, 225 insertions, 2 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 32f220897..89d1cffa1 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -13,6 +13,7 @@
#include "../Tracer.h"
#include "Player.h"
#include "Items/ItemHandler.h"
+#include "../FastRandom.h"
@@ -316,8 +317,107 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
// IsOnGround() only is false if the player is moving downwards
// TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain)
- if (!Player->IsOnGround())
+ const cEnchantments & Enchantments = Player->GetEquippedItem().m_Enchantments;
+
+ int SharpnessLevel = Enchantments.GetLevel(cEnchantments::enchSharpness);
+ int SmiteLevel = Enchantments.GetLevel(cEnchantments::enchSmite);
+ int BaneOfArthropodsLevel = Enchantments.GetLevel(cEnchantments::enchBaneOfArthropods);
+
+ if (SharpnessLevel > 0)
+ {
+ a_TDI.FinalDamage += (int)ceil(1.25 * SharpnessLevel);
+ }
+ else if (SmiteLevel > 0)
+ {
+ if (IsMob())
+ {
+ cMonster * Monster = (cMonster *)this;
+ switch (Monster->GetMobType())
+ {
+ case cMonster::mtSkeleton:
+ case cMonster::mtZombie:
+ case cMonster::mtWither:
+ case cMonster::mtZombiePigman:
+ {
+ a_TDI.FinalDamage += (int)ceil(2.5 * SmiteLevel);
+ break;
+ }
+ }
+ }
+ }
+ else if (BaneOfArthropodsLevel > 0)
{
+ if (IsMob())
+ {
+ cMonster * Monster = (cMonster *)this;
+ switch (Monster->GetMobType())
+ {
+ case cMonster::mtSpider:
+ case cMonster::mtCaveSpider:
+ case cMonster::mtSilverfish:
+ {
+ a_TDI.RawDamage += (int)ceil(2.5 * BaneOfArthropodsLevel);
+ // TODO: Add slowness effect
+
+ break;
+ };
+ default: break;
+ }
+ }
+ }
+
+ int FireAspectLevel = Enchantments.GetLevel(cEnchantments::enchFireAspect);
+ if (FireAspectLevel > 0)
+ {
+ int BurnTicks = 3;
+
+ if (FireAspectLevel > 1)
+ {
+ BurnTicks += 4 * (FireAspectLevel - 1);
+ }
+ if (!IsMob() && !IsSubmerged() && !IsSwimming())
+ {
+ StartBurning(BurnTicks * 20);
+ }
+ else if (IsMob() && !IsSubmerged() && !IsSwimming())
+ {
+ cMonster * Monster = (cMonster *)this;
+ switch (Monster->GetMobType())
+ {
+ case cMonster::mtGhast:
+ case cMonster::mtZombiePigman:
+ case cMonster::mtMagmaCube:
+ {
+ break;
+ };
+ default: StartBurning(BurnTicks * 20);
+ }
+ }
+ }
+
+ int ThornsLevel = 0;
+ const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() };
+ for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++)
+ {
+ const cItem & Item = ArmorItems[i];
+ ThornsLevel = std::max(ThornsLevel, Item.m_Enchantments.GetLevel(cEnchantments::enchThorns));
+ }
+
+ if (ThornsLevel > 0)
+ {
+ int Chance = ThornsLevel * 15;
+
+ cFastRandom Random;
+ int RandomValue = Random.GenerateRandomInteger(0, 100);
+
+ if (RandomValue <= Chance)
+ {
+ a_TDI.Attacker->TakeDamage(dtAttack, this, 0, Random.GenerateRandomInteger(1, 4), 0);
+ }
+ }
+
+ if (!Player->IsOnGround())
+ {
if ((a_TDI.DamageType == dtAttack) || (a_TDI.DamageType == dtArrowAttack))
{
a_TDI.FinalDamage += 2;
@@ -328,13 +428,123 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
Player->GetStatManager().AddValue(statDamageDealt, (StatValue)floor(a_TDI.FinalDamage * 10 + 0.5));
}
+ if (IsPlayer())
+ {
+ double TotalEPF = 0.0;
+ double EPFProtection = 0.00;
+ double EPFFireProtection = 0.00;
+ double EPFBlastProtection = 0.00;
+ double EPFProjectileProtection = 0.00;
+ double EPFFeatherFalling = 0.00;
+
+ const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() };
+ for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++)
+ {
+ const cItem & Item = ArmorItems[i];
+ int Level = Item.m_Enchantments.GetLevel(cEnchantments::enchProtection);
+ if (Level > 0)
+ {
+ EPFProtection += (6 + Level * Level) * 0.75 / 3;
+ }
+
+ Level = Item.m_Enchantments.GetLevel(cEnchantments::enchFireProtection);
+ if (Level > 0)
+ {
+ EPFFireProtection += (6 + Level * Level) * 1.25 / 3;
+ }
+
+ Level = Item.m_Enchantments.GetLevel(cEnchantments::enchFeatherFalling);
+ if (Level > 0)
+ {
+ EPFFeatherFalling += (6 + Level * Level) * 2.5 / 3;
+ }
+
+ Level = Item.m_Enchantments.GetLevel(cEnchantments::enchBlastProtection);
+ if (Level > 0)
+ {
+ EPFBlastProtection += (6 + Level * Level) * 1.5 / 3;
+ }
+
+ Level = Item.m_Enchantments.GetLevel(cEnchantments::enchProjectileProtection);
+ if (Level > 0)
+ {
+ EPFProjectileProtection += (6 + Level * Level) * 1.5 / 3;
+ }
+
+ }
+
+ TotalEPF = EPFProtection + EPFFireProtection + EPFFeatherFalling + EPFBlastProtection + EPFProjectileProtection;
+
+ EPFProtection = EPFProtection / TotalEPF;
+ EPFFireProtection = EPFFireProtection / TotalEPF;
+ EPFFeatherFalling = EPFFeatherFalling / TotalEPF;
+ EPFBlastProtection = EPFBlastProtection / TotalEPF;
+ EPFProjectileProtection = EPFProjectileProtection / TotalEPF;
+
+ if (TotalEPF > 25)
+ {
+ TotalEPF = 25;
+ }
+
+ cFastRandom Random;
+ float RandomValue = Random.GenerateRandomInteger(50, 100) * 0.01f;
+
+ TotalEPF = ceil(TotalEPF * RandomValue);
+
+ if (TotalEPF > 20)
+ {
+ TotalEPF = 20;
+ }
+
+ EPFProtection = TotalEPF * EPFProtection;
+ EPFFireProtection = TotalEPF * EPFFireProtection;
+ EPFFeatherFalling = TotalEPF * EPFFeatherFalling;
+ EPFBlastProtection = TotalEPF * EPFBlastProtection;
+ EPFProjectileProtection = TotalEPF * EPFProjectileProtection;
+
+ int RemovedDamage = 0;
+
+ if ((a_TDI.DamageType != dtInVoid) && (a_TDI.DamageType != dtAdmin))
+ {
+ RemovedDamage += (int)ceil(EPFProtection * 0.04 * a_TDI.FinalDamage);
+ }
+
+ if ((a_TDI.DamageType == dtFalling) || (a_TDI.DamageType == dtFall) || (a_TDI.DamageType == dtEnderPearl))
+ {
+ RemovedDamage += (int)ceil(EPFFeatherFalling * 0.04 * a_TDI.FinalDamage);
+ }
+
+ if (a_TDI.DamageType == dtBurning)
+ {
+ RemovedDamage += (int)ceil(EPFFireProtection * 0.04 * a_TDI.FinalDamage);
+ }
+
+ if (a_TDI.DamageType == dtExplosion)
+ {
+ RemovedDamage += (int)ceil(EPFBlastProtection * 0.04 * a_TDI.FinalDamage);
+ }
+
+ if (a_TDI.DamageType == dtProjectile)
+ {
+ RemovedDamage += (int)ceil(EPFBlastProtection * 0.04 * a_TDI.FinalDamage);
+ }
+
+ if (a_TDI.FinalDamage < RemovedDamage)
+ {
+ RemovedDamage = 0;
+ }
+
+ a_TDI.FinalDamage -= RemovedDamage;
+ }
+
m_Health -= (short)a_TDI.FinalDamage;
// TODO: Apply damage to armor
m_Health = std::max(m_Health, 0);
- if ((IsMob() || IsPlayer()) && (a_TDI.Attacker != NULL)) // Knockback for only players and mobs
+ // Add knockback:
+ if ((IsMob() || IsPlayer()) && (a_TDI.Attacker != NULL))
{
int KnockbackLevel = a_TDI.Attacker->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchKnockback); // More common enchantment
if (KnockbackLevel < 1)
@@ -1252,6 +1462,8 @@ void cEntity::HandleAir(void)
// See if the entity is /submerged/ water (block above is water)
// Get the type of block the entity is standing in:
+ int RespirationLevel = GetEquippedHelmet().m_Enchantments.GetLevel(cEnchantments::enchRespiration);
+
if (IsSubmerged())
{
if (!IsPlayer()) // Players control themselves
@@ -1259,6 +1471,11 @@ void cEntity::HandleAir(void)
SetSpeedY(1); // Float in the water
}
+ if (RespirationLevel > 0)
+ {
+ ((cPawn *)this)->AddEntityEffect(cEntityEffect::effNightVision, 200, 5, 0);
+ }
+
if (m_AirLevel <= 0)
{
// Runs the air tick timer to check whether the player should be damaged
@@ -1285,6 +1502,12 @@ void cEntity::HandleAir(void)
// Set the air back to maximum
m_AirLevel = MAX_AIR_LEVEL;
m_AirTickTimer = DROWNING_TICKS;
+
+ if (RespirationLevel > 0)
+ {
+ m_AirTickTimer = DROWNING_TICKS + (RespirationLevel * 15 * 20);
+ }
+
}
}