From 3d044d2dde2e348dc5c9f6a7fe44e914ef501878 Mon Sep 17 00:00:00 2001 From: Aiden Neill Date: Wed, 25 Nov 2020 10:56:55 -0700 Subject: [PATCH] Added magma block contact damage (#5055) * Added magma block contact damage * Fireproof entities do not take damage from magma * Fire resistance prevents magma damage * No magma damage when hovering over magma block --- Server/Plugins/APIDump/APIDesc.lua | 8 +++++ src/Defines.cpp | 3 ++ src/Defines.h | 2 ++ src/Entities/Entity.cpp | 53 +++++++++++++++++++++++++++--- src/Entities/Entity.h | 3 ++ src/Entities/Player.cpp | 1 + 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index 23167dec4..663b2ec68 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -14452,6 +14452,14 @@ end { Notes = "Damage from contact with a cactus block" }, + dtMagmaContact = + { + Notes = "Damage from contact with a magma block" + }, + dtMagma = + { + Notes = "Damage from contact with a magma block" + }, dtDrown = { Notes = "Damage received by drowning in water / lava" diff --git a/src/Defines.cpp b/src/Defines.cpp index d0b6ff956..7e4274bd5 100644 --- a/src/Defines.cpp +++ b/src/Defines.cpp @@ -273,6 +273,7 @@ AString DamageTypeToString(eDamageType a_DamageType) case dtAdmin: return "dtAdmin"; case dtAttack: return "dtAttack"; case dtCactusContact: return "dtCactusContact"; + case dtMagmaContact: return "dtMagmaContact"; case dtDrowning: return "dtDrowning"; case dtEnderPearl: return "dtEnderPearl"; case dtEnvironment: return "dtEnvironment"; @@ -323,6 +324,7 @@ eDamageType StringToDamageType(const AString & a_DamageTypeString) { dtSuffocating, "dtSuffocation"}, { dtStarving, "dtStarving"}, { dtCactusContact, "dtCactusContact"}, + { dtMagmaContact, "dtMagmaContact"}, { dtLavaContact, "dtLavaContact"}, { dtPoisoning, "dtPoisoning"}, { dtWithering, "dtWithering"}, @@ -350,6 +352,7 @@ eDamageType StringToDamageType(const AString & a_DamageTypeString) { dtCactusContact, "dtCactus"}, { dtCactusContact, "dtCactuses"}, { dtCactusContact, "dtCacti"}, + { dtMagmaContact, "dtMagma"}, { dtLavaContact, "dtLava"}, { dtPoisoning, "dtPoison"}, { dtWithering, "dtWither"}, diff --git a/src/Defines.h b/src/Defines.h index dc2835517..2f46e079c 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -278,6 +278,7 @@ enum eDamageType dtSuffocating, // Suffocating inside a block dtStarving, // Hunger dtCactusContact, // Contact with a cactus block + dtMagmaContact, // Contact with a magma block dtLavaContact, // Contact with a lava block dtPoisoning, // Having the poison effect dtWithering, // Having the wither effect @@ -306,6 +307,7 @@ enum eDamageType dtCactus = dtCactusContact, dtCactuses = dtCactusContact, dtCacti = dtCactusContact, + dtMagma = dtMagmaContact, dtLava = dtLavaContact, dtPoison = dtPoisoning, dtWither = dtWithering, diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 34d5bf6e5..579541dd3 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -147,6 +147,7 @@ bool cEntity::Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld) ); */ + ASSERT(m_World == nullptr); ASSERT(GetParentChunk() == nullptr); SetWorld(&a_EntityWorld); @@ -628,6 +629,7 @@ bool cEntity::ArmorCoversAgainst(eDamageType a_DamageType) case dtAttack: case dtArrowAttack: case dtCactusContact: + case dtMagmaContact: case dtLavaContact: case dtFireContact: case dtExplosion: @@ -656,7 +658,7 @@ float cEntity::GetEnchantmentCoverAgainst(const cEntity * a_Attacker, eDamageTyp TotalEPF += static_cast(Item.m_Enchantments.GetLevel(cEnchantments::enchProtection)) * 1; } - if ((a_DamageType == dtBurning) || (a_DamageType == dtFireContact) || (a_DamageType == dtLavaContact)) + if ((a_DamageType == dtBurning) || (a_DamageType == dtFireContact) || (a_DamageType == dtLavaContact) || (a_DamageType == dtMagmaContact)) { TotalEPF += static_cast(Item.m_Enchantments.GetLevel(cEnchantments::enchFireProtection)) * 2; } @@ -899,6 +901,23 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) DetectCacti(); } + // Handle magma block damage + if + ( + IsOnGround() && + ( + (IsMob() && !static_cast(this)->IsFireproof()) || + ( + IsPlayer() && !((static_cast(this))->IsGameModeCreative() || (static_cast(this))->IsGameModeSpectator()) + && !static_cast(this)->IsFireproof() + && !static_cast(this)->HasEntityEffect(cEntityEffect::effFireResistance) + ) + ) + ) + { + DetectMagma(); + } + // Handle drowning: if (IsMob() || IsPlayer()) { @@ -1314,6 +1333,35 @@ void cEntity::DetectCacti(void) +void cEntity::DetectMagma(void) +{ + int MinX = FloorC(GetPosX() - m_Width / 2); + int MaxX = FloorC(GetPosX() + m_Width / 2); + int MinZ = FloorC(GetPosZ() - m_Width / 2); + int MaxZ = FloorC(GetPosZ() + m_Width / 2); + int MinY = Clamp(POSY_TOINT - 1, 0, cChunkDef::Height - 1); + int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1); + + for (int x = MinX; x <= MaxX; x++) + { + for (int z = MinZ; z <= MaxZ; z++) + { + for (int y = MinY; y <= MaxY; y++) + { + if (GetWorld()->GetBlock(x, y, z) == E_BLOCK_MAGMA) + { + TakeDamage(dtMagmaContact, nullptr, 1, 0); + return; + } + } // for y + } // for z + } // for x +} + + + + + bool cEntity::DetectPortal() { // If somebody scheduled a world change, do nothing. @@ -2334,6 +2382,3 @@ float cEntity::GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_Ex return 0; } } - - - diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 4322665c3..20712e7ea 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -420,6 +420,9 @@ public: /** Detects the time for application of cacti damage */ virtual void DetectCacti(void); + /** Detects the time for application of magma block damage */ + virtual void DetectMagma(void); + /** Detects whether we are in a portal block and begins teleportation procedures if so Returns true if MoveToWorld() was called, false if not */ diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index a8afb2b95..fb0cdf271 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1194,6 +1194,7 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI) case dtSuffocating: return GetRandomProvider().RandBool() ? "git merge'd into a block" : "fused with a block"; case dtStarving: return "forgot the importance of food"; case dtCactusContact: return "was impaled on a cactus"; + case dtMagmaContact: return "discovered the floor was lava"; case dtLavaContact: return "was melted by lava"; case dtPoisoning: return "died from septicaemia"; case dtWithering: return "is a husk of their former selves";