Added proper arrows and damage

This commit is contained in:
Shoghi Cervantes 2014-08-30 01:22:46 +02:00
parent 7aeacf2705
commit bf839e821c
7 changed files with 329 additions and 14 deletions

View File

@ -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();
}
//}

View File

@ -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();
}

View File

@ -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){

View File

@ -723,7 +723,6 @@ class Level implements ChunkManager, Metadatable{
return $collides;
}
/**
* Gets the Block object on the Vector3 location
*

View 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;
}
}

View File

@ -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);
}
*/
}

View File

@ -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 . ")";
}