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 LuaTableIterator::toNextElement() { auto ret = lua_next(_luaState, -2); _hasElement = ret != 0; if (_hasElement) { LuaValue key; key.setReference(UniqueLuaReference::create(_luaState, -2)); LuaValue value; value.setReference(UniqueLuaReference::create(_luaState, -1)); _currentVal = std::make_pair(key, value); // Remove value from stack lua_pop(_luaState, 1); } }
/* ** find a "name" for the RK value 'c' */ void kname2 (LuaProto *p, int pc, int c, std::string& name) { if (ISK(c)) { /* is 'c' a constant? */ LuaValue *kvalue = &p->constants[INDEXK(c)]; if (kvalue->isString()) { /* literal constant? */ name = kvalue->getString()->c_str(); /* it is its own name */ return; } /* else no reasonable name found */ } else { /* 'c' is a register */ const char *what = getobjname2(p, pc, c, name); /* search for 'c' */ if (what && *what == 'c') { /* found a constant name? */ return; /* 'name' already filled */ } /* else no reasonable name found */ } name = "?"; /* no reasonable name found */ }
void GameEntity::updateHPBar() { float hp = 1.0f; float maxhp = 1.0f; LuaValue val; if (this->getProperty("hp", val)) { hp = val.floatValue(); } if (this->getProperty("maxhp", val)) { maxhp = val.floatValue(); } m_hpBar->drawSegment(Vec2(-20, 30), Vec2(20, 30), 5.0f, Color4F(1.0f, 1.0f, 1.0f, 1.0f)); m_hpBar->drawSegment(Vec2(-20, 30), Vec2(20, 30), 4.0f, Color4F(0.0f, 0.0f, 0.0f, 1.0f)); m_hpBar->drawSegment(Vec2(-20, 30), Vec2(-20+40*(hp/maxhp), 30), 4.0f, Color4F(1.0f, 0.0f, 0.0f, 1.0f)); }
void lua_register_ldungeon(const LuaValue& submodule, bool register_lcommon = true) { lua_State* L = submodule.luastate(); if (register_lcommon) { lua_register_lcommon(L); } lua_register_map(submodule); lua_register_areatemplate(submodule); lua_register_tunnelgen(submodule); register_libxmi_bindings(submodule); }
const char *luaL_tolstring (LuaThread *L, int idx, size_t *len) { THREAD_CHECK(L); if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ LuaValue* pv = index2addr(L, idx); assert(pv); LuaValue v = *pv; if(v.isNumber() || v.isString()) { L->stack_.copy(idx); } else if(v.isBool()) { lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); } else if(v.isNil()) { lua_pushliteral(L, "nil"); } else { lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), lua_topointer(L, idx)); } } return lua_tolstring(L, -1, len); }
void LuaTable::sort(const LuaValue& cmp) { auto func = cmp.getFunction(); vector<LuaValue> args, rets; std::sort(m_vec.begin(), m_vec.end(), [func, &args, &rets](const LuaValue& a, const LuaValue& b){ args.push_back(a); args.push_back(b); func->call(args, rets); bool r = rets[0].getBoolean(); args.clear(); rets.clear(); return r; }); }
static void lua_effect_func_callback(lua_State* L, LuaValue& value, Effect& effect, CombatGameInst* inst) { value.push(L); if (lua_isnil(L, -1)) { lua_pop(L, 1); return; } effect.state.push(L); lua_push_gameinst(L, inst); lua_call(L, 2, 0); }
static void lua_hit_callback(lua_State* L, LuaValue& callback, GameInst* user, GameInst* target) { callback.push(L); if (!lua_isnil(L, -1)) { lua_push_gameinst(L, user); lua_push_gameinst(L, target); lua_call(L, 2, 0); } else { lua_pop(L, 1); } }
bool LuaState::callFunction(std::string fname, LuaValue& value) { //place the function on the stack getGlobal(fname); //push the argument value.push(L); //do it return pcall(1, 0); }
static int new_rvo_world(lua_State* L) { int n_args = lua_gettop(L); void* valptr = luameta_newuserdata(L, lua_rvoworldmetatable, sizeof(RVOSimulator)); RVOSimulator* sim = new (valptr) RVOSimulator(); if (n_args >= 1 && !lua_isnil(L, 1)) { LuaValue obstacles(L, 1); for (int i = 1; i <= obstacles.objlen(); i++) { LuaValue obstacle = obstacles[i]; std::vector<Vector2> vec; for (int i = 1; i <= obstacle.objlen(); i++) { LuaValue point = obstacle[i]; vec.push_back(Vector2(point[1].to_num(), point[2].to_num())); } sim->addObstacle(vec); } // Note: This may take long! sim->processObstacles(); } return 1; }
GameSettings init_game_data(lua_State* L) { DataFiles dfiles = load_datafilenames("res/datafiles.yaml"); //NB: Do not re-order the way resources are loaded unless you know what you're doing! //For example, all item data types must be loaded before room generation data load_tile_data(dfiles.tile_files); lua_sprites = load_sprite_data(L, dfiles.sprite_files); lua_sprites.deinitialize(L); load_tileset_data(dfiles.tileset_files); // --- ITEM DATA --- lua_items = load_item_data(L, dfiles.item_files); lua_projectiles = load_projectile_data(L, dfiles.projectile_files, lua_items); load_projectile_item_entries(); lua_spells = load_spell_data(L, dfiles.spell_files); load_weapon_data(L, dfiles.weapon_files, &lua_items); load_weapon_item_entries(); load_armour_data(L, dfiles.armour_files, &lua_items); load_armour_item_entries(); // --- ITEM DATA --- lua_effects = load_effect_data(L, dfiles.effect_files); lua_enemies = load_enemy_data(L, dfiles.enemy_files); load_itemgenlist_data(L, dfiles.itemgenlist_files); lua_dungeon = load_dungeon_data(L, dfiles.level_files); lua_dungeon.deinitialize(L); lua_classes = load_class_data(L, dfiles.class_files); GameSettings settings = load_settings_data("res/settings.yaml", L, &lua_settings); return settings; }
static void lua_init_metatable(lua_State* L, LuaValue& value, effect_id effect) { value.push(L); /* Set self as metatable*/ lua_pushvalue(L, -1); lua_setmetatable(L, -2); /* Set index as effect object */ EffectEntry& eentry = game_effect_data.at(effect); lua_effects.table_push_value(L, eentry.name.c_str()); lua_setfield(L, -2, "__index"); /* Pop self */ lua_pop(L, 1); }
bool popValue(lua_State* luaState, LuaValue& target, int stackposition, bool remove) { if (!internal::isValidIndex(luaState, stackposition)) { return false; } target.setReference(UniqueLuaReference::create(luaState, stackposition)); if (remove) { lua_remove(luaState, stackposition); } return true; }
static bool lua_spell_check_prereq(GameState* gs, PlayerInst* p, SpellEntry& spl_entry, LuaValue& action, const Pos& target) { lua_State* L = gs->get_luastate(); bool passes = true; action.push(L); if (!lua_isnil(L, -1)) { lua_push_gameinst(L, p); lua_pushnumber(L, target.x); lua_pushnumber(L, target.y); lua_call(L, 3, 1); passes = lua_toboolean(L, -1); } /*Pop either the nill or the boolean*/ lua_pop(L, 1); return passes; }
// - LuaValue::operator== --------------------------------------------------- bool LuaValue::operator== (const LuaValue& rhs) const { std::string lhsTypeName = typeName(); std::string rhsTypeName = rhs.typeName(); if (typeName() != rhs.typeName()) return false; else switch (type()) { case LUA_TNIL: return true; case LUA_TBOOLEAN: return asBoolean() == rhs.asBoolean(); case LUA_TNUMBER: return asNumber() == rhs.asNumber(); case LUA_TSTRING: return asString() == rhs.asString(); case LUA_TTABLE: return asTable() == rhs.asTable(); case LUA_TFUNCTION: return asFunction() == rhs.asFunction(); case LUA_TUSERDATA: return asUserData() == rhs.asUserData(); default: { assert( false && "Invalid type found in a call to 'LuaValue::operator==()'."); return 0; // make compilers happy } } }
static void DumpConstants(const LuaProto* f, DumpState* D) { int n = (int)f->constants.size(); DumpInt(n,D); for(int i=0; i < n; i++) { LuaValue v = f->constants[i]; DumpChar(v.type(),D); if(v.isBool()) { DumpChar(v.getBool() ? 1 : 0,D); } else if(v.isNumber()) { DumpNumber(v.getNumber(),D); } else if(v.isString()) { DumpString(v.getString(),D); } } n = (int)f->subprotos_.size(); DumpInt(n,D); for (int i=0; i < n; i++) { DumpFunction(f->subprotos_[i],D); } }
static void luayaml_push(LuaValue& value, lua_State *L, const char* name) { value.push(L); int tableind = lua_gettop(L); lua_getfield(L, tableind, name); lua_replace(L, tableind); }
static void register_as_global(lua_State* L, LuaValue& value, const char* name) { value.push(L); lua_setglobal(L, name); }
// - LuaValue::operator> ---------------------------------------------------- bool LuaValue::operator> (const LuaValue& rhs) const { std::string lhsTypeName = typeName(); std::string rhsTypeName = rhs.typeName(); if (lhsTypeName > rhsTypeName) return true; else if (lhsTypeName < rhsTypeName) return false; else // lhsTypeName == rhsTypeName { if (lhsTypeName == "nil") return false; else if (lhsTypeName == "boolean") return asBoolean() > rhs.asBoolean(); else if (lhsTypeName == "number") return asNumber() > rhs.asNumber(); else if (lhsTypeName == "string") return asString() > rhs.asString(); else if (lhsTypeName == "function") return asFunction() > rhs.asFunction(); else if (lhsTypeName == "userdata") return asUserData() > rhs.asUserData(); else if (lhsTypeName == "table") { const LuaValueMap lhsMap = asTable(); const LuaValueMap rhsMap = rhs.asTable(); if (lhsMap.size() > rhsMap.size()) return true; else if (lhsMap.size() < rhsMap.size()) return false; else // lhsMap.size() == rhsMap.size() { typedef LuaValueMap::const_iterator iter_t; iter_t pLHS = lhsMap.begin(); iter_t pRHS = rhsMap.begin(); const iter_t end = lhsMap.end(); while (pLHS != end) { // check the key first if (pLHS->first > pRHS->first) return true; else if (pLHS->first < pRHS->first) return false; // then check the value if (pLHS->second > pRHS->second) return true; else if (pLHS->second < pRHS->second) return false; // make the iterators iterate ++pRHS; ++pLHS; } return false; } } else { assert (false && "Unsupported type found at a call " "to 'LuaValue::operator>()'"); return false; // make the compiler happy. } } }
static void lua_init_effect(lua_State* L, LuaValue& value, effect_id effect) { value.table_initialize(L); lua_init_metatable(L, value, effect); }
const char* luaL_typename(LuaThread* L, int index) { THREAD_CHECK(L); LuaValue v = L->stack_.at(index); return v.typeName(); }
void init_game_data(GameSettings& settings, lua_State* L) { LuaSpecialValue globals = luawrap::globals(L); DataFiles dfiles = load_datafilenames("game/lanarts/datafiles.yaml"); //NB: Do not re-order the way resources are loaded unless you know what you're doing! //For example, all item data types must be loaded before room generation data load_tile_data(dfiles.tile_files); lua_sprites = load_sprite_data(L, dfiles.sprite_files); lua_sprites.clear(); load_tileset_data(dfiles.tileset_files); update_loading_screen(L, 0, "Loading Items"); // --- ITEM DATA --- // TODO: Go to new system lua_items = load_item_data(L, FilenameList()); update_loading_screen(L, 10, "Loading Projectiles"); lua_projectiles = load_projectile_data(L, dfiles.projectile_files, lua_items); update_loading_screen(L, 20, "Loading Spells"); lua_spells = load_spell_data(L, dfiles.spell_files); update_loading_screen(L, 30, "Loading Weapons"); load_weapon_data(L, dfiles.weapon_files, &lua_items); update_loading_screen(L, 40, "Loading Equipment"); load_equipment_data(L, dfiles.equipment_files, &lua_items); update_loading_screen(L, 50, "Loading Enemies"); // --- ITEM DATA --- lua_effects = load_effect_data(L, dfiles.effect_files); lua_enemies = load_enemy_data(L, dfiles.enemy_files); update_loading_screen(L, 60, "Loading Item Generation Templates"); update_loading_screen(L, 90, "Loading Classes"); lua_classes = load_class_data(L, FilenameList()); update_loading_screen(L, 100, "Complete!"); // TODO clean this up globals["enemies"] = lua_enemies; globals["effects"] = lua_effects; globals["items"] = lua_items; globals["projectiles"] = lua_projectiles; LuaValue weapons = luawrap::ensure_table(globals["weapons"]); int ind = 0; for (int i = 0; i < game_item_data.size(); i++) { ItemEntry& ientry = get_item_entry(i); if (dynamic_cast<WeaponEntry*>(&ientry)) { WeaponEntry& entry = get_weapon_entry(i); weapons[++ind] = lua_items[entry.name]; } } LuaValue armour = luawrap::ensure_table(globals["armour"]); ind = 0; for (int i = 0; i < game_item_data.size(); i++) { ItemEntry& ientry = get_item_entry(i); if (dynamic_cast<EquipmentEntry*>(&ientry)) { if (dynamic_cast<WeaponEntry*>(&ientry) || dynamic_cast<ProjectileEntry*>(&ientry)) { continue; } ItemEntry& entry = get_item_entry(i); armour[++ind] = lua_items[entry.name]; } } LuaValue consumables = luawrap::ensure_table(globals["consumable"]); for (int i = 0; i < game_item_data.size(); i++) { ItemEntry& ientry = get_item_entry(i); if (!dynamic_cast<EquipmentEntry*>(&ientry)) { ItemEntry& entry = get_item_entry(i); consumables[entry.name] = lua_items[entry.name]; } } globals["spells"] = lua_spells; globals["classes"] = lua_classes; __lua_init(L, game_enemy_data); __lua_init(L, game_effect_data); for (int i = 0; i < game_item_data.size(); i++) { game_item_data[i]->initialize(L); } for (int i = 0; i < game_spell_data.size(); i++) { game_spell_data[i].initialize(L); } }