mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-06 09:56:06 +00:00
Moved bow functionality out of Player
This commit is contained in:
@ -23,6 +23,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\item;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Projectile;
|
||||
use pocketmine\event\entity\EntityShootBowEvent;
|
||||
use pocketmine\event\entity\ProjectileLaunchEvent;
|
||||
use pocketmine\level\sound\LaunchSound;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\DoubleTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Bow extends Tool{
|
||||
public function __construct(int $meta = 0){
|
||||
@ -36,4 +47,79 @@ class Bow extends Tool{
|
||||
public function getMaxDurability(){
|
||||
return 385;
|
||||
}
|
||||
|
||||
public function onReleaseUsing(Player $player) : bool{
|
||||
if($player->isSurvival() and !$player->getInventory()->contains(ItemFactory::get(Item::ARROW, 0, 1))){
|
||||
$player->getInventory()->sendContents($player);
|
||||
}
|
||||
|
||||
$nbt = new CompoundTag("", [
|
||||
new ListTag("Pos", [
|
||||
new DoubleTag("", $player->x),
|
||||
new DoubleTag("", $player->y + $player->getEyeHeight()),
|
||||
new DoubleTag("", $player->z)
|
||||
]),
|
||||
new ListTag("Motion", [
|
||||
new DoubleTag("", -sin($player->yaw / 180 * M_PI) * cos($player->pitch / 180 * M_PI)),
|
||||
new DoubleTag("", -sin($player->pitch / 180 * M_PI)),
|
||||
new DoubleTag("", cos($player->yaw / 180 * M_PI) * cos($player->pitch / 180 * M_PI))
|
||||
]),
|
||||
new ListTag("Rotation", [
|
||||
//yaw/pitch for arrows taken crosswise, not along the arrow shaft.
|
||||
new FloatTag("", ($player->yaw > 180 ? 360 : 0) - $player->yaw), //arrow yaw must range from -180 to +180
|
||||
new FloatTag("", -$player->pitch)
|
||||
]),
|
||||
new ShortTag("Fire", $player->isOnFire() ? 45 * 60 : 0)
|
||||
]);
|
||||
|
||||
$diff = $player->getItemUseDuration();
|
||||
$p = $diff / 20;
|
||||
$force = min((($p ** 2) + $p * 2) / 3, 1) * 2;
|
||||
|
||||
|
||||
$entity = Entity::createEntity("Arrow", $player->getLevel(), $nbt, $player, $force == 2);
|
||||
if($entity instanceof Projectile){
|
||||
$ev = new EntityShootBowEvent($player, $this, $entity, $force);
|
||||
|
||||
if($force < 0.1 or $diff < 5){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
|
||||
$player->getServer()->getPluginManager()->callEvent($ev);
|
||||
|
||||
$entity = $ev->getProjectile(); //This might have been changed by plugins
|
||||
|
||||
if($ev->isCancelled()){
|
||||
$entity->kill();
|
||||
$player->getInventory()->sendContents($player);
|
||||
}else{
|
||||
$entity->setMotion($entity->getMotion()->multiply($ev->getForce()));
|
||||
if($player->isSurvival()){
|
||||
$player->getInventory()->removeItem(ItemFactory::get(Item::ARROW, 0, 1));
|
||||
$this->setDamage($this->getDamage() + 1);
|
||||
if($this->getDamage() >= $this->getMaxDurability()){
|
||||
$player->getInventory()->setItemInHand(ItemFactory::get(Item::AIR, 0, 0));
|
||||
}else{
|
||||
$player->getInventory()->setItemInHand($this);
|
||||
}
|
||||
}
|
||||
|
||||
if($entity instanceof Projectile){
|
||||
$player->getServer()->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($entity));
|
||||
if($projectileEv->isCancelled()){
|
||||
$ev->getProjectile()->kill();
|
||||
}else{
|
||||
$ev->getProjectile()->spawnToAll();
|
||||
$player->level->addSound(new LaunchSound($player), $player->getViewers());
|
||||
}
|
||||
}else{
|
||||
$entity->spawnToAll();
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$entity->spawnToAll();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user