void PlayerInst::use_dngn_portal(GameState* gs, const GameAction& action) { if (!effective_stats().allowed_actions.can_use_stairs) { if (is_local_player()) { gs->game_chat().add_message( "You cannot use the exit in this state!"); } return; } cooldowns().reset_stopaction_timeout(50); FeatureInst* portal = find_usable_portal(gs, this); portal->player_interact(gs, this); reset_rest_cooldown(); std::string subject_and_verb = "You travel"; if (!is_local_player()) { subject_and_verb = player_entry(gs).player_name + " travels"; } const std::string& map_label = gs->game_world().get_level(current_floor)->label(); bool label_has_digit = false; // Does it have a number in the label? for (int i = 0; i < map_label.size(); i++) { if (isdigit(map_label[i])) { label_has_digit = true; break; } } gs->game_chat().add_message( format("%s to %s%s", subject_and_verb.c_str(), label_has_digit ? "" : "the ", map_label.c_str()), is_local_player() ? COL_WHITE : COL_YELLOW); }
void PlayerInst::use_weapon(GameState* gs, const GameAction& action) { WeaponEntry& wentry = weapon().weapon_entry(); MTwist& mt = gs->rng(); const int MAX_MELEE_HITS = 10; EffectiveStats& estats = effective_stats(); if (!cooldowns().can_doaction()) { return; } Pos start(x, y); Pos actpos(action.action_x, action.action_y); if (wentry.uses_projectile && !equipment().has_projectile()) { return; } int cooldown = 0; if (equipment().has_projectile()) { const Projectile& projectile = equipment().projectile; ProjectileEntry& pentry = projectile.projectile_entry(); item_id item = get_item_by_name(pentry.name.c_str()); int weaprange = std::max(wentry.range, pentry.range); AttackStats weaponattack(weapon()); bool wallbounce = false; int nbounces = 0; float movespeed = pentry.speed; cooldown = std::max(wentry.cooldown, pentry.cooldown); //XXX: Horrible hack REMOVE THIS LATER if (class_stats().class_type().name == "Archer" && pentry.weapon_class == "bows") { int xplevel = class_stats().xplevel; float movebonus = class_stats().xplevel / 4.0f; if (movebonus > 2) { movebonus = 2; } float cooldown_mult = 1.0f - (class_stats().xplevel - 1) / 20.0f; if (cooldown_mult <= 0.85) { cooldown_mult = 0.85; } cooldown *= cooldown_mult; movespeed += movebonus; if (xplevel >= 3 && core_stats().mp >= 5) { nbounces = 2; core_stats().mp -= 5; } } GameInst* bullet = new ProjectileInst(projectile, effective_atk_stats(mt, weaponattack), id, start, actpos, movespeed, weaprange, NONE, wallbounce, nbounces); gs->add_instance(bullet); equipment().use_ammo(); } else { int weaprange = wentry.range + this->radius + TILE_SIZE / 2; float mag = distance_between(actpos, Pos(x, y)); if (mag > weaprange) { float dx = actpos.x - x, dy = actpos.y - y; actpos = Pos(x + dx / mag * weaprange, y + dy / mag * weaprange); } GameInst* enemies[MAX_MELEE_HITS]; int max_targets = std::min(MAX_MELEE_HITS, wentry.max_targets); int numhit = get_targets(gs, this, actpos.x, actpos.y, wentry.dmgradius, enemies, max_targets); if (numhit == 0) { return; } for (int i = 0; i < numhit; i++) { EnemyInst* e = (EnemyInst*)enemies[i]; lua_hit_callback(gs->get_luastate(), wentry.on_hit_func, this, e); if (attack(gs, e, AttackStats(equipment().weapon))) { PlayerData& pc = gs->player_data(); signal_killed_enemy(); char buffstr[32]; int amnt = round( double(e->xpworth()) / pc.all_players().size()); players_gain_xp(gs, amnt); snprintf(buffstr, 32, "%d XP", amnt); gs->add_instance( new AnimatedInst(Pos(e->x - 5, e->y - 5), -1, 25, Posf(), Posf(), AnimatedInst::DEPTH, buffstr, Colour(255, 215, 11))); } } cooldown = wentry.cooldown; } cooldowns().reset_action_cooldown(cooldown * estats.cooldown_mult); reset_rest_cooldown(); }
void PlayerInst::use_item(GameState* gs, const GameAction& action) { if (!effective_stats().allowed_actions.can_use_items) { return; } itemslot_t slot = action.use_id; ItemSlot& itemslot = inventory().get(slot); Item& item = itemslot.item; ItemEntry& type = itemslot.item_entry(); lua_State* L = gs->luastate(); if (item.amount > 0) { if (item.is_equipment()) { if (itemslot.is_equipped()) { inventory().deequip(slot); } else { if (item.is_projectile()) { // Best-effort to equip, may not be possible: projectile_smart_equip(inventory(), slot); } else if (item.is_weapon()) { const Projectile& p = equipment().projectile(); if (!p.empty()) { if (!p.projectile_entry().is_standalone()) { inventory().deequip_type( EquipmentEntry::AMMO); } } equipment().equip(slot); // Try and equip a projectile WeaponEntry& wentry = item.weapon_entry(); if (wentry.uses_projectile) { const Projectile& p = equipment().projectile(); if (p.empty()) { projectile_smart_equip(inventory(), wentry.weapon_class); } } } else { equipment().equip(slot); } if (item.is_weapon() || item.is_projectile()) { last_chosen_weaponclass = weapon().weapon_entry().weapon_class; } } } else if (equipment().valid_to_use(item) && item_check_lua_prereq(L, type, this)) { item_do_lua_action(L, type, this, Pos(action.action_x, action.action_y), item.amount); if (is_local_player() && !type.inventory_use_message().empty()) { gs->game_chat().add_message(type.inventory_use_message(), Colour(100, 100, 255)); } if (item.is_projectile()) itemslot.clear(); else item.remove_copies(1); reset_rest_cooldown(); } } }