1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
AttackHandler = class(Module)
function AttackHandler:Name()
return "AttackHandler"
end
function AttackHandler:internalName()
return "attackhandler"
end
function AttackHandler:Init()
self.recruits = {}
self.counter = 8
end
function AttackHandler:Update()
-- stagger targetting if multiple shards are in the game
local f = game:Frame() + game:GetTeamID()
if math.mod(f,15) == 0 then
self:DoTargetting()
end
end
function AttackHandler:UnitDead(engineunit)
if engineunit:Team() == game:GetTeamID() then
self.counter = self.counter - 0.2
self.counter = math.max(self.counter,8)
-- try and clean up dead recruits where possible
for i,v in ipairs(self.recruits) do
if v.engineID == engineunit:ID() then
table.remove(self.recruits,i)
break
end
end
end
end
function AttackHandler:DoTargetting()
if #self.recruits > self.counter then
--[[ try and catch invalid recruits and remove them, then reevaluate
local nrecruits = {}
for i,v in ipairs(self.recruits) do
if v.unit ~= nil then
table.insert(nrecruits,v)
break
end
end
self.recruits = nrecruits
if #nrecruits > self.counter then
else
return
end]]--
-- find somewhere to attack
local cells = {}
local celllist = {}
local mapdimensions = game.map:MapDimensions()
--enemies = game:GetEnemies()
local enemies = game:GetEnemies()
if enemies and #enemies > 0 then
-- figure out where all the enemies are!
for i=1,#enemies do
local e = enemies[i]
if e ~= nil then
pos = e:GetPosition()
px = pos.x - math.fmod(pos.x,400)
pz = pos.z - math.fmod(pos.z,400)
px = px/400
pz = pz/400
if cells[px] == nil then
cells[px] = {}
end
if cells[px][pz] == nil then
local newcell = { count = 0, posx = 0,posz=0,}
cells[px][pz] = newcell
table.insert(celllist,newcell)
end
cell = cells[px][pz]
cell.count = cell.count + self:ScoreUnit(e)
-- we dont want to target the center of the cell encase its a ledge with nothing
-- on it etc so target this units position instead
cell.posx = pos.x
cell.posz = pos.z
-- @TODO: The unit chosen may not be the best unit to target, ideally pick the
-- one closest to the average location of all units in that grid
end
end
local bestCell = nil
-- now find the smallest nonvacant cell to go lynch!
for i=1,#celllist do
local cell = celllist[i]
if bestCell == nil then
bestCell = cell
else
if cell.count < bestCell.count then
bestCell = cell
end
end
end
-- if we have a cell then lets go attack it!
if bestCell ~= nil then
for i,recruit in ipairs(self.recruits) do
recruit:AttackCell(bestCell)
end
self.counter = self.counter + 0.2
self.counter = math.min(self.counter,20)
-- remove all our recruits!
self.recruits = {}
end
end
-- cleanup
cellist = nil
cells = nil
mapdimensions = nil
end
end
function AttackHandler:IsRecruit(attkbehaviour)
for i,v in ipairs(self.recruits) do
if v.engineID == attkbehaviour.engineID then
return true
end
end
return false
end
function AttackHandler:AddRecruit(attkbehaviour)
if attkbehaviour.unit == nil then
game:SendToConsole( "null unit in attack beh found ")
return
end
if not self:IsRecruit(attkbehaviour) then
table.insert(self.recruits,attkbehaviour)
end
end
function AttackHandler:RemoveRecruit(attkbehaviour)
for i,v in ipairs(self.recruits) do
if v.engineID == attkbehaviour.engineID then
table.remove(self.recruits,i)
return true
end
end
return false
end
-- How much is this unit worth?
--
-- Idea: add a table with hardcoded values,
-- and use said values if a units found in
-- that table to highlight strategic value
function AttackHandler:ScoreUnit(unit)
local value = 1
if unit:CanMove() then
if unit:CanBuild() then
value = value + 1
end
else
value = value + 1
if unit:CanBuild() then
value = value + 1
end
end
return value
end
|