Skip to content

bugfix: The KINDOF_NO_SELECT flag now prevents an object from being selected - #3125

Open
Stubbjax wants to merge 1 commit into
TheSuperHackers:mainfrom
Stubbjax:fix-no-select-flag
Open

bugfix: The KINDOF_NO_SELECT flag now prevents an object from being selected#3125
Stubbjax wants to merge 1 commit into
TheSuperHackers:mainfrom
Stubbjax:fix-no-select-flag

Conversation

@Stubbjax

Copy link
Copy Markdown

This change corrects object selection logic so that KINDOF_NO_SELECT now prevents an object from being selected as expected. It was originally only used when selecting previous/next units.

As a result, existing objects that define NO_SELECT in their KindOf field are no longer selectable, but can be still attacked. This already applies to all USA Drones (including the Spy Drone), though vehicle drones are masked via a different process and thus the flag made no difference. The only other object affected by this change is the emerging Sneak Attack, which will require a data change if undesirable.

@Stubbjax Stubbjax self-assigned this Aug 13, 2026
@Stubbjax Stubbjax added Bug Something is not working right, typically is user facing Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour labels Aug 13, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix selection gating: KINDOF_NO_SELECT now blocks object selection

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Apply KINDOF_NO_SELECT in Object::isSelectable() so flagged objects cannot be selected.
• Replace the previous KINDOF_DRONE-based exception with the correct, explicit NO_SELECT semantic.
• Align Generals and GeneralsMD selection logic so click/box selection matches prev/next-unit
 selection rules.
Diagram

graph TD
  UI["Player selection input"] --> SEL["Object::isSelectable()"] --> ALWAYS{"Always selectable?"}
  ALWAYS -->|"Yes"| ALLOW["Allow selection"] --> OUT["UI selection result"]
  ALWAYS -->|"No"| BASE{"Base checks pass?"}
  BASE -->|"No"| BLOCK["Block selection"] --> OUT
  BASE -->|"Yes"| NOSEL{"Has NO_SELECT?"}
  NOSEL -->|"Yes"| BLOCK --> OUT
  NOSEL -->|"No"| ALLOW --> OUT
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Preserve legacy drone-only gate (NO_SELECT || DRONE)
  • ➕ Minimizes behavior changes for any content relying on KINDOF_DRONE rather than KINDOF_NO_SELECT.
  • ➕ Reduces risk of unintentionally making previously-selectable drones selectable if data differs across mods.
  • ➖ Continues conflating drone-ness with selectability, which the engine already models explicitly via KINDOF_NO_SELECT.
  • ➖ Makes it harder to use KINDOF_NO_SELECT for non-drone cases (e.g., emerging/placeholder objects) as the single source of truth.
2. Enforce NO_SELECT only at UI selection handlers (not in Object::isSelectable)
  • ➕ Limits impact to direct user selection while leaving other selection-like flows untouched if they have special needs.
  • ➖ Reintroduces inconsistency: other systems that call Object::isSelectable() would still allow selection in some contexts.
  • ➖ Splits selection policy across layers, increasing long-term maintenance risk.

Recommendation: Keep the current approach: enforcing KINDOF_NO_SELECT inside Object::isSelectable() centralizes selection policy and makes NO_SELECT behave consistently across selection entrypoints. If specific units (e.g., Spy Drone or Sneak Attack emergence) should remain selectable, prefer adjusting their template KindOf (or adding KINDOF_ALWAYS_SELECTABLE) rather than weakening the core predicate.

Files changed (2) +3 / -3

Bug fix (2) +3 / -3
Object.cppUse KINDOF_NO_SELECT to gate Object::isSelectable() +1/-1

Use KINDOF_NO_SELECT to gate Object::isSelectable()

• Updates the core selection predicate to block selection for templates marked KINDOF_NO_SELECT. Replaces the previous KINDOF_DRONE-based exclusion so selection policy matches the explicit NO_SELECT semantic.

Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp

Object.cppAlign Zero Hour Object::isSelectable() with KINDOF_NO_SELECT semantics +2/-2

Align Zero Hour Object::isSelectable() with KINDOF_NO_SELECT semantics

• Switches the nested selection checks to use KINDOF_NO_SELECT (and updates the commented reference) so NO_SELECT-tagged objects cannot be selected. Keeps the existing control-flow structure while correcting the gating condition.

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

if ( !testStatus(OBJECT_STATUS_UNSELECTABLE) )
if ( !isEffectivelyDead() )
//if ( !getTemplate()->isKindOf(KINDOF_DRONE) )//Most drones are unselectable from being slaved, but the SpyDrone needs help
if ( !getTemplate()->isKindOf(KINDOF_NO_SELECT) )

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems silly but is this safe for retail compatibility? I kind of doubt it. Selection is synchronized across clients and the AIGroup is part of the CRC.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It probably depends whether this function is called in logical context or purely in client side selection (mouse and keyboard).

@Caball009 Caball009 Aug 13, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I checked and selecting your own spy drone and trying to move it causes a mismatch between builds that have this change and ones that don't.

This will need to go behind the retail compatibility macro.

@Caball009 Caball009 added the NoRetail This fix or change is not applicable with Retail game compatibility label Aug 13, 2026

@Skyaero42 Skyaero42 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I tested this against a number of replays and as @Caball009 suspected, it does mismatch.
Hence it needs to be behind RETAIL_CRC guards.

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

Labels

Bug Something is not working right, typically is user facing Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker NoRetail This fix or change is not applicable with Retail game compatibility ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants