Implement anvil fall damage (#5312)

This commit is contained in:
IvanCraft623 2023-03-27 14:17:08 -05:00 committed by GitHub
parent 04197d6b80
commit bea878e9e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 2 deletions

View File

@ -107,6 +107,14 @@ class Anvil extends Transparent implements Fallable{
return true;
}
public function getFallDamagePerBlock() : float{
return 2.0;
}
public function getMaxFallDamage() : float{
return 40.0;
}
public function getLandSound() : ?Sound{
return new AnvilFallSound();
}

View File

@ -42,6 +42,18 @@ interface Fallable{
*/
public function onHitGround(FallingBlock $blockEntity) : bool;
/**
* Returns the damage caused per fallen block. This is multiplied by the fall distance (and capped according to
* {@link Fallable::getMaxFallDamage()}) to calculate the damage dealt to any entities who intersect with the block
* when it hits the ground.
*/
public function getFallDamagePerBlock() : float;
/**
* Returns the maximum damage the block can deal to an entity when it hits the ground.
*/
public function getMaxFallDamage() : float;
/**
* Returns the sound that will be played when FallingBlock hits the ground.
*/

View File

@ -64,6 +64,14 @@ trait FallableTrait{
return true;
}
public function getFallDamagePerBlock() : float{
return 0.0;
}
public function getMaxFallDamage() : float{
return 0.0;
}
public function getLandSound() : ?Sound{
return null;
}

View File

@ -73,6 +73,7 @@ use function max;
use function min;
use function mt_getrandmax;
use function mt_rand;
use function round;
use function sqrt;
use const M_PI;
@ -429,6 +430,10 @@ abstract class Living extends Entity{
$source->setModifier(-$source->getFinalDamage() * min(ceil(min($totalEpf, 25) * (mt_rand(50, 100) / 100)), 20) * 0.04, EntityDamageEvent::MODIFIER_ARMOR_ENCHANTMENTS);
$source->setModifier(-min($this->getAbsorption(), $source->getFinalDamage()), EntityDamageEvent::MODIFIER_ABSORPTION);
if($cause === EntityDamageEvent::CAUSE_FALLING_BLOCK && $this->armorInventory->getHelmet() instanceof Armor){
$source->setModifier(-($source->getFinalDamage() / 4), EntityDamageEvent::MODIFIER_ARMOR_HELMET);
}
}
/**
@ -460,6 +465,15 @@ abstract class Living extends Entity{
if($damage > 0){
$attacker->attack(new EntityDamageByEntityEvent($this, $attacker, EntityDamageEvent::CAUSE_MAGIC, $damage));
}
if($source->getModifier(EntityDamageEvent::MODIFIER_ARMOR_HELMET) < 0){
$helmet = $this->armorInventory->getHelmet();
if($helmet instanceof Armor){
$finalDamage = $source->getFinalDamage();
$this->damageItem($helmet, (int) round($finalDamage * 4 + lcg_value() * $finalDamage * 2));
$this->armorInventory->setHelmet($helmet);
}
}
}
}

View File

@ -30,8 +30,10 @@ use pocketmine\data\bedrock\block\BlockStateDeserializeException;
use pocketmine\data\SavedDataLoadingException;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Living;
use pocketmine\entity\Location;
use pocketmine\event\entity\EntityBlockChangeEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
@ -44,6 +46,8 @@ use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
use pocketmine\world\format\io\GlobalBlockStateHandlers;
use pocketmine\world\sound\BlockBreakSound;
use function abs;
use function min;
use function round;
class FallingBlock extends Entity{
private const TAG_FALLING_BLOCK = "FallingBlock"; //TAG_Compound
@ -156,8 +160,20 @@ class FallingBlock extends Entity{
}
protected function onHitGround() : ?float{
if($this->block instanceof Fallable && !$this->block->onHitGround($this)){
$this->flagForDespawn();
if($this->block instanceof Fallable){
$damagePerBlock = $this->block->getFallDamagePerBlock();
if($damagePerBlock > 0 && ($fallenBlocks = round($this->fallDistance) - 1) > 0){
$damage = min($fallenBlocks * $damagePerBlock, $this->block->getMaxFallDamage());
foreach($this->getWorld()->getCollidingEntities($this->getBoundingBox()) as $entity){
if($entity instanceof Living){
$ev = new EntityDamageByEntityEvent($this, $entity, EntityDamageEvent::CAUSE_FALLING_BLOCK, $damage);
$entity->attack($ev);
}
}
}
if(!$this->block->onHitGround($this)){
$this->flagForDespawn();
}
}
return null;
}

View File

@ -46,6 +46,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
public const MODIFIER_TOTEM = 8;
public const MODIFIER_WEAPON_ENCHANTMENTS = 9;
public const MODIFIER_PREVIOUS_DAMAGE_COOLDOWN = 10;
public const MODIFIER_ARMOR_HELMET = 11;
public const CAUSE_CONTACT = 0;
public const CAUSE_ENTITY_ATTACK = 1;
@ -63,6 +64,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
public const CAUSE_MAGIC = 13;
public const CAUSE_CUSTOM = 14;
public const CAUSE_STARVATION = 15;
public const CAUSE_FALLING_BLOCK = 16;
private float $baseDamage;
private float $originalBase;

View File

@ -25,6 +25,7 @@ namespace pocketmine\event\player;
use pocketmine\block\BlockTypeIds;
use pocketmine\entity\Living;
use pocketmine\entity\object\FallingBlock;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
@ -155,6 +156,19 @@ class PlayerDeathEvent extends EntityDeathEvent{
case EntityDamageEvent::CAUSE_MAGIC:
return KnownTranslationFactory::death_attack_magic($name);
case EntityDamageEvent::CAUSE_FALLING_BLOCK:
if($deathCause instanceof EntityDamageByEntityEvent){
$e = $deathCause->getDamager();
if($e instanceof FallingBlock){
if($e->getBlock()->getTypeId() === BlockTypeIds::ANVIL){
return KnownTranslationFactory::death_attack_anvil($name);
}else{
return KnownTranslationFactory::death_attack_fallingBlock($name);
}
}
}
break;
case EntityDamageEvent::CAUSE_CUSTOM:
break;