int Lua_Monster_Position(lua_State *L) { if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4)) return luaL_error(L, "position: incorrect argument type"); short polygon_index = 0; if (lua_isnumber(L, 5)) { polygon_index = static_cast<int>(lua_tonumber(L, 5)); if (!Lua_Polygon::Valid(polygon_index)) return luaL_error(L, "position: invalid polygon index"); } else if (Lua_Polygon::Is(L, 5)) { polygon_index = Lua_Polygon::Index(L, 5); } else return luaL_error(L, "position: incorrect argument type"); monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1)); object_data *object = get_object_data(monster->object_index); object->location.x = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE); object->location.y = static_cast<int>(lua_tonumber(L, 3) * WORLD_ONE); object->location.z = static_cast<int>(lua_tonumber(L, 4) * WORLD_ONE); if (polygon_index != object->polygon) { remove_object_from_polygon_object_list(monster->object_index); add_object_to_polygon_object_list(monster->object_index, polygon_index); } return 0; }
// ZZZ: if in predictive mode, restore the saved partial game-state (it'd better take us back // to _exactly_ the same full game-state we saved earlier, else problems.) static void exit_predictive_mode() { if(sPredictedTicks > 0) { for(short i = 0; i < dynamic_world->player_count; i++) { player_data* player = get_player_data(i); assert(player->monster_index == sSavedPlayerData[i].monster_index); { // We *don't* restore this tiny part of the game-state back because // otherwise the player can't use [] to scroll the inventory panel. // [] scrolling happens outside the normal input/update system, so that's // enough to persuade me that not restoring this won't OOS any more often // than []-scrolling did before prediction. :) int16 saved_interface_flags = player->interface_flags; int16 saved_interface_decay = player->interface_decay; *player = sSavedPlayerData[i]; player->interface_flags = saved_interface_flags; player->interface_decay = saved_interface_decay; } if(sSavedPlayerData[i].monster_index != NONE) { assert(get_monster_data(sSavedPlayerData[i].monster_index)->object_index == sSavedPlayerMonsterData[i].object_index); *get_monster_data(sSavedPlayerData[i].monster_index) = sSavedPlayerMonsterData[i]; if(sSavedPlayerMonsterData[i].object_index != NONE) { assert(get_object_data(sSavedPlayerMonsterData[i].object_index)->parasitic_object == sSavedPlayerObjectData[i].parasitic_object); remove_object_from_polygon_object_list(sSavedPlayerMonsterData[i].object_index); *get_object_data(sSavedPlayerMonsterData[i].object_index) = sSavedPlayerObjectData[i]; // We have to defer this insertion since the object lists could still have other players // in their predictive locations etc. - we need to reconstruct everything exactly as it // was when we entered predictive mode. deferred_add_object_to_polygon_object_list(sSavedPlayerMonsterData[i].object_index, sSavedPlayerObjectNextObject[i]); if(sSavedPlayerObjectData[i].parasitic_object != NONE) *get_object_data(sSavedPlayerObjectData[i].parasitic_object) = sSavedPlayerParasiticObjectData[i]; } } } perform_deferred_polygon_object_list_manipulations(); sPredictedTicks = 0; // Sanity checking if(sSavedTickCount != dynamic_world->tick_count) logWarning2("saved tick count %d != dynamic_world->tick_count %d", sSavedTickCount, dynamic_world->tick_count); if(sSavedRandomSeed != get_random_seed()) logWarning2("saved random seed %d != get_random_seed() %d", sSavedRandomSeed, get_random_seed()); } }