KaukausInsurgency / ki-dcs

Kaukasus Insurgency
5 stars 2 forks source link

Make code coalition agnostic #169

Closed Igneous01 closed 6 years ago

Igneous01 commented 6 years ago

Currently almost all code only works for Red side - this should be configurable and agnostic to what side is being used for players.

Making this pvp compatible will be more difficult, but at least provide ability for code to run on blue coalition vs red coalition via config setting.

Igneous01 commented 6 years ago

Impacts

Functions that need to change:

CP:Fortify CP:SetCoalitionCounts KI.Loader.GenerateStaticTable SLC.SpawnSlingLoadableCargo AICOM.DoTurn AICOM.Analyze KI.Init.Depots KI.Scheduled.IsPlayerInZone KI.Scheduled.UpdateCPStatus KI.Scheduled.CheckConvoyCompletedRoute KI.Hooks.DWMOnDepotResupplied KI.Hooks.GCOnLifeExpiredCrate KI.Hooks.GCOnLifeExpiredTroops KI.lua

Work Breakdown

A) Create configuration item KI.Config.PlayerSide

B) Create configuration item KI.Config.InsurgentSide

C) Replace all references of KI.Scheduled.CheckConvoyCompletedRoute with a function that takes a side parameter.

D) Update this code in KI.Loader.GenerateStaticTable()

function KI.Loader.GenerateStaticTable(staticObj, category, component, isCargo)
  env.info("KI.Loader.GenerateStaticTable called")
  --isHidden = isHidden or true
  isCargo = isCargo or false

  local _country = ""
*******THIS CODE BELOW **********
  if staticObj:getCoalition() == 1 then
    _country = "Russia"
  else
    _country = "Insurgents"
  end

E) Update this code in SLC.SpawnSlingLoadableCargo()

function SLC.SpawnSlingLoadableCargo(rawtype, comp, pos) -- need to add country and side parameters
  env.info("SLC.SpawnSlingLoadableCargo Called")
    local cargo_name = SLC.GenerateName(comp.SpawnName)
*********** CHANGE BELOW **********
    local obj = coalition.addStaticObject(country.id.RUSSIA, {
        country = "Russia",
        category = "Cargos",
        x = pos.x,
        y = pos.z,
        type = rawtype,
        name = cargo_name,
        mass = comp.Weight,
        canCargo = true
    })

    table.insert(SLC.CargoInstances, { Object = obj, Component = comp })
  env.info("SLC.SpawnSlingLoadableCargo - Adding CargoInstance for " .. cargo_name)
  return obj
end

F) Update this code in AICOM.DoTurn()

function AICOM.DoTurn(args, time)
  env.info("AICOM.DoTurn called")

  local fncSuccess, result = xpcall(function()
    -- check the pop cap and see if we've hit the limit
******* THIS CODE BELOW *********
    local _cap = AICOM.CalculatePopulationCap(coalition.getGroups(2, Group.Category.GROUND))
    if _cap >= AICOM.Config.PopulationCap then
      env.info("AICOM.DoTurn - pop cap has been reached (" .. tostring(_cap) .. "/" .. tostring(AICOM.Config.PopulationCap) .. ") - Doing nothing")
      KI.UTDATA.AICOM_POPCAP_REACHED = true
      return time + AICOM.Config.TurnRate + AICOM.Config.Random(AICOM.Config.TurnRate / 2)
    end
Igneous01 commented 6 years ago

G) Update this code in KI.Init.Depots()

function KI.Init.Depots()
  env.info("KI.InitDepots called")
******* THIS CODE BELOW ********
  local objects = coalition.getStaticObjects(1)
  for i = 1, #objects do
    local obj = objects[i]
    local n = obj:getName()
Igneous01 commented 6 years ago

H) Update this code in KI.lua

env.info("KI - Initializing Scheduled Functions")
  timer.scheduleFunction(function(args, t)
************ THIS CODE BELOW ****************
-- IsPlayerInZone takes (side, time) as parameters
    local success, result = xpcall(function() return KI.Scheduled.IsPlayerInZone(1, t) end,
                                   function(err) env.info("KI.Scheduled.IsPlayerInZone ERROR : " .. err) end)

    if not success then
      return t + KI.Config.PlayerInZoneCheckRate
    else
      return result
    end
  end, 1, timer.getTime() + KI.Config.PlayerInZoneCheckRate)
Igneous01 commented 6 years ago

I) Update this code in AICOM.Analyze

function AICOM.Analyze(CapturePoints)
  env.info("AICOM.Analyze Called")
  if CapturePoints then
    env.info("AICOM.Analyze - CapturePoints not null")
  else
    env.info("AICOM.Analyze - WARNING CapturePoints null")
    return {}
  end
  local _cpAnalysis = {}
  for i = 1, #CapturePoints do
    local _cp = CapturePoints[i]
    if _cp.SpawnZone1 and _cp.SpawnZone2 then
      local _cost = 0
      local _own = _cp:GetOwnership()
      local _type = 0

      -- Assign initial cost values for the ownership of a point
      -- Neutral points are the most valuable to the AI
      -- Contested are second most important
      -- Blue are third, with red being forth
************** CHANGE THIS CODE BELOW****************
      if _own == "Neutral" then
        _cost = _cost + 1
        _type = AICOM.Enum.Actions.Attack
      elseif _own == "Blue" then
        _cost = _cost + 5
        _type = AICOM.Enum.Actions.Attack
      elseif _own == "Red" then
        _cost = _cost + 7
        _type = AICOM.Enum.Actions.Reinforce
      else
        -- contested
        _cost = _cost + 3
        _type = AICOM.Enum.Actions.Reinforce
      end

      -- now include blue units and red units into the cost (with red units being half the cost of a blue unit)
************* CHANGE THIS CODE BELOW *******************      
      _cost = _cost + _cp.BlueUnits
      if _cp.RedUnits > 0 then
        _cost = _cost + (_cp.RedUnits / 2)  -- add red units as a cost, but for half the price of blue units
      end

      table.insert(_cpAnalysis, { CapturePoint = _cp, Cost = _cost, Action = _type })
    else
      env.info("AICOM.Analyze - Capture Point " .. _cp.Name .. " has no spawn zone - ignoring")
    end
  end

  env.info("AICOM.Analyze - Dumping results")
  env.info(KI.Toolbox.Dump(_cpAnalysis))
  return _cpAnalysis
end
Igneous01 commented 6 years ago

J) Update this code in CP:Fortify

***** ALL REFERENCES to .RedUnits need to be side agnostic **********
function CP:Fortify(resource, val)
  env.info("CP.Fortify called")
  val = val or 1
  local msg = ""
  local result = false
  local newtotal = self.RedUnits + val
  if newtotal <= self.MaxCapacity then
    env.info("CP:Fortify - CP has enough capacity to accept this fortification")
    result = true
    msg = self.Name .. " fortified with " .. resource .. "! (Capacity: " .. tostring(newtotal) .. " / " .. tostring(self.MaxCapacity) .. ")"
  else
    msg = "Capture Point cannot be fortified any further! (Capacity: " .. tostring(self.RedUnits) .. " / " .. tostring(self.MaxCapacity) .. ")"
  end

  return result, msg
end
Igneous01 commented 6 years ago

K) Update this code in CP:SetCoalitionCounts

function CP:SetCoalitionCounts(reds, blues)
  env.info("CP.SetCoalitionCounts called")
  self.BlueUnits = blues
  self.RedUnits = reds
  local own = CP.GetOwnership(self)
  if self.Owner ~= own then
*********** UPDATE THIS CODE BELOW **************
    trigger.action.outTextForCoalition(1, "ALERT --- " .. self.Name .. " is now " .. own, 10)
    self.Owner = own
  end
end
Igneous01 commented 6 years ago

L) Update this code in KI.Scheduled.UpdateCPStatus

function KI.Scheduled.UpdateCPStatus(arg, time)
  env.info("KI.Scheduled.UpdateCPStatus called")
  local _rGroups = coalition.getGroups(1, Group.Category.GROUND)
  local _bGroups = coalition.getGroups(2, Group.Category.GROUND)
  for i = 1, #KI.Data.CapturePoints do
    local _indicesToRemove = {}

    local _cp = KI.Data.CapturePoints[i]
    local _rcnt = 0
    local _bcnt = 0
    local _z = _cp.Zone
    local _slotsdisabled = false

    -- arg is boolean indicating if this is a first time run of this function
    -- on the very first call to UpdateCPStatus - set all slots to disabled
    -- then let the function correct itself and open up any slots after counting all the units
****************** THIS CODE BELOW *************************
    if (_cp.BlueUnits > 0 or _cp.RedUnits <= 0) and not arg then
      _slotsdisabled = true
    end
Igneous01 commented 6 years ago

All code changed, unit tests passed.

Game Tests remaining:

A) Accessing Depot F10 menu works on red and blue side B) Slotblocking works on blue and red side C) ConfigChecker works as expected on new config entries D) Spawning cargo works as expected on red and blue side E) Messages to coalition are working on the correct coalition F) Fortifying CP works for both blue and red sides G) Depot Initialization works on both blue and red sides H) AICOM works on both Blue and Red sides I) IsPlayerInZone messages work for both blue and red sides J) Reloading mission data from file works correctly for blue and red sides

Igneous01 commented 6 years ago

Game Test Results: Both Red and Blue sides

A) Pass B) No Test C) Pass D) Pass E) Pass F) Pass G) Pass H) Pass I) Pass J) Pass

Igneous01 commented 6 years ago

B) Slot blocking test pass