public function index()
 {
     $request = RequestWrapper::$request;
     $target = $request->get('player');
     $target_id = $request->get('player_id');
     if ($target_id) {
         $target_player_obj = Player::find($target_id);
     } else {
         $target_player_obj = Player::findByName($target);
     }
     if ($target_player_obj === null) {
         $template = 'no-player.tpl';
         $viewed_name_for_title = null;
         $parts = array();
     } else {
         $attack_error = 'You must become a ninja first.';
         $clan = Clan::findByMember($target_player_obj);
         $combat_skills = null;
         $display_clan_options = false;
         $items = null;
         $same_clan = false;
         $self = false;
         $targeted_skills = null;
         $template = 'player.tpl';
         $viewed_name_for_title = $target_player_obj->name();
         $viewing_player_obj = Player::find(SessionFactory::getSession()->get('player_id'));
         $kills_today = query_item('SELECT sum(killpoints) FROM levelling_log WHERE _player_id = :player_id AND killsdate = CURRENT_DATE AND killpoints > 0', [':player_id' => $target_player_obj->id()]);
         $rank_spot = query_item('SELECT rank_id FROM rankings WHERE player_id = :player_id limit 1', [':player_id' => $target_player_obj->id()]);
         if ($viewing_player_obj !== null) {
             $viewers_clan = Clan::findByMember($viewing_player_obj);
             $self = $viewing_player_obj->id() === $target_player_obj->id();
             $params = ['required_turns' => 0, 'ignores_stealth' => true];
             $AttackLegal = new AttackLegal($viewing_player_obj, $target_player_obj, $params);
             $AttackLegal->check(false);
             $attack_error = $AttackLegal->getError();
             if (!$attack_error && !$self) {
                 // They're not dead or otherwise unattackable.
                 // Pull the items and some necessary data about them.
                 $inventory = new Inventory($viewing_player_obj);
                 $items = $inventory->counts();
                 $skillDAO = new SkillDAO();
                 if (!$viewing_player_obj->isAdmin()) {
                     $combat_skills = $skillDAO->getSkillsByTypeAndClass($viewing_player_obj->_class_id, 'combat', $viewing_player_obj->level);
                     $targeted_skills = $skillDAO->getSkillsByTypeAndClass($viewing_player_obj->_class_id, 'targeted', $viewing_player_obj->level);
                 } else {
                     $combat_skills = $skillDAO->all('combat');
                     $targeted_skills = $skillDAO->all('targeted');
                 }
             }
             if ($clan && $viewers_clan) {
                 $same_clan = $clan->id == $viewers_clan->id;
                 $display_clan_options = !$self && $same_clan && $viewing_player_obj->isClanLeader();
             }
         }
         $parts = ['viewing_player_obj' => $viewing_player_obj, 'target_player_obj' => $target_player_obj, 'combat_skills' => $combat_skills, 'targeted_skills' => $targeted_skills, 'self' => $self, 'rank_spot' => $rank_spot, 'kills_today' => $kills_today, 'status_list' => Player::getStatusList($target_player_obj->id()), 'clan' => $clan, 'items' => $items, 'account' => Account::findByChar($target_player_obj), 'same_clan' => $same_clan, 'display_clan_options' => $display_clan_options, 'attack_error' => $attack_error];
     }
     $parts['authenticated'] = SessionFactory::getSession()->get('authenticated', false);
     $title = 'Ninja' . ($viewed_name_for_title ? ": {$viewed_name_for_title}" : ' Profile');
     return new StreamedViewResponse($title, $template, $parts, ['quickstat' => 'player']);
 }
 /**
  * @return Response
  */
 public function index(Container $p_dependencies)
 {
     $request = RequestWrapper::$request;
     $session = SessionFactory::getSession();
     $options = ['blaze' => (bool) $request->get('blaze'), 'deflect' => (bool) $request->get('deflect'), 'duel' => (bool) $request->get('duel'), 'evade' => (bool) $request->get('evasion'), 'attack' => !(bool) $request->get('duel')];
     $target = Player::find($request->get('target'));
     $attacker = Player::find($session->get('player_id'));
     $skillListObj = new Skill();
     $ignores_stealth = false;
     $required_turns = 0;
     foreach (array_filter($options) as $type => $value) {
         $ignores_stealth = $ignores_stealth || $skillListObj->getIgnoreStealth($type);
         $required_turns += $skillListObj->getTurnCost($type);
     }
     $params = ['required_turns' => $required_turns, 'ignores_stealth' => $ignores_stealth];
     try {
         $rules = new AttackLegal($attacker, $target, $params);
         $attack_is_legal = $rules->check();
         $error = $rules->getError();
     } catch (\InvalidArgumentException $e) {
         $attack_is_legal = false;
         $error = 'Could not determine valid target';
     }
     if (!$attack_is_legal) {
         // Take away at least one turn even on attacks that fail.
         $attacker->turns = $attacker->turns - 1;
         $attacker->save();
         $parts = ['target' => $target, 'attacker' => $attacker, 'error' => $error];
         return new StreamedViewResponse('Battle Status', 'attack_mod.tpl', $parts, ['quickstat' => 'player']);
     } else {
         return $this->combat($attacker, $target, $required_turns, $options);
     }
 }
Exemple #3
0
 /**
  * Test that you can't attack if an excessive amount of turns is required
  */
 public function testCantAttackIfExcessiveAmountOfTurnsIsRequired()
 {
     $confirm = true;
     $char_id = TestAccountCreateAndDestroy::create_testing_account($confirm);
     $this->oldify_character_last_attack($char_id);
     $char_2_id = TestAccountCreateAndDestroy::create_alternate_testing_account($confirm);
     $this->oldify_character_last_attack($char_2_id);
     $char = new Player($char_2_id);
     $legal = new AttackLegal(new Player($char_id), $char, ['required_turns' => 4000000000, 'ignores_stealth' => true]);
     $this->assertFalse($legal->check(false));
 }
 public function index()
 {
     $target = $player = first_value(in('ninja'), in('player'), in('find'), in('target'));
     $target_id = first_value(in('target_id'), in('player_id'), get_char_id($target));
     // Find target_id if possible.
     $target_player_obj = Player::find($target_id);
     $viewed_name_for_title = null;
     if ($target_player_obj !== null) {
         $viewed_name_for_title = $target_player_obj->name();
     }
     if ($target_player_obj === null) {
         $template = 'no-player.tpl';
         $parts = array();
     } else {
         $player_info = $target_player_obj->as_array();
         // Pull the info out of the object.
         if (!$player_info) {
             $template = 'no-player.tpl';
             $parts = array();
         } else {
             $viewing_player_obj = Player::find(self_char_id());
             $self = self_char_id() && self_char_id() == $player_info['player_id'];
             // Record whether this is a self-viewing.
             if ($viewing_player_obj !== null) {
                 $char_info = $viewing_player_obj->dataWithClan();
                 $char_id = $viewing_player_obj->id();
                 $username = $viewing_player_obj->name();
             } else {
                 $char_info = [];
             }
             $player = $target = $player_info['uname'];
             // reset the target and target_id vars.
             $target_id = $player_info['player_id'];
             // Get the player's kills for this date.
             $kills_today = query_item('select sum(killpoints) from levelling_log where _player_id = :player_id and killsdate = CURRENT_DATE and killpoints > 0', array(':player_id' => $target_id));
             $viewers_clan = $viewing_player_obj !== null ? ClanFactory::clanOfMember($viewing_player_obj) : null;
             // Attack Legal section
             $params = array('required_turns' => 0, 'ignores_stealth' => true);
             // 0 for unstealth.
             $attack_error = 'You must become a ninja first.';
             $attack_allowed = false;
             if (null !== $viewing_player_obj) {
                 $AttackLegal = new AttackLegal($viewing_player_obj, $target_player_obj, $params);
                 $attack_allowed = $AttackLegal->check(false);
                 $attack_error = $AttackLegal->getError();
             }
             $sel_rank_spot = "SELECT rank_id FROM rankings WHERE player_id = :char_id limit 1";
             $rank_spot = query_item($sel_rank_spot, array(':char_id' => $player_info['player_id']));
             // Display the player info.
             $status_list = get_status_list($player);
             $gurl = $gravatar_url = $target_player_obj->avatarUrl();
             if ($viewing_player_obj !== null && !$attack_error && !$self) {
                 // They're not dead or otherwise unattackable.
                 // Attack or Duel
                 $skillDAO = new SkillDAO();
                 $is_admin = false;
                 if ($viewing_player_obj) {
                     $is_admin = $viewing_player_obj->isAdmin();
                 }
                 if (!$is_admin) {
                     $combat_skills = $skillDAO->getSkillsByTypeAndClass($viewing_player_obj->_class_id, 'combat', $viewing_player_obj->level);
                     $targeted_skills = $skillDAO->getSkillsByTypeAndClass($viewing_player_obj->_class_id, 'targeted', $viewing_player_obj->level);
                 } else {
                     $combat_skills = $skillDAO->all('combat');
                     $targeted_skills = $skillDAO->all('targeted');
                 }
                 // Pull the items and some necessary data about them.
                 $items = inventory_counts($char_id);
                 $valid_items = rco($items);
                 // row count
             }
             // End of the there-was-no-attack-error section
             $set_bounty_section = '';
             $communication_section = '';
             $player_clan_section = '';
             $clan = ClanFactory::clanOfMember($player_info['player_id']);
             $same_clan = false;
             // Player clan and clan members
             if ($clan) {
                 $viewer_clan = $viewing_player_obj ? ClanFactory::clanOfMember($viewing_player_obj) : null;
                 $clan_id = $clan->getID();
                 $clan_name = $clan->getName();
                 if ($viewer_clan) {
                     $same_clan = $clan->getID() == $viewer_clan->getID();
                     $display_clan_options = $viewing_player_obj && !$self && $same_clan && $viewing_player_obj->isClanLeader();
                 } else {
                     $same_clan = $display_clan_options = false;
                 }
             }
             // Send the info to the template.
             $template = 'player.tpl';
             $parts = get_certain_vars(get_defined_vars(), array('char_info', 'viewing_player_obj', 'target_player_obj', 'combat_skills', 'targeted_skills', 'player_info', 'self', 'rank_spot', 'kills_today', 'gravatar_url', 'status_list', 'clan', 'items'));
         }
     }
     return ['template' => $template, 'title' => 'Ninja' . ($viewed_name_for_title ? ": {$viewed_name_for_title}" : ' Profile'), 'parts' => $parts, 'options' => ['quickstat' => 'player']];
 }
Exemple #5
0
$ending_turns = null;
$level_check = $player->vo->level - $target->vo->level;
if ($player->hasStatus(STEALTH)) {
    $attacker_id = 'A Stealthed Ninja';
}
$use_attack_legal = true;
if ($command == 'Clone Kill' || $command == 'Harmonize') {
    $has_skill = true;
    $use_attack_legal = false;
    $attack_allowed = true;
    $attack_error = null;
    $covert = true;
} else {
    // *** Checks the skill use legality, as long as the target isn't self.
    $params = ['required_turns' => $turn_cost, 'ignores_stealth' => $ignores_stealth, 'self_use' => $self_use];
    $AttackLegal = new AttackLegal($player, $target, $params);
    $attack_allowed = $AttackLegal->check();
    $attack_error = $AttackLegal->getError();
}
if (!$attack_error) {
    // Only bother to check for other errors if there aren't some already.
    if (!$has_skill || $command == '') {
        // Set the attack error to display that that skill wasn't available.
        $attack_error = 'You do not have the requested skill.';
    } elseif ($starting_turns < $turn_cost) {
        $turn_cost = 0;
        $attack_error = "You do not have enough turns to use {$command}.";
    }
}
// Strip down the player info to get the sight data.
function pull_sight_data($target)
 /**
  * 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 #7
0
    $attack_type['duel'] = 'duel';
} else {
    $attack_type['attack'] = 'attack';
}
$target_player = new Player($target);
$attacking_player = new Player(self_char_id());
$attacker = $attacking_player->name();
$skillListObj = new Skill();
$ignores_stealth = false;
foreach ($attack_type as $type) {
    $ignores_stealth = $ignores_stealth || $skillListObj->getIgnoreStealth($type);
    $required_turns += $skillListObj->getTurnCost($type);
}
// *** Attack Legal section ***
$params = array('required_turns' => $required_turns, 'ignores_stealth' => $ignores_stealth);
$attack_legal = new AttackLegal($attacking_player, $target_player, $params);
$attack_is_legal = $attack_legal->check();
$attack_error = $attack_legal->getError();
// ***  MAIN BATTLE ALGORITHM  ***
if ($attack_is_legal) {
    // *** Target's stats. ***
    $target_health = $target_player->health;
    $target_level = $target_player->level;
    $target_str = $target_player->getStrength();
    // *** Attacker's stats. ***
    $attacker_health = $attacking_player->health;
    $attacker_level = $attacking_player->level;
    $attacker_turns = $attacking_player->turns;
    $attacker_str = $attacking_player->getStrength();
    $starting_target_health = $target_health;
    $starting_turns = $attacker_turns;
 /**
  * Use, the skills_mod equivalent
  *
  * @note Test with urls like:
  * http://nw.local/skill/use/Fire%20Bolt/10
  * http://nw.local/skill/self_use/Unstealth/
  * http://nw.local/skill/self_use/Heal/
  */
 public function useSkill($self_use = false)
 {
     // Template vars.
     $display_sight_table = $generic_skill_result_message = $generic_state_change = $killed_target = $loot = $added_bounty = $bounty = $suicided = $destealthed = null;
     $error = null;
     $char_id = SessionFactory::getSession()->get('player_id');
     $player = Player::find($char_id);
     $path = RequestWrapper::getPathInfo();
     $slugs = $this->parseSlugs($path);
     // (fullpath0) /skill1/use2/Fire%20Bolt3/tchalvak4/(beagle5/)
     $act = isset($slugs[3]) ? $slugs[3] : null;
     $target = isset($slugs[4]) ? $slugs[4] : null;
     $target2 = isset($slugs[5]) ? $slugs[5] : null;
     if (!Filter::toNonNegativeInt($target)) {
         if ($self_use) {
             $target = $char_id;
         } else {
             if ($target !== null) {
                 $targetObj = Player::findByName($target);
                 $target = $targetObj ? $targetObj->id() : null;
             } else {
                 $target = null;
             }
         }
     }
     if ($target2 && !Filter::toNonNegativeInt($target2)) {
         $target2Obj = Player::findByName($target2);
         $target2 = $target2Obj ? $target2Obj->id() : null;
     }
     $skillListObj = new Skill();
     // *** Before level-based addition.
     $turn_cost = $skillListObj->getTurnCost(strtolower($act));
     $ignores_stealth = $skillListObj->getIgnoreStealth($act);
     $self_usable = $skillListObj->getSelfUse($act);
     $use_on_target = $skillListObj->getUsableOnTarget($act);
     $ki_cost = 0;
     // Ki taken during use.
     $reuse = true;
     // Able to reuse the skill.
     $today = date("F j, Y, g:i a");
     // Check whether the user actually has the needed skill.
     $has_skill = $skillListObj->hasSkill($act, $player);
     assert($turn_cost >= 0);
     if ($self_use) {
         // Use the skill on himself.
         $return_to_target = false;
         $target = $player;
         $target_id = null;
     } else {
         if ($target != '' && $target != $player->player_id) {
             $target = Player::find($target);
             $target_id = $target->id();
             $return_to_target = true;
         } else {
             // For target that doesn't exist, e.g. http://nw.local/skill/use/Sight/zigzlklkj
             error_log('Info: Attempt to use a skill on a target that did not exist.');
             return new RedirectResponse(WEB_ROOT . 'skill/?error=' . rawurlencode('Invalid target for skill [' . rawurlencode($act) . '].'));
         }
     }
     $covert = false;
     $victim_alive = true;
     $attacker_id = $player->name();
     $attacker_char_id = $player->id();
     $starting_turns = $player->turns;
     $level_check = $player->level - $target->level;
     if ($player->hasStatus(STEALTH)) {
         $attacker_id = 'A Stealthed Ninja';
     }
     $use_attack_legal = true;
     if ($act == 'Clone Kill' || $act == 'Harmonize') {
         $has_skill = true;
         $use_attack_legal = false;
         $attack_allowed = true;
         $attack_error = null;
         $covert = true;
     } else {
         // *** Checks the skill use legality, as long as the target isn't self.
         $params = ['required_turns' => $turn_cost, 'ignores_stealth' => $ignores_stealth, 'self_use' => $self_use];
         $AttackLegal = new AttackLegal($player, $target, $params);
         $update_timer = isset($this->update_timer) ? $this->update_timer : true;
         $attack_allowed = $AttackLegal->check($update_timer);
         $attack_error = $AttackLegal->getError();
     }
     if (!$attack_error) {
         // Only bother to check for other errors if there aren't some already.
         if (!$has_skill || $act == '') {
             // Set the attack error to display that that skill wasn't available.
             $attack_error = 'You do not have the requested skill.';
         } elseif ($starting_turns < $turn_cost) {
             $turn_cost = 0;
             $attack_error = "You do not have enough turns to use {$act}.";
         }
     }
     if (!$attack_error) {
         // Nothing to prevent the attack from happening.
         // Initial attack conditions are alright.
         $result = '';
         if ($act == 'Sight') {
             $covert = true;
             $sight_data = $this->pullSightData($target);
             $display_sight_table = true;
         } elseif ($act == 'Steal') {
             $covert = true;
             $gold_decrease = min($target->gold, rand(5, 50));
             $player->setGold($player->gold + $gold_decrease);
             $player->save();
             $target->setGold($target->gold - $gold_decrease);
             $target->save();
             $msg = "{$attacker_id} stole {$gold_decrease} gold from you.";
             Event::create($attacker_char_id, $target->id(), $msg);
             $generic_skill_result_message = "You have stolen {$gold_decrease} gold from __TARGET__!";
         } else {
             if ($act == 'Unstealth') {
                 $state = 'unstealthed';
                 if ($target->hasStatus(STEALTH)) {
                     $target->subtractStatus(STEALTH);
                     $generic_state_change = "You are now {$state}.";
                 } else {
                     $turn_cost = 0;
                     $generic_state_change = "__TARGET__ is already {$state}.";
                 }
             } else {
                 if ($act == 'Stealth') {
                     $covert = true;
                     $state = 'stealthed';
                     if (!$target->hasStatus(STEALTH)) {
                         $target->addStatus(STEALTH);
                         $target->subtractStatus(STALKING);
                         $generic_state_change = "__TARGET__ is now {$state}.";
                     } else {
                         $turn_cost = 0;
                         $generic_state_change = "__TARGET__ is already {$state}.";
                     }
                 } else {
                     if ($act == 'Stalk') {
                         $state = 'stalking';
                         if (!$target->hasStatus(STALKING)) {
                             $target->addStatus(STALKING);
                             $target->subtractStatus(STEALTH);
                             $generic_state_change = "__TARGET__ is now {$state}.";
                         } else {
                             $turn_cost = 0;
                             $generic_state_change = "__TARGET__ is already {$state}.";
                         }
                     } else {
                         if ($act == 'Kampo') {
                             $covert = true;
                             // *** Get Special Items From Inventory ***
                             $user_id = $player->id();
                             $root_item_type = 7;
                             $itemCount = query_item('SELECT sum(amount) AS c FROM inventory WHERE owner = :owner AND item_type = :type GROUP BY item_type', [':owner' => $user_id, ':type' => $root_item_type]);
                             $turn_cost = min($itemCount, $starting_turns - 1, 2);
                             // Costs 1 or two depending on the number of items.
                             if ($turn_cost && $itemCount > 0) {
                                 // *** If special item count > 0 ***
                                 $inventory = new Inventory($player);
                                 $inventory->remove('ginsengroot', $itemCount);
                                 $inventory->add('tigersalve', $itemCount);
                                 $generic_skill_result_message = 'With intense focus you grind the ' . $itemCount . ' roots into potent formulas.';
                             } else {
                                 // *** no special items, give error message ***
                                 $turn_cost = 0;
                                 $generic_skill_result_message = 'You do not have the necessary ginsengroots or energy to create any Kampo formulas.';
                             }
                         } else {
                             if ($act == 'Poison Touch') {
                                 $covert = true;
                                 $target->addStatus(POISON);
                                 $target->addStatus(WEAKENED);
                                 // Weakness kills strength.
                                 $target_damage = rand(self::MIN_POISON_TOUCH, $this->maxPoisonTouch());
                                 $victim_alive = $target->harm($target_damage);
                                 $generic_state_change = "__TARGET__ has been poisoned!";
                                 $generic_skill_result_message = "__TARGET__ has taken {$target_damage} damage!";
                                 $msg = "You have been poisoned by {$attacker_id}";
                                 Event::create($attacker_char_id, $target->id(), $msg);
                             } elseif ($act == 'Fire Bolt') {
                                 $target_damage = $this->fireBoltBaseDamage($player) + rand(1, $this->fireBoltMaxDamage($player));
                                 $generic_skill_result_message = "__TARGET__ has taken {$target_damage} damage!";
                                 $victim_alive = $target->harm($target_damage);
                                 $msg = "You have had fire bolt cast on you by " . $player->name();
                                 Event::create($player->id(), $target->id(), $msg);
                             } else {
                                 if ($act == 'Heal' || $act == 'Harmonize') {
                                     // This is the starting template for self-use commands, eventually it'll be all refactored.
                                     $harmonize = false;
                                     if ($act == 'Harmonize') {
                                         $harmonize = true;
                                     }
                                     $hurt = $target->is_hurt_by();
                                     // Check how much the TARGET is hurt (not the originator, necessarily).
                                     // Check that the target is not already status healing.
                                     if ($target->hasStatus(HEALING) && !$player->isAdmin()) {
                                         $turn_cost = 0;
                                         $generic_state_change = '__TARGET__ is already under a healing aura.';
                                     } elseif ($hurt < 1) {
                                         $turn_cost = 0;
                                         $generic_skill_result_message = '__TARGET__ is already fully healed.';
                                     } else {
                                         if (!$harmonize) {
                                             $original_health = $target->health;
                                             $heal_points = $player->getStamina() + 1;
                                             $new_health = $target->heal($heal_points);
                                             // Won't heal more than possible
                                             $healed_by = $new_health - $original_health;
                                         } else {
                                             $start_health = $player->health;
                                             // Harmonize those chakra!
                                             $player = $this->harmonizeChakra($player);
                                             $healed_by = $player->health - $start_health;
                                             $ki_cost = $healed_by;
                                         }
                                         $target->addStatus(HEALING);
                                         $generic_skill_result_message = "__TARGET__ healed by {$healed_by} to " . $target->health . ".";
                                         if ($target->id() != $player->id()) {
                                             Event::create($attacker_char_id, $target->id(), "You have been healed by {$attacker_id} for {$healed_by}.");
                                         }
                                     }
                                 } else {
                                     if ($act == 'Ice Bolt') {
                                         if ($target->hasStatus(SLOW)) {
                                             $turn_cost = 0;
                                             $generic_skill_result_message = '__TARGET__ is already iced.';
                                         } else {
                                             if ($target->turns >= 10) {
                                                 $turns_decrease = rand(1, 5);
                                                 $target->turns = $target->turns - $turns_decrease;
                                                 // Changed ice bolt to kill stealth.
                                                 $target->subtractStatus(STEALTH);
                                                 $target->subtractStatus(STALKING);
                                                 $target->addStatus(SLOW);
                                                 $msg = "Ice bolt cast on you by {$attacker_id}, your turns have been reduced by {$turns_decrease}.";
                                                 Event::create($attacker_char_id, $target->id(), $msg);
                                                 $generic_skill_result_message = "__TARGET__'s turns reduced by {$turns_decrease}!";
                                             } else {
                                                 $turn_cost = 0;
                                                 $generic_skill_result_message = "__TARGET__ does not have enough turns for you to take.";
                                             }
                                         }
                                     } else {
                                         if ($act == 'Cold Steal') {
                                             if ($target->hasStatus(SLOW)) {
                                                 $turn_cost = 0;
                                                 $generic_skill_result_message = '__TARGET__ is already iced.';
                                             } else {
                                                 $critical_failure = rand(1, 100);
                                                 if ($critical_failure > 7) {
                                                     // *** If the critical failure rate wasn't hit.
                                                     if ($target->turns >= 10) {
                                                         $turns_diff = rand(2, 7);
                                                         $target->turns = $target->turns - $turns_diff;
                                                         $player->turns = $player->turns + $turns_diff;
                                                         // Stolen
                                                         $target->addStatus(SLOW);
                                                         $msg = "You have had Cold Steal cast on you for {$turns_diff} by {$attacker_id}";
                                                         Event::create($attacker_char_id, $target->id(), $msg);
                                                         $generic_skill_result_message = "You cast Cold Steal on __TARGET__ and take {$turns_diff} turns.";
                                                     } else {
                                                         $turn_cost = 0;
                                                         $generic_skill_result_message = '__TARGET__ did not have enough turns to give you.';
                                                     }
                                                 } else {
                                                     // *** CRITICAL FAILURE !!
                                                     $player->addStatus(FROZEN);
                                                     $unfreeze_time = date('F j, Y, g:i a', mktime(date('G') + 1, 0, 0, date('m'), date('d'), date('Y')));
                                                     $failure_msg = "You have experienced a critical failure while using Cold Steal. You will be unfrozen on {$unfreeze_time}";
                                                     Event::create((int) 0, $player->id(), $failure_msg);
                                                     $generic_skill_result_message = "Cold Steal has backfired! You are frozen until {$unfreeze_time}!";
                                                 }
                                             }
                                         } else {
                                             if ($act == 'Clone Kill') {
                                                 // Obliterates the turns and the health of similar accounts that get clone killed.
                                                 $reuse = false;
                                                 // Don't give a reuse link.
                                                 $clone1 = Player::findByName($target);
                                                 $clone2 = Player::findByName($target2);
                                                 if (!$clone1 || !$clone2) {
                                                     $not_a_ninja = $target;
                                                     if (!$clone2) {
                                                         $not_a_ninja = $target2;
                                                     }
                                                     $generic_skill_result_message = "There is no such ninja as {$not_a_ninja}.";
                                                 } elseif ($clone1->id() == $clone2->id()) {
                                                     $generic_skill_result_message = '__TARGET__ is just the same ninja, so not the same thing as a clone at all.';
                                                 } elseif ($clone1->id() == $char_id || $clone2->id() == $char_id) {
                                                     $generic_skill_result_message = 'You cannot clone kill yourself.';
                                                 } else {
                                                     // The two potential clones will be obliterated immediately if the criteria are met in CloneKill.
                                                     $kill_or_fail = CloneKill::kill($player, $clone1, $clone2);
                                                     if ($kill_or_fail !== false) {
                                                         $generic_skill_result_message = $kill_or_fail;
                                                     } else {
                                                         $generic_skill_result_message = "Those two ninja don't seem to be clones.";
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         // ************************** Section applies to all skills ******************************
         if (!$victim_alive) {
             // Someone died.
             if ($target->player_id == $player->player_id) {
                 // Attacker killed themself.
                 $loot = 0;
                 $suicided = true;
             } else {
                 // Attacker killed someone else.
                 $killed_target = true;
                 $gold_mod = 0.15;
                 $loot = floor($gold_mod * $target->gold);
                 $player->setGold($player->gold + $loot);
                 $target->setGold($target->gold - $loot);
                 $player->addKills(1);
                 $added_bounty = floor($level_check / 5);
                 if ($added_bounty > 0) {
                     $player->setBounty($player->bounty + $added_bounty * 25);
                 } else {
                     if ($target->bounty > 0 && $target->id() !== $player->id()) {
                         // No suicide bounty, No bounty when your bounty getting ++ed.
                         $player->setGold($player->gold + $target->bounty);
                         // Reward the bounty
                         $target->setBounty(0);
                         // Wipe the bounty
                     }
                 }
                 $target_message = "{$attacker_id} has killed you with {$act} and taken {$loot} gold.";
                 Event::create($attacker_char_id, $target->id(), $target_message);
                 $attacker_message = "You have killed {$target} with {$act} and taken {$loot} gold.";
                 Event::create($target->id(), $player->id(), $attacker_message);
             }
         }
         if (!$covert && $player->hasStatus(STEALTH)) {
             $player->subtractStatus(STEALTH);
             $destealthed = true;
         }
         $target->save();
     }
     // End of the skill use SUCCESS block.
     $player->turns = $player->turns - max(0, $turn_cost);
     // Take the skill use cost.
     $player->save();
     $ending_turns = $player->turns;
     $target_ending_health = $target->health;
     $target_name = $target->name();
     $parts = get_defined_vars();
     $options = ['quickstat' => 'player'];
     return new StreamedViewResponse('Skill Effect', 'skills_mod.tpl', $parts, $options);
 }
 /**
  * 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]);
 }