/** * Action to request class change form AND execute class change * * @todo split form request and execute into separate funcs * @return ViewSpec */ public function changeClass() { if (is_logged_in()) { $player = new Player(self_char_id()); $classes = $this->classesInfo(); $requestedIdentity = in('requested_identity'); $currentClass = $player->identity; $showMonks = false; $parts = []; if (isset($classes[$requestedIdentity])) { $error = $this->classChangeReqs($player, self::CLASS_CHANGE_COST); if ($currentClass != $requestedIdentity && !$error) { $error = $this->changePlayerClass($player, $requestedIdentity); } $currentClass = $player->identity; if (!$error) { $parts['pageParts'] = ['success-class-change']; $showMonks = true; } else { $parts['error'] = $error; } } else { $parts['pageParts'] = ['form-class-change']; } unset($classes[$currentClass]); $parts['classOptions'] = $classes; return $this->render($parts, $player, $showMonks); } else { return $this->accessDenied(); } }
function prep_page($template, $title = null, $local_vars = array(), $options = null) { // Updates the quickstat via javascript if requested. $quickstat = @$options['quickstat']; $quickstat = $quickstat ? $quickstat : @$local_vars['quickstat']; $body_classes = isset($options['body_classes']) ? $options['body_classes'] : (isset($local_vars['body_classes']) ? $local_vars['body_classes'] : null); $is_index = @$options['is_index']; // *** Initialize the template object *** $tpl = new NWTemplate(); $tpl->assignArray($local_vars); $user_id = self_char_id(); // Character id. $player = Player::find($user_id); $public_char_info = $player ? $player->publicData() : []; // Char info to pass to javascript. $tpl->assign('logged_in', $user_id); $tpl->assign('user_id', $user_id); $tpl->assign('title', $title); $tpl->assign('quickstat', $quickstat); $tpl->assign('is_index', $is_index); $tpl->assign('json_public_char_info', $public_char_info ? json_encode($public_char_info) : null); $tpl->assign('body_classes', $body_classes); $tpl->assign('main_template', $template); return $tpl; }
function globalize_user_info($private = true, $alive = true) { global $username; global $char_id; $error = null; $char_id = self_char_id(); // Will default to null. //$username = get_username(); // Will default to null. if ((!is_logged_in() || !$char_id) && $private) { $error = 'log_in'; // A non-null set of content being in the error triggers a die at the end of the header. } elseif ($char_id) { // **************** Player information settings. ******************* global $player, $player_id; // Polluting the global namespace here. Booo. $player = new Player($char_id); // Defaults to current session user. $username = $player->name(); // Set the global username. $player_id = $player->player_id; assert('isset($player_id)'); if ($alive) { // *** That page requires the player to be alive to view it. if (!$player->health()) { $error = 'dead'; } else { if ($player->hasStatus(FROZEN)) { $error = 'frozen'; } } } } return $error; }
/** * Delete the all the messages from your clan. */ public function deleteClan() { $char_id = self_char_id(); $type = 1; Message::deleteByReceiver(new Player($char_id), $type); return new RedirectResponse('/messages.php?command=clan&informational=' . url('Messages deleted')); }
/** * User command for betting on the coin toss game in the casino * * @param bet int The amount of money to bet on the coin toss game * @return Array * * @note * If the player bets within ~1% of the maximum bet, they will receive a reward item */ public function bet() { $player = new Player(self_char_id()); $bet = intval(in('bet')); $negative = $bet < 0; set_setting('bet', max(0, $bet)); $pageParts = ['reminder-max-bet']; if ($negative) { $pageParts = ['result-cheat']; $player->vo->health = subtractHealth($player->id(), 99); } else { if ($bet > $player->vo->gold) { $pageParts = ['result-no-gold']; } else { if ($bet > 0 && $bet <= self::MAX_BET) { if (rand(0, 1) === 1) { $pageParts = ['result-win']; $player->vo->gold = add_gold($player->id(), $bet); if ($bet >= round(self::MAX_BET * 0.99)) { // within about 1% of the max bet & you win, you get a reward item. add_item($player->id(), self::REWARD, 1); } } else { $player->vo->gold = subtract_gold($player->id(), $bet); $pageParts = ['result-lose']; } } } } // End of not cheating check. return $this->render(['pageParts' => $pageParts, 'player' => $player, 'bet' => get_setting('bet')]); }
/** * User command for betting on the coin toss game in the casino * * @param bet int The amount of money to bet on the coin toss game * @return Array * * @note * If the player bets within ~1% of the maximum bet, they will receive a * reward item */ public function bet() { $player = Player::find(self_char_id()); $bet = intval(in('bet')); $pageParts = ['reminder-max-bet']; if ($bet < 0) { $pageParts = ['result-cheat']; $player->harm(self::CHEAT_DMG); } else { if ($bet > $player->gold) { $pageParts = ['result-no-gold']; } else { if ($bet > 0 && $bet <= self::MAX_BET) { if (rand(0, 1) === 1) { $pageParts = ['result-win']; $player->set_gold($player->gold + $bet); if ($bet >= round(self::MAX_BET * 0.99)) { // within about 1% of the max bet & you win, you get a reward item. add_item($player->id(), self::REWARD, 1); } } else { $player->set_gold($player->gold - $bet); $pageParts = ['result-lose']; } } } } $player->save(); return $this->render(['pageParts' => $pageParts, 'player' => $player]); }
/** * The standard homepage * * @return ViewSpec */ private function game() { // Get the actual values of the vars. $ninja = new Player(self_char_id()); $playerInfo = $ninja->dataWithClan(); $unreadCount = Message::where(['send_to' => $ninja->id(), 'unread' => 1])->count(); // Assign these vars to the template. $parts = ['main_src' => '/intro', 'body_classes' => 'main-body', 'version' => 'NW Version 1.7.5 2010.12.05', 'ninja' => $ninja, 'player_info' => $playerInfo, 'unread_message_count' => $unreadCount]; return ['template' => 'index.tpl', 'title' => 'Live by the Shuriken', 'parts' => $parts, 'options' => ['is_index' => true]]; }
/** * Check whether the player has the skill. **/ public function hasSkill($skill, $username = null) { if (!$username) { $charId = self_char_id(); } else { $charId = get_char_id($username); } $player = new Player($charId); $skills = $this->skills($player); $skill = strtolower($skill); $levelReq = isset($skills[$skill]['level']) ? $skills[$skill]['level'] : 1; return isset($skills[$skill]['available']) && $player->level >= $levelReq; }
function message_to_clan($p_message) { $error = null; $user_id = self_char_id(); $clan_id = get_clan_by_player_id($user_id)->getID(); $clan_members = query_resultset("SELECT player_id, uname\n\t FROM clan JOIN clan_player ON _clan_id = clan_id JOIN players ON player_id = _player_id\n\t WHERE clan_id = :clan", array(':clan' => $clan_id)); $messaged_to = array(); foreach ($clan_members as $loop_member) { send_message($user_id, $loop_member['player_id'], $p_message, $type = 1); $messaged_to[] = $loop_member['uname']; } return implode(', ', $messaged_to); }
/** * Display the combat/action events and mark them as read when displayed. */ public function index() { $char = new Player(self_char_id()); $events = $this->getEvents($char->id(), 300); // Check for clan to use it in the nav tabs. $has_clan = (bool) ClanFactory::clanOfMember($char); $this->readEvents($char->id()); // mark events as viewed. $template = 'events.tpl'; $title = 'Events'; $parts = ['events' => $events, 'has_clan' => $has_clan, 'char' => $char]; $options = ['quickstat' => 'player']; return ['title' => $title, 'template' => $template, 'parts' => $parts, 'options' => $options]; }
/** * Check whether the player has the skill. **/ public function hasSkill($skill, $username = null) { $skill = strtolower($skill); if (!$username) { $char_id = self_char_id(); } else { $char_id = get_char_id($username); } $player_info = char_info($char_id); $player_level = $player_info['level']; $skills = $this->skills($char_id); $level_req = isset($skills[$skill]['level']) ? $skills[$skill]['level'] : 1; return isset($skills[$skill]['available']) && $player_level >= $level_req; }
/** * Get the last turns worked by a pc, and pass it to display the default * page with form */ public function index() { // Initialize variables to pass to the template. $work_multiplier = self::WORK_MULTIPLIER; $worked = null; $earned_gold = null; $not_enough_energy = null; $is_logged_in = is_logged_in(); $char = new Player(self_char_id()); // Fill out some of the variables. $recommended_to_work = self::DEFAULT_RECOMMENDED_TO_WORK; $gold_display = number_format($char->gold()); $parts = ['recommended_to_work' => $recommended_to_work, 'work_multiplier' => $work_multiplier, 'is_logged_in' => $is_logged_in, 'gold_display' => $gold_display, 'worked' => $worked, 'earned_gold' => number_format($earned_gold), 'not_enough_energy' => $not_enough_energy]; return $this->render($parts); }
/** * Take in a chat and record it to the database. * **/ public function receive() { $char_id = self_char_id(); $message = in('message', null, 'no filter'); // Essentially no filtering. $error = null; if (!empty($message)) { if ($char_id) { send_chat($char_id, $message); } else { $error = 'You must be logged in to chat.'; } } return new RedirectResponse('/village.php' . ($error ? '?error=' . url($error) : '')); }
/** * @TODO Document me! */ private function configure() { $char = Player::find(self_char_id()); // Array that simulates database display information for switching out for an npc database solution. $npcs = [['name' => 'Peasant', 'identity' => 'peasant', 'image' => 'fighter.png'], ['name' => 'Thief', 'identity' => 'thief', 'image' => 'thief.png'], ['name' => 'Merchant', 'identity' => 'merchant', 'image' => 'merchant.png'], ['name' => 'Guard', 'identity' => 'guard', 'image' => 'guard.png'], ['name' => 'Samurai', 'identity' => 'samurai', 'image' => 'samurai.png']]; $peers = $char ? $this->getNearbyPeers($char->id()) : []; $active_ninjas = Player::findActive(5, true); $char_info = $char ? $char->dataWithClan() : []; // Generic/abstracted npcs $other_npcs = NpcFactory::npcsData(); $enemy_list = $char ? $this->getCurrentEnemies($char->id()) : []; $enemy_count = rco($enemy_list); $recent_attackers = $char ? $this->getRecentAttackers($char) : []; return ['logged_in' => (bool) $char, 'enemy_list' => $enemy_list, 'enemy_count' => $enemy_count, 'char_name' => $char ? $char->name() : '', 'npcs' => $npcs, 'other_npcs' => $other_npcs, 'char_info' => $char_info, 'active_ninjas' => $active_ninjas, 'recent_attackers' => $recent_attackers, 'enemy_list' => $enemy_list, 'peers' => $peers, 'max_enemies' => self::ENEMY_LIMIT <= $enemy_count]; }
/** * For events, attacks, kills, invites, etc, and no user-created messages * * @param int $fromId * @param int $toId * @param String $msg * @return void * @throws Exception */ function send_event($fromId, $toId, $msg) { if (!$toId) { $toId = self_char_id(); } if (!is_numeric($fromId) || !is_numeric($toId)) { throw new \Exception('A player id wasn\'t sent in to the send_event function.'); } DatabaseConnection::getInstance(); $statement = DatabaseConnection::$pdo->prepare("INSERT INTO events (event_id, send_from, send_to, message, date)\n VALUES (default, :from, :to, :message, now())"); $statement->bindValue(':from', $fromId); $statement->bindValue(':to', $toId); $statement->bindValue(':message', $msg); $statement->execute(); }
function get_recent_attackers($self = null) { // If a self Player object is passed in, exclude them from the "recent attackers" list $id = $self instanceof Player ? $self->id() : null; $exclude_id = ''; if ($id > 0) { $exclude_id = ' AND player_id != :id '; } DatabaseConnection::getInstance(); $statement = DatabaseConnection::$pdo->prepare('SELECT DISTINCT player_id, send_from, uname, level, health FROM events JOIN players ON send_from = player_id WHERE send_to = :user AND active = 1 ' . $exclude_id . ' LIMIT 20'); $statement->bindValue(':user', self_char_id()); if ($id > 0) { $statement->bindValue(':id', $id, PDO::PARAM_INT); } $statement->execute(); return $statement; }
/** * Constructor * * Sets up the parameters for a attack legal check. * @param mixed $attacker_info The attacker info, an object or else an id. * @param mixed $target_info The target info, an object or an id. * @param array $conditions The further conditions of the attack. * @access public **/ public function __construct($attacker_name_or_id = null, $target_name_or_id, $params = array()) { $this->attacker = null; $this->target = null; $this->params = $params; $this->error = null; if (!isset($this->params['required_turns']) || $this->params['required_turns'] === null) { throw new Exception('Error: AttackLegal required turns not specified.'); } if ($attacker_name_or_id) { $this->attacker = new Player($attacker_name_or_id); } elseif ($char_id = self_char_id()) { // Pull logged in char_id. $this->attacker = new Player($char_id); } if ($target_name_or_id) { $this->target = new Player($target_name_or_id); } }
function get_status_list($target = null) { $states = array(); $result = ''; $target = isset($target) && (int) $target == $target ? $target : self_char_id(); // Default to showing own status. $target = new Player($target); if ($target->vo->health < 1) { $states[] = 'Dead'; } else { // *** Other statuses only display if not dead. if ($target->vo->health < 80) { $states[] = 'Injured'; } else { $states[] = 'Healthy'; } // The visibly viewable statuses. if ($target->hasStatus(STEALTH)) { $states[] = 'Stealthed'; } if ($target->hasStatus(POISON)) { $states[] = 'Poisoned'; } if ($target->hasStatus(WEAKENED)) { $states[] = 'Weakened'; } if ($target->hasStatus(FROZEN)) { $states[] = 'Frozen'; } if ($target->hasStatus(STR_UP1)) { $states[] = 'Buff'; } if ($target->hasStatus(STR_UP2)) { $states[] = 'Strength+'; } // If any of the shield skills are up, show a single status state for any. if ($target->hasStatus(FIRE_RESISTING) || $target->hasStatus(INSULATED) || $target->hasStatus(GROUNDED) || $target->hasStatus(BLESSED) || $target->hasStatus(IMMUNIZED) || $target->hasStatus(ACID_RESISTING)) { $states[] = 'Shielded'; } } return $states; }
/** * Creates all the environmental variables, with no outputting. * * Places much of the user info into the global namespace. */ function init($private, $alive) { global $today; global $username; global $char_id; // ******************** Declared variables ***************************** $today = date("F j, Y, g:i a"); // Today var is only used for creating mails. // Page viewing settings usually set before the header. update_activity_info(); // *** Updates the activity of the page viewer in the database. $error = null; $char_id = self_char_id(); // Will default to null. if ((!is_logged_in() || !$char_id) && $private) { $error = 'log_in'; // A non-null set of content being in the error triggers a die at the end of the header. } elseif ($char_id) { // **************** Player information settings. ******************* global $player, $player_id; // Polluting the global namespace here. Booo. $player = new Player($char_id); // Defaults to current session user. $username = $player->name(); // Set the global username. $player_id = $player->player_id; if ($alive) { // That page requires the player to be alive to view it if (!$player->health()) { $error = 'dead'; } else { if ($player->hasStatus(FROZEN)) { $error = 'frozen'; } } } } return $error; }
function save_settings($settings) { $user_id = self_char_id(); if ($user_id) { DatabaseConnection::getInstance(); $statement = DatabaseConnection::$pdo->prepare("SELECT count(settings_store) FROM settings WHERE player_id = :player"); $statement->bindValue(':player', $user_id); $statement->execute(); $settings_exist = $statement->fetchColumn(); if ($settings_exist) { $statement = DatabaseConnection::$pdo->prepare("UPDATE settings SET settings_store = :settings WHERE player_id = :player"); $statement->bindValue(':settings', serialize($settings)); $statement->bindValue(':player', $user_id); } else { $statement = DatabaseConnection::$pdo->prepare("INSERT INTO settings (settings_store, player_id) VALUES (:settings, :player)"); $statement->bindValue(':settings', serialize($settings)); $statement->bindValue(':player', $user_id); } $statement->execute(); } return get_settings($refresh = true); // This refreshes the static, saved settings variable. }
/** * Returns the state of the current active character from the database. **/ function self_info() { $id = self_char_id(); if (!is_numeric($id)) { // If there's no id, don't try to get any data. return null; } $player = new Player($id); // Constructor uses DAO to get player object. $player_data = array(); if ($player instanceof Player && $player->id()) { // Turn the player data vo into a simple array. $player_data = (array) $player->vo; $player_data['clan_id'] = $player->getClan() ? $player->getClan()->getID() : null; $player_data = add_data_to_player_row($player_data); } return $player_data; }
/** * Command to remove the POISON status from the current player, if poisoned * * @return Array * @par Side Effects: * On success, status attribute of $p_player is modified in memory and database * On success, gold attribute of $p_player is modified in memory and database */ public function cure() { $player = new Player(self_char_id()); // get current player if ($player->health() <= 0) { return $this->renderError('You must resurrect before you can heal.', $player); } else { if ($player->gold < self::CURE_COST_GOLD) { return $this->renderError('You need more gold to remove poison.', $player); } else { if (!$player->hasStatus(POISON)) { return $this->renderError('You are not ill.', $player); } else { $player->subtractStatus(POISON); $player->vo->gold = subtract_gold($player->id(), self::CURE_COST_GOLD); $pageParts = ['chant', 'result-cure']; return $this->render(['pageParts' => array_merge($pageParts, $this->servicesNeeded($player))]); } } } }
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']]; }
} else { if ($command == 'Stealth') { $covert = true; $state = 'stealthed'; if (!$target->hasStatus(STEALTH)) { $target->addStatus(STEALTH); $generic_state_change = "__TARGET__ is now {$state}."; } else { $turn_cost = 0; $generic_state_change = "__TARGET__ is already {$state}."; } } else { if ($command == 'Kampo') { $covert = true; // *** Get Special Items From Inventory *** $user_id = self_char_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', array(':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 *** removeItem($user_id, 'ginsengroot', $itemCount); add_item($user_id, '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 {
function json_send_chat($msg) { if (is_logged_in()) { require_once LIB_ROOT . "control/lib_chat.php"; $msg = trim($msg); $user_id = (int) self_char_id(); $info = self_char_info(); $success = send_chat($user_id, $msg); if (!$success) { return false; } else { return '{"message":"' . $msg . '","sender_id":"' . $user_id . '","uname":"' . $info['uname'] . '"}'; } } }
<?php require_once LIB_ROOT . "control/lib_inventory.php"; require_once LIB_ROOT . "data/lib_npc.php"; $alive = true; $private = true; if ($error = init($private, $alive)) { display_error($error); } else { $turn_cost = 1; $health = 1; $victim = in('victim'); $random_encounter = rand(1, 400) == 1; $combat_data = array(); $char_id = self_char_id(); $player = new Player($char_id); $error_template = 'npc.no-one.tpl'; // Error template also used down below. $npc_template = $error_template; // Error condition by default. $turns = $player->turns(); $is_villager = false; $ninja_str = $player->getStrength(); $ninja_health = $player->vo->health; $static_npcs = array('peasant', 'thief', 'merchant', 'guard', 'samurai'); $npcs = NpcFactory::npcsData(); $possible_npcs = array_merge($static_npcs, array_keys($npcs)); $victim = restrict_to($victim, $possible_npcs); // Filter to only the correct options. if ($turns > 0 && !empty($victim)) { // Strip stealth when attacking samurai or oni
/** * Grabs data from external state for other methods to us * * @return ShopController */ public function __construct() { $this->itemCosts = $this->itemForSaleCosts(); $this->sessionData = ['username' => self_name(), 'char_id' => self_char_id(), 'is_logged_in' => is_logged_in()]; }
private function jsonIndex() { DatabaseConnection::getInstance(); $user_id = self_char_id(); $player = new Player($user_id); $events = []; $messages = []; $unread_messages = null; $unread_events = null; $items = null; if ($user_id) { $events = DatabaseConnection::$pdo->prepare("SELECT event_id, message AS event, date, send_to, send_from, unread, uname AS sender FROM events JOIN players ON player_id = send_from WHERE send_to = :userID and unread = 1 ORDER BY date DESC"); $events->bindValue(':userID', $user_id); $events->execute(); $unread_events = $events->rowCount(); $messages = DatabaseConnection::$pdo->prepare("SELECT message_id, message, date, send_to, send_from, unread, uname AS sender FROM messages JOIN players ON player_id = send_from WHERE send_to = :userID1 AND send_from != :userID2 and unread = 1 ORDER BY date DESC"); $messages->bindValue(':userID1', $user_id); $messages->bindValue(':userID2', $user_id); $messages->execute(); $unread_messages = $messages->rowCount(); $items = query_array('SELECT item.item_display_name as item, amount FROM inventory join item on inventory.item_type = item.item_id WHERE owner = :user_id ORDER BY item_display_name', [':user_id' => $user_id]); } return ['player' => $player ? $player->publicData() : [], 'member_counts' => $this->memberCounts(), 'unread_messages_count' => $unread_messages, 'message' => !empty($messages) ? $messages->fetch() : null, 'inventory' => ['inv' => 1, 'items' => $items, 'hash' => md5(strtotime("now"))], 'unread_events_count' => $unread_events, 'event' => !empty($events) ? $events->fetch() : null]; }
/** * 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 }
/** * Generates a viewspec for rendering pages * * @param Array $p_parts Name-Value pairs of values to send to the view * @return Array A viewspec for rendering */ private function render($p_parts) { if (!isset($p_parts['pageParts'])) { $p_parts['pageParts'] = []; } if (!isset($p_parts['error'])) { $p_parts['error'] = null; } if (!isset($p_parts['action_message'])) { $p_parts['action_message'] = null; } $p_parts['player'] = Player::find(self_char_id()); $p_parts['myClan'] = $p_parts['player'] ? ClanFactory::clanOfMember($p_parts['player']) : null; $p_parts['clan_creator_min_level'] = self::CLAN_CREATOR_MIN_LEVEL; return ['template' => 'clan.tpl', 'title' => $p_parts['title'], 'parts' => $p_parts, 'options' => ['body_classes' => 'clan', 'quickstat' => true]]; }