void frmMain::_onSaveMenuSave(wxCommandEvent& evt) { if(m_sFilename.empty()) { _onSaveMenuSaveAs(evt); return; } map_save_t oSave; if(oSave.fFile.Open(m_sFilename, wxFile::write)) { lua_State* L = m_pGamePanel->getLua(); luaT_execute(L, "return TheApp.world.map.th"); THMap *pMap = reinterpret_cast<THMap*>(lua_touserdata(L, -1)); lua_pop(L, 1); THMapWrapper::autoSetHelipad(pMap); luaT_execute(L, "return TheApp.ui:ScreenToWorld(...)", m_pGamePanel->GetSize().GetWidth() / 2, m_pGamePanel->GetSize().GetHeight() / 2); int iCameraX = (int)lua_tointeger(L, -2); int iCameraY = (int)lua_tointeger(L, -1); lua_pop(L, 2); pMap->setPlayerCameraTile(0, iCameraX, iCameraY); pMap->save(map_save_t::writer, reinterpret_cast<void*>(&oSave)); ::wxMessageBox(wxT("Map saved."), wxT("Save"), wxOK | wxCENTER | wxICON_INFORMATION, this); } }
static int l_map_save(lua_State *L) { THMap *pMap = luaT_testuserdata<THMap>(L); std::string filename(luaL_checkstring(L, 2)); pMap->save(filename); return 0; }
static int l_map_set_parcel_owner(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int parcelId = static_cast<int>(luaL_checkinteger(L, 2)); int player = static_cast<int>(luaL_checkinteger(L, 3)); if(lua_type(L, 4) != LUA_TTABLE) { lua_settop(L, 3); lua_newtable(L); } else { lua_settop(L, 4); } std::vector<std::pair<int, int>> vSplitTiles = pMap->setParcelOwner(parcelId, player); for (std::vector<std::pair<int, int>>::size_type i = 0; i != vSplitTiles.size(); i++) { lua_pushinteger(L, i + 1); lua_createtable(L, 0, 2); lua_pushinteger(L, 1); lua_pushinteger(L, vSplitTiles[i].first + 1); lua_settable(L, 6); lua_pushinteger(L, 2); lua_pushinteger(L, vSplitTiles[i].second + 1); lua_settable(L, 6); lua_settable(L, 4); } return 1; }
static int l_map_is_parcel_purchasable(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); lua_pushboolean(L, pMap->isParcelPurchasable(static_cast<int>(luaL_checkinteger(L, 2)), static_cast<int>(luaL_checkinteger(L, 3))) ? 1 : 0); return 1; }
static int l_map_getsize(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); lua_pushinteger(L, pMap->getWidth()); lua_pushinteger(L, pMap->getHeight()); return 2; }
static int l_map_updateshadows(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); pMap->updateShadows(); lua_settop(L, 1); return 1; }
static int l_map_getcell(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX = static_cast<int>(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast<int>(luaL_checkinteger(L, 3) - 1); // the map does too. THMapNode* pNode = pMap->getNode(iX, iY); if(pNode == nullptr) { return luaL_argerror(L, 2, lua_pushfstring(L, "Map co-ordinates out " "of bounds (%d, %d)", iX + 1, iY + 1)); } if(lua_isnoneornil(L, 4)) { lua_pushinteger(L, pNode->iBlock[0]); lua_pushinteger(L, pNode->iBlock[1]); lua_pushinteger(L, pNode->iBlock[2]); lua_pushinteger(L, pNode->iBlock[3]); return 4; } else { lua_Integer iLayer = luaL_checkinteger(L, 4) - 1; if(iLayer < 0 || iLayer >= 4) return luaL_argerror(L, 4, "Layer index is out of bounds (1-4)"); lua_pushinteger(L, pNode->iBlock[iLayer]); return 1; } }
static int l_map_updatepathfinding(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); pMap->updatePathfinding(); lua_settop(L, 1); return 1; }
static int l_map_setcell(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX = static_cast<int>(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast<int>(luaL_checkinteger(L, 3) - 1); // the map does too. THMapNode* pNode = pMap->getNode(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); if(lua_gettop(L) >= 7) { pNode->iBlock[0] = (uint16_t)luaL_checkinteger(L, 4); pNode->iBlock[1] = (uint16_t)luaL_checkinteger(L, 5); pNode->iBlock[2] = (uint16_t)luaL_checkinteger(L, 6); pNode->iBlock[3] = (uint16_t)luaL_checkinteger(L, 7); } else { lua_Integer iLayer = luaL_checkinteger(L, 4) - 1; if(iLayer < 0 || iLayer >= 4) return luaL_argerror(L, 4, "Layer index is out of bounds (1-4)"); uint16_t iBlock = static_cast<uint16_t>(luaL_checkinteger(L, 5)); pNode->iBlock[iLayer] = iBlock; } lua_settop(L, 1); return 1; }
static int l_map_setwallflags(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); pMap->setAllWallDrawFlags((uint8_t)luaL_checkinteger(L, 2)); lua_settop(L, 1); return 1; }
/** * Get the value of all cell flags at a position. * @param L Lua context. * @return Number of results of the call. */ static int l_map_getcellflags(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX = static_cast<int>(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast<int>(luaL_checkinteger(L, 3) - 1); // the map does too. THMapNode* pNode = pMap->getNode(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); if(lua_type(L, 4) != LUA_TTABLE) { lua_settop(L, 3); lua_createtable(L, 0, 1); } else { lua_settop(L, 4); } // Fill Lua table with the flags and numbers of the node. for (auto val : lua_node_flag_map) { add_cellflag(L, pNode, val.second, val.first); } add_cellint(L, pNode->iRoomId, "roomId"); add_cellint(L, pNode->iParcelId, "parcelId"); add_cellint(L, pNode->iFlags >> 24, "thob"); return 1; }
static int l_anim_get_tile(lua_State *L) { THAnimation* pAnimation = luaT_testuserdata<THAnimation>(L); lua_settop(L, 1); lua_getfenv(L, 1); lua_getfield(L, 2, "map"); lua_replace(L, 2); if(lua_isnil(L, 2)) { return 0; } THMap* pMap = (THMap*)lua_touserdata(L, 2); const THLinkList* pListNode = pAnimation->getPrevious(); while(pListNode->m_pPrev) { pListNode = pListNode->m_pPrev; } // Casting pListNode to a THMapNode* is slightly dubious, but it should // work. If on the normal list, then pListNode will be a THMapNode*, and // all is fine. However, if on the early list, pListNode will be pointing // to a member of a THMapNode, so we're relying on pointer arithmetic // being a subtract and integer divide by sizeof(THMapNode) to yield the // correct map node. const THMapNode *pRootNode = pMap->getNodeUnchecked(0, 0); uintptr_t iDiff = reinterpret_cast<const char*>(pListNode) - reinterpret_cast<const char*>(pRootNode); int iIndex = (int)(iDiff / sizeof(THMapNode)); int iY = iIndex / pMap->getWidth(); int iX = iIndex - (iY * pMap->getWidth()); lua_pushinteger(L, iX + 1); lua_pushinteger(L, iY + 1); return 3; // map, x, y }
static int l_anim_set_tile(lua_State *L) { T* pAnimation = luaT_testuserdata<T>(L); if(lua_isnoneornil(L, 2)) { pAnimation->removeFromTile(); lua_pushnil(L); luaT_setenvfield(L, 1, "map"); lua_settop(L, 1); } else { THMap* pMap = luaT_testuserdata<THMap>(L, 2); THMapNode* pNode = pMap->getNode(luaL_checkint(L, 3) - 1, luaL_checkint(L, 4) - 1); if(pNode) pAnimation->attachToTile(pNode, lastLayer); else { luaL_argerror(L, 3, lua_pushfstring(L, "Map index out of bounds (" LUA_NUMBER_FMT "," LUA_NUMBER_FMT ")", lua_tonumber(L, 3), lua_tonumber(L, 4))); } lua_settop(L, 2); luaT_setenvfield(L, 1, "map"); } return 1; }
static int l_map_settemperaturedisplay(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); lua_Integer iTD = luaL_checkinteger(L, 2) - 1; if (iTD >= THMT_Count) iTD = THMT_Red; pMap->setTemperatureDisplay(static_cast<THMapTemperatureDisplay>(iTD)); return 1; }
static int l_map_get_parcel_tilecount(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iParcel = static_cast<int>(luaL_checkinteger(L, 2)); lua_Integer iCount = pMap->getParcelTileCount(iParcel); lua_pushinteger(L, iCount); return 1; }
static int l_map_persist(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); lua_settop(L, 2); lua_insert(L, 1); pMap->persist((LuaPersistWriter*)lua_touserdata(L, 1)); return 0; }
static int l_map_updatetemperature(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); uint16_t iAir = l_check_temp(L, 2); uint16_t iRadiator = l_check_temp(L, 3); pMap->updateTemperatures(iAir, iRadiator); lua_settop(L, 1); return 1; }
static int l_map_loadblank(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); if(pMap->loadBlank()) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); lua_newtable(L); return 2; }
static int l_map_set_sheet(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); THSpriteSheet* pSheet = luaT_testuserdata<THSpriteSheet>(L, 2); lua_settop(L, 2); pMap->setBlockSheet(pSheet); luaT_setenvfield(L, 1, "sprites"); return 1; }
static int l_map_gettemperature(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX = static_cast<int>(luaL_checkinteger(L, 2)) - 1; int iY = static_cast<int>(luaL_checkinteger(L, 3)) - 1; const THMapNode* pNode = pMap->getNode(iX, iY); uint16_t iTemp = pMap->getNodeTemperature(pNode); lua_pushnumber(L, static_cast<lua_Number>(iTemp) / static_cast<lua_Number>(65535)); return 1; }
static int l_map_draw(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); THRenderTarget* pCanvas = luaT_testuserdata<THRenderTarget>(L, 2); pMap->draw(pCanvas, static_cast<int>(luaL_checkinteger(L, 3)), static_cast<int>(luaL_checkinteger(L, 4)), static_cast<int>(luaL_checkinteger(L, 5)), static_cast<int>(luaL_checkinteger(L, 6)), static_cast<int>(luaL_optinteger(L, 7, 0)), static_cast<int>(luaL_optinteger(L, 8, 0))); lua_settop(L, 1); return 1; }
static int l_map_hittest(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); THDrawable* pObject = pMap->hitTest(static_cast<int>(luaL_checkinteger(L, 2)), static_cast<int>(luaL_checkinteger(L, 3))); if(pObject == nullptr) return 0; lua_rawgeti(L, luaT_upvalueindex(1), 1); lua_pushlightuserdata(L, pObject); lua_gettable(L, -2); return 1; }
/* because all the thobs are not retrieved when the map is loaded in c lua objects use the afterLoad function to be registered after a load, if the object list would not be cleared it would result in duplication of thobs in the object list. */ static int l_map_erase_thobs(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX = static_cast<int>(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast<int>(luaL_checkinteger(L, 3) - 1); // the map does too. THMapNode* pNode = pMap->getNode(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); pNode->objects.clear(); return 1; }
static int l_map_get_player_camera(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX, iY; int iPlayer = static_cast<int>(luaL_optinteger(L, 2, 1)); bool bGood = pMap->getPlayerCameraTile(iPlayer - 1, &iX, &iY); if(!bGood) return luaL_error(L, "Player index out of range: %d", iPlayer); lua_pushinteger(L, iX + 1); lua_pushinteger(L, iY + 1); return 2; }
static int l_map_set_player_heliport(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX = static_cast<int>(luaL_checkinteger(L, 2) - 1); int iY = static_cast<int>(luaL_checkinteger(L, 3) - 1); int iPlayer = static_cast<int>(luaL_optinteger(L, 4, 1)); if (iPlayer < 1 || iPlayer > player_max) return luaL_error(L, "Player index out of range: %i", iPlayer); pMap->setPlayerHeliportTile(iPlayer - 1, iX, iY); return 0; }
static int l_map_depersist(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); lua_settop(L, 2); lua_insert(L, 1); LuaPersistReader* pReader = (LuaPersistReader*)lua_touserdata(L, 1); pMap->depersist(pReader); luaT_getenvfield(L, 2, "sprites"); pMap->setBlockSheet((THSpriteSheet*)lua_touserdata(L, -1)); lua_pop(L, 1); return 0; }
static int l_map_load(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); size_t iDataLen; const uint8_t* pData = luaT_checkfile(L, 2, &iDataLen); lua_settop(L, 2); lua_newtable(L); if(pMap->loadFromTHFile(pData, iDataLen, l_map_load_obj_cb, (void*)L)) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); lua_insert(L, -2); return 2; }
static int l_map_setcellflags(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX = static_cast<int>(luaL_checkinteger(L, 2) - 1); // Lua arrays start at 1 - pretend int iY = static_cast<int>(luaL_checkinteger(L, 3) - 1); // the map does too. THMapNode* pNode = pMap->getNode(iX, iY); if(pNode == nullptr) return luaL_argerror(L, 2, "Map co-ordinates out of bounds"); luaL_checktype(L, 4, LUA_TTABLE); lua_settop(L, 4); lua_pushnil(L); while(lua_next(L, 4)) { if(lua_type(L, 5) == LUA_TSTRING) { const char *field = lua_tostring(L, 5); auto iter = lua_node_flag_map.find(field); if(iter != lua_node_flag_map.end()) { if (lua_toboolean(L, 6) == 0) pNode->flags[(*iter).second] = false; else pNode->flags[(*iter).second] = true; } else if (std::strcmp(field, "thob") == 0) { auto thob = static_cast<THObjectType>(lua_tointeger(L, 6)); pNode->objects.push_back(thob); } else if(std::strcmp(field, "parcelId") == 0) { pNode->iParcelId = static_cast<uint16_t>(lua_tointeger(L, 6)); } else if(std::strcmp(field, "roomId") == 0) { pNode->iRoomId = static_cast<uint16_t>(lua_tointeger(L,6)); } else { luaL_error(L, "Invalid flag \'%s\'", field); } } lua_settop(L, 5); } return 0; }
static int l_map_set_player_count(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int count = static_cast<int>(luaL_checkinteger(L, 2)); try { pMap->setPlayerCount(count); } catch (std::out_of_range) { return luaL_error(L, "Player count out of range %d", count); } return 0; }
static int l_map_unmark_room(lua_State *L) { THMap* pMap = luaT_testuserdata<THMap>(L); int iX_ = static_cast<int>(luaL_checkinteger(L, 2) - 1); int iY_ = static_cast<int>(luaL_checkinteger(L, 3) - 1); int iW = static_cast<int>(luaL_checkinteger(L, 4)); int iH = static_cast<int>(luaL_checkinteger(L, 5)); if(iX_ < 0 || iY_ < 0 || (iX_ + iW) > pMap->getWidth() || (iY_ + iH) > pMap->getHeight()) luaL_argerror(L, 2, "Rectangle is out of bounds"); for(int iY = iY_; iY < iY_ + iH; ++iY) { for(int iX = iX_; iX < iX_ + iW; ++iX) { THMapNode *pNode = pMap->getNodeUnchecked(iX, iY); pNode->iBlock[0] = pMap->getOriginalNodeUnchecked(iX, iY)->iBlock[0]; pNode->flags.room = false; pNode->iRoomId = 0; } } pMap->updatePathfinding(); pMap->updateShadows(); lua_settop(L, 1); return 1; }