/** * Handle Standard Abstract Npcs * * @param String $victim * @param Player $player * @param Array $npcs * @return array [$npc_template, $combat_data] */ private function attackAbstractNpc($victim, Player $player, $npcs) { $npc_stats = $npcs[$victim]; // Pull an npcs individual stats with generic fallbacks. $npco = new Npc($npc_stats); // Construct the npc object. $display_name = isset($npc_stats['name']) ? $npc_stats['name'] : ucfirst($victim); $status_effect = isset($npc_stats['status']) ? $npc_stats['status'] : null; $reward_item = isset($npc_stats['item']) && $npc_stats['item'] ? $npc_stats['item'] : null; $is_quick = (bool) ($npco->getSpeed() > $player->getSpeed()); // Beyond basic speed and they see you coming, so show that message. $is_weaker = $npco->getStrength() * 3 < $player->getStrength(); // Npc much weaker? $is_stronger = $npco->getStrength() > $player->getStrength() * 3; // Npc More than twice as strong? $image = isset($npc_stats['img']) ? $npc_stats['img'] : null; // Assume defeat... $victory = false; $received_gold = null; $received_items = null; $added_bounty = ''; $is_rewarded = null; // Gets items or gold. $statuses = null; $status_classes = null; $image_path = null; // If the image exists, set the path to it for use on the page. if ($image && file_exists(SERVER_ROOT . 'www/images/characters/' . $image)) { $image_path = IMAGE_ROOT . 'characters/' . $image; } // ******* FIGHT Logic *********** $npc_damage = $npco->damage(); $survive_fight = $player->harm($npc_damage); $kill_npc = $npco->getHealth() < $player->damage(); if ($survive_fight > 0) { // The ninja survived, they get any gold the npc has. $received_gold = $this->calcReceivedGold($npco, (bool) $reward_item); $player->setGold($player->gold + $received_gold); $received_items = array(); if ($kill_npc) { $victory = true; // Victory occurred, reward the poor sap. if ($npco->inventory()) { $inventory = new Inventory($player); foreach (array_keys($npco->inventory()) as $l_item) { $item = Item::findByIdentity($l_item); $received_items[] = $item->getName(); $inventory->add($item->identity(), 1); } } // Add bounty where applicable for npcs. if ($npco->bountyMod() > 0 && $player->level > self::MIN_LEVEL_FOR_BOUNTY && $player->level <= self::MAX_LEVEL_FOR_BOUNTY) { $added_bounty = Combat::runBountyExchange($player, $npco, $npco->bountyMod()); } } $is_rewarded = (bool) $received_gold || (bool) count($received_items); if (isset($npc_stats['status']) && null !== $npc_stats['status']) { $player->addStatus($npc_stats['status']); // Get the statuses and status classes for display. $statuses = implode(', ', Player::getStatusList()); $status_classes = implode(' ', Player::getStatusList()); } } $player->save(); return ['npc.abstract.tpl', ['victim' => $victim, 'display_name' => $display_name, 'attack_damage' => $npc_damage, 'status_effect' => $status_effect, 'display_statuses' => $statuses, 'display_statuses_classes' => $status_classes, 'received_gold' => $received_gold, 'received_display_items' => $received_items, 'is_rewarded' => $is_rewarded, 'victory' => $victory, 'survive_fight' => $survive_fight, 'kill_npc' => $kill_npc, 'image_path' => $image_path, 'npc_stats' => $npc_stats, 'is_quick' => $is_quick, 'added_bounty' => $added_bounty, 'is_villager' => $npco->hasTrait('villager'), 'race' => $npco->race(), 'is_weaker' => $is_weaker, 'is_stronger' => $is_stronger]]; }
public function testControllerAttackAsIfAgainstAMerchant2() { $_SERVER['REQUEST_URI'] = '/npc/attack/merchant2'; $init_gold = $this->char->gold(); $npco = new Npc('merchant2'); $response = $this->controller->attack(); $final_char = Player::find($this->char->id()); $this->assertNotEmpty($response); $this->assertEquals('merchant2', $response['parts']['victim']); $this->assertGreaterThan(0, $npco->min_gold()); $this->assertGreaterThan($init_gold, $final_char->gold()); }
function testGuardsThatMatchStrengthTakeEnemyStrength() { if (!DEBUG) { $this->markTestSkipped(); } $player = new Player(); $player->strength = 100; $guard = new Npc('guard2'); $guard_max_damage = $guard->maxDamage(); $guard_with_enemy = new Npc('guard2'); $improved_dam = $guard_with_enemy->maxDamage($player); $this->assertTrue($guard->hasTrait('partial_match_strength')); $this->assertGreaterThan(0, $guard_max_damage); $this->assertGreaterThan($guard_max_damage, $improved_dam, 'Guard damage should be higher with an enemy that has any strength'); }
public function testControllerAttackAsIfAgainstAMerchant2() { $this->markTestSkipped('Merchants are unreliable to test for now.'); RequestWrapper::inject(Request::create('/npc/attack/merchant2')); $this->char->strength = 9999; $this->char->health = 9999; $init_gold = $this->char->gold; $npco = new Npc('merchant2'); $response = $this->controller->attack($this->m_dependencies); $final_char = Player::find($this->char->id()); $this->assertNotEmpty($response); $reflection = new \ReflectionProperty(get_class($response), 'data'); $reflection->setAccessible(true); $response_data = $reflection->getValue($response); $this->assertEquals('merchant2', $response_data['victim']); $this->assertGreaterThan(0, $npco->minGold()); $this->assertGreaterThan($init_gold, $final_char->gold); }