mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-14 22:01:59 +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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFallDamagePerBlock() : float{
|
||||||
|
return 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMaxFallDamage() : float{
|
||||||
|
return 40.0;
|
||||||
|
}
|
||||||
|
|
||||||
public function getLandSound() : ?Sound{
|
public function getLandSound() : ?Sound{
|
||||||
return new AnvilFallSound();
|
return new AnvilFallSound();
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,18 @@ interface Fallable{
|
|||||||
*/
|
*/
|
||||||
public function onHitGround(FallingBlock $blockEntity) : bool;
|
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.
|
* Returns the sound that will be played when FallingBlock hits the ground.
|
||||||
*/
|
*/
|
||||||
|
@ -64,6 +64,14 @@ trait FallableTrait{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFallDamagePerBlock() : float{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMaxFallDamage() : float{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
public function getLandSound() : ?Sound{
|
public function getLandSound() : ?Sound{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@ use function max;
|
|||||||
use function min;
|
use function min;
|
||||||
use function mt_getrandmax;
|
use function mt_getrandmax;
|
||||||
use function mt_rand;
|
use function mt_rand;
|
||||||
|
use function round;
|
||||||
use function sqrt;
|
use function sqrt;
|
||||||
use const M_PI;
|
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(-$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);
|
$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){
|
if($damage > 0){
|
||||||
$attacker->attack(new EntityDamageByEntityEvent($this, $attacker, EntityDamageEvent::CAUSE_MAGIC, $damage));
|
$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\data\SavedDataLoadingException;
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\entity\EntitySizeInfo;
|
use pocketmine\entity\EntitySizeInfo;
|
||||||
|
use pocketmine\entity\Living;
|
||||||
use pocketmine\entity\Location;
|
use pocketmine\entity\Location;
|
||||||
use pocketmine\event\entity\EntityBlockChangeEvent;
|
use pocketmine\event\entity\EntityBlockChangeEvent;
|
||||||
|
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\nbt\tag\ByteTag;
|
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\format\io\GlobalBlockStateHandlers;
|
||||||
use pocketmine\world\sound\BlockBreakSound;
|
use pocketmine\world\sound\BlockBreakSound;
|
||||||
use function abs;
|
use function abs;
|
||||||
|
use function min;
|
||||||
|
use function round;
|
||||||
|
|
||||||
class FallingBlock extends Entity{
|
class FallingBlock extends Entity{
|
||||||
private const TAG_FALLING_BLOCK = "FallingBlock"; //TAG_Compound
|
private const TAG_FALLING_BLOCK = "FallingBlock"; //TAG_Compound
|
||||||
@ -156,8 +160,20 @@ class FallingBlock extends Entity{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function onHitGround() : ?float{
|
protected function onHitGround() : ?float{
|
||||||
if($this->block instanceof Fallable && !$this->block->onHitGround($this)){
|
if($this->block instanceof Fallable){
|
||||||
$this->flagForDespawn();
|
$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;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
|
|||||||
public const MODIFIER_TOTEM = 8;
|
public const MODIFIER_TOTEM = 8;
|
||||||
public const MODIFIER_WEAPON_ENCHANTMENTS = 9;
|
public const MODIFIER_WEAPON_ENCHANTMENTS = 9;
|
||||||
public const MODIFIER_PREVIOUS_DAMAGE_COOLDOWN = 10;
|
public const MODIFIER_PREVIOUS_DAMAGE_COOLDOWN = 10;
|
||||||
|
public const MODIFIER_ARMOR_HELMET = 11;
|
||||||
|
|
||||||
public const CAUSE_CONTACT = 0;
|
public const CAUSE_CONTACT = 0;
|
||||||
public const CAUSE_ENTITY_ATTACK = 1;
|
public const CAUSE_ENTITY_ATTACK = 1;
|
||||||
@ -63,6 +64,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
|
|||||||
public const CAUSE_MAGIC = 13;
|
public const CAUSE_MAGIC = 13;
|
||||||
public const CAUSE_CUSTOM = 14;
|
public const CAUSE_CUSTOM = 14;
|
||||||
public const CAUSE_STARVATION = 15;
|
public const CAUSE_STARVATION = 15;
|
||||||
|
public const CAUSE_FALLING_BLOCK = 16;
|
||||||
|
|
||||||
private float $baseDamage;
|
private float $baseDamage;
|
||||||
private float $originalBase;
|
private float $originalBase;
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\event\player;
|
|||||||
|
|
||||||
use pocketmine\block\BlockTypeIds;
|
use pocketmine\block\BlockTypeIds;
|
||||||
use pocketmine\entity\Living;
|
use pocketmine\entity\Living;
|
||||||
|
use pocketmine\entity\object\FallingBlock;
|
||||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
@ -155,6 +156,19 @@ class PlayerDeathEvent extends EntityDeathEvent{
|
|||||||
case EntityDamageEvent::CAUSE_MAGIC:
|
case EntityDamageEvent::CAUSE_MAGIC:
|
||||||
return KnownTranslationFactory::death_attack_magic($name);
|
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:
|
case EntityDamageEvent::CAUSE_CUSTOM:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user