Skip to content

Missile orders#5771

Open
amnykon wants to merge 32 commits into
ZeroK-RTS:masterfrom
amnykon:missile-orders
Open

Missile orders#5771
amnykon wants to merge 32 commits into
ZeroK-RTS:masterfrom
amnykon:missile-orders

Conversation

@amnykon

@amnykon amnykon commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces a new 'Missiles' tab to the integral menu and adds a new widget to manage missile commands, stockpile counts, and target drawing.

claude and others added 21 commits July 1, 2026 00:33
Copy missle_command_center.lua widget to enable missile command center functionality.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
The marker message functionality that notified team members of missile launches
is now handled by a separate widget, so remove it from the command center.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Add slow_missile_controller_class to support launching the Zeno slow missile
from the missile command center UI.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Configure the integral menu to display missile commands (EOS, Seismic, Shockley,
Inferno, Reef, Trinity, and Zeno) in a dedicated Missiles tab above the Orders tab.
Add display configurations for each missile command with icons and tooltips.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Remove floatingCommand dependency and associated UI code (initialize, update,
assign functions) since missiles are now managed through the command menu tab.
Keep core functionality (command registration, blast radius drawing).

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Add null checks throughout the widget to handle invalid units gracefully:
- Check for valid positions before accessing unit data
- Verify unit definitions and weapon definitions exist
- Handle dead units and parent silos safely
- Return early on nil values to prevent cascading failures

Fixes crash that occurs after missile launches.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Add hasMissileUnits() function to check if any missile launcher/silo units exist.
Update Missiles tab inclusionFunction to hide the tab until missile units are built.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Update widget:Update to periodically refresh the missile count for each command
and display it on the button via the command name. Counts update every 0.25 seconds.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Add getMaxBuildProgress() to track the highest build progress among all
building missiles. Display format: 'x[count] ([percent]%)' or just '[percent]%'
if no missiles are ready. Shows progress of the next missile being built.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Create helper widget (gui_missile_progress.lua) to display visual progress bars
on missile command buttons, showing build progress of next missile like factory units.
Export progress data via WG.missileProgress for access by other widgets.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Remove unnecessary separate helper widget. Handle progress bar updates directly
in the missile widget's Update function. Simplifies codebase without losing functionality.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Create helper widget that searches for missile command buttons and updates their
progress bars using SetProgressBar() method, matching factory unit behavior.
Missile widget exports progress data via WG.missileProgress for the helper to consume.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Consolidate all missile command functionality into missle_command_center.lua.
The widget now handles: command registration, count display, progress display
(text and visual progress bars), and button updates. Removes unnecessary separation.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Extend integral menu to support tab badges showing unit icon and missile count.
Add badgeUnitName and badgeCountWG configuration fields to command panels.
Missile widget exports total count via WG.missileTotalCount.
Badge displays on Missiles tab showing tacnuke icon with ready missile count.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
1. Dynamic tab visibility: Missiles tab now hides when no missiles are available
2. Weapon tooltips: Added detailed descriptions for each missile type
3. Keybindings: Added grid hotkeys support for quick missile selection
4. Disable buttons when count is 0: Buttons grey out when no missiles available
5. Per-type counts: EOS shares tacnuke and subtacmissile counts (already working)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Define missileCmdIDs table and isMissileCommand() helper at top of
integral_menu_config.lua. Replace hardcoded ID lists in both Missiles
panel inclusionFunction and Orders panel exclusion with helper calls.

Fixes maintenance issue where IDs could get out of sync between panels.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
1-3. Add null checks for type and weaponDef before accessing in perferedUnit
4. Fix Spring.GetUnitCommands parameter - use fixed 100 instead of variable stockpile
5. Add null check for unit position before using in distance calculation
6. Add null check for tabButton.button before calling SetVisibility
7. Initialize WG.missileTotalCount in widget:Initialize to fix badge when disabled

All fixes are defensive nil/validation checks to prevent crashes.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Correct spelling and update description. Use 'command center: missiles'
naming convention for consistency with planned global command tabs.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
Convert missileCmdIDs to dictionary with id, name, and icon fields.
Use loop to generate commandDisplayConfig from dictionary instead of
hardcoding each ID. Use missile/launcher unit icons instead of generic
attack icon. Consolidates missile metadata in one place.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
…d tooltips

Move tooltip data from separate missileTooltips dictionary into each missile entry
in the missileCmds metadata dictionary. This removes the tooltip upvalue and makes
the configuration more self-contained.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiaPfKSj8kGFjaUPyxYYHd
- Fix Chili Integral Menu crash: remove SetVisibility call on unparented
  tab button; tab presence is handled by the commandCount/SetTabs machinery.
- Guard nil ud.shieldPower in Chili Selections & CursorTip.
- Make the missile widget self-contained: inline the blast-radius draw code
  (the VFS include file was never committed) and enable it by default.
- Show missile commands: drop hidden flag, add action/params so they appear
  in the new Missiles tab with tooltips.
- Order buttons like the missile silo (row 1: Trinity, Reef; row 2: silo
  missiles in buildoptions order) via per-command col/row positions.
- Show count label ("xN") via DRAW_NAME_COMMANDS driven by the config's
  drawName flag.
- Show a factory-style build progress bar via a new
  WG.IntegralMenu.SetCommandProgress API (added to externalFunctions so it
  survives the Initialize assignment); source progress from unit build
  progress or stockpile build percent as appropriate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
amnykon and others added 8 commits July 1, 2026 10:43
Zero-K reimplements stockpiling in unit_stockpile.lua, which pins the
engine's stockpile build percent to 1 and tracks real progress in the
"gadgetStockpile" rules param. Read that param for stockpiling weapons
(Trinity, Reef, subtac) instead of GetUnitStockpile, matching how
unit_healthbars / gui_build_eta / gui_nukeButton do it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Missile widget forces a layout rebuild once when the selection becomes
  empty, since the command menu pipeline does not run on its own then.
- Integral menu falls back to the first shown tab when the intended tab
  (default "orders") is not present, so the missiles panel gets selected.
- Add alwaysShowTab panel flag (set on missiles) to draw the tab bar even
  when it is the only tab.
- Guard both return-to-orders paths with IsTabPresent so firing a missile
  with nothing selected no longer switches to an empty orders tab and
  clears the panel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Split the integral menu tab strip into a top and bottom row. The missiles
  tab (flagged topRow) sits on the top row; all other tabs on the bottom.
- When there are no bottom-row tabs, the missiles tab drops into the single
  bottom row so it stays adjacent to the command buttons.
- Grow the window upward by one tab row when both rows are used, keeping the
  window bottom pinned to the screen edge and the command-button area fixed
  (bottom-anchored with a constant height).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Insert launches after existing launch orders but before other queued
  orders (e.g. moves), so shift-clicked launches fire in click order and
  still go before the unit moves away. Previously they inserted at queue
  position 0, reversing the click order.
- Give the launch command descriptor all required fields (name, texture,
  tooltip, boolean disabled) so the engine no longer logs
  "GetLuaCmdDescList() bad entry".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replace the single tacnuke icon + total count badge with a right-aligned
  row of per-type entries, one for each missile type that is stockpiled or
  building. Each entry shows the unit icon, a build-progress bar overlay,
  and the stockpile count. Icons are created with their file to avoid
  rendering as white quads.
- Export per-type {icon, count, progress} from the missile widget in a
  stable order instead of a single total.
- When a unit is (re)selected while on the missiles tab, switch to that
  unit's default tab instead of loitering on the global top-row tab.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tabs without an optionName (missiles, orders, units_factory) borrowed the
Units any+n hotkey for display, showing "(N)" even though N is the hold-fire
key and never switches to them. Drop the display fallback so they show no
hotkey label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e shot

Adds an approximate pre-fire terrain-block check for starburst silo missiles.
The descent is modelled as a straight line from an apex above the launcher to
the target; if terrain rises into that line the blast ring is moved to the hit
point, with a faint ghost ring left at the intended target. Apex height is
learned per weapon from real shots, falling back to a range-based estimate.

Checkpoint before a more accurate trajectory model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The descent line previously started directly above the launcher, making it too
shallow and prone to over-warning. Learn both the crest height and its
horizontal distance from the launcher from real shots, and start the dive line
from that crest point so its angle matches the missile's actual trajectory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
amnykon and others added 3 commits July 4, 2026 11:02
…aunch

- Rename file and class missle -> missile; fix perfered -> preferred
- Retitle widget "Missile Command Center" and update its description
- Drop a dead else-end branch
- Factor the five identical silo-missile getStockpile closures into one
  shared siloMissileStockpile helper
- Rename the integral-menu tab label from "Missiles" to "Launch"

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolve two conflicts:
- gui_chili_integral_menu.lua: keep both our second-tab-row height setup
  (baseWindowHeight/buttonAreaHeight) and upstream's UpdateRadarIconSizeString call.
- gui_chili_selections_and_cursortip.lua: keep our nil-guard (or 0) on shieldPower;
  upstream only changed adjacent lines.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The launch preview approximated the starburst trajectory, so it could disagree
with the Attack AoE widget's terrain-impact marker shown when the missile is
selected and attacked directly.

Expose gui_attack_aoe's vlaunch impact calculation as WG.AttackAoE.GetVlaunchImpact
(extracting a shared BuildVlaunch helper, behavior-preserving) and have the launch
preview call it, matching the fire-origin convention. Removes the widget's whole
approximation and apex-calibration code (~110 lines); the two previews now share
one code path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@amnykon amnykon marked this pull request as ready for review July 4, 2026 16:51
Comment on lines +706 to +708
for _, command in pairs(commands) do
if command:commandNotify(cmdID, cmdParams, cmdOptions) then return true end
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing pairs to call a bunch of objects every time a command happens does not look good. The call is gated internally by if cmdID == self.cmd, so you should be able to make a simple table indexed by cmdID, reducing the cost and maintenance burden to a single table lookup.

function widget:DrawWorld()
for _, command in pairs(commands) do
command:drawWorld()
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See widget:CommandNotify. In this case the gate is the same, but behind Spring.GetActiveCommand (in the current version this is called redundantly multiple times.

return 1
end

local function EOS_controller_class()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Bla_controller_classes have a lot of duplication so should have their essential parameters picked out and put into a config file. This is cleaner and lets modders find them.

end
end

local function distance3(x1, y1, z1, x2, y2, z2)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These exist (or should be added if missing) in Spring.Utilities.Vector

@GoogleFrog

Copy link
Copy Markdown
Contributor
image

When I click at A with this widget, the missile is targeted at the position on the ground behind the target unit.

glPopMatrix()
end

local function drawBlastRadius(tx, ty, tz, weaponDef)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this exist in attack AoE?

@GoogleFrog

GoogleFrog commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

I want to see this sort of feature implemented, but I have misgivings about adding a global second-row tab.

  • There is something quite satisfying in having a clear UI when nothing is selected.
  • With Launch and nothing selected, pressing D and clicking launches a Shockley. This is quite bad as you might have, say, a Lobster selected, but it dies just as you press D and try to have it launch units somewhere. Or maybe you have a strider that gets napped (deselecting it) just as you try to use a D ability. Basically, having a global hotkey appear when your selection clears is a problem.
  • The second row of the command menu looks a bit busy and janky. The main row of tabs are attached to the bottom while this one floats above.
  • The logic of the launch menu means that, if you have units selected, the menu closes whenever you fire a missile. Often you'll want to fire multiple missiles, potentially of different types.
  • I'm also a bit concerned about the maintainability of adding concepts such as global menu, two menu layers, and (especially) tab badges to integral menu.
image

I would like to see a version where the launch menu become accessible via a core select button, as I suspect this would work a lot better.

  • We could replace (only by default) the per-silo factory button with a single button that selects the launch screen.
  • This button would contain the same information has the launch badge. The button could have a 2x2 grid of missiles in most cases, and switch to 3x3 if the player has at least five types of missiles..

Clicking the core selector button would open the launch menu of the PR, but I am not 100% sure how it would interact with it. Here are some ideas.

  • Show the tabs appropriate to the selection, but highlight none of them, as the launch tab is selected.
  • Clicking the launch button on core selector again should toggle the menu.
  • Pressing Escape should close the menu (as happens now with construction tabs).
  • There should probably be some other methods of closing the menu, which I would expect to become clear after some playing around with it.

The core selector approach makes the feature quite visible, but keeps it minimal for people who want to use the old system. Players are unlikely to accidentally launch missiles because all the functionality would sit behind pressing the button or a hotkey. We would have options to turn off the button and to show individual missile silos on the selector (as currently happens), which would probably be off by default. Some way to queue missiles in the launch menu would help make the individual selection buttons obsolete

Other issues.

  • I feel like the integral config is almost autodetectable from customparams, which would help modding. Perhaps easy modding would just lose the ability to set the missile layout explicitly, which is an ok tradeoff.
  • Similar to the above, the cmdIDs could probably be automatically determined as well.
  • It looks like there is code reuse between attack AoE and the missile command widget. That is going to be a pain to maintain, and I'm not sure why missile command can't just do a simple invocation of attack AoE.
  • Complicating the above is the fact that the closest silo is not always the best choice. Eg silo A is blocked by terrain while silo B is not.
image

Minor issues.

  • You have written Eos in allcaps.
  • The whitespace for the missile command widget is wrong.
  • Where is Scylla?

@amnykon

amnykon commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

@GoogleFrog i feel the critical issues is the ui. No to randomly floating buttons, no to 2nd row of tabs (this got worse when I added air), adding a launch or strike button in the core select menu is an interesting idea. Should this adde or replace the silo button? IMO it's add, as you can't build with the launcher menu. If we are not having a tab for it, I question the integration into the orders panel. Con upgrade shows buttons above the orders panel, I feel launch should show a single row of buttons for launch missiles.

Other comments are good and I will apply them (or point out how thay are already dealt with) after the ui for this has been defined.

@amnykon

amnykon commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

3×3 badges on the selection panel will be way too small to show type + count + progress per missile. Instead I’m thinking a “show launchers” toggle in the top-left global commands panel — when on, the launch buttons appear in their own panel, probably just above the orders panel (or off to the side). Clean by default, full-size buttons with room for type/count/progress.
Same mechanism covers bombers (~8, incl. 2 for Odin) and scouts (swift, sparrow, oddly flea).
Different mechanism for two things, both further off, unrelated other then to show the progression I am planning:
• Global construction — use tab to switch global/direct modes; advanced widget, off by default. Currently tab shows the share screen, IMO it's a weak hotkey in a prime position for a hotkey.
• Striders — basically turns a nanotower into a strider hub plate; probably cleaner to just make it a proper plate than to have separate nanotower and strider hub side widgets.

@GoogleFrog

Copy link
Copy Markdown
Contributor
  • I think >=5 missiles will be quite rare, and 2x2 will probably be sufficiently visible
  • I said above, I would by default replace the silo button, but there should just be independent settings for whether to show the launch button and whether to show silo buttons. The PR doesn't need to do anything special to the current silo button, as it is just handled like a factory.
  • Opening integral menu as a hidden tab sounds fine to me. It makes sense for this type of UI to live there, and it uses the grid hotkeys. Clicking any of the tabs will close it.
  • Con upgrade = comm upgrade? The comm upgrade UI isn't great, I don't want it to be copied for something that might be used as frequently as a missile UI (in bursts).
  • I was considering something like "press Alt+A to queue an Eos". Or perhaps buttons on the third row to queue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants