mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-23 00:55:57 +00:00
Implement anvil fall damage (#5312)
This commit is contained in:
parent
04197d6b80
commit
bea878e9e9
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user