-
-
Save ashdnazg/6d3664b76976f2afdd1a to your computer and use it in GitHub Desktop.
Allows stealing units from teammates with same widget
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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