Skip to content

Instantly share code, notes, and snippets.

@ashdnazg
Last active August 29, 2015 14:12
Show Gist options
  • Save ashdnazg/6d3664b76976f2afdd1a to your computer and use it in GitHub Desktop.
Save ashdnazg/6d3664b76976f2afdd1a to your computer and use it in GitHub Desktop.
Allows stealing units from teammates with same widget
function widget:GetInfo()
return {
name = "Hivemind",
desc = "Take control of your ally's units, win the game",
author = "ashdnazg",
date = "07 Jan 2015",
license = "GNU GPL, v2 or later",
layer = 5,
enabled = true,
}
end
-- Localisations
-- OpenGL
local glColor = gl.Color
local glPopMatrix = gl.PopMatrix
local glPushMatrix = gl.PushMatrix
local glShape = gl.Shape
local GL_LINE_STRIP = GL.LINE_STRIP
-- Localisations
-- Unsynced read
local GetMouseState = Spring.GetMouseState
local WorldToScreenCoords = Spring.WorldToScreenCoords
-- Variables
local mode
local whitelistWindow
local whitelistButton
local stealButton
local startCoords
local expectedUnits
local myTeamID = Spring.GetMyTeamID()
local myPlayerID = Spring.GetMyPlayerID()
--Constants
local MODE_IDLE = 0
local MODE_STEAL = 1
local LINE_WIDTH = 1
local COLOR_REGULAR = {1,1,1, 1}
local COLOR_SELECTED = {0.8, 0, 0, 1}
local COLOR_NONE = COLOR_REGULAR
local COLOR_ONLY_US = COLOR_SELECTED
options_path = 'Settings/HUD Panels/Hivemind'
options = {}
options_order = {}
local function UpdateColours()
stealButton.backgroundColor = mode == MODE_STEAL and COLOR_SELECTED or COLOR_REGULAR
stealButton:Invalidate()
end
local function StartStealing()
mode = MODE_STEAL
UpdateColours()
end
local function StopStealing()
mode = MODE_IDLE
startCoords = nil
UpdateColours()
end
local function ToggleStealing()
if mode == MODE_IDLE then
StartStealing()
elseif mode == MODE_STEAL then
StopStealing()
end
end
local function CloseWhitelist()
if whitelistWindow then
whitelistWindow:Dispose()
whitelistWindow = nil
end
end
local function ShowWhitelist()
WG.crude.OpenPath(options_path)
end
local function InitGUI()
local Chili = WG.Chili
whitelistButton = Chili.Button:New{
y = 20, width = 80, caption = "Whitelist",
OnClick = {
function(self) ShowWhitelist() end
}
}
stealButton = Chili.Button:New{
y = 40, width = 80, caption = "Possess",
OnClick = {
function(self) ToggleStealing() end
}
}
local window0 = Chili.Window:New{
caption = "Hivemind",
y = "50%",
right = 10,
width = 200,
height = 200,
parent = Chili.Screen0,
autosize = true,
savespace = true,
children = {
whitelistButton,
stealButton,
},
OnClick = {
function(self)
local alt, ctrl, meta, shift = Spring.GetModKeyState()
if not meta then return false end
WG.crude.OpenPath(options_path)
end
}
}
end
--------------
-- CALLINS --
--------------
function widget:DrawScreen()
if startCoords then
local startx, starty, startz = WorldToScreenCoords(unpack(startCoords))
local mx, my = GetMouseState()
local dx, dy = mx - startx, my - starty
local rotation = math.atan2(dx, dy)
local distance = math.sqrt(dx^2 + dy^2)
glPushMatrix()
glColor(1,0,0)
local vertices = {
{v = {startx, starty, 0}},
{v = {startx, my, 0}},
{v = {mx, my, 0}},
{v = {mx, starty, 0}},
{v = {startx, starty, 0}},
}
glShape(GL_LINE_STRIP, vertices)
glPopMatrix()
end
end
function widget:MousePress(mx, my, button)
if button == 1 then
if mode == MODE_STEAL then
local what, coords = Spring.TraceScreenRay(mx, my, true)
if what then
if not startCoords then
startCoords = coords
return true
end
else
StopStealing()
return false
end
end
elseif button == 3 then
if mode == MODE_STEAL then
StopStealing()
end
end
return false
end
local function StealUnits(x1, z1, x2, z2)
expectedUnits = Spring.GetUnitsInRectangle(math.min(x1, x2), math.min(z1, z2), math.max(x1,x2), math.max(z1,z2))
-- Spring.Echo(unpack(expectedUnits))
local msg = 'stealReq|' .. table.concat(expectedUnits, "|")
Spring.SendLuaUIMsg(msg, 'a')
end
function widget:MouseRelease(mx, my, button)
if button == 1 and startCoords then
local what, coords = Spring.TraceScreenRay(mx, my, true)
if what then
StealUnits(startCoords[1], startCoords[3], coords[1], coords[3])
end
StopStealing()
end
end
function widget:Initialize()
if Spring.IsReplay() or Spring.GetSpectatingState() then
Spring.Echo("Hivemind: removed widget")
widgetHandler:RemoveWidget()
return
end
local players = Spring.GetPlayerList()
for _, playerID in pairs(players) do
local playerName, _, spec, teamID = Spring.GetPlayerInfo(playerID)
if Spring.ArePlayersAllied(playerID, myPlayerID) and playerID ~= myPlayerID and not spec then
options_order[#options_order+1] = playerName
options[playerName] = {
name = playerName,
type = 'bool',
value = false,
desc = "Allow " .. playerName .. " to control your units",
}
end
end
if #options_order == 0 then
Spring.Echo("No allies, hivemind removed")
widgetHandler:RemoveWidget(self)
return
end
mode = MODE_IDLE
InitGUI()
end
local function explode(div,str) --copied from gui_epicmenu.lua
if (div=='') then return false end
local pos,arr = 0,{}
-- for each divider found
for st,sp in function() return string.find(str,div,pos,true) end do
table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider
pos = sp + 1 -- Jump past current divider
end
table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
return arr
end
local function PlaceMarker(firstUnit, numUnits, playerName)
local label = playerName .. " stole " .. numUnits .. " of our units"
local x, y, z = Spring.GetUnitPosition(firstUnit)
Spring.MarkerAddPoint(x, y, z, label)
end
function widget:RecvLuaMsg(msg, playerID)
if Spring.ArePlayersAllied(playerID, myPlayerID) and playerID ~= myPlayerID then
local playerName, _, _, teamID = Spring.GetPlayerInfo(playerID)
if myTeamID == teamID then return end
if options[playerName] and options[playerName].value then
if msg:sub(1,9) == 'stealReq|' then
msg = msg:sub(10)
local msgArray = explode('|',msg)
local unitIDArray = {}
for _, unitIDStr in pairs(msgArray) do
local unitID = tonumber(unitIDStr)
if unitID and Spring.GetUnitTeam(unitID) == myTeamID then
table.insert(unitIDArray, unitID)
end
end
if #unitIDArray == 0 then
return
end
-- Spring.Echo("sending units to " .. playerName)
local currentSelection = Spring.GetSelectedUnits()
PlaceMarker(unitIDArray[1], #unitIDArray, playerName)
Spring.SelectUnitArray(unitIDArray)
Spring.ShareResources(teamID, "units")
Spring.SelectUnitArray(currentSelection)
Spring.SendLuaUIMsg('stealAcc|' .. playerID)
elseif msg:sub(1,9) == 'stealAcc|' then
msg = msg:sub(10)
local receivingPlayer = tonumber(msg)
if myPlayerID == receivingPlayer then
-- Spring.Echo("receiving units from " .. playerName)
Spring.SelectUnitArray(expectedUnits, true)
expectedUnits = nil
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment