tics++; $mo = $w->player->mo; $cmd = ['forward' => 1.0, 'side' => 0.0, 'turn' => 0.0, 'fire' => false, 'use' => $this->tics % 24 < 2, 'weapon' => null]; // the nearest monster in sight $best = null; $bestD = 1400.0; foreach ($w->mobjs as $th) { if (!$th->is(Info::COUNTKILL) || $th->health <= 0) { continue; } $d = hypot($th->x - $mo->x, $th->y - $mo->y); if ($d < $bestD && $w->checkSight($mo, $th)) { $best = $th; $bestD = $d; } } if ($best !== null) { $want = atan2($best->y - $mo->y, $best->x - $mo->x); $delta = fmod($want - $mo->angle + 5 * M_PI, 2 * M_PI) - M_PI; $cmd['turn'] = max(-0.12, min(0.12, $delta)); $cmd['fire'] = abs($delta) < 0.12; $cmd['forward'] = $bestD > 200 ? 0.5 : -0.3; $cmd['side'] = sin($this->tics / 20) * 0.6; // the best weapon it has foreach ([4, 3, 2] as $n) { $def = Weapons::LIST[$n]; if (!empty($w->player->weapons[$n]) && $w->player->ammo[$def['ammo']] > 0) { $cmd['weapon'] = $n; break; } } return $cmd; } // wander: turn when stuck $moved = hypot($mo->x - $this->lastX, $mo->y - $this->lastY); $this->lastX = $mo->x; $this->lastY = $mo->y; $this->stuck = $moved < 0.6 ? $this->stuck + 1 : 0; if ($this->stuck > 6 && $this->turnLeft == 0.0) { $this->turnLeft = (M_PI / 2 + ($w->random() / 255) * M_PI) * (($w->random() & 1) ? 1 : -1); $this->stuck = 0; } if ($this->turnLeft != 0.0) { $step = max(-0.12, min(0.12, $this->turnLeft)); $cmd['turn'] = $step; $this->turnLeft -= $step; if (abs($this->turnLeft) < 0.01) { $this->turnLeft = 0.0; } $cmd['forward'] = 0.2; } return $cmd; } }