bool GameChat::handle_special_commands(GameState* gs, const std::string& command) { ChatMessage printed; const char* content; PlayerInst* p = gs->local_player(); //Spawn monster if (starts_with(command, "!spawn ", &content)) { const char* rest = content; int amnt = strtol(content, (char**)&rest, 10); if (content == rest) amnt = 1; rest = skip_whitespace(rest); int enemy = get_enemy_by_name(rest, false); if (enemy == -1) { printed.message = "No such monster, '" + std::string(rest) + "'!"; printed.message_colour = Colour(255, 50, 50); } else { printed.message = std::string(rest) + " has spawned !"; generate_enemy_after_level_creation(gs, enemy, amnt); printed.message_colour = Colour(50, 255, 50); } add_message(printed); return true; } //Set game speed if (starts_with(command, "!gamespeed ", &content)) { int gamespeed = squish(atoi(content), 1, 200); gs->game_settings().time_per_step = gamespeed; printed.message = std::string("Game speed set."); printed.message_colour = Colour(50, 255, 50); add_message(printed); return true; } //Gain XP if (starts_with(command, "!gainxp ", &content)) { int xp = atoi(content); if (xp > 0 && xp < 999999) { printed.message = std::string("You have gained ") + content + " experience."; printed.message_colour = Colour(50, 255, 50); add_message(printed); p->gain_xp(gs, xp); } else { printed.message = "Invalid experience amount!"; printed.message_colour = Colour(255, 50, 50); add_message(printed); } return true; } //Create item if (starts_with(command, "!item ", &content)) { const char* rest = content; int amnt = strtol(content, (char**)&rest, 10); if (content == rest) amnt = 1; rest = skip_whitespace(rest); int item = get_item_by_name(rest, false); if (item == -1) { printed.message = "No such item, '" + std::string(rest) + "'!"; printed.message_colour = Colour(255, 50, 50); } else { printed.message = std::string(rest) + " put in your inventory !"; p->stats().equipment.inventory.add(Item(item), amnt); printed.message_colour = Colour(50, 255, 50); } add_message(printed); return true; } //Kill all monsters if (starts_with(command, "!killall", &content)) { MonsterController& mc = gs->monster_controller(); for (int i = 0; i < mc.monster_ids().size(); i++) { EnemyInst* inst = (EnemyInst*)gs->get_instance(mc.monster_ids()[i]); if (inst) { inst->damage(gs, 99999); } } printed.message = "Killed all monsters."; printed.message_colour = Colour(50, 255, 50); add_message(printed); return true; } lua_State* L = gs->get_luastate(); static LuaValue script_globals; if (script_globals.empty()) { script_globals.table_initialize(L); // script_globals.push(L); // int script = lua_gettop(L); // lua_pushvalue(L, LUA_GLOBALSINDEX); // lua_setmetatable(L, script); // lua_pop(L, 1); } lua_push_gameinst(L, p); script_globals.table_pop_value(L, "player"); lua_push_combatstats(L, p); script_globals.table_pop_value(L, "stats"); //Run lua command if (starts_with(command, "!lua ", &content)) { // std::string luafunc = std::string(content); int prior_top = lua_gettop(L); luaL_loadstring(L, content); if (lua_isstring(L, -1)) { const char* val = lua_tostring(L, -1); add_message(val, /*iserr ? Colour(255,50,50) :*/ Colour(120, 120, 255)); return true; } int lfunc = lua_gettop(L); script_globals.push(L); lua_setfenv(L, lfunc); bool iserr = (lua_pcall(L, 0, LUA_MULTRET, 0) != 0); int current_top = lua_gettop(L); for (; prior_top < current_top; prior_top++) { if (lua_isstring(L, -1)) { const char* val = lua_tostring(L, -1); add_message(val, iserr ? Colour(255, 50, 50) : Colour(120, 120, 255)); } lua_pop(L, 1); } return true; } //Run lua file if (starts_with(command, "!luafile ", &content)) { int prior_top = lua_gettop(L); int err_func = luaL_loadfile(L, content); if (err_func) { const char* val = lua_tostring(L, -1); add_message(val, Colour(120, 120, 255)); lua_pop(L, 1); return true; } int lfunc = lua_gettop(L); script_globals.push(L); lua_setfenv(L, lfunc); bool err_call = (lua_pcall(L, 0, 0, 0) != 0); if (err_call) { const char* val = lua_tostring(L, -1); add_message(val, Colour(120, 120, 255)); lua_pop(L, 1); } return true; } return false; }
void PlayerInst::pickup_item(GameState* gs, const GameAction& action) { const int PICKUP_RATE = 10; GameInst* inst = gs->get_instance(action.use_id); if (!inst) { return; } ItemInst* iteminst = dynamic_cast<ItemInst*>(inst); LANARTS_ASSERT(iteminst); const Item& type = iteminst->item_type(); int amnt = iteminst->item_quantity(); bool inventory_full = false; if (type.id == get_item_by_name("Gold")) { gold() += amnt; } else { itemslot_t slot = inventory().add(type); if (slot == -1) { inventory_full = true; } else if (projectile_should_autowield(equipment(), type, this->last_chosen_weaponclass)) { projectile_smart_equip(inventory(), slot); } } if (!inventory_full) { cooldowns().reset_pickup_cooldown(PICKUP_RATE); gs->remove_instance(iteminst); } }
EquipmentEntry& get_equipment_entry(projectile_id id) { if (id == NO_ITEM) { return get_equipment_entry(get_item_by_name("Nothing")); } ItemEntry* item = game_item_data.at(id); return dynamic_cast<EquipmentEntry&>(*item); }
equipment_id get_equipment_by_name(const char* name) { if (strcmp(name, "Nothing") == 0) { return NO_ITEM; } item_id id = get_item_by_name(name); LANARTS_ASSERT(dynamic_cast<EquipmentEntry*>(game_item_data.at(id))); return (equipment_id) id; }
WeaponEntry& get_weapon_entry(weapon_id id) { if (id == NO_ITEM) { return get_weapon_entry(get_item_by_name("Unarmed")); } ItemEntry* item = game_item_data.get(id); return dynamic_cast<WeaponEntry&>(*item); }
weapon_id get_weapon_by_name(const char* name) { if (strcmp(name, "Unarmed") == 0) { return NO_ITEM; } item_id id = get_item_by_name(name); LANARTS_ASSERT(dynamic_cast<WeaponEntry*>(game_item_data.get(id))); return (weapon_id)id; }
void PlayerInst::enqueue_not_enough_mana_actions(GameState* gs) { const int AUTOUSE_MANA_POTION_CNT = 2; int item_slot = inventory().find_slot(get_item_by_name("Mana Potion")); if (gs->game_settings().autouse_mana_potions && autouse_mana_potion_try_count >= AUTOUSE_MANA_POTION_CNT && item_slot != -1) { queued_actions.push_back( game_action(gs, this, GameAction::USE_ITEM, item_slot)); autouse_mana_potion_try_count = 0; } else { autouse_mana_potion_try_count++; } }
int equip(lua_State* L) { CombatGameInst* combatinst; if ((combatinst = dynamic_cast<CombatGameInst*>(get_inst()))) { int args = lua_gettop(L); lua_pushstring(L, "name"); lua_gettable(L, 1); const char* itemname = lua_tostring(L, lua_gettop(L)); item_id item = get_item_by_name(itemname); int amnt = args >= 2 ? lua_tointeger(L, 2) : 1; combatinst->equip(item, amnt); lua_pop(L, 1); } return 0; }
void make_cube( float *data, float ao[6][4], float light[6][4], int left, int right, int top, int bottom, int front, int back, float x, float y, float z, float n, int w) { struct item_list *it = get_item_by_id(ABS(w)); if (it == NULL) { it = get_item_by_name("error"); } int wleft = it->tile->left; int wright = it->tile->right; int wtop = it->tile->top; int wbottom = it->tile->bottom; int wfront = it->tile->front; int wback = it->tile->back; make_cube_faces( data, ao, light, left, right, top, bottom, front, back, wleft, wright, wtop, wbottom, wfront, wback, x, y, z, n); }
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::enqueue_io_equipment_actions(GameState* gs, bool do_stopaction) { GameView& view = gs->view(); bool mouse_within = gs->mouse_x() < gs->view().width; int rmx = view.x + gs->mouse_x(), rmy = view.y + gs->mouse_y(); int level = gs->get_level()->id(); int frame = gs->frame(); bool item_used = false; IOController& io = gs->io_controller(); Pos p(gs->mouse_x() + view.x, gs->mouse_y() + view.y); obj_id target = this->current_target; GameInst* targetted = gs->get_instance(target); if (targetted) p = Pos(targetted->x, targetted->y); // We may have already used an item eg due to auto-use of items bool used_item = false; //Item use for (int i = 0; i < 9 && !used_item; i++) { if (io.query_event(IOEvent(IOEvent::USE_ITEM_N, i))) { if (inventory().get(i).amount() > 0) { item_used = true; queued_actions.push_back( GameAction(id, GameAction::USE_ITEM, frame, level, i, p.x, p.y)); } } } if (!used_item && gs->game_settings().autouse_health_potions && core_stats().hp < AUTOUSE_HEALTH_POTION_THRESHOLD) { int item_slot = inventory().find_slot( get_item_by_name("Health Potion")); if (item_slot > -1) { queued_actions.push_back( game_action(gs, this, GameAction::USE_ITEM, item_slot)); used_item = true; } } //Item pickup GameInst* inst = NULL; if (cooldowns().can_pickup() && gs->object_radius_test(this, &inst, 1, &item_colfilter)) { ItemInst* iteminst = (ItemInst*)inst; Item& item = iteminst->item_type(); bool was_dropper = iteminst->last_held_by() == id; bool dropper_autopickup = iteminst->autopickup_held(); bool autopickup = (item.is_normal_item() && !was_dropper && !dropper_autopickup) || (was_dropper && dropper_autopickup); bool wieldable_projectile = projectile_should_autowield(equipment(), item, this->last_chosen_weaponclass); bool pickup_io = gs->key_down_state(SDLK_LSHIFT) || gs->key_down_state(SDLK_RSHIFT); if (do_stopaction || wieldable_projectile || pickup_io || autopickup) queued_actions.push_back( GameAction(id, GameAction::PICKUP_ITEM, frame, level, iteminst->id)); } }
//Lua argument getters item_id item_from_lua(lua_State* L, int idx) { return get_item_by_name(lua_tostring(L, idx)); }