diff --git a/data/RTTR/campaigns/roman/MISS200.lua b/data/RTTR/campaigns/roman/MISS200.lua index 7c5db32121..93b1c5c41d 100644 --- a/data/RTTR/campaigns/roman/MISS200.lua +++ b/data/RTTR/campaigns/roman/MISS200.lua @@ -221,6 +221,10 @@ rttr:RegisterTranslations( } }) +function getNumPlayers() + return 1 +end + -- format mission texts -- BUG: NewLine at the end is wrongly interpreted, adding 2x Space resolves this issue function MissionText(e) @@ -252,13 +256,6 @@ function onSettingsReady() rttr:GetPlayer(0):SetNation(NAT_ROMANS) -- nation rttr:GetPlayer(0):SetColor(0) -- 0:blue, 1:red, 2:yellow, rttr:GetPlayer(0):SetPortrait(0) - - rttr:GetPlayer(1):Close() - rttr:GetPlayer(2):Close() - rttr:GetPlayer(3):Close() - rttr:GetPlayer(4):Close() - rttr:GetPlayer(5):Close() - rttr:GetPlayer(6):Close() end function getAllowedChanges() diff --git a/data/RTTR/campaigns/roman/MISS206.lua b/data/RTTR/campaigns/roman/MISS206.lua index 3e028ae0bb..06aa209119 100644 --- a/data/RTTR/campaigns/roman/MISS206.lua +++ b/data/RTTR/campaigns/roman/MISS206.lua @@ -208,8 +208,12 @@ function addPlayerBld(p, onLoad) rttr:GetPlayer(p):DisableBuilding(BLD_SHIPYARD, false) rttr:GetPlayer(p):DisableBuilding(BLD_HARBORBUILDING, false) - if(p == 2) then - if onLoad then return end + if onLoad then return end + + if(p == 1) then + rttr:GetPlayer(p):PlaceHQ(112, 82) -- !SET_HOUSE 24, 112, 82 + elseif(p == 2) then + rttr:GetPlayer(p):PlaceHQ(40, 54) -- !SET_HOUSE 24, 40, 54 rttr:GetPlayer(p):AIConstructionOrder(43, 59, BLD_FORTRESS) end end diff --git a/doc/lua/functions.md b/doc/lua/functions.md index bbbb687917..c92d47a01c 100644 --- a/doc/lua/functions.md +++ b/doc/lua/functions.md @@ -347,6 +347,10 @@ Ignored if the current player is not controlled by AI. **GetHQPos()** Return x,y of the players HQ +**PlaceHQ(x, y)** +Places this player's headquarters at map location {x, y}. +Does nothing if the player already has a valid headquarters position (e.g. set by the map or using a previous PlaceHQ call). + **Surrender(destroyBuildings)** Let the player give up either keeping its buildings or destroying them. Can be called multiple times e.g. to destroy buildings later. diff --git a/libs/s25main/GameLobby.cpp b/libs/s25main/GameLobby.cpp index e1f3496b5b..11be3ae5dc 100644 --- a/libs/s25main/GameLobby.cpp +++ b/libs/s25main/GameLobby.cpp @@ -24,3 +24,8 @@ unsigned GameLobby::getNumPlayers() const { return players_.size(); } + +void GameLobby::setNumPlayers(unsigned num) +{ + players_.resize(num); +} diff --git a/libs/s25main/GameLobby.h b/libs/s25main/GameLobby.h index 171152d721..d97cf01e67 100644 --- a/libs/s25main/GameLobby.h +++ b/libs/s25main/GameLobby.h @@ -21,6 +21,7 @@ class GameLobby const JoinPlayerInfo& getPlayer(unsigned playerId) const; const std::vector& getPlayers() const { return players_; } unsigned getNumPlayers() const; + void setNumPlayers(unsigned num); GlobalGameSettings& getSettings() { return ggs_; } const GlobalGameSettings& getSettings() const { return ggs_; } diff --git a/libs/s25main/desktops/dskGameLobby.cpp b/libs/s25main/desktops/dskGameLobby.cpp index b47f6362c9..3a291955b4 100644 --- a/libs/s25main/desktops/dskGameLobby.cpp +++ b/libs/s25main/desktops/dskGameLobby.cpp @@ -34,6 +34,7 @@ #include "ingameWindows/iwMsgbox.h" #include "lua/LuaInterfaceSettings.h" #include "network/GameClient.h" +#include "network/GameServer.h" #include "ogl/FontStyle.h" #include "gameData/GameConsts.h" #include "gameData/PortraitConsts.h" @@ -162,6 +163,13 @@ dskGameLobby::dskGameLobby(ServerType serverType, std::shared_ptr gam RTTR_Assert(gameLobby_->isHost()); LOG.write(_("Lua was disabled by the script itself\n")); lua.reset(); + } else + { + if(const auto num = lua->GetNumPlayersFromScript()) + { + GAMESERVER.SetNumPlayers(num); + gameLobby_->setNumPlayers(num); + } } if(!lua && gameLobby_->isHost()) lobbyController->RemoveLuaScript(); diff --git a/libs/s25main/lua/LuaInterfaceSettings.cpp b/libs/s25main/lua/LuaInterfaceSettings.cpp index 8f29d5658f..5b24778a53 100644 --- a/libs/s25main/lua/LuaInterfaceSettings.cpp +++ b/libs/s25main/lua/LuaInterfaceSettings.cpp @@ -247,3 +247,13 @@ bool LuaInterfaceSettings::IsMapPreviewEnabled() } return true; } + +unsigned LuaInterfaceSettings::GetNumPlayersFromScript() +{ + kaguya::LuaRef func = lua["getNumPlayers"]; + if(func.type() == LUA_TFUNCTION) + { + return func.call(); + } + return 0; +} diff --git a/libs/s25main/lua/LuaInterfaceSettings.h b/libs/s25main/lua/LuaInterfaceSettings.h index a577a3e1ed..931f50c91e 100644 --- a/libs/s25main/lua/LuaInterfaceSettings.h +++ b/libs/s25main/lua/LuaInterfaceSettings.h @@ -36,6 +36,7 @@ class LuaInterfaceSettings : public LuaInterfaceGameBase /// Get addons that are allowed to be changed std::vector GetAllowedAddons(); bool IsMapPreviewEnabled(); + unsigned GetNumPlayersFromScript(); private: IGameLobbyController& lobbyServerController_; diff --git a/libs/s25main/lua/LuaPlayer.cpp b/libs/s25main/lua/LuaPlayer.cpp index 850678d7eb..7984ca2ee7 100644 --- a/libs/s25main/lua/LuaPlayer.cpp +++ b/libs/s25main/lua/LuaPlayer.cpp @@ -9,6 +9,7 @@ #include "ai/AIPlayer.h" #include "buildings/nobBaseWarehouse.h" #include "buildings/nobHQ.h" +#include "factories/BuildingFactory.h" #include "helpers/EnumRange.h" #include "helpers/toString.h" #include "lua/LuaHelpers.h" @@ -46,6 +47,7 @@ void LuaPlayer::Register(kaguya::State& state) .addFunction("GetNumPeople", &LuaPlayer::GetNumPeople) .addFunction("GetStatisticsValue", &LuaPlayer::GetStatisticsValue) .addFunction("AIConstructionOrder", &LuaPlayer::AIConstructionOrder) + .addFunction("PlaceHQ", &LuaPlayer::PlaceHQ) .addFunction("ModifyHQ", &LuaPlayer::ModifyHQ) .addFunction("GetHQPos", &LuaPlayer::GetHQPos) .addFunction("IsDefeated", &LuaPlayer::IsDefeated) @@ -259,6 +261,19 @@ bool LuaPlayer::AIConstructionOrder(unsigned x, unsigned y, lua::SafeEnum @@ -50,6 +51,7 @@ class LuaPlayer : public LuaPlayerBase unsigned GetNumPeople(lua::SafeEnum job) const; unsigned GetStatisticsValue(lua::SafeEnum stat) const; bool AIConstructionOrder(unsigned x, unsigned y, lua::SafeEnum bld); + void PlaceHQ(MapCoord x, MapCoord y); void ModifyHQ(bool isTent); bool IsDefeated() const; void Surrender(bool destroyBlds); diff --git a/libs/s25main/network/GameClient.cpp b/libs/s25main/network/GameClient.cpp index b365405b44..45a82978d0 100644 --- a/libs/s25main/network/GameClient.cpp +++ b/libs/s25main/network/GameClient.cpp @@ -330,8 +330,10 @@ void GameClient::StartGame(const unsigned random_init) gameWorld.GetPlayer(i).MakeStartPacts(); MapLoader loader(gameWorld); - if(!loader.Load(mapinfo.filepath) - || (!mapinfo.luaFilepath.empty() && !loader.LoadLuaScript(*game, *this, mapinfo.luaFilepath))) + if((!mapinfo.luaFilepath.empty() && !loader.LoadLuaScript(*game, *this, mapinfo.luaFilepath)) + || !loader.Load(mapinfo.filepath)) // Do not reorder: load lua first, load map second. + // If the map is loaded first and it does not have a player HQ set, it + // will not load correctly, even though the HQ may be set using LUA. { OnError(ClientError::InvalidMap); return; diff --git a/libs/s25main/network/GameServer.cpp b/libs/s25main/network/GameServer.cpp index 11cce77d21..d60ab232a5 100644 --- a/libs/s25main/network/GameServer.cpp +++ b/libs/s25main/network/GameServer.cpp @@ -519,6 +519,14 @@ bool GameServer::assignPlayersOfRandomTeams(std::vector& playerI return playerWasAssigned; } +void GameServer::SetNumPlayers(unsigned num) +{ + playerInfos.resize(num); +} + +/** + * startet das Spiel. + */ bool GameServer::StartGame() { lanAnnouncer.Stop(); diff --git a/libs/s25main/network/GameServer.h b/libs/s25main/network/GameServer.h index 59abae6137..5e27230de8 100644 --- a/libs/s25main/network/GameServer.h +++ b/libs/s25main/network/GameServer.h @@ -52,6 +52,8 @@ class GameServer : /// Assign players that do not have a fixed team, return true if any player was assigned. static bool assignPlayersOfRandomTeams(std::vector& playerInfos); + void SetNumPlayers(unsigned num); + private: bool StartGame(); diff --git a/libs/s25main/world/MapLoader.cpp b/libs/s25main/world/MapLoader.cpp index b3b60b0dcb..888d5102b3 100644 --- a/libs/s25main/world/MapLoader.cpp +++ b/libs/s25main/world/MapLoader.cpp @@ -409,8 +409,11 @@ bool MapLoader::PlaceHQs(GameWorldBase& world, std::vector hqPositions // Does the HQ have a position? if(i >= hqPositions.size() || !hqPositions[i].isValid()) { - LOG.write(_("Player %u does not have a valid start position!")) % i; - return false; + LOG.write(_("Player %u does not have a valid start position!\n")) % i; + if(world.HasLua()) // HQ can be placed in the script, so don't signal error + continue; + else + return false; } BuildingFactory::CreateBuilding(world, BuildingType::Headquarters, hqPositions[i], i,