@@ -1540,30 +1540,18 @@ GameMessage::Type CommandTranslator::evaluateForceAttack( Drawable *draw, const
15401540 return retVal;
15411541}
15421542
1543- // ------------------------------------------------------------------------------------------------
1544- /* * This method and the order of operations in the check here, determine what command would
1545- * actually happen (if type parameter == DO_COMMAND) if the user clicked on the drawable
1546- * 'draw'. If type == DO_HINT, then the user hasn't actually clicked, but has moused over
1547- * the drawable 'draw' and we want to generate a hint message as to what the actual
1548- * command would be if clicked
1549- * NOTE: draw can be null, in which case we give a hint for the location */
1550- // ------------------------------------------------------------------------------------------------
1551- GameMessage::Type CommandTranslator::evaluateContextCommand ( Drawable *draw,
1552- const Coord3D *pos,
1553- CommandEvaluateType type )
1554- {
1555- Object *obj = draw ? draw->getObject () : nullptr ;
1556- Drawable *drawableInWay = draw;
1557-
1543+ // TheSuperHackers @refactor RiQQ 15/5/2026 Extracted from evaluateContextCommand monolith. Preparation for proper refactor
1544+ void CommandTranslator::normalizeContextInputs (Drawable*& draw, Object*& obj, Drawable*& drawableInWay) {
15581545 // This piece of code is used to prevent interaction with unselectable objects or masked objects. When we
15591546 // call this function, we typically pass in both a position and a drawable (if applicable), so if the
15601547 // drawable is invalid... then convert it to a position to be evaluated instead.
15611548 // Added: shrubberies are the exception for interactions...
15621549 // Removed: GS Took out ObjectStatusUnselectable, since that status only prevents selection, not everything
1563- if ( obj == nullptr ||
1564- ( obj->getStatusBits ().test ( OBJECT_STATUS_MASKED ) &&
1565- !obj->isKindOf (KINDOF_SHRUBBERY ) && !obj->isKindOf (KINDOF_FORCEATTACKABLE ) ) )
1566- {
1550+ if ( obj == nullptr ||
1551+ ( obj->getStatusBits ().test ( OBJECT_STATUS_MASKED ) &&
1552+ !obj->isKindOf (KINDOF_SHRUBBERY ) &&
1553+ !obj->isKindOf (KINDOF_FORCEATTACKABLE ) )
1554+ ) {
15671555 // Nulling out the draw and obj pointer will force the remainder of this code to evaluate
15681556 // a position interaction.
15691557 draw = nullptr ;
@@ -1576,116 +1564,137 @@ GameMessage::Type CommandTranslator::evaluateContextCommand( Drawable *draw,
15761564 obj = nullptr ;
15771565 }
15781566
1579- if ( TheInGameUI->isInForceMoveToMode () )
1580- {
1567+ if ( TheInGameUI->isInForceMoveToMode () ) {
15811568 // Nulling out the draw and obj pointer will force the remainder of this code to evaluate
15821569 // a position interaction.
15831570 draw = nullptr ;
15841571 obj = nullptr ;
1585- } else if (TheInGameUI->isInForceAttackMode () ) {
1572+ }
1573+ else if (TheInGameUI->isInForceAttackMode () ) {
15861574 // setting the drawableInWay to draw will allow us to force attack in the issue move command
15871575 // if there is a location to which we should attack.
15881576 drawableInWay = draw;
15891577 }
1578+ }
15901579
1580+ // TheSuperHackers @refactor RiQQ 15/5/2026 Extracted from evaluateContextCommand monolith. Preparation for proper refactor
1581+ GameMessage::Type CommandTranslator::handleWaypointModeCommand (const Coord3D* pos, Drawable* draw, const CommandEvaluateType& type) {
15911582 GameMessage::Type msgType = GameMessage::MSG_INVALID ;
15921583
1584+ // Override any *other* commands with waypoint commands.
1585+ if ( type == DO_COMMAND || type == EVALUATE_ONLY ) {
1586+ if ( TheTerrainLogic ) {
1587+ msgType = issueMoveToLocationCommand ( pos, draw, type );
1588+ }
1589+ }
1590+ else {
1591+ msgType = GameMessage::MSG_ADD_WAYPOINT_HINT ;
1592+ GameMessage* hintMessage = TheMessageStream->appendMessage ( msgType );
1593+ hintMessage->appendLocationArgument ( *pos );
1594+ }
1595+
1596+ return msgType;
1597+ }
1598+
1599+ // TheSuperHackers @refactor RiQQ 15/5/2026 Extracted from evaluateContextCommand monolith. Preparation for proper refactor
1600+ void CommandTranslator::normalizeGuiCommandTarget ( const CommandButton* command, Drawable*& draw, Object*& obj ) {
1601+ if ( obj && obj->isKindOf ( KINDOF_SHRUBBERY ) && !BitIsSet ( command->getOptions (), ALLOW_SHRUBBERY_TARGET ) ) {
1602+ // If our object is a shrubbery, and we don't allow targeting it... then null it out.
1603+ // Nulling out the draw and obj pointer will force the remainder of this code to evaluate
1604+ // a position interaction.
1605+ draw = nullptr ;
1606+ obj = nullptr ;
1607+ }
1608+
1609+ if ( obj && obj->isKindOf ( KINDOF_MINE ) && !BitIsSet ( command->getOptions (), ALLOW_MINE_TARGET ) ) {
1610+ // If our object is a mine, and we don't allow targeting it... then null it out.
1611+ // Nulling out the draw and obj pointer will force the remainder of this code to evaluate
1612+ // a position interaction.
1613+ draw = nullptr ;
1614+ obj = nullptr ;
1615+ }
1616+
1617+ // Kris: September 27, 2002
1618+ // Added relationship tests to make sure we're not attempting a context-command on a restricted relationship.
1619+ // This case prevents rebels from using tranq darts on allies.
1620+ if ( obj && BitIsSet ( command->getOptions (), COMMAND_OPTION_NEED_OBJECT_TARGET ) ) {
1621+ Relationship relationship = ThePlayerList->getLocalPlayer ()->getRelationship ( obj->getTeam () );
1622+
1623+ switch ( relationship ) {
1624+ case ALLIES :
1625+ if ( !BitIsSet ( command->getOptions (), NEED_TARGET_ALLY_OBJECT ) ) {
1626+ draw = nullptr ;
1627+ obj = nullptr ;
1628+ }
1629+ break ;
1630+ case ENEMIES :
1631+ if ( !BitIsSet ( command->getOptions (), NEED_TARGET_ENEMY_OBJECT ) ) {
1632+ draw = nullptr ;
1633+ obj = nullptr ;
1634+ }
1635+ break ;
1636+ case NEUTRAL :
1637+ if ( !BitIsSet ( command->getOptions (), NEED_TARGET_NEUTRAL_OBJECT ) ) {
1638+ draw = nullptr ;
1639+ obj = nullptr ;
1640+ }
1641+ break ;
1642+ }
1643+ }
1644+ }
1645+
1646+ // ------------------------------------------------------------------------------------------------
1647+ /* * This method and the order of operations in the check here, determine what command would
1648+ * actually happen (if type parameter == DO_COMMAND) if the user clicked on the drawable
1649+ * 'draw'. If type == DO_HINT, then the user hasn't actually clicked, but has moused over
1650+ * the drawable 'draw' and we want to generate a hint message as to what the actual
1651+ * command would be if clicked
1652+ * NOTE: draw can be null, in which case we give a hint for the location */
1653+ // ------------------------------------------------------------------------------------------------
1654+ GameMessage::Type CommandTranslator::evaluateContextCommand (
1655+ Drawable *draw,
1656+ const Coord3D *pos,
1657+ CommandEvaluateType type
1658+ ) {
1659+ Object *obj = draw ? draw->getObject () : nullptr ;
1660+ Drawable *drawableInWay = draw;
1661+ normalizeContextInputs (draw, obj, drawableInWay);
1662+
15931663 // Then we should determine if the game currently prefers selection events. If it does, then return
15941664 // the invalid message.
1595- if (obj) {
1596- if (obj->isLocallyControlled () && TheInGameUI->isInPreferSelectionMode ()) {
1597- return msgType;
1598- }
1665+ if (obj && obj->isLocallyControlled () && TheInGameUI->isInPreferSelectionMode ()) {
1666+ return GameMessage::MSG_INVALID ;
15991667 }
16001668
16011669 // Kris: Now that we can select non-controllable units/structures, don't allow any actions to be performed.
16021670 const CommandButton *command = TheInGameUI->getGUICommand ();
1671+ GameMessage::Type msgType = GameMessage::MSG_INVALID ;
16031672
1604- if (command && command->getCommandType () == GUICOMMANDMODE_PLACE_BEACON )
1605- {
1673+ if (command && command->getCommandType () == GUICOMMANDMODE_PLACE_BEACON ) {
16061674 msgType = GameMessage::MSG_VALID_GUICOMMAND_HINT ;
16071675 TheMessageStream->appendMessage (msgType);
1676+ return msgType;
1677+ }
1678+
1679+ const bool canPerformActions = (
1680+ TheInGameUI->areSelectedObjectsControllable () ||
1681+ (command && command->getCommandType () == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT )
1682+ );
1683+ if ( !canPerformActions ) {
1684+ return GameMessage::MSG_INVALID ;
16081685 }
1609- else if ( TheInGameUI->areSelectedObjectsControllable ()
1610- || (command && command->getCommandType () == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT ))
1611- {
1612- GameMessage *hintMessage;
16131686
1614- if ( TheInGameUI->isInWaypointMode () )
1615- {
1616- // Override any *other* commands with waypoint commands.
1617- if ( type == DO_COMMAND || type == EVALUATE_ONLY )
1618- {
1619- if ( TheTerrainLogic )
1620- {
1621- msgType = issueMoveToLocationCommand ( pos, draw, type );
1622- }
1623- }
1624- else
1625- {
1626- msgType = GameMessage::MSG_ADD_WAYPOINT_HINT ;
1627- hintMessage = TheMessageStream->appendMessage ( msgType );
1628- hintMessage->appendLocationArgument ( *pos );
1687+ {
1688+ if ( TheInGameUI->isInWaypointMode () ) {
1689+ msgType = handleWaypointModeCommand (pos, draw, type);
1690+ if (msgType != GameMessage::MSG_INVALID ) {
1691+ return msgType;
16291692 }
1630- return msgType;
16311693 }
16321694
16331695 CanAttackResult result;
1696+ GameMessage *hintMessage;
16341697
1635- if (command &&
1636- (command->isContextCommand ()
1637- || command->getCommandType () == GUI_COMMAND_SPECIAL_POWER
1638- || command->getCommandType () == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT ))
1639- {
1640- if ( obj && obj->isKindOf ( KINDOF_SHRUBBERY ) && !BitIsSet ( command->getOptions (), ALLOW_SHRUBBERY_TARGET ) )
1641- {
1642- // If our object is a shrubbery, and we don't allow targeting it... then null it out.
1643- // Nulling out the draw and obj pointer will force the remainder of this code to evaluate
1644- // a position interaction.
1645- draw = nullptr ;
1646- obj = nullptr ;
1647- }
1648-
1649- if ( obj && obj->isKindOf ( KINDOF_MINE ) && !BitIsSet ( command->getOptions (), ALLOW_MINE_TARGET ) )
1650- {
1651- // If our object is a mine, and we don't allow targeting it... then null it out.
1652- // Nulling out the draw and obj pointer will force the remainder of this code to evaluate
1653- // a position interaction.
1654- draw = nullptr ;
1655- obj = nullptr ;
1656- }
1657-
1658- // Kris: September 27, 2002
1659- // Added relationship tests to make sure we're not attempting a context-command on a restricted relationship.
1660- // This case prevents rebels from using tranq darts on allies.
1661- if ( obj && BitIsSet ( command->getOptions (), COMMAND_OPTION_NEED_OBJECT_TARGET ) )
1662- {
1663- Relationship relationship = ThePlayerList->getLocalPlayer ()->getRelationship ( obj->getTeam () );
1664- switch ( relationship )
1665- {
1666- case ALLIES :
1667- if ( !BitIsSet ( command->getOptions (), NEED_TARGET_ALLY_OBJECT ) )
1668- {
1669- draw = nullptr ;
1670- obj = nullptr ;
1671- }
1672- break ;
1673- case ENEMIES :
1674- if ( !BitIsSet ( command->getOptions (), NEED_TARGET_ENEMY_OBJECT ) )
1675- {
1676- draw = nullptr ;
1677- obj = nullptr ;
1678- }
1679- break ;
1680- case NEUTRAL :
1681- if ( !BitIsSet ( command->getOptions (), NEED_TARGET_NEUTRAL_OBJECT ) )
1682- {
1683- draw = nullptr ;
1684- obj = nullptr ;
1685- }
1686- break ;
1687- }
1688- }
16891698
16901699 Bool currentlyValid = FALSE ;
16911700 ObjectID objectID = obj ? obj->getID () : INVALID_ID ;
0 commit comments