place !== null) $this->place->getLevel()->removeEntity($this->place->getCoord()); $this->place = $place; if ($this->place !== null) $this->place->getLevel()->insertEntity($this->place->getCoord(), $this); } public function getPlace() { return $this->place; } public function drawPath(Entity $target, $callback) { $targetX = $target->getPlace()->getCoord()->x; $targetY = $target->getPlace()->getCoord()->y; $startX = $this->getPlace()->getCoord()->x; $startY = $this->getPlace()->getCoord()->y; if ($startX == $targetX && $startY == $targetY) return; $diffX = $targetX - $startX; $diffY = $targetY - $startY; $step = max(abs($diffX), abs($diffY)); $stepX = $diffX / $step; $stepY = $diffY / $step; if ($stepX != 0) $steps = floor($diffX / $stepX); else $steps = floor($diffY / $stepY); $x = $startX; $y = $startY; $i = 0; do { $x += $stepX; $y += $stepY; ++$i; if (!$callback(new Coord(floor($x), floor($y)))) return; } while ((floor($x) != $targetX || floor($y) != $targetY) && $i < $steps); } public function canSee(Entity $target) { // Check if already marked as seen if (isset($this->seenCells[$target->getPlace()->getCoord()->x][$target->getPlace()->getCoord()->y])) return true; // Check distance if ($this->getSight() < $this->getPlace()->getCoord()->getDistance($target->getPlace()->getCoord())) return false; // Check each cell on the way for opaque objects $level = $this->getPlace()->getLevel(); $return = true; $seenCells =& $this->seenCells; $this->drawPath($target, function(Coord $coord) use (&$return, $level, $target, &$seenCells) { $obj = $level->whatsAt($coord); if ($obj !== null && $obj != $target && $obj->getVisibility() == Entity::VSB_VISIBLE) { $return = false; return false; } $seenCells[$coord->x][$coord->y] = true; return true; }); return $return; } }