Well I probably won't finish it here is the code if someone thinks about adding this feature...
Code: Select all
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--
-- file: unit_templates.lua
-- brief: Saves and builds building templates.
-- original author: Pendrokar
--
-- Copyright (C) 2007.
-- Licensed under the terms of the GNU GPL, v2 or later.
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function widget:GetInfo()
return {
name = "Templates",
desc = "Saves and builds building templates.",
author = "Pendrokar",
date = "Jul 26, 2009",
license = "GNU GPL, v2 or later",
layer = 0,
enabled = false -- loaded by default?
}
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local game = Game.modShortName
local TFILE = LUAUI_DIRNAME .. "Widgets/" .. "building-templates/" .. game ..".lua"
local tselected = 999 --which template selected? 999 - for none, I doubt somebody will ever have that many templates
local myteamid = Spring.GetMyTeamID()
local yourunitids = {}
local countup, facing = 0
local templates = {} --loaded templates
function compTimeBuilt(a,b)
if(yourunitids[a]) then a = yourunitids[a] end
if(yourunitids[b]) then b = yourunitids[b] end
return a < b
end
function widget:Initialize()
if Spring.GetSpectatingState() then
widgetHandler:RemoveWidget()
return
end
LoadTemplates()
end
function widget:Shutdown()
SaveTemplates()
end
---------------------Template saving and adding----------------------
function SaveTemplates()
if(#templates ~= 0) then
table.save(templates, TFILE)
else
table.save({}, TFILE)
end
end
function LoadTemplates()
if VFS.FileExists(TFILE, VFS.RAW) then
Spring.Echo("Loaded Template File")
templates = VFS.Include(TFILE, nil, VFS.RAW)
if(not #templates) then
templates = {}
end
else
Spring.Echo(TFILE .. "No Template File")
end
end
function AddTemplate()
local selected = Spring.GetSelectedUnits()
local x, x1, x2, z, z1, z2, posx, posz, pic = 0, 0, 0, 0, 0, 0, 0, 0, 0
local templatename = ""
local unitfacing, unitdefid = 0, 0
local template = {}
template[2] = {}
local unit = {}
table.sort(selected, compTimeBuilt)
--check min and max coordinates between units(find center)
for k,i in ipairs(selected) do
if(not yourunitids[i]) then
Spring.Echo("Unit with unknown creation time detected. Template could not be added.")
return
end
unitdefid = Spring.GetUnitDefID(i)
if (UnitDefs[unitdefid]["isBuilding"] or UnitDefs[unitdefid]["isFactory"]) then
x, _, z = Spring.GetUnitPosition(i)
if (x<x1) or (x1==0) then
x1 = x
end
if (x>x2) then
x2 = x
end
if (z<z1) or (z1==0) then
z1 = z
end
if (z>z2) then
z2 = z
end
end
end
x2 = (x2-x1)/2
z2 = (z2-z1)/2
--use the same function to add units to template
for k,uid in ipairs(selected) do
unitdefid = Spring.GetUnitDefID(uid)
if (UnitDefs[unitdefid]["isBuilding"] or UnitDefs[unitdefid]["isFactory"]) then
x, _, z = Spring.GetUnitPosition(uid)
posx, posz = x-x1-x2, z-z1-z2
unitdefid = Spring.GetUnitDefID(uid)
if(k == 1) then templatename = UnitDefs[unitdefid].name end
if(k == 1) then pic = k end
unitfacing = Spring.GetUnitBuildFacing(uid)
template[2][k] = {unitdefid = unitdefid, unitname = UnitDefs[unitdefid].name, unitfacing = unitfacing, posx = posx, posz = posz}
end
end
template[0] = templatename
template[1] = pic
table.insert(templates, template)
Spring.Echo("Building template added.")
end
---------------------Template editing----------------------
function ChangeTemplateName(templatenum, newname)
templates[templatenum][0] = newname
Spring.Echo("Template name changed to "..newname)
end
function ChangeTemplatePic(templatenum, newpic)
templates[templatenum][1] = newpic
Spring.Echo("Template pic changed")
end
---------------------Template deployment----------------------
function CheckBuilds()
local selected = Spring.GetSelectedUnits()
local unitlist = {} --array of units that can be built by specific unit
local checktemp = {} -- templates which can be built by all selected units
local ntemplates = templates --remove template from template list if one con cannot build
local unitdefid
for _, unitid in ipairs(selected) do
unitdefid = Spring.GetUnitDefID(unitid)
local ud = UnitDefs[unitdefid]
if(#ud.buildOptions ~= 0) then
for _, unitdefid in ipairs(ud.buildOptions) do
unitlist[unitdefid] = true
end
for templatenum, template in ipairs(ntemplates) do
for _, unit in ipairs(template[2]) do
if(unitlist[ (unit["unitdefid"]) ]) then
checktemp[templatenum] = true
else
checktemp[templatenum] = nil
ntemplates[templatenum] = nil
break
end
end
end
end
unitlist = {}
end
end
function BuildTemplate(builders, x, z, buildings, withshift)
local orderarray = {}
local newx, newz, newfacing
local getfacing = Spring.GetBuildFacing()
if(withshift == "") then tselected = 999 end
for k,building in ipairs(buildings) do
if(getfacing == 0) then -- switch didnt work for me
newx, newz = z+building["posz"], x+building["posx"]
newfacing = building["unitfacing"]
elseif(getfacing == 1) then
newx, newz = z+building["posz"], (x+(building["posx"]*(-1)))
if(1+building["unitfacing"] == 4) then
newfacing = 0
end
elseif(getfacing == 2) then
newx, newz = (x+(building["posx"]*(-1))), (z+(building["posz"]*(-1)))
if(1+building["unitfacing"] == 4) then
newfacing = 0
elseif(1+building["facing"] == 5) then
newfacing = 1
end
elseif(getfacing == 3) then
newx, newz = (z+(building["posz"]*(-1))), x+building["posx"]
if(1+building["unitfacing"] == 4) then
newfacing = 0
elseif(1+building["unitfacing"] == 5) then
newfacing = 1
elseif(1+building["unitfacing"] == 6) then
newfacing = 2
end
end
newx, _, newz = Spring.Pos2BuildPos(building["unitdefid"], (x+building["posx"]), 0, (z+building["posz"]))
if (Spring.TestBuildOrder(building["unitdefid"], newx, 0, newz, newfacing) ~= 0) then
orderarray[k] = {-building["unitdefid"], newx, 0, newz, newfacing, {withshift}}
withshift = "shift"
end
end
Spring.GiveOrderArrayToUnitArray(builders, orderarray)
end
function widget:KeyPress(key)
if (key == 111) then -- "O" for selecting last template from templates
tselected = #templates
return false
end
if (key == 117) then -- "U" for adding selected units to a template
AddTemplate()
return false
end
end
function widget:UnitFinished(unitid, unitdefid, teamid)
if(myteamid == teamid) and (UnitDefs[unitdefid]["isBuilding"] or UnitDefs[unitdefid]["isFactory"]) and not UnitDefs[unitdefid]["isFeature"] then
yourunitids[unitid] = countup
countup = countup + 1
end
end
function widget:UnitTaken(unitid, unitdefid, teamid)
if(myteamid == teamid) and (UnitDefs[unitdefid]["isBuilding"] or UnitDefs[unitdefid]["isFactory"]) then
yourunitids[unitid] = countup
countup = countup + 1
end
end
function widget:UnitDestroyed(unitid, unitdefid, teamid)
if(myteamid == teamid) and (UnitDefs[unitdefid]["isBuilding"] or UnitDefs[unitdefid]["isFactory"]) then
yourunitids[unitid] = nil
end
end
function widget:UnitGiven(unitid, unitdefid, teamid)
if(myteamid == teamid) and (UnitDefs[unitdefid]["isBuilding"] or UnitDefs[unitdefid]["isFactory"]) then
yourunitids[unitid] = nil
end
end
function widget:DrawWorld()
if(tselected ~= 999) then
DrawTemplate()
end
end
function DrawTemplate()
gl.Color(1.0, 1.0, 1.0, 0.35 )
gl.DepthTest(true)
local x, z = Spring.GetMouseState() --z as World z even though it's y for mouse
local getfacing = Spring.GetBuildFacing()
local height, newx, newz, newfacing
local cord = {}
local dimensions = {}
if(not Spring.IsAboveMiniMap(x,z)) then
x, z = math.floor(x), math.floor(z)
_, cord = Spring.TraceScreenRay(x, z, true)
if(cord ~= nil) then
x = cord[1]
z = cord[3]
for k,unit in ipairs(templates[tselected][2]) do
if(getfacing == 0) then -- switch didnt work for me
newx, newz = x+unit["posx"], z+unit["posz"]
newfacing = unit["unitfacing"]
elseif(getfacing == 1) then
newx, newz = z+unit["posz"], (x+(unit["posx"]*(-1)))
if(1+unit["unitfacing"] == 2) then
newfacing = 0
end
elseif(getfacing == 2) then
newx, newz = (x+(unit["posx"]*(-1))), (z+(unit["posz"]*(-1)))
if(1+unit["unitfacing"] == 3) then
newfacing = 0
elseif(1+unit["unitfacing"] == 5) then
newfacing = 1
end
elseif(getfacing == 3) then
newx, newz = (z+(unit["posz"]*(-1))), x+unit["posx"]
if(1+unit["unitfacing"] == 4) then
newfacing = 0
elseif(1+unit["unitfacing"] == 5) then
newfacing = 1
elseif(1+unit["unitfacing"] == 6) then
newfacing = 2
end
end
newx, _, newz = Spring.Pos2BuildPos(unit["unitdefid"], newx, 0, newz)
if (Spring.TestBuildOrder(unit["unitdefid"], newx, 0, newz, newfacing) ~= 0) then
gl.Color(0.1, 1.0, 0.1, 0.40 ) --Can be built -> Green
else
gl.Color(1.0, 0.1, 0.1, 0.40 ) --Cannot be built -> Red
end
gl.PushMatrix()
height = Spring.GetGroundHeight( newx, newz )
gl.Translate( (newx+10), (height+10), (z+newz) )
dimensions = Spring.GetUnitDefDimensions(unit["unitdefid"])
gl.Rotate(90, x, 0, 0)
gl.Rect(dimensions["minx"], dimensions["minx"], dimensions["maxx"], dimensions["maxx"])
gl.Rotate(-90, x, 0, 0)
gl.Translate( 0, (-10), 0)
gl.Rotate((newfacing*90), 0, height, 0)
gl.UnitShape( unit["unitdefid"], myteamid )
gl.PopMatrix()
end
else --Out of map bounds/etc
end
end
gl.DepthTest(false)
gl.Color(1, 1, 1, 1)
end
function widget:MousePress(x, y, button)
if (tselected ~= 999) and (button == 1) then
local x, y, z
local cord = {}
local builders = Spring.GetSelectedUnits()
x, y = Spring.GetMouseState()
x, y = math.floor(x), math.floor(y)
_, cord = Spring.TraceScreenRay(x, y, true)
x, z = cord[1], cord[3]
local _, _, _, shiftpressed = Spring.GetModKeyState()
if(shiftpressed) then shiftpressed = "shift"
else shiftpressed = ""
end
BuildTemplate(builders, x, z, templates[tselected][2], shiftpressed)
return true
elseif (tselected ~= 999) and (button == 3) then
tselected = 999
return true
end
return false
end
function widget:MouseMove(x, y, dx, dy, button)
if (button == 1) then
Spring.Echo(x.." - "..y.." - "..dx.." - "..dy)
end
return true
end