@@ -10,7 +10,7 @@ function widget:GetInfo()
1010 license = " GNU GPL, v2 or later" ,
1111 layer = 0 ,
1212 handler = true ,
13- enabled = false ,
13+ enabled = true ,
1414 }
1515end
1616
2121---- ----------------------------------------------------------------------------
2222---- ----------------------------------------------------------------------------
2323
24- VFS .Include (LUAUI_DIRNAME .. " Widgets/Utilities/engine_blast_radius.lua" )
24+ local glVertex = gl .Vertex
25+ local glPushAttrib = gl .PushAttrib
26+ local glLineStipple = gl .LineStipple
27+ local glDepthTest = gl .DepthTest
28+ local glLineWidth = gl .LineWidth
29+ local glColor = gl .Color
30+ local glBeginEnd = gl .BeginEnd
31+ local glPopAttrib = gl .PopAttrib
32+ local glPopMatrix = gl .PopMatrix
33+ local glPushMatrix = gl .PushMatrix
34+ local glScale = gl .Scale
35+ local glTranslate = gl .Translate
36+ local GL_LINE_LOOP = GL .LINE_LOOP
37+
38+ local circleDivs = 64
39+
40+ local PI = math.pi
41+ local cos = math.cos
42+ local sin = math.sin
43+
44+ local aoeLineWidthMult = 64
45+ local numAoECircles = 9
46+ local aoeColor = {1 , 0 , 0 , 1 }
47+ local mouseDistance = 1000
48+ local floor = math.floor
49+
50+ local pulse_timmer = Spring .GetTimer ()
51+ local function getPulse ()
52+ local time = Spring .DiffTimers (Spring .GetTimer (), pulse_timmer )
53+ return 1 - (time - floor (time ))
54+ end
55+
56+ local function UnitCircleVertices ()
57+ for i = 1 , circleDivs do
58+ local theta = 2 * PI * i / circleDivs
59+ glVertex (cos (theta ), 0 , sin (theta ))
60+ end
61+ end
62+
63+ local function DrawCircle (x , y , z , radius )
64+ glPushMatrix ()
65+ glTranslate (x , y , z )
66+ glScale (radius , radius , radius )
67+ glBeginEnd (GL_LINE_LOOP , UnitCircleVertices )
68+ glPopMatrix ()
69+ end
70+
71+ local function drawBlastRadius (tx , ty , tz , weaponDef )
72+ local aoe = weaponDef .damageAreaOfEffect
73+ local ee = weaponDef .edgeEffectiveness
74+
75+ glLineWidth (math.max (0.05 , aoeLineWidthMult * aoe / mouseDistance ))
76+
77+ for i = 1 , numAoECircles do
78+ local proportion = i / (numAoECircles + 1 )
79+ local radius = aoe * proportion
80+ local alpha = aoeColor [4 ] * (1 - proportion ) / (1 - proportion * ee ) * getPulse ()
81+ glColor (aoeColor [1 ], aoeColor [2 ], aoeColor [3 ], alpha )
82+ DrawCircle (tx , ty , tz , radius )
83+ end
84+
85+ glColor (1 ,1 ,1 ,1 )
86+ glLineWidth (1 )
87+ end
88+
89+ local function drawLine (x1 , y1 , z1 , x2 , y2 , z2 )
90+ glPushAttrib (GL .LINE_BITS )
91+ glLineStipple (" springdefault" )
92+ glDepthTest (false )
93+ glLineWidth (1 )
94+ glColor (1 , 0 , 0 , 1 )
95+ glBeginEnd (GL .LINES , function ()
96+ glVertex (x1 , y1 , z1 )
97+ glVertex (x2 , y2 , z2 )
98+ end )
99+
100+ glColor (1 , 1 , 1 , 1 )
101+ glLineStipple (false )
102+ glPopAttrib ()
103+ end
25104
26105---- ----------------------------------------------------------------------------
27106---- ----------------------------------------------------------------------------
@@ -123,9 +202,17 @@ local function missle_class()
123202 if not Spring .GetUnitIsDead (unitID ) then
124203 local unitDefID = Spring .GetUnitDefID (unitID )
125204 if unitDefID and self .launchableTypes [unitDefID ] then
205+ -- Silo-built missiles exist as nanoframes while under construction.
126206 local _ , _ , _ , _ , buildProgress = Spring .GetUnitHealth (unitID )
127207 if buildProgress and buildProgress < 1 then
128208 maxProgress = math.max (maxProgress , buildProgress )
209+ else
210+ -- Stockpiling weapons (Trinity, Reef, subtac) report progress toward
211+ -- the next missile via the stockpile build percentage.
212+ local _ , _ , stockpileProgress = Spring .GetUnitStockpile (unitID )
213+ if stockpileProgress and stockpileProgress > 0 and stockpileProgress < 1 then
214+ maxProgress = math.max (maxProgress , stockpileProgress )
215+ end
129216 end
130217 end
131218 end
@@ -237,10 +324,13 @@ local function missle_class()
237324 local customCommands = widgetHandler .customCommands
238325
239326 customCommands [# customCommands + 1 ] = {
240- id = self .cmd ,
241- type = self .cmdType ,
242- hidden = true ,
243- cursor = ' Attack' ,
327+ id = self .cmd ,
328+ type = self .cmdType ,
329+ cursor = ' Attack' ,
330+ action = " missile_" .. self .name ,
331+ name = self .displayName ,
332+ disabled = self .disabled ,
333+ params = {},
244334 }
245335 end
246336
@@ -532,42 +622,6 @@ local commands = {
532622
533623local UPDATE_FREQUENCY = 0.25
534624local timer = UPDATE_FREQUENCY + 1
535- local buttonCache = {}
536-
537- local missileCommandIDs = {
538- [39610 ] = true ,
539- [39611 ] = true ,
540- [39612 ] = true ,
541- [39613 ] = true ,
542- [39614 ] = true ,
543- [39615 ] = true ,
544- [39616 ] = true ,
545- }
546-
547- local function findButtonsByCommand ()
548- local screen = WG .Chili .Screen0
549- if not screen then return end
550-
551- local function searchChildren (control )
552- if not control then return end
553-
554- if control .cmdID and missileCommandIDs [control .cmdID ] then
555- buttonCache [control .cmdID ] = control
556- end
557-
558- if control .children then
559- for _ , child in ipairs (control .children ) do
560- searchChildren (child )
561- end
562- end
563- end
564-
565- if screen .children then
566- for _ , child in ipairs (screen .children ) do
567- searchChildren (child )
568- end
569- end
570- end
571625
572626---- ----------------------------------------------------------------------------
573627---- ----------------------------------------------------------------------------
@@ -585,48 +639,44 @@ function widget:Update(dt)
585639 end
586640 timer = 0
587641
588- findButtonsByCommand ()
589-
590642 local totalMissileCount = 0
643+ local changed = false
591644
592645 for _ , command in pairs (commands ) do
593646 local count = command :getCount ()
594647 local buildProgress = command :getMaxBuildProgress ()
595- local customCommands = widgetHandler .customCommands
596648
597649 totalMissileCount = totalMissileCount + count
598650
599- for i = 1 , # customCommands do
600- if customCommands [i ].id == command .cmd then
601- local displayName = " "
602- if count > 0 then
603- displayName = " x" .. count
604- end
605- if buildProgress > 0 then
606- local progressPercent = math.floor (buildProgress * 100 )
607- if displayName ~= " " then
608- displayName = displayName .. " (" .. progressPercent .. " %)"
609- else
610- displayName = progressPercent .. " %"
611- end
612- end
613- customCommands [i ].name = displayName
651+ -- Count string shown on the button (e.g. "x3"), empty when none stockpiled.
652+ -- This is drawn by the integral menu via the command's name field (see
653+ -- DRAW_NAME_COMMANDS / commandDisplayConfig.drawName).
654+ local displayName = " "
655+ if count > 0 then
656+ displayName = " x" .. count
657+ end
614658
615- -- Disable button if no missiles available
616- customCommands [i ].disabled = (count == 0 )
659+ -- Factory-style build progress bar on the button.
660+ if WG .IntegralMenu and WG .IntegralMenu .SetCommandProgress then
661+ WG .IntegralMenu .SetCommandProgress (command .cmd , buildProgress )
662+ end
617663
618- -- Update visual progress bar on button
619- local button = buttonCache [command .cmd ]
620- if button and button .SetProgressBar then
621- button :SetProgressBar (buildProgress )
622- end
623- break
624- end
664+ local disabled = (count == 0 )
665+ if command .displayName ~= displayName or command .disabled ~= disabled then
666+ command .displayName = displayName
667+ command .disabled = disabled
668+ changed = true
625669 end
626670 end
627671
628672 -- Export total count for tab badge
629673 WG .missileTotalCount = totalMissileCount
674+
675+ -- The integral menu only re-reads custom commands on CommandsChanged, so force
676+ -- a layout update when the displayed count / progress actually changed.
677+ if changed then
678+ Spring .ForceLayoutUpdate ()
679+ end
630680end
631681
632682function widget :CommandNotify (cmdID , cmdParams , cmdOptions )
0 commit comments