Skip to content

Buying stacks instead of spam clicking#4640

Open
U-LF wants to merge 8 commits into
openfrontio:mainfrom
U-LF:main
Open

Buying stacks instead of spam clicking#4640
U-LF wants to merge 8 commits into
openfrontio:mainfrom
U-LF:main

Conversation

@U-LF

@U-LF U-LF commented Jul 18, 2026

Copy link
Copy Markdown

Before opening a PR: discuss new features on Discord first, and file bugs or small improvements as issues. You must be assigned to an approved issue — unsolicited PRs will be auto-closed.

Add approved & assigned issue number here: Resolves #3541

Description:

This PR introduces the ability for players to upgrade their structures in bulk stacks (x5, x10, x25, x50), significantly improving late-game UX by minimizing repetitive interactions. This feature integrates seamlessly across both the HTML Build Menu and the Radial Dial interface, supported by a 3D preview system to prevent unintentional expenditures.

Key Changes

  • Radial Sub-Menu for Stacked Upgrades: Added a nested sub-menu to the radial dial interface. Activating an upgradable structure now exposes secondary options allowing players to instantly select upgrade multipliers.
image
  • HTML Build Menu Interface Extension: Extended the HTML BuildMenu to support a multiplier selection state. Selecting an upgradable structure transforms the menu to display the available multiplier amounts alongside their dynamically calculated total costs.
image
  • 3D Ghost Preview Visual Indicators: Enhanced the WorldTextPass WebGL rendering pipeline to support multi-line labels. The active multiplier (e.g., x5) is now rendered prominently above the structure preview icon, with the total cost positioned below.
Screenshot (66)
  • Network & Execution Scalability: Extended UpgradeStructureExecution and the intent schema to process the multiplier in a single, authoritative server loop to prevent packet spam or race conditions.
  • Testing & Standards: Extracted hardcoded UI strings into en.json using translateText(). Ran all formatting/linting tasks and added a comprehensive Vitest suite (UpgradeStructureExecution.test.ts) to assert accurate scaling and safety checks.

Reviewer Testing Steps

  1. Launch the local development server (npm run dev).
  2. Generate sufficient gold to afford bulk upgrades.
  3. Open the Build Menu (Ctrl + Click / Modifier Key), select a structure, and verify the x5/x10/x25/x50 selection panel.
  4. Enter Build Mode via hotkeys (e.g., 1), use the mouse scroll wheel to cycle multipliers, and verify the ghost cursor correctly renders the multiplier above the structure and the cost below.
  5. Access the radial menu on an existing structure and verify the nested bulk-upgrade options function correctly.
  6. Run the test suite via npm test to verify execution logic.

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory

Please put your Discord username so you can be contacted if a bug or regression is found:

DISCORD_USERNAME: ulf (Underscore on both sides)

@CLAassistant

CLAassistant commented Jul 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds stacked structure upgrades with selectable amounts of 1, 5, 10, 25, or 50. The client previews multiplied costs, menus confirm affordable quantities, intents carry the amount, and execution applies upgrades repeatedly until completion or insufficient funds.

Changes

Stacked structure upgrades

Layer / File(s) Summary
Upgrade amount contract and execution
src/core/Schemas.ts, src/client/Transport.ts, src/core/execution/*, tests/core/executions/*
Upgrade intents accept validated amounts, transport forwards them, and execution applies repeated affordable upgrades with full and partial completion tests.
Client multiplier state and preview
src/client/UIState.ts, src/client/InputHandler.ts, src/client/controllers/BuildPreviewController.ts, src/client/render/..., src/client/hud/GameRenderer.ts, tests/InputHandler.test.ts
Ghost selections cycle upgrade multipliers, preview costs scale accordingly, and rendered cost labels show the multiplier.
Upgrade amount selection UI
src/client/hud/layers/*, src/client/view/PlayerView.ts, resources/lang/en.json, tests/client/graphics/RadialMenuElements.test.ts
Build and radial menus offer fixed upgrade quantities, disable unaffordable choices, confirm selections, and use the updated build handler.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Player
  participant BuildMenu
  participant Transport
  participant ExecutionManager
  participant UpgradeStructureExecution
  Player->>BuildMenu: select upgrade amount
  BuildMenu->>Transport: emit upgrade_structure with amount
  Transport->>ExecutionManager: send intent payload
  ExecutionManager->>UpgradeStructureExecution: create amount-bounded execution
  UpgradeStructureExecution->>UpgradeStructureExecution: apply affordable upgrades
Loading

Possibly related PRs

Suggested labels: UI/UX, Feature

Poem

Click once, then five in a row,
Upgrade stacks begin to grow.
Costs appear with x in flight,
Gold keeps every choice in sight.
One intent, many levels bright!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements stack-style multipliers and shortcut-driven upgrade selection, which matches the linked request.
Out of Scope Changes check ✅ Passed The changes stay focused on bulk upgrade UX, rendering, intent handling, and tests with no clear unrelated additions.
Title check ✅ Passed The title matches the main change: adding bulk stack upgrades instead of repeated clicking.
Description check ✅ Passed The description clearly matches the bulk upgrade UI, intent handling, rendering, and tests in the changeset.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/client/hud/layers/BuildMenu.ts`:
- Around line 388-391: Update handleBuildClick and the _selectedUpgradeUnit flow
to store only the selected buildable unit’s stable type or ID, not the full
BuildableUnit snapshot. Before rendering the upgrade panel and confirming the
action, resolve that identifier against the current playerBuildables collection
so cost, target ID, and upgrade state reflect refresh() results.
- Around line 451-453: Route all visible multiplier labels through localization
using translateText() and add the required entry to resources/lang/en.json:
update src/client/hud/layers/BuildMenu.ts lines 451-453 to use the translated
upgrade-amount message; update src/client/hud/layers/RadialMenuElements.ts lines
468-470 to translate both name and text; and in
src/client/render/gl/passes/WorldTextPass.ts lines 355-358, format the
translated label upstream and pass it into the pure rendering pass.

In `@tests/core/executions/UpgradeStructureExecution.test.ts`:
- Around line 9-14: Replace the manual GameImpl and player initialization with
the tests/util/Setup.ts setup() helper at
tests/core/executions/UpgradeStructureExecution.test.ts lines 9-14 and lines
35-40. Update both test cases to obtain their game and player through setup(),
preserving each test’s existing configuration and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5c54526a-bd3a-4e2c-9ca0-0adefd18c8e0

📥 Commits

Reviewing files that changed from the base of the PR and between eee7d79 and 185dfdc.

📒 Files selected for processing (17)
  • resources/lang/en.json
  • src/client/InputHandler.ts
  • src/client/Transport.ts
  • src/client/UIState.ts
  • src/client/controllers/BuildPreviewController.ts
  • src/client/hud/GameRenderer.ts
  • src/client/hud/layers/BuildMenu.ts
  • src/client/hud/layers/RadialMenuElements.ts
  • src/client/render/gl/Renderer.ts
  • src/client/render/gl/passes/WorldTextPass.ts
  • src/client/render/types/Renderer.ts
  • src/client/view/PlayerView.ts
  • src/core/Schemas.ts
  • src/core/execution/ExecutionManager.ts
  • src/core/execution/UpgradeStructureExecution.ts
  • tests/client/graphics/RadialMenuElements.test.ts
  • tests/core/executions/UpgradeStructureExecution.test.ts

Comment thread src/client/hud/layers/BuildMenu.ts
Comment thread src/client/hud/layers/BuildMenu.ts
Comment thread tests/core/executions/UpgradeStructureExecution.test.ts Outdated
@github-project-automation github-project-automation Bot moved this from Triage to Development in OpenFront Release Management Jul 18, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 18, 2026
@U-LF

U-LF commented Jul 22, 2026

Copy link
Copy Markdown
Author

@evanpelle Can you kindly review this

@evanpelle

Copy link
Copy Markdown
Collaborator

CLA assistant check Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.You have signed the CLA already but the status is still pending? Let us recheck it.

mind signing

@evanpelle evanpelle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

a few thoughts:

I'm not sure about the radial menu, as that adds another click/press to upgrade buildings. I wonder if there's a way to avoid like, like instead long press to increase the upgrade amount.

could we also use the same system for atom bombs, since that has been a pain point for a while?

@U-LF

U-LF commented Jul 24, 2026

Copy link
Copy Markdown
Author

CLA assistant check Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.You have signed the CLA already but the status is still pending? Let us recheck it.

mind signing

Damn I missed it 😅, signed now!

@U-LF

U-LF commented Jul 24, 2026

Copy link
Copy Markdown
Author

a few thoughts:

I'm not sure about the radial menu, as that adds another click/press to upgrade buildings. I wonder if there's a way to avoid like, like instead long press to increase the upgrade amount.

could we also use the same system for atom bombs, since that has been a pain point for a while?

I originally wanted to avoid the radial menu myself but then I added it as without it the experience that the feature aims to provide might not be same and consistent for everyone as different users have different play styles and preferences. Long presses can be frustrating to deal with especially in situations where you wanna upgrade quickly.

Yes we should be able to use the same system for atom bombs, at most would just require a few adjustments to the nearest launch site finding algo to support multi launches at the same time. Would you like me to look into this and implement it?

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

Labels

None yet

Projects

Status: Development

Development

Successfully merging this pull request may close these issues.

Buying stacks instead of spam clicking.

3 participants