From a3b6dbc93c2e7a6bf4afa8e7948a8a018a6520f8 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Thu, 12 Feb 2026 13:54:32 +0200 Subject: [PATCH] redone CPU player behaviour --- Assets/Scripts/Core/player.lua | 328 ++++++++++-------- Assets/Scripts/Core/playerInit.lua | 57 ++- Assets/Scripts/GameObjects/Units/unitData.lua | 71 ++-- activeGameState.cpp | 7 +- freezer.cpp | 2 +- game.cpp | 33 +- game.h | 3 +- gameManager.cpp | 8 + gameObjectFactory.cpp | 5 +- inGameAppState.cpp | 2 +- structure.cpp | 2 +- unit.cpp | 5 +- unit.h | 8 +- vehicle.cpp | 4 +- 14 files changed, 323 insertions(+), 212 deletions(-) diff --git a/Assets/Scripts/Core/player.lua b/Assets/Scripts/Core/player.lua index 416c70d..6d3a94d 100644 --- a/Assets/Scripts/Core/player.lua +++ b/Assets/Scripts/Core/player.lua @@ -2,105 +2,43 @@ Player.numStartEngis = 3 Player.baseDir = nil Player.numDefWarMechs = 1 Player.behaviour = {} +Player.pointDefenseTrans = {} + +Player.unitClassMappings = { + {UnitId.ACS_MECH, UnitId.AINC_MECH, UnitId.ER_MECH}, --WAR_MECH = 0, + {UnitId.ACS_TANK, UnitId.AINC_TANK, UnitId.ER_TANK}, --TANK = 1, + {UnitId.ACS_ARTILLERY, UnitId.AINC_ARTILLERY, UnitId.ER_ARTILLERY}, --ARTILLERY = 2, + {UnitId.ACS_ROBO_ENGINEER, UnitId.AINC_ROBO_ENGINEER, UnitId.ER_ROBO_ENGINEER}, --ENGINEER = 3, + {UnitId.ACS_CYBORG_ENGINEER, UnitId.AINC_CYBORG_ENGINEER, UnitId.ER_CYBORG_ENGINEER}, --ENGINEER = 3, + {UnitId.ACS_MECH, UnitId.AINC_MECH, UnitId.ER_MECH}, --TRANSPORT = 4, + {UnitId.ACS_CARGO_SHIP, UnitId.AINC_CARGO_SHIP, UnitId.ER_CARGO_SHIP}, --RESOURCE_ROVER = 5, + {UnitId.ACS_CRUISER, UnitId.AINC_CRUISER, UnitId.ER_CRUISER}, --CRUISER = 6, + {UnitId.ACS_ANTI_SUB_CRUISER, UnitId.AINC_ANTI_SUB_CRUISER, UnitId.ER_ANTI_SUB_CRUISER}, --CRUISER = 6, + {nil, nil, nil}, --CARRIER = 8, + {UnitId.ACS_SUBMARINE, UnitId.AINC_SUBMARINE, UnitId.ER_SUBMARINE}, --SUBMARINE = 9, + {UnitId.ACS_MISSILE_SUBMARINE, UnitId.AINC_MISSILE_SUBMARINE, UnitId.ER_MISSILE_SUBMARINE}, --SUBMARINE = 9, + {UnitId.ACS_ICEBREAKER, UnitId.AINC_ICEBREAKER, UnitId.ER_ICEBREAKER}, --ICEBREAKER = 10, + {nil, UnitId.FREEZER, nil}, --FREEZER = 11, + {nil, UnitId.EMP_BOAT, nil}, --EMP_BOAT = 12, + {UnitId.ACS_LAND_FACTORY, UnitId.AINC_LAND_FACTORY, UnitId.ER_LAND_FACTORY}, --LAND_FACTORY = 13, + {UnitId.ACS_NAVAL_FACTORY, UnitId.AINC_NAVAL_FACTORY, UnitId.ER_NAVAL_FACTORY}, --NAVAL_FACTORY = 14, + {UnitId.ACS_TRADE_CENTER, UnitId.AINC_TRADE_CENTER, UnitId.ER_TRADE_CENTER}, --TRADE_CENTER = 15, + {UnitId.ACS_LAB, UnitId.AINC_LAB, UnitId.ER_LAB}, --LAB = 16, + {UnitId.POINT_DEFENSE, UnitId.POINT_DEFENSE, UnitId.POINT_DEFENSE}, --POINT_DEFENSE = 17, + {UnitId.EXTRACTOR, UnitId.EXTRACTOR, UnitId.EXTRACTOR}, --EXTRACTOR = 18, + {UnitId.ACS_REFINERY, UnitId.AINC_REFINERY, UnitId.ER_REFINERY}, --REFINERY = 19, + --{UnitId.ACS_MECH, UnitId.AINC_MECH, UnitId.ER_MECH}, --ICE_SHEET = 20, +} Player.taskForceData = { - {class = UnitClass.WAR_MECH, buildId = 0, numUnits = 2}, - {class = UnitClass.TANK, buildId = 1, numUnits = 1}, - {class = UnitClass.ARTILLERY, buildId = 2, numUnits = 1} + {class = UnitClass.MECH, numUnits = 2}, + {class = UnitClass.TANK, numUnits = 1}, + {class = UnitClass.ARTILLERY, numUnits = 1} } Player.taskForces = {} -function Player:getBuildableUnitIdFromClass(unit, unitClass) - buildableUnits = unit:getBuildableUnits() - - for i = 1, #buildableUnits do - if buildableUnits[i].buildable and units[buildableUnits[i].id + 1].unitClass == unitClass then - return i - end - end - - return -1 -end - -function Player:getFactionUnitIdFromClass(unitClass) - faction = self:getFaction() - - if unitClass == UnitClass.LAND_FACTORY then - if faction == 0 then - return UnitId.AINC_LAND_FACTORY - elseif faction == 1 then - return UnitId.ER_LAND_FACTORY - elseif faction == 2 then - return UnitId.ACS_LAND_FACTORY - end - elseif unitClass == UnitClass.REFINERY then - if faction == 0 then - return UnitId.AINC_REFINERY - elseif faction == 1 then - return UnitId.ER_REFINERY - elseif faction == 2 then - return UnitId.ACS_REFINERY - end - elseif unitClass == UnitClass.LAB then - if faction == 0 then - return UnitId.AINC_LAB - elseif faction == 1 then - return UnitId.ER_LAB - elseif faction == 2 then - return UnitId.ACS_LAB - end - elseif unitClass == UnitClass.ENGINEER then - if faction == 0 then - return UnitId.AINC_ROBO_ENGINEER - elseif faction == 1 then - return UnitId.ER_ROBO_ENGINEER - elseif faction == 2 then - return UnitId.ACS_ROBO_ENGINEER - end - elseif unitClass == UnitClass.MECH then - if faction == 0 then - return UnitId.AINC_MECH - elseif faction == 1 then - return UnitId.ER_MECH - elseif faction == 2 then - return UnitId.ACS_MECH - end - elseif unitClass == UnitClass.TANK then - if faction == 0 then - return UnitId.AINC_TANK - elseif faction == 1 then - return UnitId.ER_TANK - elseif faction == 2 then - return UnitId.ACS_TANK - end - elseif unitClass == UnitClass.ARTILLERY then - if faction == 0 then - return UnitId.AINC_ARTILLERY - elseif faction == 1 then - return UnitId.ER_ARTILLERY - elseif faction == 2 then - return UnitId.ACS_ARTILLERY - end - end - - return -1 -end - ---TODO simplify building construction -function Player:buildFort(arguments) - forts = self:getUnitsByClass(UnitClass.LAND_FACTORY, 1) - - if #forts > 0 then - return forts[1]:toStructure():getBuildStatus() == 100 and BTNodeResult.SUCCESS or BTNodeResult.RUNNING - end - - engis = self:getUnitsByClass(UnitClass.ENGINEER, 1) - if #engis == 0 then return BTNodeResult.FAILURE end - - self:deselectUnits() - self:selectUnits({engis[1]}) - +function Player:initBaseDir() map = Map.getSingleton() sp = map:getSpawnPoint(self:getSpawnPointId()) minDistId = nil @@ -118,31 +56,48 @@ function Player:buildFort(arguments) end self.baseDir = map:getSpawnPoint(minDistId):subtr(sp):norm() - right = (self.baseDir:getAngleBetween(Vector3:new(1, 0, 0)) > 1.57) - angle = self.baseDir:getAngleBetween(Vector3:new(0, 0, 1)) * (right and -1 or 1) - fort = GameObjectFactory.createUnit(self, self:getFactionUnitIdFromClass(UnitClass.LAND_FACTORY), sp, Quaternion:new(angle, Vector3:new(0, 1, 0)), 0) - self:addUnit(fort) - self:issueOrder(OrderType.BUILD, Vector3:new(0, 0, 0), {Target:new(fort:toGameObject(), Vector3:new(0, 0, 0))}, false) - - return BTNodeResult.RUNNING end -function Player:trainEngineers(arguments) - fort = self:getUnitsByClass(UnitClass.LAND_FACTORY, 1)[1]:toFactory() - engineers = self:getUnitsByClass(UnitClass.ENGINEER, -1) - engineerDiffNum = self.numStartEngis - #engineers - queueDiff = engineerDiffNum - #fort:getQueue() +function Player:initPdSpots() + numPd = 6 + radius = 40 + map = Map.getSingleton() + mapSize = map:getMapSize() - engiBuildId = self:getBuildableUnitIdFromClass(fort, UnitClass.ENGINEER) + for i = 1, numPd do + angle = (i - 1) * 2 * math.pi / numPd + rotDir = Quaternion:new(angle, Vector3:new(0, 1, 0)):multVec(self.baseDir) + pdPos = map:getSpawnPoint(self:getSpawnPointId()):add(rotDir:norm():mult(radius)) - for i = 1, queueDiff do fort:appendToQueue(engiBuildId) end + if math.abs(pdPos.x) < .5 * mapSize.x and math.abs(pdPos.z) < .5 * mapSize.z then + self.pointDefenseTrans[#self.pointDefenseTrans + 1] = {pos = pdPos, angle = angle} + end + end - engisStartNumBuilt = (#self:getUnitsByClass(UnitClass.ENGINEER, -1) == self.numStartEngis) - return (engisStartNumBuilt and BTNodeResult.SUCCESS or BTNodeResult.RUNNING) + print('num pd pos: ' .. #self.pointDefenseTrans) +end + +function Player:init() + self:initBaseDir() + self:initPdSpots() +end + +function Player:buildStructure(engineer, buildingId, buildPos, buildAngle) + if not engineer then return BTNodeResult.FAILURE end + + self:deselectUnits() + self:selectUnits({engineer}) + + building = GameObjectFactory.createUnit(self, buildingId, buildPos, Quaternion:new(buildAngle, Vector3:new(0, 1, 0)), 0) + self:issueOrder(OrderType.BUILD, Vector3:new(0, 0, 0), {Target:new(building:toGameObject(), Vector3:new(0, 0, 0))}, false) +end + +function Player:findSuitableSpot() + return Vector3:new(0, 0, 0) end function Player:findIdleEngineer() - engineers = self:getUnitsByClass(UnitClass.ENGINEER, -1) + engineers = self:getUnitsByClass(UnitClass.CYBORG_ENGINEER, -1) for i = 1, #engineers do if engineers[i]:getNumOrders() == 0 then return engineers[i] end @@ -151,55 +106,127 @@ function Player:findIdleEngineer() return nil end -function Player:buildStructure(engineer, buildingId, buildPos, buildAngle) - if not engineer then return BTNodeResult.FAILURE end +function Player:getBuildableUnitSlotId(buildingUnit, buildableUnitId) + for i = 1, #buildingUnit:getBuildableUnits() do + bu = buildingUnit:getBuildableUnit(i - 1) - unitClass = units[buildingId + 1].unitClass - - if #self:getUnitsByClass(unitClass, 1) == 0 then - self:deselectUnits() - self:selectUnits({engineer}) - - building = GameObjectFactory.createUnit(self, buildingId, buildPos, Quaternion:new(1, 0, 0, 0), 0) - self:addUnit(building) - self:issueOrder(OrderType.BUILD, Vector3:new(0, 0, 0), {Target:new(building:toGameObject(), Vector3:new(0, 0, 0))}, false) + if bu.buildable and bu.id == buildableUnitId then + print('returning ' .. i - 1) + return i - 1 + end end - building = self:getUnitsByClass(unitClass, 1)[1] - return (building:toStructure():getBuildStatus() == 100 and BTNodeResult.SUCCESS or BTNodeResult.RUNNING) + print('returning nil') + return nil +end + +--TODO simplify building construction +function Player:buildLandFactory(arguments) + factory = self:getUnitsByClass(UnitClass.LAND_FACTORY, 1)[1] + + if factory then + return factory:toStructure():isComplete() and BTNodeResult.SUCCESS or BTNodeResult.RUNNING + end + + engis = self:getUnitsByClass(UnitClass.CYBORG_ENGINEER, 1) + if #engis == 0 then return BTNodeResult.FAILURE end + + self:deselectUnits() + self:selectUnits({engis[1]}) + + right = (self.baseDir:getAngleBetween(Vector3:new(1, 0, 0)) > .5 * math.pi) + angle = self.baseDir:getAngleBetween(Vector3:new(0, 0, 1)) * (right and -1 or 1) + rot = Quaternion:new(angle, Vector3:new(0, 1, 0)) + + factId = self.unitClassMappings[UnitClass.LAND_FACTORY + 1][self:getFaction() + 1] + sp = Map.getSingleton():getSpawnPoint(self:getSpawnPointId()) + self:buildStructure(self:findIdleEngineer(), factId, sp, angle) + + return BTNodeResult.RUNNING +end + +function Player:trainEngineers(arguments) + factory = self:getUnitsByClass(UnitClass.LAND_FACTORY, 1)[1]:toFactory() + engineers = self:getUnitsByClass(UnitClass.CYBORG_ENGINEER, -1) + engineerDiffNum = self.numStartEngis - #engineers + queueDiff = engineerDiffNum - #factory:getQueue() + + engiBuildId = self.unitClassMappings[UnitClass.CYBORG_ENGINEER + 1][self:getFaction() + 1] + + for i = 1, queueDiff do + factory:appendToQueue(self:getBuildableUnitSlotId(factory, engiBuildId)) + end + + engisStartNumBuilt = (#self:getUnitsByClass(UnitClass.CYBORG_ENGINEER, -1) == self.numStartEngis) + return (engisStartNumBuilt and BTNodeResult.SUCCESS or BTNodeResult.RUNNING) end function Player:buildRefinery(arguments) + refinery = self:getUnitsByClass(UnitClass.REFINERY, 1)[1] + + if refinery then + print('cpu player: ') + print(self) + print('ref1: ') + print(refinery) + print('ref2: ') + print(refinery:toStructure()) + return (refinery:toStructure():isComplete() and BTNodeResult.SUCCESS or BTNodeResult.RUNNING) + end + buildPos = Map.getSingleton():getSpawnPoint(self:getSpawnPointId()):add(self.baseDir:mult(20)) - return self:buildStructure(self:findIdleEngineer(), self:getFactionUnitIdFromClass(UnitClass.REFINERY), buildPos, -.1) + factId = self.unitClassMappings[UnitClass.REFINERY + 1][self:getFaction() + 1] + self:buildStructure(self:findIdleEngineer(), factId, buildPos, -.0) + + return BTNodeResult.RUNNING end -- TODO optimize deposit position check function Player:buildExtractor(arguments) - deposits = {} + extractor = self:getUnitsByClass(UnitClass.EXTRACTOR, -1)[1] + + if extractor then + return (extractor:toStructure():isComplete() and BTNodeResult.SUCCESS or BTNodeResult.RUNNING) + end + + visibleDeposits = {} players = Game.getSingleton():getPlayers(true) for i = 1, #players do - deps = players[i]:getResourceDeposits() - table.move(deps, 1, #deps, #deposits + 1, deposits) + deposits = players[i]:getResourceDeposits() + + for j = 1, #deposits do + for k = 1, #self:getUnits() do + unit = self:getUnit(k - 1) + + if unit:getPos():getDistanceFrom(deposits[j]:getPos()) <= unit:getLineOfSight() and not deposits[j]:getExtractor() then + visibleDeposits[#visibleDeposits + 1] = deposits[i] + goto continue + end + end + + ::continue:: + end end - if #deposits == 0 then return BTNodeResult.FAILURE end + if #visibleDeposits == 0 then return BTNodeResult.FAILURE end - depPos = deposits[1]:getPos() + depPos = visibleDeposits[1]:getPos() spawnPoint = Map.getSingleton():getSpawnPoint(self:getSpawnPointId()) - for i = 1, #deposits do - if deposits[i]:getPos():getDistanceFrom(spawnPoint) < depPos:getDistanceFrom(spawnPoint) then + for i = 1, #visibleDeposits do + if visibleDeposits[i]:getPos():getDistanceFrom(spawnPoint) < depPos:getDistanceFrom(spawnPoint) then depPos = deposits[i]:getPos() end end - return self:buildStructure(self:findIdleEngineer(), UnitId.EXTRACTOR, depPos, 0) + self:buildStructure(self:findIdleEngineer(), UnitId.EXTRACTOR, depPos, 0) + + return BTNodeResult.RUNNING end function Player:buildHarvester(arguments) - if self:getUnitsByClass(UnitClass.RESOURCE_ROVER, 1)[1] then + if #self:getUnitsByClass(UnitClass.RESOURCE_ROVER, 1) > 0 then return BTNodeResult.SUCCESS end @@ -207,8 +234,11 @@ function Player:buildHarvester(arguments) if not factory then return BTNodeResult.FAILURE end factory = factory:toFactory() + roverSlotId = self.unitClassMappings[UnitClass.RESOURCE_ROVER + 1][self:getFaction() + 1] - if #factory:getQueue() == 0 then factory:appendToQueue(3) end + if #factory:getQueue() == 0 then + factory:appendToQueue(self:getBuildableUnitSlotId(factory, roverSlotId)) + end return BTNodeResult.RUNNING end @@ -232,7 +262,7 @@ function Player:startHarvesting() return BTNodeResult.SUCCESS end -function Player:buildTaskForces(arguments) +function Player:buildLandDefForce(arguments) landFactory = self:getUnitsByClass(UnitClass.LAND_FACTORY, 1)[1] if not landFactory then return BTNodeResult.FAILURE end @@ -252,15 +282,22 @@ function Player:buildTaskForces(arguments) end end - if enoughUnits then return BTNodeResult.SUCCESS end + print('about to...') + if enoughUnits then + print('here it comes...') + return BTNodeResult.SUCCESS + end + else + return BTNodeResult.RUNNING end - if #landFactory:getQueue() > 0 then return BTNodeResult.RUNNING end - for i = 1, numAttackableSpawnPoints do for j = 1, #self.taskForceData do for k = 1, self.taskForceData[j].numUnits do - landFactory:appendToQueue(self.taskForceData[j].buildId) + print('queueing...') + unitId = self.unitClassMappings[self.taskForceData[j].class + 1][self:getFaction() + 1] + slotId = self:getBuildableUnitSlotId(landFactory, unitId) + landFactory:appendToQueue(slotId) end end end @@ -268,6 +305,17 @@ function Player:buildTaskForces(arguments) return BTNodeResult.RUNNING end +function Player:buildPointDefenseRing(arguments) + pointDefs = self:getUnitsByClass(UnitClass.POINT_DEFENSE, -1) + if #pointDefs == #self.pointDefenseTrans then return BTNodeResult.SUCCESS end + + pdId = self.unitClassMappings[UnitClass.POINT_DEFENSE + 1][self:getFaction() + 1] + pdTrans = self.pointDefenseTrans[#pointDefs + 1] + self:buildStructure(self:findIdleEngineer(), pdId, pdTrans.pos, pdTrans.angle) + + return BTNodeResult.RUNNING +end + function Player:formTaskForce(arguments) if self.taskForces[arguments.tfId] then return BTNodeResult.SUCCESS end @@ -358,6 +406,7 @@ function Player:attackSpawnPoint(arguments) return BTNodeResult.RUNNING end +--[[ function Player:generateTaskforceActions() numSpawnPoints = Map.getSingleton():getNumSpawnPoints() actionsTable = {} @@ -382,3 +431,4 @@ function Player:generateTaskforceActions() return actionsTable end +]]-- diff --git a/Assets/Scripts/Core/playerInit.lua b/Assets/Scripts/Core/playerInit.lua index 9f001df..7ef2bcb 100644 --- a/Assets/Scripts/Core/playerInit.lua +++ b/Assets/Scripts/Core/playerInit.lua @@ -1,28 +1,62 @@ -for i = 1, #game.players do - game.players[i].behaviour = { +for i = 1, #game.cpuPlayers do + game.cpuPlayers[i]:init() + + game.cpuPlayers[i].behaviour = { type = BTNodeType.SEQUENCE, children = { - {type = BTNodeType.FUNCTION, func = 'buildFort'}, + {type = BTNodeType.FUNCTION, func = 'buildLandFactory'}, {type = BTNodeType.FUNCTION, func = 'trainEngineers'}, { type = BTNodeType.PARALLEL, children = { - { - type = BTNodeType.SEQUENCE, - children = { - {type = BTNodeType.FUNCTION, func = 'buildHarvester'}, - } - }, {type = BTNodeType.FUNCTION, func = 'buildRefinery'}, { type = BTNodeType.SEQUENCE, children = { {type = BTNodeType.FUNCTION, func = 'buildExtractor'}, - {type = BTNodeType.FUNCTION, func = 'startHarvesting'}, + {type = BTNodeType.FUNCTION, func = 'buildHarvester'}, } } } }, + { + type = BTNodeType.SEQUENCE, + children = { + {type = BTNodeType.FUNCTION, func = 'buildLandDefForce'}, + {type = BTNodeType.FUNCTION, func = 'buildPointDefenseRing'} + } + }, + --[[ + ]]-- + --[[ + { + type = BTNodeType.SELECTOR, + children = { + {type = BTNodeType.FUNCTION, func = 'hasLandRouteToAllSpawnPoints'}, + { + type = BTNodeType.SEQUENCE, + children = { + {type = BTNodeType.FUNCTION, func = 'buildNavalFactory'}, + {type = BTNodeType.FUNCTION, func = 'buildNavalForce'} + } + }, + } + }, + { + type = BTNodeType.SELECTOR, + children = { + {type = BTNodeType.FUNCTION, func = 'hasLandRouteToSpawnPoint'}, + { + type = BTNodeType.SEQUENCE, + children = { + {type = BTNodeType.FUNCTION, func = 'boardTransports'}, + {type = BTNodeType.FUNCTION, func = 'moveTransports'} + {type = BTNodeType.FUNCTION, func = 'unloadTransports'} + } + }, + } + }, + {type = BTNodeType.FUNCTION, func = 'occupySpawnpoint'}, { type = BTNodeType.PARALLEL, children = { @@ -30,11 +64,10 @@ for i = 1, #game.players do { type = BTNodeType.PARALLEL, numMinSuccesses = 2, - children = game.players[i]:generateTaskforceActions() + children = game.cpuPlayers[i]:generateTaskforceActions() }, } }, - --[[ ]]-- } } diff --git a/Assets/Scripts/GameObjects/Units/unitData.lua b/Assets/Scripts/GameObjects/Units/unitData.lua index ac10fed..163ed50 100644 --- a/Assets/Scripts/GameObjects/Units/unitData.lua +++ b/Assets/Scripts/GameObjects/Units/unitData.lua @@ -73,26 +73,29 @@ UnitId = { } WeaponClass = {DAMAGE = 0, FREEZE = 1} UnitClass = { - WAR_MECH = 0, + MECH = 0, TANK = 1, ARTILLERY = 2, - ENGINEER = 3, - TRANSPORT = 4, - RESOURCE_ROVER = 5, - CRUISER = 6, - CARRIER = 7, - SUBMARINE = 8, - ICEBREAKER = 9, - FREEZER = 10, - EMP_BOAT = 11, - LAND_FACTORY = 12, - NAVAL_FACTORY = 13, - TRADE_CENTER = 14, - LAB = 15, - POINT_DEFENSE = 16, - EXTRACTOR = 17, - REFINERY = 18, - ICE_SHEET = 19, + ROBO_ENGINEER = 3, + CYBORG_ENGINEER = 4, + TRANSPORT = 5, + RESOURCE_ROVER = 6, + CRUISER = 7, + ANTI_SUB_CRUISER = 8, + CARRIER = 9, + SUBMARINE = 10, + MISSILE_SUBMARINE = 11, + ICEBREAKER = 12, + FREEZER = 13, + EMP_BOAT = 14, + LAND_FACTORY = 15, + NAVAL_FACTORY = 16, + TRADE_CENTER = 17, + LAB = 18, + POINT_DEFENSE = 19, + EXTRACTOR = 20, + REFINERY = 21, + ICE_SHEET = 22, } UnitType = {UNDERWATER = 0, SEA_LEVEL = 1, HOVER = 2, LAND = 3, AIR = 4} @@ -169,7 +172,7 @@ units = { }, } }, - unitClass = UnitClass.WAR_MECH, + unitClass = UnitClass.MECH, unitType = UnitType.LAND, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -242,7 +245,7 @@ units = { }, } }, - unitClass = UnitClass.WAR_MECH, + unitClass = UnitClass.MECH, unitType = UnitType.LAND, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -314,7 +317,7 @@ units = { }, } }, - unitClass = UnitClass.WAR_MECH, + unitClass = UnitClass.MECH, unitType = UnitType.LAND, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -699,7 +702,7 @@ units = { {id = UnitId.POINT_DEFENSE, buildable = true, trigger = 80}, {id = UnitId.EXTRACTOR, buildable = true, trigger = 69}, }, - unitClass = UnitClass.ENGINEER, + unitClass = UnitClass.ROBO_ENGINEER, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -744,7 +747,7 @@ units = { {id = UnitId.EXTRACTOR, buildable = true, trigger = 69}, }, abilityButtons = {{buttonType = ButtonType.ORDER, name = 'Hack', orderType = OrderType.HACK}}, - unitClass = UnitClass.ENGINEER, + unitClass = UnitClass.CYBORG_ENGINEER, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -780,7 +783,7 @@ units = { {id = UnitId.POINT_DEFENSE, buildable = true, trigger = 80}, {id = UnitId.EXTRACTOR, buildable = true, trigger = 69}, }, - unitClass = UnitClass.ENGINEER, + unitClass = UnitClass.ROBO_ENGINEER, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -825,7 +828,7 @@ units = { {id = UnitId.EXTRACTOR, buildable = true, trigger = 69}, }, abilityButtons = {{buttonType = ButtonType.ORDER, name = 'Hack', orderType = OrderType.HACK}}, - unitClass = UnitClass.ENGINEER, + unitClass = UnitClass.CYBORG_ENGINEER, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -861,7 +864,7 @@ units = { {id = UnitId.POINT_DEFENSE, buildable = true, trigger = 80}, {id = UnitId.EXTRACTOR, buildable = true, trigger = 69}, }, - unitClass = UnitClass.ENGINEER, + unitClass = UnitClass.ROBO_ENGINEER, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -906,7 +909,7 @@ units = { {id = UnitId.EXTRACTOR, buildable = true, trigger = 69}, }, abilityButtons = {{buttonType = ButtonType.ORDER, name = 'Hack', orderType = OrderType.HACK}}, - unitClass = UnitClass.ENGINEER, + unitClass = UnitClass.CYBORG_ENGINEER, unitType = UnitType.HOVER, armor = {ArmorType.MECHANIC}, maxUnevenness = .5, @@ -1219,7 +1222,7 @@ units = { armor = {ArmorType.CAST}, maxUnevenness = .5, alignToSurface = true, - capacity = 3000, + capacity = 1000, loadRate = 1, loadSpeed = 5, isVehicle = true, @@ -1673,7 +1676,7 @@ units = { hitFx = {} }, }, - unitClass = UnitClass.CRUISER, + unitClass = UnitClass.ANTI_SUB_CRUISER, unitType = UnitType.SEA_LEVEL, armor = {ArmorType.STEEL}, isVehicle = true, @@ -1803,7 +1806,7 @@ units = { }, }, }, - unitClass = UnitClass.CRUISER, + unitClass = UnitClass.ANTI_SUB_CRUISER, unitType = UnitType.SEA_LEVEL, armor = {ArmorType.STEEL}, isVehicle = true, @@ -1963,7 +1966,7 @@ units = { }, }, }, - unitClass = UnitClass.CRUISER, + unitClass = UnitClass.ANTI_SUB_CRUISER, unitType = UnitType.SEA_LEVEL, armor = {ArmorType.STEEL}, isVehicle = true, @@ -2016,7 +2019,7 @@ units = { projectile = {id = ProjectileId.CRUISE_MISSILE, pos = {x = 0, y = 15, z = -3.5}, rot = {w = .707, x = -.707, y = 0, z = 0}} }, }, - unitClass = UnitClass.SUBMARINE, + unitClass = UnitClass.MISSILE_SUBMARINE, unitType = UnitType.UNDERWATER, isVehicle = true, health = 500, @@ -2068,7 +2071,7 @@ units = { projectile = {id = ProjectileId.CRUISE_MISSILE, pos = {x = 0, y = 15, z = -3.5}, rot = {w = .707, x = -.707, y = 0, z = 0}} }, }, - unitClass = UnitClass.SUBMARINE, + unitClass = UnitClass.MISSILE_SUBMARINE, unitType = UnitType.UNDERWATER, isVehicle = true, health = 500, @@ -2120,7 +2123,7 @@ units = { projectile = {id = ProjectileId.CRUISE_MISSILE, pos = {x = 0, y = 15, z = -3.5}, rot = {w = .707, x = -.707, y = 0, z = 0}} }, }, - unitClass = UnitClass.SUBMARINE, + unitClass = UnitClass.MISSILE_SUBMARINE, unitType = UnitType.UNDERWATER, isVehicle = true, health = 500, diff --git a/activeGameState.cpp b/activeGameState.cpp index 59141b7..21b569e 100755 --- a/activeGameState.cpp +++ b/activeGameState.cpp @@ -252,7 +252,7 @@ namespace battleship{ orderPossible = (roverSelected && transferResource); } else if(cursorState == CursorState::HACK) - orderPossible = (!ownGameObj && gameObjUnit && mainPlayer->getSelectedUnit(0)->getUnitClass() == UnitClass::ENGINEER); + orderPossible = (!ownGameObj && gameObjUnit && mainPlayer->getSelectedUnit(0)->getUnitClass() == UnitClass::CYBORG_ENGINEER); else if(controlPressed) cursorState = CursorState::ATTACK; else @@ -285,7 +285,6 @@ namespace battleship{ void ActiveGameState::update() { ConcreteGuiManager *guiManager = ConcreteGuiManager::getSingleton(); - guiManager->getText("depth")->setText(L"Depth: " + to_wstring(depth)); guiManager->getText("refineds")->setText(to_wstring(mainPlayer->getResource(ResourceType::REFINEDS))); guiManager->getText("wealth")->setText(to_wstring(mainPlayer->getResource(ResourceType::WEALTH))); guiManager->getText("research")->setText(to_wstring(mainPlayer->getResource(ResourceType::RESEARCH))); @@ -723,7 +722,8 @@ namespace battleship{ Order::TYPE type; switch(selectedUnits[0]->getUnitClass()){ - case UnitClass::ENGINEER: + case UnitClass::ROBO_ENGINEER: + case UnitClass::CYBORG_ENGINEER: case UnitClass::FREEZER: type = Order::TYPE::BUILD; break; @@ -740,7 +740,6 @@ namespace battleship{ Unit *buildStruct = GameObjectFactory::createUnit(mainPlayer, gmObjFr.getId(), gmObjFr.getPos(), gmObjFr.getRot()); issueOrder(type, vector{Order::Target(buildStruct, gmObjFr.getPos())}, shiftPressed); - mainPlayer->addUnit(buildStruct); } buildableStructSelected = false; diff --git a/freezer.cpp b/freezer.cpp index 1cd5c8c..5450a0a 100644 --- a/freezer.cpp +++ b/freezer.cpp @@ -33,7 +33,7 @@ namespace battleship{ Vehicle::build(order); - if(targ->getUnitClass() == UnitClass::ICE_SHEET && ((Structure*)targ)->getBuildStatus() >= 100) + if(targ->getUnitClass() == UnitClass::ICE_SHEET && ((Structure*)targ)->isComplete()) removeOrder(0); } } diff --git a/game.cpp b/game.cpp index 4b2256d..d9cb555 100644 --- a/game.cpp +++ b/game.cpp @@ -43,14 +43,14 @@ namespace battleship{ } void Game::update(){ - updateLuaPlayers(false); + //updateLuaPlayers(false); sol::state_view SOL_LUA_VIEW = generateView(); - for(int i = 0; i < players.size(); i++) - if(players[i]->isCpuPlayer()){ - string plStr = "game.players[" + to_string(i + 1) + "]"; - SOL_LUA_VIEW.script("executeBtNode(" + plStr + ", " + plStr + ".behaviour)"); - } + for(int i = 0; i < getCpuPlayers().size(); i++) { + string plStr = "game.cpuPlayers[" + to_string(i + 1) + "]"; + SOL_LUA_VIEW.script("executeBtNode(" + plStr + ", " + plStr + ".behaviour)"); + //SOL_LUA_VIEW.script("tbl = " + plStr + ":getUnitsByClass(UnitClass.CYBORG_ENGINEER, -1)"); + } int numPlayersWithUnits = 0; @@ -76,18 +76,19 @@ namespace battleship{ FxManager::getSingleton()->update(); } - void Game::updateLuaPlayers(bool resetBehaviour){ + void Game::initLuaPlayers(bool resetBehaviour){ sol::state_view SOL_LUA_VIEW = generateView(); + vector cpuPlayers = getCpuPlayers(); - for(int i = 0; i < players.size(); i++) - SOL_LUA_VIEW["game"]["players"][i + 1] = players[i]; + for(int i = 0; i < cpuPlayers.size(); i++) + SOL_LUA_VIEW["game"]["cpuPlayers"][i + 1] = cpuPlayers[i]; if(resetBehaviour) SOL_LUA_VIEW.script_file(GameManager::getSingleton()->getPath() + "Scripts/Core/playerInit.lua"); } void Game::removeAllElements(){ - generateView().script("game.players = {}"); + generateView().script("game.cpuPlayers = {}"); while(!players.empty()){ delete players[0]; @@ -113,7 +114,7 @@ namespace battleship{ for(string f : configData::scripts) SOL_LUA_VIEW.script_file(gm->getPath() + f); - updateLuaPlayers(true); + initLuaPlayers(); guiManager->readLuaScreenScript("inGame.lua", activeState->getGuiButtons()); string gop = SOL_LUA_VIEW["gameObjPrefix"], vfxp = SOL_LUA_VIEW["vfxPrefix"]; @@ -233,4 +234,14 @@ namespace battleship{ return playersVec; } + + vector Game::getCpuPlayers(){ + vector playersVec; + + for(Player *pl : players) + if(pl->isCpuPlayer()) + playersVec.push_back(pl); + + return playersVec; + } } diff --git a/game.h b/game.h index d2bd4e5..19ffbff 100644 --- a/game.h +++ b/game.h @@ -20,13 +20,14 @@ namespace battleship{ public: static Game* getSingleton(); void update(); - void updateLuaPlayers(bool); + void initLuaPlayers(bool = false); void togglePause(); void removeAllElements(); void initTechnologies(); float calcAbilFromTech(Ability::Type, std::vector, int, int); bool isUnitUnlocked(std::vector, int); std::vector getPlayers(bool = false); + std::vector getCpuPlayers(); inline void setDebug(bool d){this->debug = d;} inline void addPlayer(Player *pl){players.push_back(pl);} inline bool isDebug(){return debug;} diff --git a/gameManager.cpp b/gameManager.cpp index 8eb1edc..4b476fd 100755 --- a/gameManager.cpp +++ b/gameManager.cpp @@ -14,6 +14,7 @@ #include "guiAppState.h" #include "defConfigs.h" #include "player.h" +#include "extractor.h" #include "factory.h" #include "engineer.h" #include "destructable.h" @@ -85,6 +86,7 @@ namespace battleship{ SOL_LUA_STATE.new_usertype( "Structure", sol::constructors(), "getPos", &GameObject::getPos, + "isComplete", &Structure::isComplete, "getBuildStatus", &Structure::getBuildStatus ); @@ -124,8 +126,13 @@ namespace battleship{ "getUnitsByClass", &Player::getUnitsByClass ); + SOL_LUA_STATE.new_usertype( + "Extractor", sol::constructors() + ); + SOL_LUA_STATE.new_usertype( "ResourceDeposit", sol::constructors(), + "getExtractor", &ResourceDeposit::getExtractor, "getPos", &GameObject::getPos ); @@ -161,6 +168,7 @@ namespace battleship{ SOL_LUA_STATE.new_usertype( "Map", "getSingleton", &Map::getSingleton, + "getMapSize", &Map::getMapSize, "getSpawnPoint", &Map::getSpawnPoint, "getNumSpawnPoints", &Map::getNumSpawnPoints ); diff --git a/gameObjectFactory.cpp b/gameObjectFactory.cpp index 5a4873d..9fded44 100644 --- a/gameObjectFactory.cpp +++ b/gameObjectFactory.cpp @@ -34,11 +34,13 @@ namespace battleship{ if(vehicle) switch((UnitClass)unitClass){ - case UnitClass::ENGINEER: + case UnitClass::ROBO_ENGINEER: + case UnitClass::CYBORG_ENGINEER: return new Engineer(player, id, pos, rot, Unit::State::STAND_GROUND); case UnitClass::RESOURCE_ROVER: return new ResourceRover(player, id, pos, rot, Unit::State::STAND_GROUND); case UnitClass::SUBMARINE: + case UnitClass::MISSILE_SUBMARINE: return new Submarine(player, id, pos, rot, Unit::State::STAND_GROUND); case UnitClass::FREEZER: return new Freezer(player, id, pos, rot, Unit::State::STAND_GROUND); @@ -47,7 +49,6 @@ namespace battleship{ } else switch((UnitClass)unitClass){ - case UnitClass::FORT: case UnitClass::LAND_FACTORY: case UnitClass::NAVAL_FACTORY: return new Factory(player, id, pos, rot, buildStatus, Unit::State::STAND_GROUND); diff --git a/inGameAppState.cpp b/inGameAppState.cpp index c852c1c..281b147 100755 --- a/inGameAppState.cpp +++ b/inGameAppState.cpp @@ -74,7 +74,7 @@ namespace battleship{ activeState = new ActiveGameState(guiState, playerId); stateManager->attachAppState(activeState); - Game::getSingleton()->updateLuaPlayers(true); + Game::getSingleton()->initLuaPlayers(true); Map::Minimap::getSingleton()->updateImage(); } diff --git a/structure.cpp b/structure.cpp index 3926dae..a054347 100644 --- a/structure.cpp +++ b/structure.cpp @@ -31,7 +31,7 @@ namespace battleship{ vector selectingPlayers = getSelectingPlayers(); bool mainPlayerSelecting = (activeState && find(selectingPlayers.begin(), selectingPlayers.end(), mainPlayer) != selectingPlayers.end()); - if(buildStatus < 100) + if(!isComplete()) destructable->displayStats(buildStatusForeground, buildStatusBackground, buildStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); else{ buildStatusBackground->setVisible(false); diff --git a/unit.cpp b/unit.cpp index 82bb397..a115fc1 100755 --- a/unit.cpp +++ b/unit.cpp @@ -413,7 +413,7 @@ namespace battleship{ return destructTarg && !getWeaponsByOrder(Order::TYPE::ATTACK).empty(); } case Order::TYPE::BUILD: - return (unitClass == UnitClass::ENGINEER || unitClass == UnitClass::FREEZER); + return (unitClass == UnitClass::ROBO_ENGINEER || unitClass == UnitClass::CYBORG_ENGINEER || unitClass == UnitClass::FREEZER); case Order::TYPE::PATROL: case Order::TYPE::MOVE: return vehicle; @@ -465,6 +465,9 @@ namespace battleship{ } orders.push_back(order); + + if(order.type == Order::TYPE::BUILD && order.targets[0].unit) + player->addUnit((Unit*)order.targets[0].unit); } void Unit::halt() { diff --git a/unit.h b/unit.h index da424bf..2da7709 100755 --- a/unit.h +++ b/unit.h @@ -67,15 +67,18 @@ namespace battleship{ enum class Corner {FRONT_LEFT, FRONT_RIGHT, REAR_LEFT, REAR_RIGHT}; enum class UnitType {UNDERWATER, SEA_LEVEL, HOVER, LAND, AIR, NONE = -1}; enum class UnitClass { - WAR_MECH, + MECH, TANK, ARTILLERY, - ENGINEER, + ROBO_ENGINEER, + CYBORG_ENGINEER, TRANSPORT, RESOURCE_ROVER, CRUISER, + ANTI_SUB_CRUISER, CARRIER, SUBMARINE, + MISSILE_SUBMARINE, ICEBREAKER, FREEZER, EMP_BOAT, @@ -86,7 +89,6 @@ namespace battleship{ POINT_DEFENSE, EXTRACTOR, REFINERY, - FORT, ICE_SHEET }; diff --git a/vehicle.cpp b/vehicle.cpp index 9017dc9..9e8f074 100644 --- a/vehicle.cpp +++ b/vehicle.cpp @@ -470,12 +470,12 @@ namespace battleship{ sol::table targTable = generateView()["units"][structure->getId()]; int costRate = (int)targTable["cost"] / 100, buildRate = (int)targTable["buildTime"] / 100; - if(structure->getBuildStatus() < 100 && player->getResource(ResourceType::REFINEDS) >= costRate && getTime() - lastBuildTime > buildRate){ + if(!structure->isComplete() && player->getResource(ResourceType::REFINEDS) >= costRate && getTime() - lastBuildTime > buildRate){ structure->incrementBuildStatus(); player->updateResource(ResourceType::REFINEDS, -costRate, true); lastBuildTime = getTime(); } - else if(structure->getBuildStatus() >= 100){ + else if(structure->isComplete()){ removeOrder(0); player->incStructuresBuilt(); }