/**
  * @return StreamedViewResponse
  */
 private function combat(Player $attacker, Player $target, $required_turns = 0, $options)
 {
     $error = '';
     $stealthed_attack = false;
     $stealth_damage = false;
     $stealth_lost = false;
     $bounty_result = false;
     $rewarded_ki = false;
     $wrath = false;
     $loot = 0;
     $killpoints = 1;
     $rounds = 1;
     $victor = null;
     $loser = null;
     $starting_attacker = clone $attacker;
     $starting_target = clone $target;
     $turns_counter = $options['duel'] ? -1 : 1;
     $attacker_label = $attacker->name();
     if (!$options['duel'] && $attacker->hasStatus(STEALTH)) {
         $stealthed_attack = true;
         $this->stealthStrike($attacker, $target);
         $gold_mod = self::STEALTH_GOLD_MOD;
         if ($target->health > 0) {
             $stealth_damage = true;
         } else {
             $attacker_label = 'a stealthed ninja';
             $victor = $attacker;
             $loser = $target;
         }
         $attack_label = "attacked %s from the shadows";
     } else {
         $gold_mod = $options['duel'] ? self::DUEL_GOLD_MOD : self::DEFAULT_GOLD_MOD;
         if ($attacker->hasStatus(STEALTH)) {
             $stealth_lost = true;
         }
         $attacker->subtractStatus(STEALTH);
         while ($turns_counter != 0 && $attacker->health > 0 && $target->health > 0) {
             $turns_counter--;
             $rounds++;
             $this->strike($attacker, $target, $options['blaze'], $options['deflect']);
             /**
              * Evasion effect:
              *
              * Break off the duel/attack if less than 10% health or
              * health is less than average of defender's strength
              */
             if ($options['evade'] && ($attacker->health < $target->getStrength() * 0.5 || $attacker->health < $attacker->health * 0.1)) {
                 break;
             }
         }
         $attacker->turns = $attacker->turns - max(0, $required_turns);
         $attack_label = $options['duel'] ? 'dueled %s' : 'attacked %s';
     }
     if ($target->health > 0 && $attacker->health > 0) {
         $combat_msg = "%s {$attack_label} for %s damage, but they got away before you could kill them!";
         Event::create($attacker->id(), $target->id(), sprintf($combat_msg, $attacker->name(), 'you', $starting_target->health - $target->health));
         if ($attacker->hasStatus(STEALTH)) {
             $stealth_lost = true;
         }
         $attacker->subtractStatus(STEALTH);
     } else {
         if ($target->health < 1 && $attacker->health < 1) {
             $loot = 0;
             $this->win($attacker, $target, $loot, $killpoints);
             $this->win($target, $attacker, $loot, 1);
             $this->lose($attacker, $target, $loot);
             $this->lose($target, $attacker, $loot);
         } else {
             if ($target->health < 1) {
                 $victor = $attacker;
                 $loser = $target;
                 $bounty_result = Combat::runBountyExchange($victor, $loser);
                 $loot = floor($gold_mod * $loser->gold);
                 if ($options['duel']) {
                     $killpoints = Combat::killpointsFromDueling($attacker, $target);
                     $skillListObj = new Skill();
                     if ($skillListObj->hasSkill('wrath', $attacker)) {
                         // They'll regain some health for the kill, at the end.
                         $attacker->heal(self::BASE_WRATH_REGAIN);
                         $wrath = true;
                     }
                 }
                 $reporting_victor = $victor;
                 if ($victor->hasStatus(STEALTH)) {
                     $reporting_victor = new Player();
                     $reporting_victor->uname = 'a stealthed ninja';
                     $reporting_victor->player_id = 0;
                 }
                 $this->lose($loser, $reporting_victor, $loot);
                 $this->win($victor, $loser, $loot, $killpoints);
             } else {
                 $victor = $target;
                 $loser = $attacker;
                 $loot = floor($gold_mod * $loser->gold);
                 $this->lose($loser, $victor, $loot);
                 $this->win($victor, $loser, $loot, $killpoints);
             }
         }
     }
     if ($options['duel']) {
         $this->logDuel($attacker, $target, $victor, $killpoints);
     }
     if ($rounds > self::EVEN_MATCH_ROUND_COUNT) {
         // Evenly matched battle! Reward some ki to the attacker, even if they die
         $rewarded_ki = self::EVEN_MATCH_KI_REWARD;
         $attacker->setKi($attacker->ki + $rewarded_ki);
     }
     $target->save();
     $attacker->save();
     return new StreamedViewResponse('Battle Status', 'attack_mod.tpl', get_defined_vars(), ['quickstat' => 'player']);
 }
Exemple #2
0
 /**
  * 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]];
 }
Exemple #3
0
 public function testBountyAtLeastMoreThanBountyModFromNpcs()
 {
     $pc = new MockPlayer();
     $pc->difficulty = 0;
     $pc->level = 1;
     $npc = new MockNpc();
     $npc->data['bounty_mod'] = 20;
     $bounty_mess = Combat::runBountyExchange($pc, $npc, $npc->bountyMod());
     // With a high powered pc, some bounty should be put on by attacking a low powered npc.
     $this->assertNotEquals('', $bounty_mess);
 }
 /**
  * Use an item on a target
  * @note /use/ is aliased to useItem externally because use is a php reserved keyword
  */
 public function useItem($give = false, $self_use = false)
 {
     // Formats are:
     // http://nw.local/item/self_use/amanita/
     // http://nw.local/item/use/shuriken/10/
     // http://nw.local/item/give/shuriken/10/
     // http://nw.local/item/use/shuriken/156001/
     $slugs = $this->parse_slugs($give, $self_use);
     // Pull the parsed slugs
     $link_back = $slugs['link_back'];
     $selfTarget = $slugs['selfTarget'];
     $item_in = $slugs['item_in'];
     // Item identifier, either it's id or internal name
     $in_target = $slugs['in_target'];
     $give = $slugs['give'];
     $target = $in_target;
     if (positive_int($in_target)) {
         $target_id = positive_int($target);
     } else {
         $target_id = get_char_id($target);
     }
     $give = in_array($give, array('on', 'Give'));
     $player = new Player(self_char_id());
     $victim_alive = true;
     $using_item = true;
     $item_used = true;
     $stealthLost = false;
     $error = false;
     $suicide = false;
     $kill = false;
     $repeat = false;
     $ending_turns = null;
     $turns_change = null;
     $turns_to_take = null;
     $gold_mod = NULL;
     $result = NULL;
     $targetResult = NULL;
     // result message to send to target of item use
     $targetName = '';
     $targetHealth = '';
     $bountyMessage = '';
     $resultMessage = '';
     $alternateResultMessage = '';
     if ($item_in == (int) $item_in && is_numeric($item_in)) {
         // Can be cast to an id.
         $item = $item_obj = getItemByID($item_in);
     } elseif (is_string($item_in)) {
         $item = $item_obj = $this->getItemByIdentity($item_in);
     } else {
         $item = null;
     }
     if (!is_object($item)) {
         return new RedirectResponse(WEB_ROOT . 'inventory?error=noitem');
     } else {
         $item_count = $this->itemCount($player->id(), $item);
         // Check whether use on self is occurring.
         $self_use = $selfTarget || $target_id === $player->id();
         if ($self_use) {
             $target = $player->name();
             $targetObj = $player;
         } else {
             if ($target_id) {
                 $targetObj = new Player($target_id);
                 $target = $targetObj->name();
             }
         }
         $starting_turns = $player->turns;
         $username_turns = $starting_turns;
         $username_level = $player->level;
         if ($targetObj instanceof Player && $targetObj->id()) {
             $targets_turns = $targetObj->turns;
             $targets_level = $targetObj->level;
             $target_hp = $targetObj->health;
         } else {
             $targets_turns = $targets_level = $target_hp = null;
         }
         $max_power_increase = 10;
         $level_difference = $targets_level - $username_level;
         $level_check = $username_level - $targets_level;
         $near_level_power_increase = $this->nearLevelPowerIncrease($level_difference, $max_power_increase);
         // Sets the page to link back to.
         if ($target_id && ($link_back == "" || $link_back == 'player') && $target_id != $player->id()) {
             $return_to = 'player';
         } else {
             $return_to = 'inventory';
         }
         // Exceptions to the rules, using effects.
         if ($item->hasEffect('wound')) {
             // Minor damage by default items.
             $item->setTargetDamage(rand(1, $item->getMaxDamage()));
             // DEFAULT, overwritable.
             // e.g. Shuriken slices, for some reason.
             if ($item->hasEffect('slice')) {
                 // Minor slicing damage.
                 $item->setTargetDamage(rand(1, max(9, $player->getStrength() - 4)) + $near_level_power_increase);
             }
             // Piercing weapon, and actually does any static damage.
             if ($item->hasEffect('pierce')) {
                 // Minor static piercing damage, e.g. 1-50 plus the near level power increase.
                 $item->setTargetDamage(rand(1, $item->getMaxDamage()) + $near_level_power_increase);
             }
             // Increased damage from damaging effects, minimum of 20.
             if ($item->hasEffect('fire')) {
                 // Major fire damage
                 $item->setTargetDamage(rand(20, $player->getStrength() + 20) + $near_level_power_increase);
             }
         }
         // end of wounds section.
         // Exclusive speed/slow turn changes.
         if ($item->hasEffect('slow')) {
             $item->setTurnChange(-1 * $this->caltropTurnLoss($targets_turns, $near_level_power_increase));
         } else {
             if ($item->hasEffect('speed')) {
                 $item->setTurnChange($item->getMaxTurnChange());
             }
         }
         $turn_change = $item_obj->getTurnChange();
         $itemName = $item->getName();
         $itemType = $item->getType();
         $article = self::getIndefiniteArticle($item_obj->getName());
         if ($give) {
             $turn_cost = 1;
             $using_item = false;
         } else {
             $turn_cost = $item->getTurnCost();
         }
         // Attack Legal section
         $attacker = $player->name();
         $params = ['required_turns' => $turn_cost, 'ignores_stealth' => $item_obj->ignoresStealth(), 'self_use' => $item->isSelfUsable()];
         assert(!!$selfTarget || $attacker != $target);
         $AttackLegal = new AttackLegal($player, $targetObj, $params);
         $attack_allowed = $AttackLegal->check();
         $attack_error = $AttackLegal->getError();
         // *** Any ERRORS prevent attacks happen here  ***
         if (!$attack_allowed) {
             //Checks for error conditions before starting.
             $error = 1;
         } else {
             if (is_string($item) || $target == "") {
                 $error = 2;
             } else {
                 if ($item_count < 1) {
                     $error = 3;
                 } else {
                     /**** MAIN SUCCESSFUL USE ****/
                     if ($give) {
                         $this->giveItem($player->name(), $target, $item->getName());
                         $alternateResultMessage = "__TARGET__ will receive your {$item->getName()}.";
                     } else {
                         if (!$item->isOtherUsable()) {
                             // If it doesn't do damage or have an effect, don't use up the item.
                             $resultMessage = $result = 'This item is not usable on __TARGET__, so it remains unused.';
                             $item_used = false;
                             $using_item = false;
                         } else {
                             if ($item->hasEffect('stealth')) {
                                 $targetObj->addStatus(STEALTH);
                                 $alternateResultMessage = "__TARGET__ is now stealthed.";
                                 $targetResult = ' be shrouded in smoke.';
                             }
                             if ($item->hasEffect('vigor')) {
                                 if ($targetObj->hasStatus(STR_UP1)) {
                                     $result = "__TARGET__'s body cannot become more vigorous!";
                                     $item_used = false;
                                     $using_item = false;
                                 } else {
                                     $targetObj->addStatus(STR_UP1);
                                     $result = "__TARGET__'s muscles experience a strange tingling.";
                                 }
                             }
                             if ($item->hasEffect('strength')) {
                                 if ($targetObj->hasStatus(STR_UP2)) {
                                     $result = "__TARGET__'s body cannot become any stronger!";
                                     $item_used = false;
                                     $using_item = false;
                                 } else {
                                     $targetObj->addStatus(STR_UP2);
                                     $result = "__TARGET__ feels a surge of power!";
                                 }
                             }
                             // Slow and speed effects are exclusive.
                             if ($item->hasEffect('slow')) {
                                 $turns_change = $item->getTurnChange();
                                 if ($targetObj->hasStatus(SLOW)) {
                                     // If the effect is already in play, it will have a decreased effect.
                                     $turns_change = ceil($turns_change * 0.3);
                                     $alternateResultMessage = "__TARGET__ is already moving slowly.";
                                 } else {
                                     if ($targetObj->hasStatus(FAST)) {
                                         $targetObj->subtractStatus(FAST);
                                         $alternateResultMessage = "__TARGET__ is no longer moving quickly.";
                                     } else {
                                         $targetObj->addStatus(SLOW);
                                         $alternateResultMessage = "__TARGET__ begins to move slowly...";
                                     }
                                 }
                                 if ($turns_change == 0) {
                                     $alternateResultMessage .= " You fail to take any turns from __TARGET__.";
                                 }
                                 $targetResult = " lose " . abs($turns_change) . " turns.";
                                 $targetObj->subtractTurns($turns_change);
                             } else {
                                 if ($item->hasEffect('speed')) {
                                     // Note that speed and slow effects are exclusive.
                                     $turns_change = $item->getTurnChange();
                                     if ($targetObj->hasStatus(FAST)) {
                                         // If the effect is already in play, it will have a decreased effect.
                                         $turns_change = ceil($turns_change * 0.5);
                                         $alternateResultMessage = "__TARGET__ is already moving quickly.";
                                     } else {
                                         if ($targetObj->hasStatus(SLOW)) {
                                             $targetObj->subtractStatus(SLOW);
                                             $alternateResultMessage = "__TARGET__ is no longer moving slowly.";
                                         } else {
                                             $targetObj->addStatus(FAST);
                                             $alternateResultMessage = "__TARGET__ begins to move quickly!";
                                         }
                                     }
                                     // Actual turn gain is 1 less because 1 is used each time you use an item.
                                     $targetResult = " gain {$turns_change} turns.";
                                     $targetObj->changeTurns($turns_change);
                                     // Still adding some turns.
                                 }
                             }
                             if ($item->getTargetDamage() > 0) {
                                 // *** HP Altering ***
                                 $alternateResultMessage .= " __TARGET__ takes " . $item->getTargetDamage() . " damage.";
                                 if ($self_use) {
                                     $result .= "You take " . $item->getTargetDamage() . " damage!";
                                 } else {
                                     if (strlen($targetResult) > 0) {
                                         $targetResult .= " You also";
                                         // Join multiple targetResult messages.
                                     }
                                     $targetResult .= " take " . $item->getTargetDamage() . " damage!";
                                 }
                                 $victim_alive = $targetObj->subtractHealth($item->getTargetDamage());
                                 // This is the other location that $victim_alive is set, to determine whether the death proceedings should occur.
                             }
                             if ($item->hasEffect('death')) {
                                 $targetObj->death();
                                 $resultMessage = "The life force drains from __TARGET__ and they drop dead before your eyes!";
                                 $victim_alive = false;
                                 $targetResult = " be drained of your life-force and die!";
                                 $gold_mod = 0.25;
                                 //The Dim Mak takes away 25% of a targets' gold.
                             }
                             if ($turns_change !== null) {
                                 // Even if $turns_change is set to zero, let them know that.
                                 if ($turns_change > 0) {
                                     $resultMessage .= "__TARGET__ has gained back {$turns_change} turns!";
                                 } else {
                                     if ($turns_change === 0) {
                                         $resultMessage .= "__TARGET__ did not lose any turns!";
                                     } else {
                                         $resultMessage .= "__TARGET__ has lost " . abs($turns_change) . " turns!";
                                     }
                                     if ($targetObj->turns <= 0) {
                                         // Message when a target has no more turns to remove.
                                         $resultMessage .= "  __TARGET__ no longer has any turns.";
                                     }
                                 }
                             }
                             if (empty($resultMessage) && !empty($result)) {
                                 $resultMessage = $result;
                             }
                             if (!$victim_alive) {
                                 // Target was killed by the item.
                                 if (!$self_use) {
                                     // *** SUCCESSFUL KILL, not self-use of an item ***
                                     $attacker_id = $player->hasStatus(STEALTH) ? "A Stealthed Ninja" : $player->name();
                                     if (!$gold_mod) {
                                         $gold_mod = 0.15;
                                     }
                                     $initial_gold = $targetObj->gold();
                                     $loot = floor($gold_mod * $initial_gold);
                                     $targetObj->set_gold($initial_gold - $loot);
                                     $player->set_gold($player->gold() + $loot);
                                     $player->save();
                                     $targetObj->save();
                                     $player->addKills(1);
                                     $kill = true;
                                     $bountyMessage = Combat::runBountyExchange($player->name(), $target);
                                     //Rewards or increases bounty.
                                 } else {
                                     $loot = 0;
                                     $suicide = true;
                                 }
                                 // Send mails if the target was killed.
                                 $this->sendKillMails($player->name(), $target, $attacker_id, $article, $item->getName(), $loot);
                             } else {
                                 // They weren't killed.
                                 $attacker_id = $player->name();
                             }
                             if (!$self_use && $item_used) {
                                 if (!$targetResult) {
                                     error_log('Debug: Issue 226 - An attack was made using ' . $item->getName() . ', but no targetResult message was set.');
                                 }
                                 // Notify targets when they get an item used on them.
                                 $message_to_target = "{$attacker_id} has used {$article} {$item->getName()} on you";
                                 if ($targetResult) {
                                     $message_to_target .= " and caused you to {$targetResult}";
                                 } else {
                                     $message_to_target .= '.';
                                 }
                                 send_event($player->id(), $target_id, str_replace('  ', ' ', $message_to_target));
                             }
                             // Unstealth
                             if (!$item->isCovert() && !$item->hasEffect('stealth') && $player->hasStatus(STEALTH)) {
                                 //non-covert acts
                                 $player->subtractStatus(STEALTH);
                                 $stealthLost = true;
                             } else {
                                 $stealthLost = false;
                             }
                         }
                     }
                     $targetName = $targetObj->uname;
                     $targetHealth = $targetObj->health;
                     $turns_to_take = 1;
                     if ($item_used) {
                         // *** remove Item ***
                         removeItem($player->id(), $item->getName(), 1);
                         // *** Decreases the item amount by 1.
                     }
                     if ($victim_alive && $using_item) {
                         $repeat = true;
                     }
                 }
             }
         }
         // *** Take away at least one turn even on attacks that fail to prevent page reload spamming ***
         if ($turns_to_take < 1) {
             $turns_to_take = 1;
         }
         $ending_turns = $player->subtractTurns($turns_to_take);
         assert($item->hasEffect('speed') || $ending_turns < $starting_turns || $starting_turns == 0);
         return ['template' => 'inventory_mod.tpl', 'title' => 'Use Item', 'parts' => get_defined_vars(), 'options' => ['body_classes' => 'inventory-use', 'quickstat' => 'player']];
     }
     // Item was not valid object
 }
Exemple #5
0
     }
     $attacking_player->addKills($killpoints);
     // Attacker gains their killpoints.
     $target_player->death();
     if (!$simultaneousKill) {
         // This stuff only happens if you don't die also.
         $loot = floor($gold_mod * $target_player->gold());
         // Add the wrath health regain to the attacker.
         if (isset($wrath_regain)) {
             $attacking_player->changeHealth($wrath_regain);
         }
     }
     $target_msg = "DEATH: You've been killed by {$attacker} and lost {$loot} gold!";
     sendMessage($attacker, $target, $target_msg);
     // Stopped telling attackers when they win a duel.
     $bounty_result = Combat::runBountyExchange($attacker, $target);
     // *** Determines bounty for dueling. ***
 }
 if ($attackerHealthRemaining < 1) {
     // *** DEFENDER KILLS ATTACKER! ***
     if ($simultaneousKill = $attackerHealthRemaining < 1) {
         // *** If both died at the same time. ***
     } else {
         $victor = $target;
         $loser = $attacker;
     }
     $attacker_died = true;
     $defenderKillpoints = 1;
     if ($duel) {
         // *** if they were dueling when they died ***
         $duel_log_msg = "{$attacker} has dueled {$target} and lost at " . date("F j, Y, g:i a");
 /**
  * Use an item on a target
  *
  * http://nw.local/item/use/shuriken/10/
  *
  * @return Response
  * @note
  * /use/ is aliased to useItem externally because use is a php reserved keyword
  */
 public function useItem(Container $p_dependencies)
 {
     $slugs = $this->parseSlugs();
     $target = $this->findPlayer($slugs['in_target']);
     $player = Player::find(SessionFactory::getSession()->get('player_id'));
     $inventory = new Inventory($player);
     $had_stealth = $player->hasStatus(STEALTH);
     $error = false;
     $turns_to_take = 1;
     // Take away one turn even on attacks that fail to prevent page reload spamming
     $bounty_message = '';
     $display_message = '';
     $extra_message = '';
     $attacker_label = $player->name();
     $loot = null;
     try {
         $item = $this->findItem($slugs['item_in']);
         $article = $item ? self::getIndefiniteArticle($item->getName()) : '';
     } catch (\InvalidArgumentException $e) {
         return new RedirectResponse(WEB_ROOT . 'inventory?error=noitem');
     }
     if (empty($target)) {
         $error = 2;
     } else {
         if ($this->itemCount($player, $item) < 1) {
             $error = 3;
         } else {
             if ($target->id() === $player->id()) {
                 return $this->selfUse();
             } else {
                 $params = ['required_turns' => $item->getTurnCost(), 'ignores_stealth' => $item->ignoresStealth()];
                 $attack_legal = new AttackLegal($player, $target, $params);
                 if (!$attack_legal->check()) {
                     $error = 1;
                     $display_message = $attack_legal->getError();
                 } else {
                     if (!$item->isOtherUsable()) {
                         $error = 1;
                         $display_message = 'This item cannot be used on others!';
                     } else {
                         $result = $this->applyItemEffects($player, $target, $item);
                         if ($result['success']) {
                             $message_to_target = "{$attacker_label} has used {$article} " . $item->getName() . " on you{$result['notice']}";
                             Event::create($player->id(), $target->id(), str_replace('  ', ' ', $message_to_target));
                             $inventory->remove($item->identity(), 1);
                             if ($target->health <= 0) {
                                 // Target was killed by the item
                                 $attacker_label = $player->hasStatus(STEALTH) ? "A Stealthed Ninja" : $player->name();
                                 $gold_mod = $item->hasEffect('death') ? 0.25 : 0.15;
                                 $loot = floor($gold_mod * $target->gold);
                                 $target->setGold($target->gold - $loot);
                                 $player->setGold($player->gold + $loot);
                                 $player->addKills(1);
                                 $bounty_message = Combat::runBountyExchange($player, $target);
                                 //Rewards or increases bounty.
                                 $this->sendKillMails($player, $target, $attacker_label, $article, $item->getName(), $loot);
                             }
                         }
                         $display_message = $result['message'];
                         $extra_message = $result['extra_message'];
                     }
                 }
                 $player->changeTurns(-1 * $turns_to_take);
                 $target->save();
                 $player->save();
             }
         }
     }
     return $this->renderUse(['action' => 'use', 'return_to' => in_array(RequestWrapper::getPostOrGet('link_back'), ['', 'player']) ? 'player' : 'inventory', 'error' => $error, 'target' => $target, 'resultMessage' => $display_message, 'alternateResultMessage' => $extra_message, 'stealthLost' => $had_stealth && $player->hasStatus(STEALTH), 'repeat' => $target->health > 0 && empty($error), 'item' => $item, 'bountyMessage' => $bounty_message, 'article' => $article, 'loot' => $loot]);
 }