feat(client): Shift click to queue or cancel five units at once - #3222
feat(client): Shift click to queue or cancel five units at once#3222triatomic wants to merge 2 commits into
Conversation
Shift clicking a unit cameo queues five copies instead of one, and shift clicking a build queue slot cancels five instead of one. Queueing re-runs canMakeUnit before each additional unit rather than firing five messages blindly. That check covers money, queue space, parking places and per player unit caps, all of which move as the batch is queued, so a shift click on the last affordable unit queues what it can and stops quietly. Only the first unit reports a failure, so the player is not spammed with five identical "not enough money" messages. Cancelling walks the queue forwards from the clicked slot, which takes the most recently queued copies first and leaves the item currently building alone for as long as possible. It only cancels entries of the same production type, so a shift click cannot silently eat unrelated queued items. Each unit still gets its own production id and its own MSG_QUEUE_UNIT_CREATE, so the logic side sees exactly what it would from five separate clicks. No new message type, and nothing about the batch is resolved client side beyond reading the modifier key.
PR Summary by QodoAdd Shift-click batching for unit production queues
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo
1. Batch cancels unrelated units
|
|
| Filename | Overview |
|---|---|
| Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp | Adds five-item Shift queue/cancel behavior, but the previously reported mixed-template cancellation remains in the current implementation. |
Sequence Diagram
sequenceDiagram
participant Player
participant ControlBar
participant MessageStream
participant GameLogic
Player->>ControlBar: Shift-click queue slot
ControlBar->>MessageStream: Cancel clicked production ID
loop Up to four later PRODUCTION_UNIT slots
ControlBar->>MessageStream: Cancel slot production ID
end
MessageStream->>GameLogic: Deliver cancellation commands
GameLogic->>GameLogic: Cancel and refund each matching production ID
Reviews (2): Last reviewed commit: "fix(client): Cancel the newest queued en..." | Re-trigger Greptile
| continue; | ||
| if( m_queueData[ j ].type != PRODUCTION_UNIT ) | ||
| continue; |
There was a problem hiding this comment.
Cancellation conflates unit templates
When later queue slots contain different unit templates, this loop treats every PRODUCTION_UNIT as a copy of the clicked unit and cancels it by production ID, causing Shift-click to remove and refund up to four unrelated queued units.
Prompt To Fix With AI
This is a comment left during a code review.
Path: Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp
Line: 523-525
Comment:
**Cancellation conflates unit templates**
When later queue slots contain different unit templates, this loop treats every `PRODUCTION_UNIT` as a copy of the clicked unit and cancels it by production ID, causing Shift-click to remove and refund up to four unrelated queued units.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Deliberate, and now stated in the code (b2b70ca): the batch is positional, not per template - its point is to clear what was just queued, whatever it was, the same way five individual clicks on the tail would. The PRODUCTION_UNIT check exists to keep an upgrade entry from being swept up, not to filter templates. The suggested template comparison is intentionally not taken.
…batch The extra cancels scanned upward from the clicked slot, and the queue is displayed oldest to newest - so the batch took the oldest entries after the click, removing units close to production while newer copies survived at the tail. Walk from the tail towards the clicked slot instead, so the most recently queued entries go first. The batch deliberately stays unfiltered by template: its point is to clear what was just queued, whatever it was. Only unit entries are taken, so an upgrade in the queue is never swept up - now stated in the comment.
Shift-clicking a unit cameo queues five copies instead of one, and shift-clicking a build queue slot cancels five instead of one. No option needed — plain clicks behave exactly as retail; only the Shift modifier changes anything.
Queueing re-runs
canMakeUnitbefore each additional unit rather than firing five messages blindly. That check covers money, queue space, parking places and per-player unit caps — all of which move as the batch is queued — so a shift-click on the last affordable unit queues what it can and stops quietly. Only the first unit reports a failure, so the player is not spammed with five identical "not enough money" messages.Cancelling walks the queue forward from the clicked slot, taking the most recently queued copies first and leaving the item currently building alone for as long as possible. It only cancels entries of the same production type, so a shift-click cannot silently eat unrelated queued items.
Each unit still gets its own production id and its own
MSG_QUEUE_UNIT_CREATE, so the logic side sees exactly what it would from five separate clicks. No new message type, and nothing about the batch is resolved client-side beyond reading the modifier key — no determinism risk in multiplayer or replays.Works in both Zero Hour and Generals — everything lives in the shared command bar processing.
This ships in the Contra mod's engine fork and has been played there; this PR is the port onto current main. Code was written with LLM assistance and human-reviewed, adapted and playtested by the author.
Prepared for Squash and Merge.