diff options
Diffstat (limited to 'src/Entities/Entity.cpp')
-rw-r--r-- | src/Entities/Entity.cpp | 227 |
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); + } + } } |