mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-08 11:57:39 +08:00
Ghast fireball reflections (besides arrows)
This commit is contained in:
parent
11ca2cf4c0
commit
a3f1af6f78
@ -249,21 +249,21 @@ void cEntity::TakeDamage(cEntity & a_Attacker)
|
||||
|
||||
|
||||
|
||||
void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, double a_KnockbackAmount)
|
||||
void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, double a_KnockbackAmount, const eExplosionSource a_ExplosionSource)
|
||||
{
|
||||
float FinalDamage = static_cast<float>(a_RawDamage);
|
||||
float ArmorCover = GetArmorCoverAgainst(a_Attacker, a_DamageType, a_RawDamage);
|
||||
|
||||
ApplyArmorDamage(static_cast<int>(ArmorCover));
|
||||
|
||||
cEntity::TakeDamage(a_DamageType, a_Attacker, a_RawDamage, FinalDamage, a_KnockbackAmount);
|
||||
cEntity::TakeDamage(a_DamageType, a_Attacker, a_RawDamage, FinalDamage, a_KnockbackAmount, a_ExplosionSource);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEntity::TakeDamage(eDamageType a_DamageType, UInt32 a_AttackerID, int a_RawDamage, double a_KnockbackAmount)
|
||||
void cEntity::TakeDamage(eDamageType a_DamageType, UInt32 a_AttackerID, int a_RawDamage, double a_KnockbackAmount, const eExplosionSource a_ExplosionSource)
|
||||
{
|
||||
m_World->DoWithEntityByID(a_AttackerID, [=](cEntity & a_Attacker)
|
||||
{
|
||||
@ -277,7 +277,7 @@ void cEntity::TakeDamage(eDamageType a_DamageType, UInt32 a_AttackerID, int a_Ra
|
||||
Attacker = nullptr;
|
||||
}
|
||||
|
||||
TakeDamage(a_DamageType, Attacker, a_RawDamage, a_KnockbackAmount);
|
||||
TakeDamage(a_DamageType, Attacker, a_RawDamage, a_KnockbackAmount, a_ExplosionSource);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@ -287,11 +287,13 @@ void cEntity::TakeDamage(eDamageType a_DamageType, UInt32 a_AttackerID, int a_Ra
|
||||
|
||||
|
||||
|
||||
void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, float a_FinalDamage, double a_KnockbackAmount)
|
||||
void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, float a_FinalDamage, double a_KnockbackAmount, const eExplosionSource a_ExplosionSource)
|
||||
{
|
||||
TakeDamageInfo TDI;
|
||||
TDI.DamageType = a_DamageType;
|
||||
if ((a_Attacker != nullptr) && a_Attacker->IsPawn())
|
||||
TDI.ExplosionSource = a_ExplosionSource;
|
||||
|
||||
if (a_Attacker != nullptr)
|
||||
{
|
||||
TDI.Attacker = a_Attacker;
|
||||
}
|
||||
|
@ -58,11 +58,12 @@ class cMonster;
|
||||
// tolua_begin
|
||||
struct TakeDamageInfo
|
||||
{
|
||||
eDamageType DamageType; // Where does the damage come from? Being hit / on fire / contact with cactus / ...
|
||||
cEntity * Attacker; // The attacking entity; valid only for dtAttack
|
||||
int RawDamage; // What damage would the receiver get without any armor. Usually: attacker mob type + weapons
|
||||
float FinalDamage; // What actual damage will be received. Usually: m_RawDamage minus armor
|
||||
Vector3d Knockback; // The amount and direction of knockback received from the damage
|
||||
eDamageType DamageType; // Where does the damage come from? Being hit / on fire / contact with cactus / ...
|
||||
cEntity * Attacker; // The attacking entity; valid only for dtAttack
|
||||
int RawDamage; // What damage would the receiver get without any armor. Usually: attacker mob type + weapons
|
||||
float FinalDamage; // What actual damage will be received. Usually: m_RawDamage minus armor
|
||||
Vector3d Knockback; // The amount and direction of knockback received from the damage
|
||||
eExplosionSource ExplosionSource; // The explosion source; valid only for dtExplosion
|
||||
// TODO: Effects - list of effects that the hit is causing. Unknown representation yet
|
||||
} ;
|
||||
// tolua_end
|
||||
@ -263,13 +264,13 @@ public:
|
||||
void TakeDamage(cEntity & a_Attacker);
|
||||
|
||||
/** Makes this entity take the specified damage. The final damage is calculated using current armor, then DoTakeDamage() called */
|
||||
void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, double a_KnockbackAmount);
|
||||
void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, double a_KnockbackAmount, const eExplosionSource a_ExplosionSource = esOther);
|
||||
|
||||
/** Makes this entity take the specified damage. The final damage is calculated using current armor, then DoTakeDamage() called */
|
||||
void TakeDamage(eDamageType a_DamageType, UInt32 a_Attacker, int a_RawDamage, double a_KnockbackAmount);
|
||||
void TakeDamage(eDamageType a_DamageType, UInt32 a_Attacker, int a_RawDamage, double a_KnockbackAmount, const eExplosionSource a_ExplosionSource = esOther);
|
||||
|
||||
/** Makes this entity take the specified damage. The values are packed into a TDI, knockback calculated, then sent through DoTakeDamage() */
|
||||
void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, float a_FinalDamage, double a_KnockbackAmount);
|
||||
void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, float a_FinalDamage, double a_KnockbackAmount, const eExplosionSource a_ExplosionSource = esOther);
|
||||
|
||||
float GetGravity(void) const { return m_Gravity; }
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "GhastFireballEntity.h"
|
||||
#include "../World.h"
|
||||
|
||||
|
||||
|
||||
@ -13,6 +12,32 @@ cGhastFireballEntity::cGhastFireballEntity(cEntity * a_Creator, Vector3d a_Pos,
|
||||
SetSpeed(a_Speed);
|
||||
SetGravity(0);
|
||||
SetAirDrag(0);
|
||||
|
||||
m_Shooter = a_Creator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cGhastFireballEntity::ReflectFromAttack(cEntity * a_AttackingEnt)
|
||||
{
|
||||
Vector3d Motion = NotchReflect(*a_AttackingEnt);
|
||||
SetSpeed(Motion * 20);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Vector3d cGhastFireballEntity::NotchReflect(cEntity & a_AttackingEnt)
|
||||
{
|
||||
float f1 = cos(-a_AttackingEnt.GetYaw() * 0.017453292F - 3.1415927F);
|
||||
float f2 = sin(-a_AttackingEnt.GetYaw() * 0.017453292F - 3.1415927F);
|
||||
float f3 = -cos(-a_AttackingEnt.GetPitch() * 0.017453292F);
|
||||
float f4 = sin(-a_AttackingEnt.GetPitch() * 0.017453292F);
|
||||
|
||||
return Vector3d((double) (f2 * f3), (double) f4, (double) (f1 * f3));
|
||||
}
|
||||
|
||||
|
||||
@ -43,3 +68,24 @@ void cGhastFireballEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos)
|
||||
Destroy();
|
||||
Explode(a_HitPos.Floor());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cGhastFireballEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
{
|
||||
if (this->IsInvisible())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn())
|
||||
{
|
||||
ReflectFromAttack(a_TDI.Attacker);
|
||||
m_Shooter = a_TDI.Attacker;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -30,15 +30,25 @@ public: // tolua_export
|
||||
|
||||
cGhastFireballEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed);
|
||||
|
||||
cEntity * GetShooter(void) { return m_Shooter; };
|
||||
|
||||
protected:
|
||||
|
||||
void Explode(Vector3i a_Block);
|
||||
|
||||
void ReflectFromAttack(cEntity * a_AttackingEnt);
|
||||
Vector3d NotchReflect(cEntity & a_AttackingEnt);
|
||||
|
||||
// cProjectileEntity overrides:
|
||||
virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override;
|
||||
virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override;
|
||||
|
||||
// TODO: Deflecting the fireballs by arrow- or sword- hits
|
||||
// cEntity overrides:
|
||||
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
||||
|
||||
private:
|
||||
|
||||
cEntity * m_Shooter;
|
||||
|
||||
} ; // tolua_export
|
||||
|
||||
|
@ -64,6 +64,28 @@ bool cGhast::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a_TDI.Attacker != nullptr) && (a_TDI.DamageType == dtExplosion) && (a_TDI.ExplosionSource == esGhastFireball))
|
||||
{
|
||||
a_TDI.FinalDamage = 1000.0F;
|
||||
|
||||
cGhastFireballEntity * GhastFireball = static_cast<cGhastFireballEntity *>(a_TDI.Attacker);
|
||||
|
||||
if (GhastFireball != nullptr)
|
||||
{
|
||||
cEntity * Shooter = GhastFireball->GetShooter();
|
||||
|
||||
if ((Shooter != nullptr) && Shooter->IsPlayer())
|
||||
{
|
||||
cPlayer * Player = static_cast<cPlayer *>(Shooter);
|
||||
|
||||
if (Player != nullptr)
|
||||
{
|
||||
Player->AwardAchievement(CustomStatistic::AchGhast); // Return to Sender!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Super::DoTakeDamage(a_TDI);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "Globals.h"
|
||||
#include "BlockInfo.h"
|
||||
#include "Explodinator.h"
|
||||
#include "Blocks/BlockHandler.h"
|
||||
#include "Blocks/ChunkInterface.h"
|
||||
#include "Chunk.h"
|
||||
#include "ClientHandle.h"
|
||||
@ -202,12 +201,12 @@ namespace Explodinator
|
||||
}
|
||||
|
||||
/** Applies distance-based damage and knockback to all entities within the explosion's effect range. */
|
||||
static void DamageEntities(const cChunk & a_Chunk, const Vector3f a_Position, const int a_Power)
|
||||
static void DamageEntities(cEntity * a_ExplodingEntity, const cChunk & a_Chunk, const Vector3f a_Position, const int a_Power, const eExplosionSource a_ExplosionSource = esOther)
|
||||
{
|
||||
const auto Radius = a_Power * 2;
|
||||
const auto SquareRadius = Radius * Radius;
|
||||
|
||||
a_Chunk.GetWorld()->ForEachEntityInBox({ a_Position, Radius * 2.f }, [&a_Chunk, a_Position, a_Power, Radius, SquareRadius](cEntity & Entity)
|
||||
a_Chunk.GetWorld()->ForEachEntityInBox({ a_Position, Radius * 2.f }, [a_ExplodingEntity, &a_Chunk, a_Position, a_Power, a_ExplosionSource, Radius, SquareRadius](cEntity & Entity)
|
||||
{
|
||||
// Percentage of rays unobstructed.
|
||||
const auto Exposure = CalculateEntityExposure(a_Chunk, Entity, a_Position, SquareRadius);
|
||||
@ -218,7 +217,7 @@ namespace Explodinator
|
||||
if (!Entity.IsTNT() && !Entity.IsFallingBlock())
|
||||
{
|
||||
const auto Damage = (Impact * Impact + Impact) * 7 * a_Power + 1;
|
||||
Entity.TakeDamage(dtExplosion, nullptr, FloorC(Damage), 0);
|
||||
Entity.TakeDamage(dtExplosion, a_ExplodingEntity, FloorC(Damage), 0, a_ExplosionSource);
|
||||
}
|
||||
|
||||
// Impact reduced by armour, expensive call so only apply to Pawns:
|
||||
@ -430,12 +429,12 @@ namespace Explodinator
|
||||
}
|
||||
}
|
||||
|
||||
void Kaboom(cWorld & a_World, const Vector3f a_Position, const int a_Power, const bool a_Fiery, const cEntity * const a_ExplodingEntity)
|
||||
void Kaboom(cWorld & a_World, const Vector3f a_Position, const int a_Power, const bool a_Fiery, cEntity * a_ExplodingEntity, const eExplosionSource a_ExplosionSource)
|
||||
{
|
||||
a_World.DoWithChunkAt(a_Position.Floor(), [a_Position, a_Power, a_Fiery, a_ExplodingEntity](cChunk & a_Chunk)
|
||||
a_World.DoWithChunkAt(a_Position.Floor(), [a_Position, a_Power, a_Fiery, a_ExplodingEntity, a_ExplosionSource](cChunk & a_Chunk)
|
||||
{
|
||||
LagTheClient(a_Chunk, a_Position, a_Power);
|
||||
DamageEntities(a_Chunk, a_Position, a_Power);
|
||||
DamageEntities(a_ExplodingEntity, a_Chunk, a_Position, a_Power, a_ExplosionSource);
|
||||
DamageBlocks(a_Chunk, AbsoluteToRelative(a_Position, a_Chunk.GetPos()), a_Power, a_Fiery, a_ExplodingEntity);
|
||||
|
||||
return false;
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Blocks/BlockHandler.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@ -17,5 +19,5 @@ namespace Explodinator
|
||||
For maximum efficiency, Position should be in the centre of the entity or block that exploded.
|
||||
The entity pointer is used to trigger OnBreak for the destroyed blocks.
|
||||
Kaboom indeed, you drunken wretch. */
|
||||
void Kaboom(cWorld & World, Vector3f Position, int Power, bool Fiery, const cEntity * a_ExplodingEntity);
|
||||
void Kaboom(cWorld & World, Vector3f Position, int Power, bool Fiery, cEntity * a_ExplodingEntity, const eExplosionSource = esOther);
|
||||
}
|
||||
|
@ -1370,7 +1370,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
|
||||
{
|
||||
// TODO: CanCauseFire gets reset to false for some reason, (plugin has ability to change it, might be related)
|
||||
|
||||
const cEntity * Entity;
|
||||
cEntity * Entity;
|
||||
switch (a_Source)
|
||||
{
|
||||
case eExplosionSource::esEnderCrystal:
|
||||
@ -1380,7 +1380,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
|
||||
case eExplosionSource::esWitherBirth:
|
||||
case eExplosionSource::esWitherSkull:
|
||||
{
|
||||
Entity = static_cast<const cEntity *>(a_SourceData);
|
||||
Entity = static_cast<cEntity *>(a_SourceData);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1389,7 +1389,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
|
||||
}
|
||||
}
|
||||
|
||||
Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC(a_ExplosionSize), a_CanCauseFire, Entity);
|
||||
Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC(a_ExplosionSize), a_CanCauseFire, Entity, a_Source);
|
||||
cPluginManager::Get()->CallHookExploded(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user