Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Core/GameEngine/Include/GameClient/SelectionXlat.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class SelectionTranslator : public GameMessageTranslator
friend Bool killThemKillThemAllWrapper( Drawable *draw, void *userData );
private:

Bool m_pendingDeselection;
Bool m_leftMouseButtonIsDown;
Bool m_dragSelecting;
UnsignedInt m_lastGroupSelTime;
Expand Down
14 changes: 7 additions & 7 deletions Core/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,7 @@ GameMessage::Type CommandTranslator::issueSpecialPowerCommand( const CommandButt
if( spUpdate )
{
//Deselect the drawables before posting the selection message.
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);

//Because we just launched a special power via shortcut, and the special power accepts input
//from the player (particle uplink cannon, spectre gunship), simply select the object now.
Expand Down Expand Up @@ -2585,7 +2585,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
if(newDrawable != nullptr )
{
//deselect other units
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);

// create a new group.
GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP );
Expand Down Expand Up @@ -2701,7 +2701,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
if(newDrawable != nullptr )
{
//deselect other units
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);
// select the unit

// create a new group.
Expand Down Expand Up @@ -2814,7 +2814,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
if(newDrawable != nullptr )
{
//deselect other units
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);

// select the unit
// create a new group.
Expand Down Expand Up @@ -2929,7 +2929,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
if(newDrawable != nullptr )
{
//deselect other units
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);
// select the unit

// create a new group.
Expand Down Expand Up @@ -2982,7 +2982,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
if ( heroDraw == nullptr )
break;

TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);

// create a new group.
GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP );
Expand Down Expand Up @@ -3067,7 +3067,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage


/*
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);

GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP );
// creating a new team so pass in true
Expand Down
45 changes: 23 additions & 22 deletions Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,6 @@ static Bool canSelectWrapper( Drawable *draw, void *userData )
return CanSelectDrawable( draw, dragSelecting );
}

//-----------------------------------------------------------------------------
/**
* Deselect all drawables, and emit a "TEAM_DESTROY" message, since
* the "team" was the group of currently selected units.
*/
static void deselectAll()
{

// deselect it all
TheInGameUI->deselectAllDrawables();
}

//-----------------------------------------------------------------------------
/**
* Select the given drawable, without playing its sound.
Expand All @@ -230,14 +218,14 @@ static void deselectAll()
static Bool selectSingleDrawableWithoutSound( Drawable *draw )
{

// since we are single selecting a drawable, unselect everything else
deselectAll();

// do the drawable selection
TheInGameUI->selectDrawable( draw );

Object *obj = draw->getObject();
if (obj != nullptr) {
// since we are single selecting a drawable, unselect everything else
TheInGameUI->deselectAllDrawables(FALSE);

// do the drawable selection
TheInGameUI->selectDrawable(draw);

GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_CREATE_SELECTED_GROUP_NO_SOUND);
msg->appendBooleanArgument(TRUE);
msg->appendObjectIDArgument(obj->getID());
Expand All @@ -255,6 +243,7 @@ SelectionTranslator *TheSelectionTranslator = nullptr;
//-----------------------------------------------------------------------------
SelectionTranslator::SelectionTranslator()
{
m_pendingDeselection = FALSE;
m_leftMouseButtonIsDown = FALSE;
m_dragSelecting = FALSE;
m_lastGroupSelTime = 0;
Expand Down Expand Up @@ -409,6 +398,15 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa
case GameMessage::MSG_MOUSE_LEFT_CLICK:
{
disp = onMouseLeftClick(msg);

// TheSuperHackers @tweak Avoid double deselection when selecting a new object with another object selected,
// originally triggered by RAW_MOUSE_LEFT_BUTTON_UP and MOUSE_LEFT_CLICK, respectively.
if (m_pendingDeselection)
{
m_pendingDeselection = FALSE;
TheInGameUI->deselectAllDrawables();
}

break;
}
// Note that the raw left messages are only used to draw feedback now when
Expand Down Expand Up @@ -895,7 +893,8 @@ GameMessageDisposition SelectionTranslator::onMouseLeftClick(MAYBE_UNUSED const
{
if (!addToGroup)
{
deselectAll();
m_pendingDeselection = FALSE;
TheInGameUI->deselectAllDrawables(FALSE);
}

GameMessage *newMsg = TheMessageStream->appendMessage(GameMessage::MSG_CREATE_SELECTED_GROUP);
Expand Down Expand Up @@ -1065,7 +1064,7 @@ GameMessageDisposition SelectionTranslator::onRawMouseLeftButtonUp(MAYBE_UNUSED
{
if( !TheInGameUI->getPreventLeftClickDeselectionInAlternateMouseModeForOneClick() )
{
deselectAll();
m_pendingDeselection = TRUE;
m_lastGroupSelGroup = -1;
}
else
Expand Down Expand Up @@ -1131,7 +1130,7 @@ GameMessageDisposition SelectionTranslator::onRawMouseRightButtonUp(MAYBE_UNUSED
else if (!TheGlobalData->m_useAlternateMouse)
{
//No GUI command mode, so deselect everyone if we're in regular mouse mode.
deselectAll();
TheInGameUI->deselectAllDrawables();
}
}
}
Expand Down Expand Up @@ -1270,6 +1269,7 @@ GameMessageDisposition SelectionTranslator::onMetaAddTeam(MAYBE_UNUSED const Gam
}
else
{
Bool deselectedAllDrawables = FALSE;

Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
if( draw && draw->isKindOf( KINDOF_STRUCTURE ) )
Expand All @@ -1278,6 +1278,7 @@ GameMessageDisposition SelectionTranslator::onMetaAddTeam(MAYBE_UNUSED const Gam
//Can't select other units if you have a structure selected. So deselect the structure to prevent
//group force attack exploit.
TheInGameUI->deselectAllDrawables();
deselectedAllDrawables = TRUE;
}

// no need to send two messages for selecting the same group.
Expand All @@ -1292,7 +1293,7 @@ GameMessageDisposition SelectionTranslator::onMetaAddTeam(MAYBE_UNUSED const Gam
Int numObjs = objlist.size();

// TheSuperHackers @bugfix skyaero 22/07/2025 Can't select other units if you have a structure selected. So deselect the structure to prevent group force attack exploit.
if (numObjs > 0 && objlist[0]->getDrawable()->isKindOf(KINDOF_STRUCTURE))
if (!deselectedAllDrawables && numObjs > 0 && objlist[0]->getDrawable()->isKindOf(KINDOF_STRUCTURE))
{
TheInGameUI->deselectAllDrawables();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData )
if (currentlySelectedGroup && TheRecorder->isPlaybackMode() && TheGlobalData->m_useCameraInReplay && TheControlBar->getObserverLookAtPlayer() == msgPlayer /*&& !TheRecorder->isMultiplayer()*/)
{
const VecObjectID& selectedObjects = currentlySelectedGroup->getAllIDs();
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);
for (VecObjectID::const_iterator it = selectedObjects.begin(); it != selectedObjects.end(); ++it)
{
const Object *obj = findObjectByID(*it);
Expand Down
2 changes: 1 addition & 1 deletion GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ friend class Drawable; // for selection/deselection transactions
// Drawable selection mechanisms
virtual void selectDrawable( Drawable *draw ); ///< Mark given Drawable as "selected"
virtual void deselectDrawable( Drawable *draw ); ///< Clear "selected" status from Drawable
virtual void deselectAllDrawables( Bool postMsg = true ); ///< Clear the "select" flag from all drawables
virtual void deselectAllDrawables( Bool updateGameLogic = true ); ///< Clear the "select" flag from all drawables
virtual Int getSelectCount() { return m_selectCount; } ///< Get count of currently selected drawables
virtual Int getMaxSelectCount() { return m_maxSelectCount; } ///< Get the max number of selected drawables
virtual UnsignedInt getFrameSelectionChanged() { return m_frameSelectionChanged; } ///< Get the max number of selected drawables
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
}

//deselect other units
TheInGameUI->deselectAllDrawables();
TheInGameUI->deselectAllDrawables(FALSE);

// create a new group.
GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP );
Expand Down
21 changes: 10 additions & 11 deletions GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3563,9 +3563,10 @@ void InGameUI::deselectDrawable( Drawable *draw )
//-------------------------------------------------------------------------------------------------
/** Clear all drawables' "select" status */
//-------------------------------------------------------------------------------------------------
void InGameUI::deselectAllDrawables( Bool postMsg )
void InGameUI::deselectAllDrawables( Bool updateGameLogic )
Comment thread
xezon marked this conversation as resolved.
{
const DrawableList *selected = getAllSelectedDrawables();
const Bool hadSelectedDrawables = !selected->empty();

// loop through all the selected drawables
for ( DrawableListCIt it = selected->begin(); it != selected->end(); )
Expand All @@ -3586,16 +3587,14 @@ void InGameUI::deselectAllDrawables( Bool postMsg )
// our selection can no longer consist of exactly one angry mob
m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID;


///@todo don't we want to not emit this message if there wasn't a group at all? (CBD)
/** @todo also, we probably are sending this message too much, we should come up with
some kind of "selections are dirty" status that we can check once per frame and send
the correct group info over the network ... could be tricky tho (or impossible) given
the order of operations of things happening in the code (CBD) */
if( postMsg )
if (updateGameLogic)
{
// TheSuperHackers @tweak Originally this message had one boolean argument, but it wasn't used for anything.
TheMessageStream->appendMessage( GameMessage::MSG_DESTROY_SELECTED_GROUP );
// TheSuperHackers @tweak Only send this message when objects were previously selected.
if (hadSelectedDrawables)
{
// TheSuperHackers @tweak Originally this message had one boolean argument, but it wasn't used for anything.
TheMessageStream->appendMessage(GameMessage::MSG_DESTROY_SELECTED_GROUP);
}
}
}

Expand Down Expand Up @@ -5897,7 +5896,7 @@ void InGameUI::selectNextIdleWorker()
if(selectThisObject)
{
DEBUG_ASSERTCRASH(selectThisObject->getContainedBy() == nullptr, ("InGameUI::selectNextIdleWorker Selected idle object should not be contained"));
deselectAllDrawables();
deselectAllDrawables(FALSE);
GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP );


Expand Down
Loading