From 6669c1e8c225ca4ea23d1438ca3ed86d27aa74af Mon Sep 17 00:00:00 2001 From: devZoGok Date: Tue, 3 Mar 2026 16:26:35 +0200 Subject: [PATCH] optimized CPU player spawn point occupation implementation bugfix for navigating empty paths --- Assets/Scripts/Core/player.lua | 78 +++++++++++++++++------------- Assets/Scripts/Core/playerInit.lua | 1 + gameManager.cpp | 1 + player.cpp | 11 +++++ player.h | 1 + vehicle.cpp | 5 +- 6 files changed, 62 insertions(+), 35 deletions(-) diff --git a/Assets/Scripts/Core/player.lua b/Assets/Scripts/Core/player.lua index 0d5f16b..ead20ef 100644 --- a/Assets/Scripts/Core/player.lua +++ b/Assets/Scripts/Core/player.lua @@ -237,6 +237,24 @@ function Player:getBuildableUnitSlotId(buildingUnit, buildableUnitId) return nil end +function Player:updateTaskForces(arguments) + units = self:getUnits() + + for i = 1, #self.taskForces do + for j = #self.taskForces[i].units, 1, -1 do + for k = 1, #units do + if self.taskForces[i].units[j] == units[k] then goto continue end + end + + table.remove(self.taskForces[i].units, j) + + ::continue:: + end + end + + return BTNodeResult.SUCCESS +end + function Player:buildLandFactory(arguments) factory = self:getUnitsByClass(UnitClass.LAND_FACTORY, 1)[1] @@ -244,13 +262,17 @@ function Player:buildLandFactory(arguments) return factory:toStructure():isComplete() and BTNodeResult.SUCCESS or BTNodeResult.RUNNING end + engi = self:findIdleEngineer() + + if not engi then return BTNodeResult.FAILURE end + factId = self.unitClassMappings[UnitClass.LAND_FACTORY + 1][self:getFaction() + 1] rd = self.baseQuat:multVec(Vector3:new(0, 0, 1)):mult(self.baseRadius) sp = Map.getSingleton():getSpawnPoint(self:getSpawnPointId()) pos = self:findSuitableSpot(factId, sp) if pos then - self:buildStructure(self:findIdleEngineer(), factId, pos, self.baseQuat:getAngle()) + self:buildStructure(engi, factId, pos, self.baseQuat:getAngle()) factory = self:getUnitsByClass(UnitClass.LAND_FACTORY, 1)[1]:toFactory() factory:setRallyPoint(factory:getPos():add(factory:getDirVec():mult(40))) return BTNodeResult.RUNNING @@ -401,25 +423,6 @@ function Player:buildNavalFactory(arguments) else return BTNodeResult.FAILURE end end -function Player:buildNavalForce(arguments) - transports = self:getUnitsByClass(UnitClass.TRANSPORT, -1) - - if #transports >= #self.taskForces then return BTNodeResult.SUCCESS end - - factory = self:getUnitsByClass(UnitClass.NAVAL_FACTORY, 1)[1]:toFactory() - - if #factory:getQueue() > 0 then return BTNodeResult.RUNNING end - - transportBuildId = self.unitClassMappings[UnitClass.TRANSPORT + 1][self:getFaction() + 1] - numBuildTransports = #self.taskForces - #transports - - for i = 1, numBuildTransports do - factory:appendToQueue(self:getBuildableUnitSlotId(factory, transportBuildId)) - end - - return BTNodeResult.RUNNING -end - function Player:buildTaskForces(arguments) factory = self:getUnitsByClass(arguments.factoryClass, 1) @@ -489,7 +492,7 @@ function Player:formLandTaskForces(arguments) for i = 1, numSpawnPoints do if i - 1 == self:getSpawnPointId() then goto continue end - self.taskForces[tfId] = {units = {}, moving = false, arrived = false, landed = false, spawnPointId = i - 1} + self.taskForces[tfId] = {units = {}, moving = false, attacking = false, arrived = false, landed = false, spawnPointId = i - 1} for j = 1, #self.landTaskForceData do subArrId = (tfId - 1) * self.landTaskForceData[j].numUnits + 1 @@ -529,7 +532,6 @@ function Player:getTransportData(transports) end function Player:boardTransports(arguments) - print('executing BOARD ' .. arguments.taskForceId) taskForce = self.taskForces[arguments.taskForceId] if taskForce.landed then return BTNodeResult.SUCCESS end @@ -621,31 +623,41 @@ function Player:occupySpawnPoint(arguments) end if #self.taskForces[tfId].units > 0 then - if self.taskForces[tfId].moving then - return BTNodeResult.RUNNING - elseif self.taskForces[tfId].arrived then + if self.taskForces[tfId].arrived then return BTNodeResult.SUCCESS end elseif #self.taskForces[tfId].units == 0 then return BTNodeResult.FAILURE end + hostileUnits = self:getHostileUnits() spawnPoint = Map.getSingleton():getSpawnPoint(self.taskForces[tfId].spawnPointId) minDist = 10 - for i = 1, #self.taskForces[tfId].units do - if self.taskForces[tfId].units[i]:getPos():getDistanceFrom(spawnPoint) < minDist then - self.taskForces[tfId].moving = false - self.taskForces[tfId].arrived = true - return BTNodeResult.SUCCESS + if #hostileUnits == 0 then + for i = 1, #self.taskForces[tfId].units do + if self.taskForces[tfId].units[i]:getPos():getDistanceFrom(spawnPoint) < minDist then + self.taskForces[tfId].moving = false + self.taskForces[tfId].arrived = true + return BTNodeResult.SUCCESS + end end - end - if not self.taskForces[tfId].moving then + if not self.taskForces[tfId].moving then + self.taskForces[tfId].moving = true + self:deselectUnits() + self:selectUnits(self.taskForces[tfId].units) + self:issueOrder(OrderType.MOVE, Vector3:new(0, 0, 0), {Target:new(nil, spawnPoint)}, false) + end + + self.taskForces[tfId].attacking = false self.taskForces[tfId].moving = true + elseif #hostileUnits > 0 and self.taskForces[tfId].units[1]:getNumOrders() == 0 then self:deselectUnits() self:selectUnits(self.taskForces[tfId].units) - self:issueOrder(OrderType.MOVE, Vector3:new(0, 0, 0), {Target:new(nil, spawnPoint)}, false) + self:issueOrder(OrderType.ATTACK, Vector3:new(0, 0, 0), {Target:new(hostileUnits[1]:toGameObject(), Vector3:new(0, 0, 0))}, false) + self.taskForces[tfId].attacking = true + self.taskForces[tfId].movign = false end return BTNodeResult.RUNNING diff --git a/Assets/Scripts/Core/playerInit.lua b/Assets/Scripts/Core/playerInit.lua index b8fa9f4..2c7a289 100644 --- a/Assets/Scripts/Core/playerInit.lua +++ b/Assets/Scripts/Core/playerInit.lua @@ -5,6 +5,7 @@ for i = 1, #game.cpuPlayers do player.behaviour = { type = BTNodeType.SEQUENCE, children = { + --{type = BTNodeType.FUNCTION, func = player.updateTaskForces}, {type = BTNodeType.FUNCTION, func = player.buildLandFactory}, { type = BTNodeType.FUNCTION, diff --git a/gameManager.cpp b/gameManager.cpp index 3ec792e..ef5311d 100755 --- a/gameManager.cpp +++ b/gameManager.cpp @@ -148,6 +148,7 @@ namespace battleship{ "getFaction", &Player::getFaction, "getTeam", &Player::getTeam, "getUnits", &Player::getUnits, + "getHostileUnits", &Player::getHostileUnits, "getUnitsById", &Player::getUnitsById, "getUnitsByClass", &Player::getUnitsByClass ); diff --git a/player.cpp b/player.cpp index 6592f60..72efd66 100755 --- a/player.cpp +++ b/player.cpp @@ -308,6 +308,17 @@ namespace battleship{ return friendlyUnits; } + vector Player::getHostileUnits(){ + vector hostileUnits, friendlyUnits = getFriendlyUnits(true); + + for (Player *pl : Game::getSingleton()->getPlayers(true)) + for (Unit *u : pl->getUnits()) + if(pl->getTeam() != getTeam() && isObjectVisible(u, friendlyUnits)) + hostileUnits.push_back(u); + + return hostileUnits; + } + //TODO improve this for greater accuracy bool Player::isObjectVisible(GameObject *object, std::vector friendlyUnits) { Player *objPlayer = object->getPlayer(); diff --git a/player.h b/player.h index e104312..3fc2f55 100755 --- a/player.h +++ b/player.h @@ -41,6 +41,7 @@ namespace battleship{ std::vector getDestructables(); void updateGameStats(Unit*); std::vector getFriendlyUnits(bool = true); + std::vector getHostileUnits(); bool isObjectVisible(GameObject*, std::vector); inline int getResource(ResourceType rt){return resources[(int)rt];} inline void updateResource(ResourceType rt, int amount, bool add){resources[(int)rt] = (add ? resources[(int)rt] + amount : amount);} diff --git a/vehicle.cpp b/vehicle.cpp index cc02956..8c5d338 100644 --- a/vehicle.cpp +++ b/vehicle.cpp @@ -238,6 +238,8 @@ namespace battleship{ } void Vehicle::navigate(float destOffset){ + if(pathPoints.empty()) return; + Vector3 hypVec = (pathPoints[0] - pos); Vector3 baseDir = getVecToPlane(pos, hypVec, upVec); float angle = baseDir.getAngleBetween(dirVec); @@ -253,8 +255,7 @@ namespace battleship{ void Vehicle::move(Order order) { navigate(0.5 * Map::getSingleton()->getCellSize().x); - if(pathPoints.empty()) - removeOrder(0); + if(pathPoints.empty()) removeOrder(0); } void Vehicle::exitGarrisonable(Vector3 exitPos){