mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 08:44:01 +00:00
Added proper arrows and damage
This commit is contained in:
parent
7aeacf2705
commit
bf839e821c
@ -1545,7 +1545,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
new Float("", $this->pitch)
|
||||
]),
|
||||
]);
|
||||
$arrow = new Arrow($this->chunk, $nbt);
|
||||
$arrow = new Arrow($this->chunk, $nbt, $this);
|
||||
$arrow->spawnToAll();
|
||||
}
|
||||
//}
|
||||
|
@ -22,8 +22,12 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\level\format\FullChunk;
|
||||
use pocketmine\level\MovingObjectPosition;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\network\protocol\AddEntityPacket;
|
||||
@ -36,9 +40,20 @@ class Arrow extends Projectile{
|
||||
public $width = 0.5;
|
||||
public $length = 0.5;
|
||||
public $height = 0.5;
|
||||
|
||||
/** @var Entity */
|
||||
public $shootingEntity = null;
|
||||
|
||||
protected $gravity = 0.05;
|
||||
protected $drag = 0.01;
|
||||
|
||||
private $damage = 6;
|
||||
|
||||
public function __construct(FullChunk $chunk, Compound $nbt, Entity $shootingEntity = null){
|
||||
$this->shootingEntity = $shootingEntity;
|
||||
parent::__construct($chunk, $nbt);
|
||||
}
|
||||
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Arrow");
|
||||
$this->setMaxHealth(1);
|
||||
@ -46,6 +61,7 @@ class Arrow extends Projectile{
|
||||
if(isset($this->namedtag->Age)){
|
||||
$this->age = $this->namedtag["Age"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function onUpdate(){
|
||||
@ -55,9 +71,64 @@ class Arrow extends Projectile{
|
||||
return false;
|
||||
}
|
||||
|
||||
$movingObjectPosition = null;
|
||||
|
||||
$this->motionY -= $this->gravity;
|
||||
|
||||
$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
|
||||
$moveVector = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
|
||||
|
||||
$list = $this->getLevel()->getCollidingEntities($this->boundingBox->addCoord($this->motionX, $this->motionY, $this->motionZ)->expand(1, 1, 1), $this);
|
||||
|
||||
$nearDistance = PHP_INT_MAX;
|
||||
$nearEntity = null;
|
||||
|
||||
|
||||
foreach($list as $entity){
|
||||
if(!$entity->canCollideWith($this) or ($entity === $this->shootingEntity and $this->ticksLived < 5)){
|
||||
continue;
|
||||
}
|
||||
|
||||
$axisalignedbb = $entity->boundingBox->grow(0.3, 0.3, 0.3);
|
||||
$ob = $axisalignedbb->calculateIntercept($this, $moveVector);
|
||||
|
||||
if($ob === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$distance = $this->distance($ob->hitVector);
|
||||
|
||||
if($distance < $nearDistance){
|
||||
$nearDistance = $distance;
|
||||
$nearEntity = $entity;
|
||||
}
|
||||
}
|
||||
|
||||
if($nearEntity !== null){
|
||||
$movingObjectPosition = MovingObjectPosition::fromEntity($nearEntity);
|
||||
}
|
||||
|
||||
if($movingObjectPosition !== null){
|
||||
if($movingObjectPosition->entityHit !== null){
|
||||
$motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2);
|
||||
$damage = ceil($motion * $this->damage);
|
||||
|
||||
|
||||
$ev = new EntityDamageByEntityEvent($this->shootingEntity === null ? $this : $this->shootingEntity, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$movingObjectPosition->entityHit->attack($damage, $ev);
|
||||
if($this->fireTicks > 0){
|
||||
$movingObjectPosition->entityHit->setOnFire(5);
|
||||
}
|
||||
$this->kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
$friction = 1 - $this->drag;
|
||||
@ -81,6 +152,12 @@ class Arrow extends Projectile{
|
||||
$this->motionZ = 0;
|
||||
}
|
||||
|
||||
if($this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0){
|
||||
$f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2));
|
||||
$this->yaw = (atan2($this->motionX, $this->motionZ) * 180 / M_PI);
|
||||
$this->pitch = (atan2($this->motionY, $f) * 180 / M_PI);
|
||||
}
|
||||
|
||||
if($this->age > 1200){
|
||||
$this->kill();
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ abstract class Entity extends Position implements Metadatable{
|
||||
}
|
||||
|
||||
public function canCollideWith(Entity $entity){
|
||||
return !$this->justCreated;
|
||||
return !$this->justCreated and $entity !== $this;
|
||||
}
|
||||
|
||||
protected function checkObstruction($x, $y, $z){
|
||||
|
@ -723,7 +723,6 @@ class Level implements ChunkManager, Metadatable{
|
||||
return $collides;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Block object on the Vector3 location
|
||||
*
|
||||
|
83
src/pocketmine/level/MovingObjectPosition.php
Normal file
83
src/pocketmine/level/MovingObjectPosition.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\level;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class MovingObjectPosition{
|
||||
|
||||
/** 0 = block, 1 = entity */
|
||||
public $typeOfHit;
|
||||
|
||||
public $blockX;
|
||||
public $blockY;
|
||||
public $blockZ;
|
||||
|
||||
/**
|
||||
* Which side was hit. If its -1 then it went the full length of the ray trace.
|
||||
* Bottom = 0, Top = 1, East = 2, West = 3, North = 4, South = 5.
|
||||
*/
|
||||
public $sideHit;
|
||||
|
||||
/** @var Vector3 */
|
||||
public $hitVector;
|
||||
|
||||
/** @var Entity */
|
||||
public $entityHit = null;
|
||||
|
||||
protected function __construct(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $side
|
||||
* @param Vector3 $hitVector
|
||||
*
|
||||
* @return MovingObjectPosition
|
||||
*/
|
||||
public static function fromBlock($x, $y, $z, $side, Vector3 $hitVector){
|
||||
$ob = new MovingObjectPosition;
|
||||
$ob->typeOfHit = 0;
|
||||
$ob->blockX = $x;
|
||||
$ob->blockY = $y;
|
||||
$ob->blockZ = $z;
|
||||
$ob->hitVector = new Vector3($hitVector->x, $hitVector->y, $hitVector->z);
|
||||
return $ob;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*
|
||||
* @return MovingObjectPosition
|
||||
*/
|
||||
public static function fromEntity(Entity $entity){
|
||||
$ob = new MovingObjectPosition;
|
||||
$ob->typeOfHit = 1;
|
||||
$ob->entityHit = $entity;
|
||||
$ob->hitVector = new Vector3($entity->x, $entity->y, $entity->z);
|
||||
return $ob;
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
namespace pocketmine\math;
|
||||
use pocketmine\level\MovingObjectPosition;
|
||||
|
||||
/**
|
||||
* WARNING: This class is available on the PocketMine-MP Zephir project.
|
||||
@ -54,25 +55,27 @@ class AxisAlignedBB{
|
||||
}
|
||||
|
||||
public function addCoord($x, $y, $z){
|
||||
$vec = clone $this;
|
||||
|
||||
if($x < 0){
|
||||
$this->minX += $x;
|
||||
$vec->minX += $x;
|
||||
}elseif($x > 0){
|
||||
$this->maxX += $x;
|
||||
$vec->maxX += $x;
|
||||
}
|
||||
|
||||
if($y < 0){
|
||||
$this->minY += $y;
|
||||
$vec->minY += $y;
|
||||
}elseif($y > 0){
|
||||
$this->maxY += $y;
|
||||
$vec->maxY += $y;
|
||||
}
|
||||
|
||||
if($z < 0){
|
||||
$this->minZ += $z;
|
||||
$vec->minZ += $z;
|
||||
}elseif($z > 0){
|
||||
$this->maxZ += $z;
|
||||
$vec->maxZ += $z;
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $vec;
|
||||
}
|
||||
|
||||
public function grow($x, $y, $z){
|
||||
@ -261,9 +264,81 @@ class AxisAlignedBB{
|
||||
return $vector->x >= $this->minX and $vector->x <= $this->maxX and $vector->y >= $this->minY and $vector->y <= $this->maxY;
|
||||
}
|
||||
|
||||
/*
|
||||
public function calculateIntercept(...){
|
||||
|
||||
|
||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2){
|
||||
$v1 = $pos1->getIntermediateWithXValue($pos2, $this->minX);
|
||||
$v2 = $pos1->getIntermediateWithXValue($pos2, $this->maxX);
|
||||
$v3 = $pos1->getIntermediateWithYValue($pos2, $this->minY);
|
||||
$v4 = $pos1->getIntermediateWithYValue($pos2, $this->maxY);
|
||||
$v5 = $pos1->getIntermediateWithZValue($pos2, $this->minZ);
|
||||
$v6 = $pos1->getIntermediateWithZValue($pos2, $this->maxZ);
|
||||
|
||||
if($v1 !== null and !$this->isVectorInYZ($v1)){
|
||||
$v1 = null;
|
||||
}
|
||||
|
||||
if($v2 !== null and !$this->isVectorInYZ($v2)){
|
||||
$v2 = null;
|
||||
}
|
||||
|
||||
if($v3 !== null and !$this->isVectorInXZ($v3)){
|
||||
$v3 = null;
|
||||
}
|
||||
|
||||
if($v4 !== null and !$this->isVectorInXZ($v4)){
|
||||
$v4 = null;
|
||||
}
|
||||
|
||||
if($v5 !== null and !$this->isVectorInXY($v5)){
|
||||
$v5 = null;
|
||||
}
|
||||
|
||||
if($v6 !== null and !$this->isVectorInXY($v6)){
|
||||
$v6 = null;
|
||||
}
|
||||
|
||||
$vector = $v1;
|
||||
|
||||
if($v2 !== null and ($vector === null or $pos1->distanceSquared($v2) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v2;
|
||||
}
|
||||
|
||||
if($v3 !== null and ($vector === null or $pos1->distanceSquared($v3) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v3;
|
||||
}
|
||||
|
||||
if($v4 !== null and ($vector === null or $pos1->distanceSquared($v4) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v4;
|
||||
}
|
||||
|
||||
if($v5 !== null and ($vector === null or $pos1->distanceSquared($v5) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v5;
|
||||
}
|
||||
|
||||
if($v6 !== null and ($vector === null or $pos1->distanceSquared($v6) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v6;
|
||||
}
|
||||
|
||||
if($vector === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
$f = -1;
|
||||
|
||||
if($vector === $v1){
|
||||
$f = 4;
|
||||
}elseif($vector === $v2){
|
||||
$f = 5;
|
||||
}elseif($vector === $v3){
|
||||
$f = 0;
|
||||
}elseif($vector === $v4){
|
||||
$f = 1;
|
||||
}elseif($vector === $v5){
|
||||
$f = 2;
|
||||
}elseif($vector === $v6){
|
||||
$f = 3;
|
||||
}
|
||||
|
||||
return MovingObjectPosition::fromBlock(0, 0, 0, $f, $vector);
|
||||
}
|
||||
*/
|
||||
}
|
@ -200,6 +200,87 @@ class Vector3{
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new vector with x value equal to the second parameter, along the line between this vector and the
|
||||
* passed in vector, or null if not possible.
|
||||
*
|
||||
* @param Vector3 $v
|
||||
* @param float $x
|
||||
*
|
||||
* @return Vector3
|
||||
*/
|
||||
public function getIntermediateWithXValue(Vector3 $v, $x){
|
||||
$xDiff = $v->x - $this->x;
|
||||
$yDiff = $v->y - $this->y;
|
||||
$zDiff = $v->z - $this->z;
|
||||
|
||||
if(($xDiff ** 2) < 1){
|
||||
return null;
|
||||
}
|
||||
|
||||
$f = ($x - $this->x) / $xDiff;
|
||||
|
||||
if($f < 0 or $f > 1){
|
||||
return null;
|
||||
}else{
|
||||
return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $this->z + $zDiff * $f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new vector with y value equal to the second parameter, along the line between this vector and the
|
||||
* passed in vector, or null if not possible.
|
||||
*
|
||||
* @param Vector3 $v
|
||||
* @param float $y
|
||||
*
|
||||
* @return Vector3
|
||||
*/
|
||||
public function getIntermediateWithYValue(Vector3 $v, $y){
|
||||
$xDiff = $v->x - $this->x;
|
||||
$yDiff = $v->y - $this->y;
|
||||
$zDiff = $v->z - $this->z;
|
||||
|
||||
if(($yDiff ** 2) < 1){
|
||||
return null;
|
||||
}
|
||||
|
||||
$f = ($y - $this->y) / $yDiff;
|
||||
|
||||
if($f < 0 or $f > 1){
|
||||
return null;
|
||||
}else{
|
||||
return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $this->z + $zDiff * $f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new vector with z value equal to the second parameter, along the line between this vector and the
|
||||
* passed in vector, or null if not possible.
|
||||
*
|
||||
* @param Vector3 $v
|
||||
* @param float $z
|
||||
*
|
||||
* @return Vector3
|
||||
*/
|
||||
public function getIntermediateWithZValue(Vector3 $v, $z){
|
||||
$xDiff = $v->x - $this->x;
|
||||
$yDiff = $v->y - $this->y;
|
||||
$zDiff = $v->z - $this->z;
|
||||
|
||||
if(($zDiff ** 2) < 1){
|
||||
return null;
|
||||
}
|
||||
|
||||
$f = ($z - $this->z) / $zDiff;
|
||||
|
||||
if($f < 0 or $f > 1){
|
||||
return null;
|
||||
}else{
|
||||
return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $this->z + $zDiff * $f);
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
return "Vector3(x=" . $this->x . ",y=" . $this->y . ",z=" . $this->z . ")";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user