Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,514 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FILE: GUICommandTranslator.cpp /////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, March 2002
|
||||
// Desc: Translator for commands activated from the selection GUI, such as special unit
|
||||
// actions, that require additional clicks in the world like selecting a target
|
||||
// object or location
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/ActionManager.h"
|
||||
#include "Common/GameCommon.h"
|
||||
#include "Common/GameAudio.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/SpecialPower.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "Common/Geometry.h"
|
||||
#include "GameClient/GUICommandTranslator.h"
|
||||
#include "GameClient/CommandXlat.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// PRIVATE ////////////////////////////////////////////////////////////////////////////////////////
|
||||
static enum CommandStatus
|
||||
{
|
||||
COMMAND_INCOMPLETE = 0,
|
||||
COMMAND_COMPLETE
|
||||
};
|
||||
|
||||
// PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PickAndPlayInfo::PickAndPlayInfo()
|
||||
{
|
||||
m_air = FALSE;
|
||||
m_drawTarget = NULL;
|
||||
m_weaponSlot = NULL;
|
||||
m_specialPowerType = SPECIAL_INVALID;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GUICommandTranslator::GUICommandTranslator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GUICommandTranslator::~GUICommandTranslator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Is the object under the mouse position a valid target for the command */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static Object *validUnderCursor( const ICoord2D *mouse, const CommandButton *command, PickType pickType )
|
||||
{
|
||||
Object *pickObj = NULL;
|
||||
|
||||
// pick a drawable at the mouse location
|
||||
Drawable *pick = TheTacticalView->pickDrawable( mouse, FALSE, pickType );
|
||||
|
||||
// only continue if there is something there
|
||||
if( pick && pick->getObject() )
|
||||
{
|
||||
Player *player = ThePlayerList->getLocalPlayer();
|
||||
|
||||
// get object we picked
|
||||
pickObj = pick->getObject();
|
||||
|
||||
if (!command->isValidObjectTarget(player, pickObj))
|
||||
pickObj = NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
|
||||
return pickObj;
|
||||
|
||||
} // end validUnderCursor
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static CommandStatus doFireWeaponCommand( const CommandButton *command, const ICoord2D *mouse )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( command == NULL || mouse == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
//
|
||||
// for single object selections get the source ID and sanity check for illegal object and
|
||||
// bail along the way
|
||||
//
|
||||
ObjectID sourceID = INVALID_ID;
|
||||
if( TheInGameUI->getSelectCount() == 1 )
|
||||
{
|
||||
Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
|
||||
|
||||
// sanity
|
||||
if( draw == NULL || draw->getObject() == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
// get object id
|
||||
sourceID = draw->getObject()->getID();
|
||||
|
||||
} // end if
|
||||
|
||||
// create message and send to the logic
|
||||
GameMessage *msg;
|
||||
if( BitTest( command->getOptions(), NEED_TARGET_POS ) )
|
||||
{
|
||||
Coord3D world;
|
||||
|
||||
// translate the mouse location into world coords
|
||||
TheTacticalView->screenToTerrain( mouse, &world );
|
||||
|
||||
// create the message and append arguments
|
||||
msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_WEAPON_AT_LOCATION );
|
||||
msg->appendIntegerArgument( command->getWeaponSlot() );
|
||||
msg->appendLocationArgument( world );
|
||||
msg->appendIntegerArgument( command->getMaxShotsToFire() );
|
||||
|
||||
//Also append the object ID (incase weapon doesn't like obstacles on land).
|
||||
Object *target = validUnderCursor( mouse, command, PICK_TYPE_SELECTABLE );
|
||||
ObjectID targetID = target ? target->getID() : INVALID_ID;
|
||||
msg->appendObjectIDArgument( targetID );
|
||||
|
||||
|
||||
} // end if
|
||||
else if( BitTest( command->getOptions(), COMMAND_OPTION_NEED_OBJECT_TARGET ) )
|
||||
{
|
||||
|
||||
// setup the pick type ... some commands allow us to target shrubbery
|
||||
PickType pickType = PICK_TYPE_SELECTABLE;
|
||||
|
||||
if( BitTest( command->getOptions(), ALLOW_SHRUBBERY_TARGET ) == TRUE )
|
||||
pickType = (PickType)((Int)pickType | (Int)PICK_TYPE_SHRUBBERY);
|
||||
|
||||
if( BitTest( command->getOptions(), ALLOW_MINE_TARGET ) == TRUE )
|
||||
pickType = (PickType)((Int)pickType | (Int)PICK_TYPE_MINES);
|
||||
|
||||
// get the target object under the cursor
|
||||
Object *target = validUnderCursor( mouse, command, pickType );
|
||||
|
||||
// only continue if the object meets all the command criteria
|
||||
if( target )
|
||||
{
|
||||
|
||||
msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_WEAPON_AT_OBJECT );
|
||||
msg->appendIntegerArgument( command->getWeaponSlot() );
|
||||
msg->appendObjectIDArgument( target->getID() );
|
||||
msg->appendIntegerArgument( command->getMaxShotsToFire() );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end else
|
||||
else
|
||||
{
|
||||
msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_WEAPON );
|
||||
msg->appendIntegerArgument( command->getWeaponSlot() );
|
||||
msg->appendIntegerArgument( command->getMaxShotsToFire() );
|
||||
|
||||
//This could be legit now -- think of firing a self destruct weapon
|
||||
//-----------------------------------------------------------------
|
||||
//DEBUG_ASSERTCRASH( 0, ("doFireWeaponCommand: Command options say it doesn't need additional user input '%s'\n",
|
||||
// command->m_name.str()) );
|
||||
//return COMMAND_COMPLETE;
|
||||
|
||||
} // end else
|
||||
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
} // end fire weapon
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static CommandStatus doGuardCommand( const CommandButton *command, GuardMode guardMode, const ICoord2D *mouse )
|
||||
{
|
||||
// sanity
|
||||
if( command == NULL || mouse == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
if( TheInGameUI->getSelectCount() == 0 )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
GameMessage *msg = NULL;
|
||||
|
||||
if ( msg == NULL && BitTest( command->getOptions(), COMMAND_OPTION_NEED_OBJECT_TARGET ) )
|
||||
{
|
||||
// get the target object under the cursor
|
||||
Object* target = validUnderCursor( mouse, command, PICK_TYPE_SELECTABLE );
|
||||
if( target )
|
||||
{
|
||||
msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_GUARD_OBJECT );
|
||||
msg->appendObjectIDArgument( target->getID() );
|
||||
msg->appendIntegerArgument(guardMode);
|
||||
pickAndPlayUnitVoiceResponse(TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_DO_GUARD_OBJECT);
|
||||
}
|
||||
}
|
||||
|
||||
if( msg == NULL )
|
||||
{
|
||||
Coord3D world;
|
||||
if (BitTest( command->getOptions(), NEED_TARGET_POS ))
|
||||
{
|
||||
// translate the mouse location into world coords
|
||||
TheTacticalView->screenToTerrain( mouse, &world );
|
||||
}
|
||||
else
|
||||
{
|
||||
Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
|
||||
if( draw == NULL || draw->getObject() == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
world = *draw->getObject()->getPosition();
|
||||
}
|
||||
|
||||
// create the message and append arguments
|
||||
msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_GUARD_POSITION );
|
||||
msg->appendLocationArgument(world);
|
||||
msg->appendIntegerArgument(guardMode);
|
||||
pickAndPlayUnitVoiceResponse(TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_DO_GUARD_POSITION);
|
||||
}
|
||||
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Do the set rally point command */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static CommandStatus doAttackMoveCommand( const CommandButton *command, const ICoord2D *mouse )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( command == NULL || mouse == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
//
|
||||
// we can only set rally points for structures ... and we never multiple select structures
|
||||
// so we must be sure there is only one thing selected (that thing we will set the point on)
|
||||
//
|
||||
Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
|
||||
DEBUG_ASSERTCRASH( draw, ("doAttackMoveCommand: No selected object(s)\n") );
|
||||
|
||||
// sanity
|
||||
if( draw == NULL || draw->getObject() == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
// convert mouse point to world coords
|
||||
Coord3D world;
|
||||
TheTacticalView->screenToTerrain( mouse, &world );
|
||||
|
||||
// send the message to set the rally point
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_ATTACKMOVETO );
|
||||
msg->appendLocationArgument( world );
|
||||
|
||||
// Play the unit voice response
|
||||
pickAndPlayUnitVoiceResponse(TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_DO_ATTACKMOVETO);
|
||||
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Do the set rally point command */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static CommandStatus doSetRallyPointCommand( const CommandButton *command, const ICoord2D *mouse )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( command == NULL || mouse == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
//
|
||||
// we can only set rally points for structures ... and we never multiple select structures
|
||||
// so we must be sure there is only one thing selected (that thing we will set the point on)
|
||||
//
|
||||
DEBUG_ASSERTCRASH( TheInGameUI->getSelectCount() == 1,
|
||||
("doSetRallyPointCommand: The selected count is not 1, we can only set a rally point on a *SINGLE* building\n") );
|
||||
Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
|
||||
DEBUG_ASSERTCRASH( draw, ("doSetRallyPointCommand: No selected object\n") );
|
||||
|
||||
// sanity
|
||||
if( draw == NULL || draw->getObject() == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
// convert mouse point to world coords
|
||||
Coord3D world;
|
||||
TheTacticalView->screenToTerrain( mouse, &world );
|
||||
|
||||
// send the message to set the rally point
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_SET_RALLY_POINT );
|
||||
msg->appendObjectIDArgument( draw->getObject()->getID() );
|
||||
msg->appendLocationArgument( world );
|
||||
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
} // end doSetRallyPointCommand
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Do the beacon placement command */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static CommandStatus doPlaceBeacon( const CommandButton *command, const ICoord2D *mouse )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( command == NULL || mouse == NULL )
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
// convert mouse point to world coords
|
||||
Coord3D world;
|
||||
TheTacticalView->screenToTerrain( mouse, &world );
|
||||
|
||||
// send the message to set the rally point
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_PLACE_BEACON );
|
||||
msg->appendLocationArgument( world );
|
||||
|
||||
return COMMAND_COMPLETE;
|
||||
|
||||
} // end doPlaceBeacon
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GameMessageDisposition GUICommandTranslator::translateGameMessage(const GameMessage *msg)
|
||||
{
|
||||
GameMessageDisposition disp = KEEP_MESSAGE;
|
||||
|
||||
// only pay attention to clicks in this translator if there is a pending GUI command
|
||||
const CommandButton *command = TheInGameUI->getGUICommand();
|
||||
if( command == NULL )
|
||||
return disp;
|
||||
|
||||
switch( msg->getType() )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN:
|
||||
{
|
||||
|
||||
//
|
||||
//
|
||||
// it is necessary to use this input when there is a pending gui command, we don't wan't
|
||||
// it to fall through to the rest of the system when we're in pending gui command "mode"
|
||||
// because things like selection rectangles will start when we want to stay totally
|
||||
// within the gui command "mode" here
|
||||
//
|
||||
disp = DESTROY_MESSAGE;
|
||||
|
||||
break;
|
||||
|
||||
} // end left mouse down
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GameMessage::MSG_MOUSE_LEFT_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_MOUSE_LEFT_CLICK:
|
||||
{
|
||||
CommandStatus commandStatus = COMMAND_COMPLETE;
|
||||
ICoord2D mouse = msg->getArgument(0)->pixelRegion.hi;
|
||||
|
||||
// do the command action
|
||||
if( command && !command->isContextCommand() )
|
||||
{
|
||||
switch( command->getCommandType() )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_FIRE_WEAPON:
|
||||
{
|
||||
commandStatus = doFireWeaponCommand( command, &mouse );
|
||||
|
||||
PickAndPlayInfo info;
|
||||
WeaponSlotType slot = command->getWeaponSlot();
|
||||
info.m_weaponSlot = &slot;
|
||||
|
||||
pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_DO_WEAPON_AT_LOCATION, &info );
|
||||
break;
|
||||
|
||||
} // end fire weapon command
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_EVACUATE:
|
||||
{
|
||||
if (BitTest(command->getOptions(), NEED_TARGET_POS)) {
|
||||
Coord3D worldPos;
|
||||
|
||||
TheTacticalView->screenToTerrain(&mouse, &worldPos);
|
||||
|
||||
GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_EVACUATE);
|
||||
msg->appendLocationArgument(worldPos);
|
||||
|
||||
pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_EVACUATE );
|
||||
|
||||
commandStatus = COMMAND_COMPLETE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_GUARD:
|
||||
{
|
||||
commandStatus = doGuardCommand( command, GUARDMODE_NORMAL, &mouse );
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_GUARD_WITHOUT_PURSUIT:
|
||||
{
|
||||
commandStatus = doGuardCommand( command, GUARDMODE_GUARD_WITHOUT_PURSUIT, &mouse );
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_GUARD_FLYING_UNITS_ONLY:
|
||||
{
|
||||
commandStatus = doGuardCommand( command, GUARDMODE_GUARD_FLYING_UNITS_ONLY, &mouse );
|
||||
break;
|
||||
}
|
||||
|
||||
//Special weapons are now always context commands...
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_SPECIAL_POWER:
|
||||
case GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER:
|
||||
{
|
||||
return KEEP_MESSAGE;
|
||||
break;
|
||||
|
||||
} // end special power
|
||||
|
||||
case GUI_COMMAND_ATTACK_MOVE:
|
||||
{
|
||||
commandStatus = doAttackMoveCommand( command, &mouse );
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_SET_RALLY_POINT:
|
||||
{
|
||||
commandStatus = doSetRallyPointCommand( command, &mouse );
|
||||
break;
|
||||
|
||||
} // end set rally point
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
case GUICOMMANDMODE_PLACE_BEACON:
|
||||
{
|
||||
commandStatus = doPlaceBeacon( command, &mouse );
|
||||
break;
|
||||
|
||||
} // end set rally point
|
||||
|
||||
} // end switch
|
||||
|
||||
// used the input
|
||||
disp = DESTROY_MESSAGE;
|
||||
|
||||
// get out of GUI command mode if we completed the command one way or another
|
||||
if( commandStatus == COMMAND_COMPLETE )
|
||||
TheInGameUI->setGUICommand( NULL );
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end left mouse up
|
||||
|
||||
} // end switch
|
||||
|
||||
// If we're destroying the message, it means we used it. Therefore, destroy the current
|
||||
// attack move instruction as well.
|
||||
if (disp == DESTROY_MESSAGE)
|
||||
TheInGameUI->clearAttackMoveToMode();
|
||||
|
||||
|
||||
return disp;
|
||||
|
||||
} // end translateMessage
|
||||
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// HintSpy.cpp
|
||||
// The HintSpy sits on the message stream and watches for certain messages,
|
||||
// for which it then generates visual "hints".
|
||||
// Author: Michael S. Booth, March 2001
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/MessageStream.h"
|
||||
#include "GameClient/HintSpy.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
/**
|
||||
* This message handler displays UI "hints" (ie: a rectangle for drag selection) based
|
||||
* upon the messages that pass through it.
|
||||
*/
|
||||
GameMessageDisposition HintSpyTranslator::translateGameMessage(const GameMessage *msg)
|
||||
{
|
||||
GameMessageDisposition disp = KEEP_MESSAGE;
|
||||
|
||||
/// @todo Create an automated way to associate method callbacks with messages
|
||||
switch( msg->getType() )
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_MOUSEOVER_DRAWABLE_HINT:
|
||||
{
|
||||
TheInGameUI->createMouseoverHint( msg );
|
||||
|
||||
disp = DESTROY_MESSAGE; //hint no longer needed by anyone. Eat it.
|
||||
}
|
||||
break;
|
||||
case GameMessage::MSG_MOUSEOVER_LOCATION_HINT:
|
||||
{
|
||||
TheInGameUI->createMouseoverHint( msg );
|
||||
|
||||
disp = DESTROY_MESSAGE; //hint no longer needed by anyone. Eat it.
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_DEFECTOR_HINT:
|
||||
|
||||
disp = DESTROY_MESSAGE; //hint no longer needed by anyone. Eat it.
|
||||
|
||||
case GameMessage::MSG_DO_MOVETO_HINT:
|
||||
case GameMessage::MSG_DO_ATTACKMOVETO_HINT:
|
||||
case GameMessage::MSG_DO_ATTACK_OBJECT_HINT:
|
||||
case GameMessage::MSG_DO_ATTACK_OBJECT_AFTER_MOVING_HINT:
|
||||
case GameMessage::MSG_DO_FORCE_ATTACK_OBJECT_HINT:
|
||||
case GameMessage::MSG_DO_FORCE_ATTACK_GROUND_HINT:
|
||||
case GameMessage::MSG_ADD_WAYPOINT_HINT:
|
||||
case GameMessage::MSG_GET_REPAIRED_HINT:
|
||||
case GameMessage::MSG_DOCK_HINT:
|
||||
case GameMessage::MSG_GET_HEALED_HINT:
|
||||
case GameMessage::MSG_DO_REPAIR_HINT:
|
||||
case GameMessage::MSG_RESUME_CONSTRUCTION_HINT:
|
||||
case GameMessage::MSG_ENTER_HINT:
|
||||
case GameMessage::MSG_HIJACK_HINT:
|
||||
case GameMessage::MSG_CONVERT_TO_CARBOMB_HINT:
|
||||
#ifdef ALLOW_SURRENDER
|
||||
case GameMessage::MSG_PICK_UP_PRISONER_HINT:
|
||||
#endif
|
||||
case GameMessage::MSG_VALID_GUICOMMAND_HINT:
|
||||
case GameMessage::MSG_INVALID_GUICOMMAND_HINT:
|
||||
case GameMessage::MSG_CAPTUREBUILDING_HINT:
|
||||
case GameMessage::MSG_HACK_HINT:
|
||||
case GameMessage::MSG_SET_RALLY_POINT_HINT:
|
||||
case GameMessage::MSG_IMPOSSIBLE_ATTACK_HINT:
|
||||
case GameMessage::MSG_DO_SPECIAL_POWER_OVERRIDE_DESTINATION_HINT:
|
||||
case GameMessage::MSG_DO_SALVAGE_HINT:
|
||||
case GameMessage::MSG_DO_INVALID_HINT:
|
||||
TheInGameUI->createCommandHint( msg );
|
||||
disp = DESTROY_MESSAGE; //hint no longer needed by anyone. Eat it.
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_AREA_SELECTION_HINT:
|
||||
TheInGameUI->beginAreaSelectHint( msg );
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// An AREA_SELECTION_HINT is always followed by an AREA_SELECTION, so
|
||||
// watch for it to stop hinting.
|
||||
case GameMessage::MSG_AREA_SELECTION:
|
||||
TheInGameUI->endAreaSelectHint( msg );
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_DO_MOVETO:
|
||||
case GameMessage::MSG_DO_ATTACKMOVETO:
|
||||
case GameMessage::MSG_DO_FORCEMOVETO:
|
||||
case GameMessage::MSG_ADD_WAYPOINT:
|
||||
TheInGameUI->createMoveHint( msg );
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_DO_ATTACK_OBJECT:
|
||||
TheInGameUI->createAttackHint( msg );
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_DO_FORCE_ATTACK_GROUND:
|
||||
case GameMessage::MSG_DO_FORCE_ATTACK_OBJECT:
|
||||
TheInGameUI->createForceAttackHint( msg );
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_ENTER:
|
||||
TheInGameUI->createGarrisonHint( msg );
|
||||
break;
|
||||
|
||||
}
|
||||
return disp;
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FILE: HotKey.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Sep 2002
|
||||
//
|
||||
// Filename: HotKey.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "GameClient/HotKey.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/MetaEvent.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/keyboard.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "Common/AudioEventRTS.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
GameMessageDisposition HotKeyTranslator::translateGameMessage(const GameMessage *msg)
|
||||
{
|
||||
GameMessageDisposition disp = KEEP_MESSAGE;
|
||||
GameMessage::Type t = msg->getType();
|
||||
|
||||
if ( t == GameMessage::MSG_RAW_KEY_UP)
|
||||
{
|
||||
|
||||
//char key = msg->getArgument(0)->integer;
|
||||
Int keyState = msg->getArgument(1)->integer;
|
||||
|
||||
// for our purposes here, we don't care to distinguish between right and left keys,
|
||||
// so just fudge a little to simplify things.
|
||||
Int newModState = 0;
|
||||
|
||||
if( keyState & KEY_STATE_CONTROL )
|
||||
{
|
||||
newModState |= CTRL;
|
||||
}
|
||||
|
||||
if( keyState & KEY_STATE_SHIFT )
|
||||
{
|
||||
newModState |= SHIFT;
|
||||
}
|
||||
|
||||
if( keyState & KEY_STATE_ALT )
|
||||
{
|
||||
newModState |= ALT;
|
||||
}
|
||||
if(newModState != 0)
|
||||
return disp;
|
||||
WideChar key = TheKeyboard->getPrintableKey(msg->getArgument(0)->integer, 0);
|
||||
UnicodeString uKey;
|
||||
uKey.set(&key);
|
||||
AsciiString aKey;
|
||||
aKey.translate(uKey);
|
||||
if(TheHotKeyManager && TheHotKeyManager->executeHotKey(aKey))
|
||||
disp = DESTROY_MESSAGE;
|
||||
}
|
||||
return disp;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HotKey::HotKey()
|
||||
{
|
||||
m_win = NULL;
|
||||
//Added By Sadullah Nader
|
||||
//Initializations missing and needed
|
||||
m_key.clear();
|
||||
//
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HotKeyManager::HotKeyManager( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HotKeyManager::~HotKeyManager( void )
|
||||
{
|
||||
m_hotKeyMap.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HotKeyManager::init( void )
|
||||
{
|
||||
m_hotKeyMap.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HotKeyManager::reset( void )
|
||||
{
|
||||
m_hotKeyMap.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HotKeyManager::addHotKey( GameWindow *win, const AsciiString& keyIn)
|
||||
{
|
||||
AsciiString key = keyIn;
|
||||
key.toLower();
|
||||
HotKeyMap::iterator it = m_hotKeyMap.find(key);
|
||||
if( it != m_hotKeyMap.end() )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(FALSE,("Hotkey %s is already mapped to window %s, current window is %s", key.str(), it->second.m_win->winGetInstanceData()->m_decoratedNameString.str(), win->winGetInstanceData()->m_decoratedNameString.str()));
|
||||
return;
|
||||
}
|
||||
HotKey newHK;
|
||||
newHK.m_key.set(key);
|
||||
newHK.m_win = win;
|
||||
m_hotKeyMap[key] = newHK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Bool HotKeyManager::executeHotKey( const AsciiString& keyIn )
|
||||
{
|
||||
AsciiString key = keyIn;
|
||||
key.toLower();
|
||||
HotKeyMap::iterator it = m_hotKeyMap.find(key);
|
||||
if( it == m_hotKeyMap.end() )
|
||||
return FALSE;
|
||||
GameWindow *win = it->second.m_win;
|
||||
if( !win )
|
||||
return FALSE;
|
||||
if( !BitTest( win->winGetStatus(), WIN_STATUS_HIDDEN ) )
|
||||
{
|
||||
if( BitTest( win->winGetStatus(), WIN_STATUS_ENABLED ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( win->winGetParent(), GBM_SELECTED, (WindowMsgData)win, win->winGetWindowId() );
|
||||
|
||||
// here we make the same click sound that the GUI uses when you click a button
|
||||
AudioEventRTS buttonClick("GUIClick");
|
||||
|
||||
if( TheAudio )
|
||||
{
|
||||
TheAudio->addAudioEvent( &buttonClick );
|
||||
} // end if
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
AudioEventRTS disabledClick( "GUIClickDisabled" );
|
||||
if( TheAudio )
|
||||
{
|
||||
TheAudio->addAudioEvent( &disabledClick );
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
AsciiString HotKeyManager::searchHotKey( const AsciiString& label)
|
||||
{
|
||||
return searchHotKey(TheGameText->fetch(label));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
AsciiString HotKeyManager::searchHotKey( const UnicodeString& uStr )
|
||||
{
|
||||
if(uStr.isEmpty())
|
||||
return AsciiString::TheEmptyString;
|
||||
|
||||
const WideChar *marker = (const WideChar *)uStr.str();
|
||||
while (marker && *marker)
|
||||
{
|
||||
if (*marker == L'&')
|
||||
{
|
||||
// found a '&' - now look for the next char
|
||||
UnicodeString tmp = UnicodeString::TheEmptyString;
|
||||
tmp.concat(*(marker+1));
|
||||
AsciiString retStr;
|
||||
retStr.translate(tmp);
|
||||
return retStr;
|
||||
}
|
||||
marker++;
|
||||
}
|
||||
return AsciiString::TheEmptyString;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HotKeyManager *TheHotKeyManager = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -0,0 +1,681 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// LookAtXlat.cpp
|
||||
// Translate raw input events into camera movement commands
|
||||
// Author: Michael S. Booth, April 2001
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
#include "Common/GameType.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/Recorder.h"
|
||||
#include "Common/StatsCollector.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/PartitionManager.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/Mouse.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/View.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/LookAtXlat.h"
|
||||
#include "GameLogic/Module/UpdateModule.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
#include "Common/GlobalData.h" // for camera pitch angle only
|
||||
|
||||
LookAtTranslator *TheLookAtTranslator = NULL;
|
||||
|
||||
static enum
|
||||
{
|
||||
DIR_UP = 0,
|
||||
DIR_DOWN,
|
||||
DIR_LEFT,
|
||||
DIR_RIGHT
|
||||
};
|
||||
|
||||
static Bool scrollDir[4] = { false, false, false, false };
|
||||
|
||||
Int SCROLL_AMT = 100;
|
||||
|
||||
static const Int edgeScrollSize = 3;
|
||||
|
||||
static Mouse::MouseCursor prevCursor = Mouse::ARROW;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void LookAtTranslator::setScrolling(Int x)
|
||||
{
|
||||
if (!TheInGameUI->getInputEnabled())
|
||||
return;
|
||||
|
||||
prevCursor = TheMouse->getMouseCursor();
|
||||
m_isScrolling = true;
|
||||
TheInGameUI->setScrolling( TRUE );
|
||||
TheTacticalView->setMouseLock( TRUE );
|
||||
m_scrollType = x;
|
||||
if(TheStatsCollector)
|
||||
TheStatsCollector->startScrollTime();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void LookAtTranslator::stopScrolling( void )
|
||||
{
|
||||
m_isScrolling = false;
|
||||
TheInGameUI->setScrolling( FALSE );
|
||||
TheTacticalView->setMouseLock( FALSE );
|
||||
TheMouse->setCursor(prevCursor);
|
||||
m_scrollType = SCROLL_NONE;
|
||||
|
||||
// if we have a stats collectore increment the stats
|
||||
if(TheStatsCollector)
|
||||
TheStatsCollector->endScrollTime();
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
LookAtTranslator::LookAtTranslator() :
|
||||
m_isScrolling(false),
|
||||
m_isRotating(false),
|
||||
m_isPitching(false),
|
||||
m_isChangingFOV(false),
|
||||
m_timestamp(0),
|
||||
m_lastPlaneID(INVALID_DRAWABLE_ID),
|
||||
m_lastMouseMoveFrame(0),
|
||||
m_scrollType(SCROLL_NONE)
|
||||
{
|
||||
//Added By Sadullah Nader
|
||||
//Initializations misssing and needed
|
||||
m_anchor.x = m_anchor.y = 0;
|
||||
m_currentPos.x = m_currentPos.y = 0;
|
||||
m_originalAnchor.x = m_originalAnchor.y = 0;
|
||||
//
|
||||
|
||||
DEBUG_ASSERTCRASH(!TheLookAtTranslator, ("Already have a LookAtTranslator - why do you need two?"));
|
||||
TheLookAtTranslator = this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
LookAtTranslator::~LookAtTranslator()
|
||||
{
|
||||
if (TheLookAtTranslator == this)
|
||||
TheLookAtTranslator = NULL;
|
||||
}
|
||||
|
||||
const ICoord2D* LookAtTranslator::getRMBScrollAnchor(void)
|
||||
{
|
||||
if (m_isScrolling && m_scrollType == SCROLL_RMB)
|
||||
{
|
||||
return &m_anchor;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Bool LookAtTranslator::hasMouseMovedRecently( void )
|
||||
{
|
||||
if (m_lastMouseMoveFrame > TheGameLogic->getFrame())
|
||||
m_lastMouseMoveFrame = 0; // reset for new game
|
||||
|
||||
if (m_lastMouseMoveFrame + LOGICFRAMES_PER_SECOND < TheGameLogic->getFrame())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LookAtTranslator::setCurrentPos( const ICoord2D& pos )
|
||||
{
|
||||
m_currentPos = pos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* The LookAt Translator is responsible for camera movements. It is directly responsible for
|
||||
* right mouse button scrolling, and CTRL-<F key> bookmarking. It also responds to certain
|
||||
* LOOKAT message on the message stream.
|
||||
*/
|
||||
GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage *msg)
|
||||
{
|
||||
GameMessageDisposition disp = KEEP_MESSAGE;
|
||||
|
||||
GameMessage::Type t = msg->getType();
|
||||
switch (t)
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_KEY_DOWN:
|
||||
case GameMessage::MSG_RAW_KEY_UP:
|
||||
{
|
||||
// get key and state from args
|
||||
UnsignedByte key = msg->getArgument( 0 )->integer;
|
||||
UnsignedByte state = msg->getArgument( 1 )->integer;
|
||||
Bool isPressed = !(BitTest( state, KEY_STATE_UP ));
|
||||
|
||||
if (TheShell && TheShell->isShellActive())
|
||||
break;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case KEY_UP:
|
||||
scrollDir[DIR_UP] = isPressed;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
scrollDir[DIR_DOWN] = isPressed;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
scrollDir[DIR_LEFT] = isPressed;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
scrollDir[DIR_RIGHT] = isPressed;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TheInGameUI->isSelecting() || (m_isScrolling && m_scrollType != SCROLL_KEY))
|
||||
break;
|
||||
|
||||
// see if we need to start/stop scrolling
|
||||
Int numDirs = 0;
|
||||
for (Int i=0; i<4; ++i)
|
||||
{
|
||||
if (scrollDir[i])
|
||||
numDirs++;
|
||||
}
|
||||
|
||||
if (numDirs && !m_isScrolling)
|
||||
{
|
||||
setScrolling( SCROLL_KEY );
|
||||
}
|
||||
else if (!numDirs && m_isScrolling)
|
||||
{
|
||||
stopScrolling();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN:
|
||||
{
|
||||
m_lastMouseMoveFrame = TheGameLogic->getFrame();
|
||||
|
||||
m_anchor = msg->getArgument( 0 )->pixel;
|
||||
m_currentPos = msg->getArgument( 0 )->pixel;
|
||||
|
||||
// disable mouse scrolling in alternate mouse mode, per Harvard 7/15/03
|
||||
if (!TheGlobalData->m_useAlternateMouse && !TheInGameUI->isSelecting() && !m_isScrolling)
|
||||
{
|
||||
setScrolling(SCROLL_RMB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP:
|
||||
{
|
||||
m_lastMouseMoveFrame = TheGameLogic->getFrame();
|
||||
|
||||
if (m_scrollType == SCROLL_RMB)
|
||||
{
|
||||
stopScrolling();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN:
|
||||
{
|
||||
m_lastMouseMoveFrame = TheGameLogic->getFrame();
|
||||
|
||||
m_isRotating = true;
|
||||
m_anchor = msg->getArgument( 0 )->pixel;
|
||||
m_originalAnchor = msg->getArgument( 0 )->pixel;
|
||||
m_currentPos = msg->getArgument( 0 )->pixel;
|
||||
m_timestamp = TheGameClient->getFrame();
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP:
|
||||
{
|
||||
m_lastMouseMoveFrame = TheGameLogic->getFrame();
|
||||
|
||||
const UnsignedInt CLICK_DURATION = 5;
|
||||
const UnsignedInt PIXEL_OFFSET = 5;
|
||||
|
||||
m_isRotating = false;
|
||||
Int dx = m_currentPos.x-m_originalAnchor.x;
|
||||
if (dx<0) dx = -dx;
|
||||
Int dy = m_currentPos.y-m_originalAnchor.y;
|
||||
Bool didMove = dx>PIXEL_OFFSET || dy>PIXEL_OFFSET;
|
||||
// if middle button is "clicked", reset to "home" orientation
|
||||
if (!didMove && TheGameClient->getFrame() - m_timestamp < CLICK_DURATION)
|
||||
{
|
||||
TheTacticalView->setAngleAndPitchToDefault();
|
||||
TheTacticalView->setZoomToDefault();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_POSITION:
|
||||
{
|
||||
if (m_currentPos.x != msg->getArgument( 0 )->pixel.x || m_currentPos.y != msg->getArgument( 0 )->pixel.y)
|
||||
m_lastMouseMoveFrame = TheGameLogic->getFrame();
|
||||
|
||||
m_currentPos = msg->getArgument( 0 )->pixel;
|
||||
|
||||
UnsignedInt height = TheDisplay->getHeight();
|
||||
UnsignedInt width = TheDisplay->getWidth();
|
||||
|
||||
if (TheInGameUI->getInputEnabled() == FALSE) {
|
||||
// We don't care how we're scrolling, just stop.
|
||||
if (m_isScrolling)
|
||||
stopScrolling();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TheGlobalData->m_windowed)
|
||||
{
|
||||
if (m_isScrolling)
|
||||
{
|
||||
if ( m_scrollType == SCROLL_SCREENEDGE && (m_currentPos.x >= edgeScrollSize && m_currentPos.y >= edgeScrollSize && m_currentPos.y < height-edgeScrollSize && m_currentPos.x < width-edgeScrollSize) )
|
||||
{
|
||||
stopScrolling();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_currentPos.x < edgeScrollSize || m_currentPos.y < edgeScrollSize || m_currentPos.y >= height-edgeScrollSize || m_currentPos.x >= width-edgeScrollSize )
|
||||
{
|
||||
setScrolling(SCROLL_SCREENEDGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rotate the view
|
||||
if (m_isRotating)
|
||||
{
|
||||
const Real FACTOR = 0.01f;
|
||||
|
||||
Real angle = FACTOR * (m_currentPos.x - m_anchor.x);
|
||||
|
||||
TheTacticalView->setAngle( TheTacticalView->getAngle() + angle );
|
||||
m_anchor = msg->getArgument( 0 )->pixel;
|
||||
}
|
||||
|
||||
// rotate the view up/down
|
||||
if (m_isPitching)
|
||||
{
|
||||
const Real FACTOR = 0.01f;
|
||||
|
||||
Real angle = FACTOR * (m_currentPos.y - m_anchor.y);
|
||||
|
||||
TheTacticalView->setPitch( TheTacticalView->getPitch() + angle );
|
||||
m_anchor = msg->getArgument( 0 )->pixel;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
// adjust the field of view
|
||||
if (m_isChangingFOV)
|
||||
{
|
||||
const Real FACTOR = 0.01f;
|
||||
|
||||
Real angle = FACTOR * (m_currentPos.y - m_anchor.y);
|
||||
|
||||
TheTacticalView->setFieldOfView( TheTacticalView->getFieldOfView() + angle );
|
||||
m_anchor = msg->getArgument( 0 )->pixel;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_WHEEL:
|
||||
{
|
||||
m_lastMouseMoveFrame = TheGameLogic->getFrame();
|
||||
|
||||
Int spin = msg->getArgument( 1 )->integer;
|
||||
|
||||
if (spin > 0)
|
||||
{
|
||||
for ( ; spin > 0; spin--)
|
||||
TheTacticalView->zoomIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ;spin < 0; spin++ )
|
||||
TheTacticalView->zoomOut();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_META_OPTIONS:
|
||||
{
|
||||
// stop the scrolling
|
||||
stopScrolling();
|
||||
// let the message drop through, cause we need to process this message for
|
||||
// selection as well.
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
case GameMessage::MSG_FRAME_TICK:
|
||||
{
|
||||
Coord2D offset = {0, 0};
|
||||
|
||||
// If we've been forced to stop scrolling (script action?) then stop
|
||||
if (m_isScrolling && !TheInGameUI->isScrolling())
|
||||
{
|
||||
TheInGameUI->setScrollAmount(offset);
|
||||
stopScrolling();
|
||||
}
|
||||
else
|
||||
// scroll the view
|
||||
if (m_isScrolling)
|
||||
{
|
||||
switch (m_scrollType)
|
||||
{
|
||||
case SCROLL_RMB:
|
||||
{
|
||||
if (TheInGameUI->shouldMoveRMBScrollAnchor())
|
||||
{
|
||||
Int maxX = TheDisplay->getWidth()/2;
|
||||
Int maxY = TheDisplay->getHeight()/2;
|
||||
|
||||
if (m_currentPos.x + maxX < m_anchor.x)
|
||||
m_anchor.x = m_currentPos.x + maxX;
|
||||
else if (m_currentPos.x - maxX > m_anchor.x)
|
||||
m_anchor.x = m_currentPos.x - maxX;
|
||||
|
||||
if (m_currentPos.y + maxY < m_anchor.y)
|
||||
m_anchor.y = m_currentPos.y + maxY;
|
||||
else if (m_currentPos.y - maxY > m_anchor.y)
|
||||
m_anchor.y = m_currentPos.y - maxY;
|
||||
}
|
||||
|
||||
offset.x = TheGlobalData->m_horizontalScrollSpeedFactor * (m_currentPos.x - m_anchor.x);
|
||||
offset.y = TheGlobalData->m_verticalScrollSpeedFactor * (m_currentPos.y - m_anchor.y);
|
||||
Coord2D vec;
|
||||
vec.x = offset.x;
|
||||
vec.y = offset.y;
|
||||
vec.normalize();
|
||||
// Add in the window scroll amount as the minimum.
|
||||
offset.x += TheGlobalData->m_horizontalScrollSpeedFactor * vec.x * sqr(TheGlobalData->m_keyboardScrollFactor);
|
||||
offset.y += TheGlobalData->m_verticalScrollSpeedFactor * vec.y * sqr(TheGlobalData->m_keyboardScrollFactor);
|
||||
}
|
||||
break;
|
||||
case SCROLL_KEY:
|
||||
{
|
||||
if (scrollDir[DIR_UP])
|
||||
{
|
||||
offset.y -= TheGlobalData->m_verticalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
if (scrollDir[DIR_DOWN])
|
||||
{
|
||||
offset.y += TheGlobalData->m_verticalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
if (scrollDir[DIR_LEFT])
|
||||
{
|
||||
offset.x -= TheGlobalData->m_horizontalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
if (scrollDir[DIR_RIGHT])
|
||||
{
|
||||
offset.x += TheGlobalData->m_horizontalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCROLL_SCREENEDGE:
|
||||
{
|
||||
UnsignedInt height = TheDisplay->getHeight();
|
||||
UnsignedInt width = TheDisplay->getWidth();
|
||||
if (m_currentPos.y < edgeScrollSize)
|
||||
{
|
||||
offset.y -= TheGlobalData->m_verticalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
if (m_currentPos.y >= height-edgeScrollSize)
|
||||
{
|
||||
offset.y += TheGlobalData->m_verticalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
if (m_currentPos.x < edgeScrollSize)
|
||||
{
|
||||
offset.x -= TheGlobalData->m_horizontalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
if (m_currentPos.x >= width-edgeScrollSize)
|
||||
{
|
||||
offset.x += TheGlobalData->m_horizontalScrollSpeedFactor * SCROLL_AMT * TheGlobalData->m_keyboardScrollFactor;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TheInGameUI->setScrollAmount(offset);
|
||||
TheTacticalView->scrollBy( &offset );
|
||||
}
|
||||
else //not scrolling so reset amount
|
||||
TheInGameUI->setScrollAmount(offset);
|
||||
|
||||
#if !defined(_PLAYTEST)
|
||||
//if (TheGlobalData->m_saveCameraInReplay /*&& TheRecorder->getMode() != RECORDERMODETYPE_PLAYBACK *//**/&& (TheGameLogic->isInSinglePlayerGame() || TheGameLogic->isInSkirmishGame())/**/)
|
||||
//if (TheGlobalData->m_saveCameraInReplay && (TheGameLogic->isInMultiplayerGame() || TheGameLogic->isInSinglePlayerGame() || TheGameLogic->isInSkirmishGame()))
|
||||
if (TheGlobalData->m_saveCameraInReplay && (TheGameLogic->isInSinglePlayerGame() || TheGameLogic->isInSkirmishGame()))
|
||||
{
|
||||
ViewLocation currentView;
|
||||
TheTacticalView->getLocation(¤tView);
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_SET_REPLAY_CAMERA );
|
||||
msg->appendLocationArgument( currentView.m_pos );
|
||||
msg->appendRealArgument( currentView.m_angle );
|
||||
msg->appendRealArgument( currentView.m_pitch );
|
||||
msg->appendRealArgument( currentView.m_zoom );
|
||||
msg->appendIntegerArgument( (Int)TheMouse->getMouseCursor() );
|
||||
msg->appendPixelArgument( m_currentPos );
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
case GameMessage::MSG_META_DEMO_BEGIN_ADJUST_PITCH:
|
||||
{
|
||||
DEBUG_ASSERTCRASH(!m_isPitching, ("hmm, mismatched m_isPitching"));
|
||||
m_isPitching = true;
|
||||
disp = DESTROY_MESSAGE;
|
||||
break;
|
||||
}
|
||||
#endif // #if defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
case GameMessage::MSG_META_DEMO_END_ADJUST_PITCH:
|
||||
{
|
||||
DEBUG_ASSERTCRASH(m_isPitching, ("hmm, mismatched m_isPitching"));
|
||||
m_isPitching = false;
|
||||
disp = DESTROY_MESSAGE;
|
||||
break;
|
||||
}
|
||||
#endif // #if defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
case GameMessage::MSG_META_DEMO_DESHROUD:
|
||||
{
|
||||
ThePartitionManager->revealMapForPlayerPermanently( ThePlayerList->getLocalPlayer()->getPlayerIndex() );
|
||||
break;
|
||||
}
|
||||
#endif // #if defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
case GameMessage::MSG_META_DEMO_ENSHROUD:
|
||||
{
|
||||
// Need to first undo the permanent Look laid down by DEMO_DESHROUD, then blast a shroud dollop.
|
||||
ThePartitionManager->undoRevealMapForPlayerPermanently( ThePlayerList->getLocalPlayer()->getPlayerIndex() );
|
||||
ThePartitionManager->shroudMapForPlayer( ThePlayerList->getLocalPlayer()->getPlayerIndex() );
|
||||
break;
|
||||
}
|
||||
#endif // #if defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
case GameMessage::MSG_META_DEMO_BEGIN_ADJUST_FOV:
|
||||
{
|
||||
DEBUG_ASSERTCRASH(!m_isChangingFOV, ("hmm, mismatched m_isChangingFOV"));
|
||||
m_isChangingFOV = true;
|
||||
m_anchor = m_currentPos;
|
||||
break;
|
||||
}
|
||||
#endif // #if defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
case GameMessage::MSG_META_DEMO_END_ADJUST_FOV:
|
||||
{
|
||||
DEBUG_ASSERTCRASH(m_isChangingFOV, ("hmm, mismatched m_isChangingFOV"));
|
||||
m_isChangingFOV = false;
|
||||
break;
|
||||
}
|
||||
#endif // #if defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
case GameMessage::MSG_META_SAVE_VIEW1:
|
||||
case GameMessage::MSG_META_SAVE_VIEW2:
|
||||
case GameMessage::MSG_META_SAVE_VIEW3:
|
||||
case GameMessage::MSG_META_SAVE_VIEW4:
|
||||
case GameMessage::MSG_META_SAVE_VIEW5:
|
||||
case GameMessage::MSG_META_SAVE_VIEW6:
|
||||
case GameMessage::MSG_META_SAVE_VIEW7:
|
||||
case GameMessage::MSG_META_SAVE_VIEW8:
|
||||
{
|
||||
Int slot = t - GameMessage::MSG_META_SAVE_VIEW1 + 1;
|
||||
if ( slot > 0 && slot <= MAX_VIEW_LOCS )
|
||||
{
|
||||
TheTacticalView->getLocation( &m_viewLocation[slot-1] );
|
||||
UnicodeString msg;
|
||||
msg.format( TheGameText->fetch( "GUI:BookmarkXSet" ), slot );
|
||||
TheInGameUI->message( msg );
|
||||
}
|
||||
disp = DESTROY_MESSAGE;
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
case GameMessage::MSG_META_VIEW_VIEW1:
|
||||
case GameMessage::MSG_META_VIEW_VIEW2:
|
||||
case GameMessage::MSG_META_VIEW_VIEW3:
|
||||
case GameMessage::MSG_META_VIEW_VIEW4:
|
||||
case GameMessage::MSG_META_VIEW_VIEW5:
|
||||
case GameMessage::MSG_META_VIEW_VIEW6:
|
||||
case GameMessage::MSG_META_VIEW_VIEW7:
|
||||
case GameMessage::MSG_META_VIEW_VIEW8:
|
||||
{
|
||||
Int slot = t - GameMessage::MSG_META_VIEW_VIEW1 + 1;
|
||||
if ( slot > 0 && slot <= MAX_VIEW_LOCS )
|
||||
{
|
||||
TheTacticalView->setLocation( &m_viewLocation[slot-1] );
|
||||
}
|
||||
disp = DESTROY_MESSAGE;
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
case GameMessage::MSG_META_DEMO_LOCK_CAMERA_TO_PLANES:
|
||||
{
|
||||
Drawable *first = NULL;
|
||||
|
||||
if (m_lastPlaneID)
|
||||
first = TheGameClient->findDrawableByID( m_lastPlaneID );
|
||||
|
||||
if (first == NULL)
|
||||
first = TheGameClient->firstDrawable();
|
||||
|
||||
if (first)
|
||||
{
|
||||
Drawable *d = first;
|
||||
Bool done = false;
|
||||
|
||||
while(!done)
|
||||
{
|
||||
// get next Drawable, wrapping around to head of list if necessary
|
||||
d = d->getNextDrawable();
|
||||
if (d == NULL)
|
||||
d = TheGameClient->firstDrawable();
|
||||
|
||||
// if we've found an airborne object, lock onto it
|
||||
// "isAboveTerrain" only indicates that we are currently in the air, but that
|
||||
// could be the case if we are a buggy jumping a hill, or a unit being paradropped.
|
||||
// the right thing would be to look at the locomotors.
|
||||
// so this isn't really right, but will suffice for demo purposes.
|
||||
if (d->getObject() && d->getObject()->isAboveTerrain() )
|
||||
{
|
||||
Bool doLock = true;
|
||||
|
||||
// but don't lock onto projectiles
|
||||
ProjectileUpdateInterface* pui = NULL;
|
||||
for (BehaviorModule** u = d->getObject()->getBehaviorModules(); *u; ++u)
|
||||
{
|
||||
if ((pui = (*u)->getProjectileUpdateInterface()) != NULL)
|
||||
{
|
||||
doLock = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doLock)
|
||||
{
|
||||
TheTacticalView->setCameraLock( d->getObject()->getID() );
|
||||
m_lastPlaneID = d->getID();
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
} // if airborne found
|
||||
|
||||
// if we're back to the first, quit
|
||||
if (d == first)
|
||||
break;
|
||||
} // while
|
||||
} // end plane lock
|
||||
|
||||
disp = DESTROY_MESSAGE;
|
||||
break;
|
||||
}
|
||||
#endif // #if defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
} // end switch
|
||||
|
||||
return disp;
|
||||
|
||||
} // end LookAtTranslator
|
||||
|
||||
void LookAtTranslator::resetModes()
|
||||
{
|
||||
m_isScrolling = FALSE;
|
||||
m_isRotating = FALSE;
|
||||
m_isPitching = FALSE;
|
||||
m_isChangingFOV = FALSE;
|
||||
}
|
|
@ -0,0 +1,641 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FILE: MetaEvent.cpp ////////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, September 2001
|
||||
// Desc: Translating keystrokes into event command messages
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/INI.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/Team.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/Mouse.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/ParticleSys.h" // for ParticleSystemDebugDisplay
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/DebugDisplay.h" // for AudioDebugDisplay
|
||||
|
||||
#include "GameClient/MetaEvent.h"
|
||||
|
||||
#include "GameLogic/GameLogic.h" // for TheGameLogic->getFrame()
|
||||
|
||||
MetaMap *TheMetaMap = NULL;
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
///#pragma optimize("", off)
|
||||
///#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const LookupListRec GameMessageMetaTypeNames[] =
|
||||
{
|
||||
{ "SAVE_VIEW1", GameMessage::MSG_META_SAVE_VIEW1 },
|
||||
{ "SAVE_VIEW2", GameMessage::MSG_META_SAVE_VIEW2 },
|
||||
{ "SAVE_VIEW3", GameMessage::MSG_META_SAVE_VIEW3 },
|
||||
{ "SAVE_VIEW4", GameMessage::MSG_META_SAVE_VIEW4 },
|
||||
{ "SAVE_VIEW5", GameMessage::MSG_META_SAVE_VIEW5 },
|
||||
{ "SAVE_VIEW6", GameMessage::MSG_META_SAVE_VIEW6 },
|
||||
{ "SAVE_VIEW7", GameMessage::MSG_META_SAVE_VIEW7 },
|
||||
{ "SAVE_VIEW8", GameMessage::MSG_META_SAVE_VIEW8 },
|
||||
{ "VIEW_VIEW1", GameMessage::MSG_META_VIEW_VIEW1 },
|
||||
{ "VIEW_VIEW2", GameMessage::MSG_META_VIEW_VIEW2 },
|
||||
{ "VIEW_VIEW3", GameMessage::MSG_META_VIEW_VIEW3 },
|
||||
{ "VIEW_VIEW4", GameMessage::MSG_META_VIEW_VIEW4 },
|
||||
{ "VIEW_VIEW5", GameMessage::MSG_META_VIEW_VIEW5 },
|
||||
{ "VIEW_VIEW6", GameMessage::MSG_META_VIEW_VIEW6 },
|
||||
{ "VIEW_VIEW7", GameMessage::MSG_META_VIEW_VIEW7 },
|
||||
{ "VIEW_VIEW8", GameMessage::MSG_META_VIEW_VIEW8 },
|
||||
{ "CREATE_TEAM0", GameMessage::MSG_META_CREATE_TEAM0 },
|
||||
{ "CREATE_TEAM1", GameMessage::MSG_META_CREATE_TEAM1 },
|
||||
{ "CREATE_TEAM2", GameMessage::MSG_META_CREATE_TEAM2 },
|
||||
{ "CREATE_TEAM3", GameMessage::MSG_META_CREATE_TEAM3 },
|
||||
{ "CREATE_TEAM4", GameMessage::MSG_META_CREATE_TEAM4 },
|
||||
{ "CREATE_TEAM5", GameMessage::MSG_META_CREATE_TEAM5 },
|
||||
{ "CREATE_TEAM6", GameMessage::MSG_META_CREATE_TEAM6 },
|
||||
{ "CREATE_TEAM7", GameMessage::MSG_META_CREATE_TEAM7 },
|
||||
{ "CREATE_TEAM8", GameMessage::MSG_META_CREATE_TEAM8 },
|
||||
{ "CREATE_TEAM9", GameMessage::MSG_META_CREATE_TEAM9 },
|
||||
{ "SELECT_TEAM0", GameMessage::MSG_META_SELECT_TEAM0 },
|
||||
{ "SELECT_TEAM1", GameMessage::MSG_META_SELECT_TEAM1 },
|
||||
{ "SELECT_TEAM2", GameMessage::MSG_META_SELECT_TEAM2 },
|
||||
{ "SELECT_TEAM3", GameMessage::MSG_META_SELECT_TEAM3 },
|
||||
{ "SELECT_TEAM4", GameMessage::MSG_META_SELECT_TEAM4 },
|
||||
{ "SELECT_TEAM5", GameMessage::MSG_META_SELECT_TEAM5 },
|
||||
{ "SELECT_TEAM6", GameMessage::MSG_META_SELECT_TEAM6 },
|
||||
{ "SELECT_TEAM7", GameMessage::MSG_META_SELECT_TEAM7 },
|
||||
{ "SELECT_TEAM8", GameMessage::MSG_META_SELECT_TEAM8 },
|
||||
{ "SELECT_TEAM9", GameMessage::MSG_META_SELECT_TEAM9 },
|
||||
{ "ADD_TEAM0", GameMessage::MSG_META_ADD_TEAM0 },
|
||||
{ "ADD_TEAM1", GameMessage::MSG_META_ADD_TEAM1 },
|
||||
{ "ADD_TEAM2", GameMessage::MSG_META_ADD_TEAM2 },
|
||||
{ "ADD_TEAM3", GameMessage::MSG_META_ADD_TEAM3 },
|
||||
{ "ADD_TEAM4", GameMessage::MSG_META_ADD_TEAM4 },
|
||||
{ "ADD_TEAM5", GameMessage::MSG_META_ADD_TEAM5 },
|
||||
{ "ADD_TEAM6", GameMessage::MSG_META_ADD_TEAM6 },
|
||||
{ "ADD_TEAM7", GameMessage::MSG_META_ADD_TEAM7 },
|
||||
{ "ADD_TEAM8", GameMessage::MSG_META_ADD_TEAM8 },
|
||||
{ "ADD_TEAM9", GameMessage::MSG_META_ADD_TEAM9 },
|
||||
{ "VIEW_TEAM0", GameMessage::MSG_META_VIEW_TEAM0 },
|
||||
{ "VIEW_TEAM1", GameMessage::MSG_META_VIEW_TEAM1 },
|
||||
{ "VIEW_TEAM2", GameMessage::MSG_META_VIEW_TEAM2 },
|
||||
{ "VIEW_TEAM3", GameMessage::MSG_META_VIEW_TEAM3 },
|
||||
{ "VIEW_TEAM4", GameMessage::MSG_META_VIEW_TEAM4 },
|
||||
{ "VIEW_TEAM5", GameMessage::MSG_META_VIEW_TEAM5 },
|
||||
{ "VIEW_TEAM6", GameMessage::MSG_META_VIEW_TEAM6 },
|
||||
{ "VIEW_TEAM7", GameMessage::MSG_META_VIEW_TEAM7 },
|
||||
{ "VIEW_TEAM8", GameMessage::MSG_META_VIEW_TEAM8 },
|
||||
{ "VIEW_TEAM9", GameMessage::MSG_META_VIEW_TEAM9 },
|
||||
{ "SELECT_MATCHING_UNITS", GameMessage::MSG_META_SELECT_MATCHING_UNITS },
|
||||
{ "SELECT_NEXT_UNIT", GameMessage::MSG_META_SELECT_NEXT_UNIT },
|
||||
{ "SELECT_PREV_UNIT", GameMessage::MSG_META_SELECT_PREV_UNIT },
|
||||
{ "SELECT_NEXT_WORKER", GameMessage::MSG_META_SELECT_NEXT_WORKER },
|
||||
{ "SELECT_PREV_WORKER", GameMessage::MSG_META_SELECT_PREV_WORKER },
|
||||
{ "SELECT_HERO", GameMessage::MSG_META_SELECT_HERO },
|
||||
{ "SELECT_ALL", GameMessage::MSG_META_SELECT_ALL },
|
||||
{ "VIEW_COMMAND_CENTER", GameMessage::MSG_META_VIEW_COMMAND_CENTER },
|
||||
{ "VIEW_LAST_RADAR_EVENT", GameMessage::MSG_META_VIEW_LAST_RADAR_EVENT },
|
||||
{ "SCATTER", GameMessage::MSG_META_SCATTER },
|
||||
{ "STOP", GameMessage::MSG_META_STOP },
|
||||
{ "DEPLOY", GameMessage::MSG_META_DEPLOY },
|
||||
{ "CREATE_FORMATION", GameMessage::MSG_META_CREATE_FORMATION },
|
||||
{ "FOLLOW", GameMessage::MSG_META_FOLLOW },
|
||||
{ "CHAT_PLAYERS", GameMessage::MSG_META_CHAT_PLAYERS },
|
||||
{ "CHAT_ALLIES", GameMessage::MSG_META_CHAT_ALLIES },
|
||||
{ "CHAT_EVERYONE", GameMessage::MSG_META_CHAT_EVERYONE },
|
||||
{ "DIPLOMACY", GameMessage::MSG_META_DIPLOMACY },
|
||||
{ "PLACE_BEACON", GameMessage::MSG_META_PLACE_BEACON },
|
||||
{ "DELETE_BEACON", GameMessage::MSG_META_REMOVE_BEACON },
|
||||
{ "OPTIONS", GameMessage::MSG_META_OPTIONS },
|
||||
{ "TOGGLE_LOWER_DETAILS", GameMessage::MSG_META_TOGGLE_LOWER_DETAILS },
|
||||
{ "TOGGLE_CONTROL_BAR", GameMessage::MSG_META_TOGGLE_CONTROL_BAR },
|
||||
{ "BEGIN_PATH_BUILD", GameMessage::MSG_META_BEGIN_PATH_BUILD },
|
||||
{ "END_PATH_BUILD", GameMessage::MSG_META_END_PATH_BUILD },
|
||||
{ "BEGIN_FORCEATTACK", GameMessage::MSG_META_BEGIN_FORCEATTACK },
|
||||
{ "END_FORCEATTACK", GameMessage::MSG_META_END_FORCEATTACK },
|
||||
{ "BEGIN_FORCEMOVE", GameMessage::MSG_META_BEGIN_FORCEMOVE },
|
||||
{ "END_FORCEMOVE", GameMessage::MSG_META_END_FORCEMOVE },
|
||||
{ "BEGIN_WAYPOINTS", GameMessage::MSG_META_BEGIN_WAYPOINTS },
|
||||
{ "END_WAYPOINTS", GameMessage::MSG_META_END_WAYPOINTS },
|
||||
{ "BEGIN_PREFER_SELECTION", GameMessage::MSG_META_BEGIN_PREFER_SELECTION },
|
||||
{ "END_PREFER_SELECTION", GameMessage::MSG_META_END_PREFER_SELECTION },
|
||||
|
||||
{ "TAKE_SCREENSHOT", GameMessage::MSG_META_TAKE_SCREENSHOT },
|
||||
{ "ALL_CHEER", GameMessage::MSG_META_ALL_CHEER },
|
||||
|
||||
{ "BEGIN_CAMERA_ROTATE_LEFT", GameMessage::MSG_META_BEGIN_CAMERA_ROTATE_LEFT },
|
||||
{ "END_CAMERA_ROTATE_LEFT", GameMessage::MSG_META_END_CAMERA_ROTATE_LEFT },
|
||||
{ "BEGIN_CAMERA_ROTATE_RIGHT", GameMessage::MSG_META_BEGIN_CAMERA_ROTATE_RIGHT },
|
||||
{ "END_CAMERA_ROTATE_RIGHT", GameMessage::MSG_META_END_CAMERA_ROTATE_RIGHT },
|
||||
{ "BEGIN_CAMERA_ZOOM_IN", GameMessage::MSG_META_BEGIN_CAMERA_ZOOM_IN },
|
||||
{ "END_CAMERA_ZOOM_IN", GameMessage::MSG_META_END_CAMERA_ZOOM_IN },
|
||||
{ "BEGIN_CAMERA_ZOOM_OUT", GameMessage::MSG_META_BEGIN_CAMERA_ZOOM_OUT },
|
||||
{ "END_CAMERA_ZOOM_OUT", GameMessage::MSG_META_END_CAMERA_ZOOM_OUT },
|
||||
{ "CAMERA_RESET", GameMessage::MSG_META_CAMERA_RESET },
|
||||
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
{ "HELP", GameMessage::MSG_META_HELP },
|
||||
{ "DEMO_INSTANT_QUIT", GameMessage::MSG_META_DEMO_INSTANT_QUIT },
|
||||
|
||||
{ "DEMO_TOGGLE_BEHIND_BUILDINGS", GameMessage::MSG_META_DEMO_TOGGLE_BEHIND_BUILDINGS },
|
||||
{ "DEMO_LOD_DECREASE", GameMessage::MSG_META_DEMO_LOD_DECREASE },
|
||||
{ "DEMO_LOD_INCREASE", GameMessage::MSG_META_DEMO_LOD_INCREASE },
|
||||
{ "DEMO_TOGGLE_LETTERBOX", GameMessage::MSG_META_DEMO_TOGGLE_LETTERBOX },
|
||||
{ "DEMO_TOGGLE_MESSAGE_TEXT", GameMessage::MSG_META_DEMO_TOGGLE_MESSAGE_TEXT },
|
||||
|
||||
{ "DEMO_GIVE_ALL_SCIENCES", GameMessage::MSG_META_DEMO_GIVE_ALL_SCIENCES },
|
||||
{ "DEMO_GIVE_RANKLEVEL", GameMessage::MSG_META_DEMO_GIVE_RANKLEVEL },
|
||||
{ "DEMO_TAKE_RANKLEVEL", GameMessage::MSG_META_DEMO_TAKE_RANKLEVEL },
|
||||
{ "DEMO_GIVE_SCIENCEPURCHASEPOINTS", GameMessage::MSG_META_DEMO_GIVE_SCIENCEPURCHASEPOINTS },
|
||||
{ "DEMO_SWITCH_TEAMS", GameMessage::MSG_META_DEMO_SWITCH_TEAMS },
|
||||
{ "DEMO_SWITCH_TEAMS_CHINA_USA", GameMessage::MSG_META_DEMO_SWITCH_TEAMS_BETWEEN_CHINA_USA },
|
||||
{ "DEMO_TOGGLE_CASHMAPDEBUG", GameMessage::MSG_META_DEMO_TOGGLE_CASHMAPDEBUG },
|
||||
{ "DEMO_TOGGLE_GRAPHICALFRAMERATEBAR", GameMessage::MSG_META_DEMO_TOGGLE_GRAPHICALFRAMERATEBAR },
|
||||
{ "DEMO_TOGGLE_PARTICLEDEBUG", GameMessage::MSG_META_DEMO_TOGGLE_PARTICLEDEBUG },
|
||||
{ "DEMO_TOGGLE_THREATDEBUG", GameMessage::MSG_META_DEMO_TOGGLE_THREATDEBUG },
|
||||
{ "DEMO_TOGGLE_VISIONDEBUG", GameMessage::MSG_META_DEMO_TOGGLE_VISIONDEBUG },
|
||||
{ "DEMO_TOGGLE_PROJECTILEDEBUG", GameMessage::MSG_META_DEMO_TOGGLE_PROJECTILEDEBUG },
|
||||
{ "DEMO_LOD_DECREASE", GameMessage::MSG_META_DEMO_LOD_DECREASE },
|
||||
{ "DEMO_LOD_INCREASE", GameMessage::MSG_META_DEMO_LOD_INCREASE },
|
||||
{ "DEMO_TOGGLE_SHADOW_VOLUMES", GameMessage::MSG_META_DEMO_TOGGLE_SHADOW_VOLUMES },
|
||||
{ "DEMO_TOGGLE_FOGOFWAR", GameMessage::MSG_META_DEMO_TOGGLE_FOGOFWAR },
|
||||
{ "DEMO_KILL_ALL_ENEMIES", GameMessage::MSG_META_DEMO_KILL_ALL_ENEMIES },
|
||||
{ "DEMO_KILL_SELECTION", GameMessage::MSG_META_DEMO_KILL_SELECTION },
|
||||
{ "DEMO_TOGGLE_HURT_ME_MODE", GameMessage::MSG_META_DEMO_TOGGLE_HURT_ME_MODE },
|
||||
{ "DEMO_TOGGLE_HAND_OF_GOD_MODE", GameMessage::MSG_META_DEMO_TOGGLE_HAND_OF_GOD_MODE },
|
||||
{ "DEMO_DEBUG_SELECTION", GameMessage::MSG_META_DEMO_DEBUG_SELECTION },
|
||||
{ "DEMO_LOCK_CAMERA_TO_SELECTION", GameMessage::MSG_META_DEMO_LOCK_CAMERA_TO_SELECTION },
|
||||
{ "DEMO_TOGGLE_SOUND", GameMessage::MSG_META_DEMO_TOGGLE_SOUND },
|
||||
{ "DEMO_TOGGLE_TRACKMARKS", GameMessage::MSG_META_DEMO_TOGGLE_TRACKMARKS },
|
||||
{ "DEMO_TOGGLE_WATERPLANE", GameMessage::MSG_META_DEMO_TOGGLE_WATERPLANE },
|
||||
{ "DEMO_TIME_OF_DAY", GameMessage::MSG_META_DEMO_TIME_OF_DAY },
|
||||
{ "DEMO_TOGGLE_MILITARY_SUBTITLES", GameMessage::MSG_META_DEMO_TOGGLE_MILITARY_SUBTITLES },
|
||||
{ "DEMO_TOGGLE_MUSIC", GameMessage::MSG_META_DEMO_TOGGLE_MUSIC },
|
||||
{ "DEMO_MUSIC_NEXT_TRACK", GameMessage::MSG_META_DEMO_MUSIC_NEXT_TRACK },
|
||||
{ "DEMO_MUSIC_PREV_TRACK", GameMessage::MSG_META_DEMO_MUSIC_PREV_TRACK },
|
||||
{ "DEMO_NEXT_OBJECTIVE_MOVIE", GameMessage::MSG_META_DEMO_NEXT_OBJECTIVE_MOVIE },
|
||||
{ "DEMO_PLAY_OBJECTIVE_MOVIE1", GameMessage::MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE1 },
|
||||
{ "DEMO_PLAY_OBJECTIVE_MOVIE2", GameMessage::MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE2 },
|
||||
{ "DEMO_PLAY_OBJECTIVE_MOVIE3", GameMessage::MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE3 },
|
||||
{ "DEMO_PLAY_OBJECTIVE_MOVIE4", GameMessage::MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE4 },
|
||||
{ "DEMO_PLAY_OBJECTIVE_MOVIE5", GameMessage::MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE5 },
|
||||
{ "DEMO_PLAY_OBJECTIVE_MOVIE6", GameMessage::MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE6 },
|
||||
{ "DEMO_BEGIN_ADJUST_PITCH", GameMessage::MSG_META_DEMO_BEGIN_ADJUST_PITCH },
|
||||
{ "DEMO_END_ADJUST_PITCH", GameMessage::MSG_META_DEMO_END_ADJUST_PITCH },
|
||||
{ "DEMO_BEGIN_ADJUST_FOV", GameMessage::MSG_META_DEMO_BEGIN_ADJUST_FOV },
|
||||
{ "DEMO_END_ADJUST_FOV", GameMessage::MSG_META_DEMO_END_ADJUST_FOV },
|
||||
{ "DEMO_LOCK_CAMERA_TO_PLANES", GameMessage::MSG_META_DEMO_LOCK_CAMERA_TO_PLANES },
|
||||
{ "DEMO_REMOVE_PREREQ", GameMessage::MSG_META_DEMO_REMOVE_PREREQ },
|
||||
{ "DEMO_RUNSCRIPT1", GameMessage::MSG_META_DEMO_RUNSCRIPT1 },
|
||||
{ "DEMO_RUNSCRIPT2", GameMessage::MSG_META_DEMO_RUNSCRIPT2 },
|
||||
{ "DEMO_RUNSCRIPT3", GameMessage::MSG_META_DEMO_RUNSCRIPT3 },
|
||||
{ "DEMO_RUNSCRIPT4", GameMessage::MSG_META_DEMO_RUNSCRIPT4 },
|
||||
{ "DEMO_RUNSCRIPT5", GameMessage::MSG_META_DEMO_RUNSCRIPT5 },
|
||||
{ "DEMO_RUNSCRIPT6", GameMessage::MSG_META_DEMO_RUNSCRIPT6 },
|
||||
{ "DEMO_RUNSCRIPT7", GameMessage::MSG_META_DEMO_RUNSCRIPT7 },
|
||||
{ "DEMO_RUNSCRIPT8", GameMessage::MSG_META_DEMO_RUNSCRIPT8 },
|
||||
{ "DEMO_RUNSCRIPT9", GameMessage::MSG_META_DEMO_RUNSCRIPT9 },
|
||||
{ "DEMO_ADDCASH", GameMessage::MSG_META_DEMO_ADD_CASH },
|
||||
{ "DEMO_TOGGLE_RENDER", GameMessage::MSG_META_DEMO_TOGGLE_RENDER },
|
||||
{ "DEMO_TOGGLE_BW_VIEW", GameMessage::MSG_META_DEMO_TOGGLE_BW_VIEW },
|
||||
{ "DEMO_TOGGLE_RED_VIEW", GameMessage::MSG_META_DEMO_TOGGLE_RED_VIEW },
|
||||
{ "DEMO_TOGGLE_GREEN_VIEW", GameMessage::MSG_META_DEMO_TOGGLE_GREEN_VIEW },
|
||||
{ "DEMO_TOGGLE_MOTION_BLUR_ZOOM", GameMessage::MSG_META_DEMO_TOGGLE_MOTION_BLUR_ZOOM },
|
||||
{ "DEMO_SHOW_EXTENTS", GameMessage::MSG_META_DEBUG_SHOW_EXTENTS },
|
||||
{ "DEMO_SHOW_HEALTH", GameMessage::MSG_META_DEBUG_SHOW_HEALTH },
|
||||
{ "DEMO_GIVE_VETERANCY", GameMessage::MSG_META_DEBUG_GIVE_VETERANCY },
|
||||
{ "DEMO_TAKE_VETERANCY", GameMessage::MSG_META_DEBUG_TAKE_VETERANCY },
|
||||
{ "DEMO_BATTLE_CRY", GameMessage::MSG_META_DEMO_BATTLE_CRY },
|
||||
#ifdef ALLOW_SURRENDER
|
||||
{ "DEMO_TEST_SURRENDER", GameMessage::MSG_META_DEMO_TEST_SURRENDER },
|
||||
#endif
|
||||
{ "DEMO_TOGGLE_AVI", GameMessage::MSG_META_DEMO_TOGGLE_AVI },
|
||||
{ "DEMO_PLAY_CAMEO_MOVIE", GameMessage::MSG_META_DEMO_PLAY_CAMEO_MOVIE },
|
||||
{ "DEMO_TOGGLE_ZOOM_LOCK", GameMessage::MSG_META_DEMO_TOGGLE_ZOOM_LOCK },
|
||||
{ "DEMO_TOGGLE_SPECIAL_POWER_DELAYS", GameMessage::MSG_META_DEMO_TOGGLE_SPECIAL_POWER_DELAYS },
|
||||
|
||||
{ "DEMO_TOGGLE_METRICS", GameMessage::MSG_META_DEMO_TOGGLE_METRICS},
|
||||
{ "DEMO_DESHROUD", GameMessage::MSG_META_DEMO_DESHROUD },
|
||||
{ "DEMO_ENSHROUD", GameMessage::MSG_META_DEMO_ENSHROUD },
|
||||
{ "DEMO_TOGGLE_AI_DEBUG", GameMessage::MSG_META_DEMO_TOGGLE_AI_DEBUG },
|
||||
{ "DEMO_TOGGLE_NO_DRAW", GameMessage::MSG_NO_DRAW },
|
||||
{ "DEMO_CYCLE_LOD_LEVEL", GameMessage::MSG_META_DEMO_CYCLE_LOD_LEVEL },
|
||||
{ "DEMO_DUMP_ASSETS", GameMessage::MSG_META_DEBUG_DUMP_ASSETS},
|
||||
|
||||
{ "DEMO_INSTANT_BUILD", GameMessage::MSG_META_DEMO_INSTANT_BUILD },
|
||||
{ "DEMO_TOGGLE_CAMERA_DEBUG", GameMessage::MSG_META_DEMO_TOGGLE_CAMERA_DEBUG },
|
||||
|
||||
/// Begin VTUNE
|
||||
{ "DEMO_VTUNE_ON", GameMessage::MSG_META_DEBUG_VTUNE_ON },
|
||||
{ "DEMO_VTUNE_OFF", GameMessage::MSG_META_DEBUG_VTUNE_OFF },
|
||||
/// End VTUNE
|
||||
|
||||
|
||||
//lorenzen's feather water
|
||||
{ "DEMO_TOGGLE_FEATHER_WATER", GameMessage::MSG_META_DEBUG_TOGGLE_FEATHER_WATER },
|
||||
|
||||
{ "DEMO_INCR_ANIM_SKATE_SPEED", GameMessage::MSG_META_DEBUG_INCR_ANIM_SKATE_SPEED },
|
||||
{ "DEMO_DECR_ANIM_SKATE_SPEED", GameMessage::MSG_META_DEBUG_DECR_ANIM_SKATE_SPEED },
|
||||
{ "DEMO_CYCLE_EXTENT_TYPE", GameMessage::MSG_META_DEBUG_CYCLE_EXTENT_TYPE },
|
||||
{ "DEMO_INCR_EXTENT_MAJOR", GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MAJOR },
|
||||
{ "DEMO_DECR_EXTENT_MAJOR", GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MAJOR },
|
||||
{ "DEMO_INCR_EXTENT_MAJOR_LARGE", GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MAJOR_BIG },
|
||||
{ "DEMO_DECR_EXTENT_MAJOR_LARGE", GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MAJOR_BIG },
|
||||
{ "DEMO_INCR_EXTENT_MINOR", GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MINOR },
|
||||
{ "DEMO_DECR_EXTENT_MINOR", GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MINOR },
|
||||
{ "DEMO_INCR_EXTENT_MINOR_LARGE", GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MINOR_BIG },
|
||||
{ "DEMO_DECR_EXTENT_MINOR_LARGE", GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MINOR_BIG },
|
||||
{ "DEMO_INCR_EXTENT_HEIGHT", GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT },
|
||||
{ "DEMO_DECR_EXTENT_HEIGHT", GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT },
|
||||
{ "DEMO_INCR_EXTENT_HEIGHT_LARGE", GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT_BIG },
|
||||
{ "DEMO_DECR_EXTENT_HEIGHT_LARGE", GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT_BIG },
|
||||
{ "DEMO_TOGGLE_NETWORK", GameMessage::MSG_META_DEBUG_TOGGLE_NETWORK },
|
||||
{ "DEBUG_DUMP_PLAYER_OBJECTS", GameMessage::MSG_META_DEBUG_DUMP_PLAYER_OBJECTS },
|
||||
{ "DEBUG_DUMP_ALL_PLAYER_OBJECTS", GameMessage::MSG_META_DEBUG_DUMP_ALL_PLAYER_OBJECTS },
|
||||
{ "DEMO_WIN", GameMessage::MSG_META_DEBUG_WIN },
|
||||
{ "DEMO_TOGGLE_DEBUG_STATS", GameMessage::MSG_META_DEMO_TOGGLE_DEBUG_STATS },
|
||||
#endif // defined(_DEBUG) || defined(_INTERNAL)
|
||||
|
||||
|
||||
#if defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
|
||||
{ "DEMO_TOGGLE_AUDIODEBUG", GameMessage::MSG_META_DEMO_TOGGLE_AUDIODEBUG },
|
||||
#endif//defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
|
||||
#ifdef DUMP_PERF_STATS
|
||||
{ "DEMO_PERFORM_STATISTICAL_DUMP", GameMessage::MSG_META_DEMO_PERFORM_STATISTICAL_DUMP },
|
||||
#endif//DUMP_PERF_STATS
|
||||
|
||||
|
||||
{ NULL, 0 }// keep this last!
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static const FieldParse TheMetaMapFieldParseTable[] =
|
||||
{
|
||||
|
||||
{ "Key", INI::parseLookupList, KeyNames, offsetof( MetaMapRec, m_key ) },
|
||||
{ "Transition", INI::parseLookupList, TransitionNames, offsetof( MetaMapRec, m_transition ) },
|
||||
{ "Modifiers", INI::parseLookupList, ModifierNames, offsetof( MetaMapRec, m_modState ) },
|
||||
{ "UseableIn", INI::parseBitString32, TheCommandUsableInNames, offsetof( MetaMapRec, m_usableIn ) },
|
||||
{ "Category", INI::parseLookupList, CategoryListName, offsetof( MetaMapRec, m_category ) },
|
||||
{ "Description", INI::parseAndTranslateLabel, 0, offsetof( MetaMapRec, m_description ) },
|
||||
{ "DisplayName", INI::parseAndTranslateLabel, 0, offsetof( MetaMapRec, m_displayName ) },
|
||||
|
||||
{ NULL, NULL, 0, 0 } // keep this last
|
||||
|
||||
};
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
MetaEventTranslator::MetaEventTranslator() :
|
||||
m_lastKeyDown(MK_NONE),
|
||||
m_lastModState(0)
|
||||
{
|
||||
for (Int i = 0; i < NUM_MOUSE_BUTTONS; ++i) {
|
||||
m_nextUpShouldCreateDoubleClick[i] = FALSE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
MetaEventTranslator::~MetaEventTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static const char * findGameMessageNameByType(GameMessage::Type type)
|
||||
{
|
||||
for (const LookupListRec* metaNames = GameMessageMetaTypeNames; metaNames->name; metaNames++)
|
||||
if (metaNames->value == (Int)type)
|
||||
return metaNames->name;
|
||||
|
||||
DEBUG_CRASH(("MetaTypeName %d not found -- did you remember to add it to GameMessageMetaTypeNames[] ?\n"));
|
||||
return "???";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessage *msg)
|
||||
{
|
||||
GameMessageDisposition disp = KEEP_MESSAGE;
|
||||
GameMessage::Type t = msg->getType();
|
||||
|
||||
if (t == GameMessage::MSG_RAW_KEY_DOWN || t == GameMessage::MSG_RAW_KEY_UP)
|
||||
{
|
||||
MappableKeyType key = (MappableKeyType)msg->getArgument(0)->integer;
|
||||
Int keyState = msg->getArgument(1)->integer;
|
||||
|
||||
// for our purposes here, we don't care to distinguish between right and left keys,
|
||||
// so just fudge a little to simplify things.
|
||||
Int newModState = 0;
|
||||
|
||||
if( keyState & KEY_STATE_CONTROL )
|
||||
{
|
||||
newModState |= CTRL;
|
||||
}
|
||||
|
||||
if( keyState & KEY_STATE_SHIFT )
|
||||
{
|
||||
newModState |= SHIFT;
|
||||
}
|
||||
|
||||
if( keyState & KEY_STATE_ALT )
|
||||
{
|
||||
newModState |= ALT;
|
||||
}
|
||||
|
||||
for (const MetaMapRec *map = TheMetaMap->getFirstMetaMapRec(); map; map = map->m_next)
|
||||
{
|
||||
DEBUG_ASSERTCRASH(map->m_meta > GameMessage::MSG_BEGIN_META_MESSAGES &&
|
||||
map->m_meta < GameMessage::MSG_END_META_MESSAGES, ("hmm, expected only meta-msgs here"));
|
||||
|
||||
//
|
||||
// if this command is *only* usable in the game, we will ignore it if the game client
|
||||
// has not yet incremented to frame 1 (keeps us from doing in-game commands during
|
||||
// a map load, which throws the input system into wack because there isn't a
|
||||
// client frame for the input event, and in the case of a command that pauses the
|
||||
// game, like the quit menu, the client frame will never get beyond 0 and we
|
||||
// lose the ability to process any input
|
||||
//
|
||||
if( map->m_usableIn == COMMANDUSABLE_GAME && TheGameClient->getFrame() < 1 )
|
||||
continue;
|
||||
|
||||
// if the shell is active, and this command is not usable in shell, continue
|
||||
if (TheShell && TheShell->isShellActive() && !(map->m_usableIn & COMMANDUSABLE_SHELL) )
|
||||
continue;
|
||||
|
||||
// if the shell is not active and this command is not usable in the game, continue
|
||||
if (TheShell && !TheShell->isShellActive() && !(map->m_usableIn & COMMANDUSABLE_GAME) )
|
||||
continue;
|
||||
|
||||
// check for the special case of mods-only-changed.
|
||||
if (
|
||||
map->m_key == MK_NONE &&
|
||||
newModState != m_lastModState &&
|
||||
(
|
||||
(map->m_transition == UP && map->m_modState == m_lastModState) ||
|
||||
(map->m_transition == DOWN && map->m_modState == newModState)
|
||||
)
|
||||
)
|
||||
{
|
||||
//DEBUG_LOG(("Frame %d: MetaEventTranslator::translateGameMessage() Mods-only change: %s\n", TheGameLogic->getFrame(), findGameMessageNameByType(map->m_meta)));
|
||||
/*GameMessage *metaMsg =*/ TheMessageStream->appendMessage(map->m_meta);
|
||||
disp = DESTROY_MESSAGE;
|
||||
break;
|
||||
}
|
||||
|
||||
// ok, now check for "normal" key transitions.
|
||||
if (
|
||||
map->m_key == key &&
|
||||
map->m_modState == newModState &&
|
||||
(
|
||||
(map->m_transition == UP && (keyState & KEY_STATE_UP)) ||
|
||||
(map->m_transition == DOWN && (keyState & KEY_STATE_DOWN)) //||
|
||||
//(map->m_transition == DOUBLEDOWN && (keyState & KEY_STATE_DOWN) && m_lastKeyDown == key)
|
||||
)
|
||||
)
|
||||
{
|
||||
|
||||
if( keyState & KEY_STATE_AUTOREPEAT )
|
||||
{
|
||||
// if it's an autorepeat of a "known" key, don't generate the meta-event,
|
||||
// but DO eat the keystroke so no one else can mess with it
|
||||
//DEBUG_LOG(("Frame %d: MetaEventTranslator::translateGameMessage() auto-repeat: %s\n", TheGameLogic->getFrame(), findGameMessageNameByType(map->m_meta)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*GameMessage *metaMsg =*/ TheMessageStream->appendMessage(map->m_meta);
|
||||
//DEBUG_LOG(("Frame %d: MetaEventTranslator::translateGameMessage() normal: %s\n", TheGameLogic->getFrame(), findGameMessageNameByType(map->m_meta)));
|
||||
}
|
||||
disp = DESTROY_MESSAGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (t == GameMessage::MSG_RAW_KEY_DOWN)
|
||||
m_lastKeyDown = key;
|
||||
m_lastModState = newModState;
|
||||
}
|
||||
|
||||
|
||||
if (t > GameMessage::MSG_RAW_MOUSE_BEGIN && t < GameMessage::MSG_RAW_MOUSE_END )
|
||||
{
|
||||
Int index = 0;
|
||||
switch (t)
|
||||
{
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN:
|
||||
{
|
||||
// Fill out which the current mouse down position
|
||||
if (t == GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN)
|
||||
index = 1;
|
||||
else if (t == GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN)
|
||||
index = 2;
|
||||
// else index == 0
|
||||
m_mouseDownPosition[index] = msg->getArgument(0)->pixel;
|
||||
m_nextUpShouldCreateDoubleClick[index] = FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK:
|
||||
{
|
||||
if (t == GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK)
|
||||
index = 1;
|
||||
else if (t == GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK)
|
||||
index = 2;
|
||||
// else index == 0
|
||||
|
||||
m_nextUpShouldCreateDoubleClick[index] = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP:
|
||||
{
|
||||
ICoord2D location = msg->getArgument(0)->pixel;
|
||||
|
||||
// Fill out which the current mouse down position
|
||||
if (t == GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP)
|
||||
index = 1;
|
||||
else if (t == GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP)
|
||||
index = 2;
|
||||
// else index == 0
|
||||
|
||||
GameMessage *newMessage = NULL;
|
||||
if (t == GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP)
|
||||
{
|
||||
if (m_nextUpShouldCreateDoubleClick[index])
|
||||
newMessage = TheMessageStream->insertMessage(GameMessage::MSG_MOUSE_LEFT_DOUBLE_CLICK, const_cast<GameMessage*>(msg));
|
||||
else
|
||||
newMessage = TheMessageStream->insertMessage(GameMessage::MSG_MOUSE_LEFT_CLICK, const_cast<GameMessage*>(msg));
|
||||
m_nextUpShouldCreateDoubleClick[index] = FALSE;
|
||||
}
|
||||
else if (t == GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP)
|
||||
{
|
||||
if (m_nextUpShouldCreateDoubleClick[index])
|
||||
newMessage = TheMessageStream->insertMessage(GameMessage::MSG_MOUSE_MIDDLE_DOUBLE_CLICK, const_cast<GameMessage*>(msg));
|
||||
else
|
||||
newMessage = TheMessageStream->insertMessage(GameMessage::MSG_MOUSE_MIDDLE_CLICK, const_cast<GameMessage*>(msg));
|
||||
m_nextUpShouldCreateDoubleClick[index] = FALSE;
|
||||
}
|
||||
else if (t == GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP)
|
||||
{
|
||||
if (m_nextUpShouldCreateDoubleClick[index])
|
||||
newMessage = TheMessageStream->insertMessage(GameMessage::MSG_MOUSE_RIGHT_DOUBLE_CLICK, const_cast<GameMessage*>(msg));
|
||||
else
|
||||
newMessage = TheMessageStream->insertMessage(GameMessage::MSG_MOUSE_RIGHT_CLICK, const_cast<GameMessage*>(msg));
|
||||
m_nextUpShouldCreateDoubleClick[index] = FALSE;
|
||||
}
|
||||
|
||||
IRegion2D pixelRegion;
|
||||
buildRegion( &m_mouseDownPosition[index], &location, &pixelRegion );
|
||||
if (abs(pixelRegion.hi.x - pixelRegion.lo.x) < TheMouse->m_dragTolerance &&
|
||||
abs(pixelRegion.hi.y - pixelRegion.lo.y) < TheMouse->m_dragTolerance)
|
||||
{
|
||||
pixelRegion.hi.x = pixelRegion.lo.x;
|
||||
pixelRegion.hi.y = pixelRegion.lo.y;
|
||||
}
|
||||
|
||||
newMessage->appendPixelRegionArgument( pixelRegion );
|
||||
|
||||
// append the modifier keys to the message.
|
||||
newMessage->appendIntegerArgument( msg->getArgument(1)->integer );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
MetaMap::MetaMap() :
|
||||
m_metaMaps(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
MetaMap::~MetaMap()
|
||||
{
|
||||
while (m_metaMaps)
|
||||
{
|
||||
MetaMapRec *next = m_metaMaps->m_next;
|
||||
m_metaMaps->deleteInstance();
|
||||
m_metaMaps = next;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GameMessage::Type MetaMap::findGameMessageMetaType(const char* name)
|
||||
{
|
||||
for (const LookupListRec* metaNames = GameMessageMetaTypeNames; metaNames->name; metaNames++)
|
||||
if (stricmp(metaNames->name, name) == 0)
|
||||
return (GameMessage::Type)metaNames->value;
|
||||
|
||||
DEBUG_CRASH(("MetaTypeName %s not found -- did you remember to add it to GameMessageMetaTypeNames[] ?", name));
|
||||
return GameMessage::MSG_INVALID;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
MetaMapRec *MetaMap::getMetaMapRec(GameMessage::Type t)
|
||||
{
|
||||
for (MetaMapRec *map = m_metaMaps; map; map = map->m_next)
|
||||
{
|
||||
if (map->m_meta == t)
|
||||
return map;
|
||||
}
|
||||
|
||||
// not found.. create a new one.
|
||||
MetaMapRec *m = newInstance(MetaMapRec);
|
||||
m->m_meta = t;
|
||||
m->m_key = MK_NONE;
|
||||
m->m_transition = DOWN;
|
||||
m->m_modState = NONE;
|
||||
m->m_usableIn = COMMANDUSABLE_NONE;
|
||||
m->m_category = CATEGORY_MISC;
|
||||
m->m_description.clear();
|
||||
m->m_displayName.clear();
|
||||
m->m_next = m_metaMaps;
|
||||
m_metaMaps = m;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*static */ void MetaMap::parseMetaMap(INI* ini)
|
||||
{
|
||||
// read and ignore the meta-map name
|
||||
const char *c = ini->getNextToken();
|
||||
|
||||
GameMessage::Type t = TheMetaMap->findGameMessageMetaType(c);
|
||||
if (t == GameMessage::MSG_INVALID)
|
||||
throw INI_INVALID_DATA;
|
||||
|
||||
MetaMapRec *map = TheMetaMap->getMetaMapRec(t);
|
||||
if (map == NULL)
|
||||
throw INI_INVALID_DATA;
|
||||
|
||||
ini->initFromINI(map, TheMetaMapFieldParseTable);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*static*/ void INI::parseMetaMapDefinition( INI* ini )
|
||||
{
|
||||
MetaMap::parseMetaMap(ini);
|
||||
}
|
||||
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FILE: PlaceEventTranslator.cpp ///////////////////////////////////////////////////////////
|
||||
// Author: Steven Johnson, Dec 2001
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameAudio.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/BuildAssistant.h"
|
||||
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
#include "GameClient/CommandXlat.h"
|
||||
#include "GameClient/PlaceEventTranslator.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/Eva.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
PlaceEventTranslator::PlaceEventTranslator() : m_frameOfUpButton(-1)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
PlaceEventTranslator::~PlaceEventTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Translator to process raw input messages into the "place something" message(s) */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMessage *msg)
|
||||
{
|
||||
GameMessageDisposition disp = KEEP_MESSAGE;
|
||||
|
||||
switch(msg->getType())
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN:
|
||||
{
|
||||
// if we're in a building placement mode, do the place and send to all players
|
||||
const ThingTemplate *build = TheInGameUI->getPendingPlaceType();
|
||||
if( build && TheInGameUI->isPlacementAnchored() == FALSE )
|
||||
{
|
||||
ICoord2D mouse = msg->getArgument(0)->pixel;
|
||||
Coord3D world;
|
||||
|
||||
// translate mouse position to world position
|
||||
TheTacticalView->screenToTerrain( &mouse, &world );
|
||||
|
||||
//
|
||||
// placing things causes a dozer to go over and build it ... get the dozer in question
|
||||
// from the in game UI
|
||||
//
|
||||
Object *builderObject = TheGameLogic->findObjectByID( TheInGameUI->getPendingPlaceSourceObjectID() );
|
||||
|
||||
// if our source object is gone cancel this whole placement process
|
||||
if( builderObject == NULL )
|
||||
{
|
||||
|
||||
TheInGameUI->placeBuildAvailable( NULL, NULL );
|
||||
break;
|
||||
|
||||
} // end if
|
||||
|
||||
// set this location as the placement anchor
|
||||
TheInGameUI->setPlacementStart( &mouse );
|
||||
|
||||
/*
|
||||
//
|
||||
// This block of code checks for valid placement on a down mouse click, but since we can
|
||||
// rotate a building into a valid location, this check prevents us from placing things
|
||||
// down in some legal locations
|
||||
//
|
||||
// get the type of thing we want to build
|
||||
const ThingTemplate *whatToBuild = TheInGameUI->getPendingPlaceType();
|
||||
|
||||
//
|
||||
// if the spot at which they choose to place this thing is illegal we won't start
|
||||
// the placement anchor, instead we play a "can't do that" sound
|
||||
//
|
||||
LegalBuildCode lbc;
|
||||
lbc = TheBuildAssistant->isLocationLegalToBuild( &world,
|
||||
whatToBuild,
|
||||
TheInGameUI->getPlacementAngle(),
|
||||
BuildAssistant::USE_QUICK_PATHFIND |
|
||||
BuildAssistant::TERRAIN_RESTRICTIONS |
|
||||
BuildAssistant::CLEAR_PATH |
|
||||
BuildAssistant::NO_OBJECT_OVERLAP,
|
||||
builderObject );
|
||||
if( lbc != LBC_OK )
|
||||
{
|
||||
static const Sound *noCanDoSound = TheAudio->Sounds->getSound( "NoCanDoSound" );
|
||||
|
||||
// play a can't do that sound
|
||||
TheAudio->Sounds->playSound( noCanDoSound );
|
||||
|
||||
// display a message to the user as to why you can't build there
|
||||
TheInGameUI->displayCantBuildMessage( lbc );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// start placement anchor
|
||||
TheInGameUI->setPlacementStart(&mouse);
|
||||
|
||||
} // end else
|
||||
*/
|
||||
|
||||
// used the input
|
||||
disp = DESTROY_MESSAGE;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GameMessage::MSG_MOUSE_LEFT_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_MOUSE_LEFT_CLICK:
|
||||
{
|
||||
// if we're in a building placement mode, do the place and send to all players
|
||||
const ThingTemplate *build = TheInGameUI->getPendingPlaceType();
|
||||
|
||||
// ... and also remove any radius cursor that is active.
|
||||
// (srj sez: not sure if this is always necessary... more of a failsafe to make it go away.)
|
||||
TheInGameUI->setRadiusCursorNone();
|
||||
|
||||
if (build && TheInGameUI->isPlacementAnchored())
|
||||
{
|
||||
GameMessage *placeMsg;
|
||||
// Player *player = ThePlayerList->getLocalPlayer();
|
||||
Coord3D world;
|
||||
Real angle;
|
||||
ICoord2D anchorStart, anchorEnd;
|
||||
Bool isLineBuild = TheBuildAssistant->isLineBuildTemplate( build );
|
||||
|
||||
// get the angle of the drawable at the cursor to use as the initial angle
|
||||
angle = TheInGameUI->getPlacementAngle();
|
||||
|
||||
// get start point from the anchor arrow used to place and select angles
|
||||
TheInGameUI->getPlacementPoints( &anchorStart, &anchorEnd );
|
||||
|
||||
// translate the screen position of start to world target location
|
||||
TheTacticalView->screenToTerrain( &anchorStart, &world );
|
||||
|
||||
// get the source object ID of the thing that is "building" the object
|
||||
ObjectID builderID = INVALID_ID;
|
||||
Object *builderObj = TheGameLogic->findObjectByID( TheInGameUI->getPendingPlaceSourceObjectID() );
|
||||
if( builderObj )
|
||||
builderID = builderObj->getID();
|
||||
|
||||
//Kris: September 27, 2002
|
||||
//Make sure we have enough CASH to build it! It's possible that between the
|
||||
//time we initiated it and the time we confirm it, a hacker has stolen some of
|
||||
//our cash!
|
||||
CanMakeType cmt = TheBuildAssistant->canMakeUnit( builderObj, build );
|
||||
if( cmt != CANMAKE_OK )
|
||||
{
|
||||
if (cmt == CANMAKE_NO_MONEY)
|
||||
{
|
||||
TheEva->setShouldPlay(EVA_InsufficientFunds);
|
||||
TheInGameUI->message( "GUI:NotEnoughMoneyToBuild" );
|
||||
break;
|
||||
}
|
||||
else if (cmt == CANMAKE_QUEUE_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ProductionQueueFull" );
|
||||
break;
|
||||
}
|
||||
else if (cmt == CANMAKE_PARKING_PLACES_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ParkingPlacesFull" );
|
||||
break;
|
||||
}
|
||||
else if( cmt == CANMAKE_MAXED_OUT_FOR_PLAYER )
|
||||
{
|
||||
TheInGameUI->message( "GUI:UnitMaxedOut" );
|
||||
break;
|
||||
}
|
||||
// get out of pending placement mode, this will also clear the arrow anchor status
|
||||
TheInGameUI->placeBuildAvailable( NULL, NULL );
|
||||
break;
|
||||
}
|
||||
|
||||
// check to see if this is a legal location to build something at
|
||||
LegalBuildCode lbc;
|
||||
lbc = TheBuildAssistant->isLocationLegalToBuild( &world,
|
||||
build,
|
||||
angle,
|
||||
BuildAssistant::USE_QUICK_PATHFIND |
|
||||
BuildAssistant::TERRAIN_RESTRICTIONS |
|
||||
BuildAssistant::CLEAR_PATH |
|
||||
BuildAssistant::NO_OBJECT_OVERLAP |
|
||||
BuildAssistant::SHROUD_REVEALED,
|
||||
builderObj, NULL );
|
||||
if( lbc == LBC_OK )
|
||||
{
|
||||
|
||||
/** @todo Do not send local player id as argument once we have player ids
|
||||
tied into all messages automatically */
|
||||
|
||||
// create the right kind of message
|
||||
if( isLineBuild )
|
||||
placeMsg = TheMessageStream->appendMessage( GameMessage::MSG_DOZER_CONSTRUCT_LINE );
|
||||
else
|
||||
placeMsg = TheMessageStream->appendMessage( GameMessage::MSG_DOZER_CONSTRUCT );
|
||||
|
||||
placeMsg->appendIntegerArgument(build->getTemplateID());
|
||||
placeMsg->appendLocationArgument(world);
|
||||
placeMsg->appendRealArgument(angle);
|
||||
if( isLineBuild )
|
||||
{
|
||||
Coord3D worldEnd;
|
||||
|
||||
TheTacticalView->screenToTerrain( &anchorEnd, &worldEnd );
|
||||
placeMsg->appendLocationArgument( worldEnd );
|
||||
|
||||
} // end if
|
||||
|
||||
pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), placeMsg->getType() );
|
||||
|
||||
// get out of pending placement mode, this will also clear the arrow anchor status
|
||||
TheInGameUI->placeBuildAvailable( NULL, NULL );
|
||||
|
||||
} // end if, location legal to build at
|
||||
else
|
||||
{
|
||||
// can't place, display why
|
||||
TheInGameUI->displayCantBuildMessage( lbc );
|
||||
|
||||
//Cannot build here -- play the voice sound from the dozer
|
||||
AudioEventRTS sound = *builderObj->getTemplate()->getPerUnitSound( "VoiceNoBuild" );
|
||||
sound.setObjectID( builderObj->getID() );
|
||||
TheAudio->addAudioEvent( &sound );
|
||||
|
||||
// play a can't do that sound (UI beep type sound)
|
||||
static AudioEventRTS noCanDoSound( "NoCanDoSound" );
|
||||
TheAudio->addAudioEvent( &noCanDoSound );
|
||||
|
||||
// unhook the anchor so they can try again
|
||||
TheInGameUI->setPlacementStart( NULL );
|
||||
|
||||
} // end else
|
||||
|
||||
// used the input
|
||||
disp = DESTROY_MESSAGE;
|
||||
m_frameOfUpButton = TheGameLogic->getFrame();
|
||||
|
||||
}
|
||||
|
||||
if (disp == DESTROY_MESSAGE)
|
||||
TheInGameUI->clearAttackMoveToMode();
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_POSITION:
|
||||
{
|
||||
// if a building placement is in progress update the destination position
|
||||
if (TheInGameUI->isPlacementAnchored())
|
||||
{
|
||||
const Int PLACEMENT_DRAG_THRESHOLD_DIST = 5; // in pixels away from anchor point
|
||||
ICoord2D mouse = msg->getArgument(0)->pixel;
|
||||
|
||||
//
|
||||
// we will only process placement end point sets (clicking, and dragging to set angles)
|
||||
// if we have moved far enough away from the start point
|
||||
//
|
||||
ICoord2D start;
|
||||
TheInGameUI->getPlacementPoints( &start, NULL );
|
||||
|
||||
Int x, y;
|
||||
x = mouse.x - start.x;
|
||||
y = mouse.y - start.y;
|
||||
if( sqrt( (x * x) + (y * y) ) >= PLACEMENT_DRAG_THRESHOLD_DIST )
|
||||
{
|
||||
|
||||
TheInGameUI->setPlacementEnd(&mouse);
|
||||
disp = DESTROY_MESSAGE;
|
||||
|
||||
} // end if
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
** Command & Conquer Generals(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// (c) 2001-2003 Electronic Arts Inc. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FILE: WindowXlat.cpp ///////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: WindowXlat.cpp
|
||||
//
|
||||
// Created: Colin Day, September 2001
|
||||
//
|
||||
// Desc: Window system translator that monitors raw input messages
|
||||
// on the stream from the input devices and acts on anything
|
||||
// relevant to the windowing system.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/MessageStream.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/WindowXlat.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/Display.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(_DEBUG) || defined(_INTERNAL) //debug hack to view object under mouse stats
|
||||
extern ICoord2D TheMousePos;
|
||||
#endif
|
||||
|
||||
// rawMouseToWindowMessage ====================================================
|
||||
/** Translate a raw mouse input event to a game window specific message
|
||||
* for the window system */
|
||||
//=============================================================================
|
||||
static GameWindowMessage rawMouseToWindowMessage( const GameMessage *msg )
|
||||
{
|
||||
GameWindowMessage gwm = GWM_NONE;
|
||||
|
||||
switch( msg->getType() )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_POSITION:
|
||||
gwm = GWM_MOUSE_POS;
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Strange, but true. The window stuff really doesn't care about double clicks, so just
|
||||
// treat it as a down click.. Kinda like a second click.
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN:
|
||||
gwm = GWM_LEFT_DOWN;
|
||||
break;
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP:
|
||||
gwm = GWM_LEFT_UP;
|
||||
break;
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_DRAG:
|
||||
gwm = GWM_LEFT_DRAG;
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN:
|
||||
gwm = GWM_MIDDLE_DOWN;
|
||||
break;
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP:
|
||||
gwm = GWM_MIDDLE_UP;
|
||||
break;
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_DRAG:
|
||||
gwm = GWM_MIDDLE_DRAG;
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN:
|
||||
gwm = GWM_RIGHT_DOWN;
|
||||
break;
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP:
|
||||
gwm = GWM_RIGHT_UP;
|
||||
break;
|
||||
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_DRAG:
|
||||
gwm = GWM_RIGHT_DRAG;
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_WHEEL:
|
||||
if( msg->getArgument( 1 )->integer > 0 )
|
||||
gwm = GWM_WHEEL_UP;
|
||||
else
|
||||
gwm = GWM_WHEEL_DOWN;
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
|
||||
return gwm;
|
||||
|
||||
} // end rawMouseToWindowMessage
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//=============================================================================
|
||||
WindowTranslator::WindowTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
WindowTranslator::~WindowTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
// WindowTranslator ===========================================================
|
||||
/** Window translator that monitors raw input messages on the stream and
|
||||
* acts on anything relavant to the windowing system */
|
||||
//=============================================================================
|
||||
GameMessageDisposition WindowTranslator::translateGameMessage(const GameMessage *msg)
|
||||
{
|
||||
GameMessageDisposition disp = KEEP_MESSAGE;
|
||||
Bool forceKeepMessage = FALSE;
|
||||
WinInputReturnCode returnCode = WIN_INPUT_NOT_USED;
|
||||
|
||||
if (TheTacticalView && TheTacticalView->isMouseLocked())
|
||||
{
|
||||
return KEEP_MESSAGE;
|
||||
}
|
||||
|
||||
switch( msg->getType() )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_META_TOGGLE_ATTACKMOVE:
|
||||
{
|
||||
// Basically, we're cheating here. The mouse no longer sends us useless spam.
|
||||
ICoord2D mousePos = TheMouse->getMouseStatus()->pos;
|
||||
|
||||
if( TheWindowManager )
|
||||
TheWindowManager->winProcessMouseEvent( GWM_NONE, &mousePos, NULL );
|
||||
|
||||
// Force it to keep the message, regardless of what the window thinks it did with the input.
|
||||
return KEEP_MESSAGE;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP:
|
||||
{
|
||||
if( TheInGameUI && TheInGameUI->isPlacementAnchored() )
|
||||
{
|
||||
//If we release the button outside
|
||||
forceKeepMessage = TRUE;
|
||||
}
|
||||
//FALL THROUGH INTENTIONALLY!
|
||||
}
|
||||
case GameMessage::MSG_RAW_MOUSE_POSITION:
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN:
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP:
|
||||
{
|
||||
// all window events have the position of the mouse as arg 0
|
||||
ICoord2D mousePos = msg->getArgument( 0 )->pixel;
|
||||
#if defined(_DEBUG) || defined(_INTERNAL) //debug hack to view object under mouse stats
|
||||
TheMousePos.x = mousePos.x;
|
||||
TheMousePos.y = mousePos.y;
|
||||
#endif
|
||||
|
||||
// process the mouse event position
|
||||
GameWindowMessage gwm = rawMouseToWindowMessage( msg );
|
||||
if( TheWindowManager )
|
||||
returnCode = TheWindowManager->winProcessMouseEvent( gwm, &mousePos, NULL );
|
||||
|
||||
if( TheShell && TheShell->isShellActive() )
|
||||
returnCode = WIN_INPUT_USED;
|
||||
|
||||
if ( TheInGameUI && TheInGameUI->getInputEnabled() == FALSE )
|
||||
returnCode = WIN_INPUT_USED;
|
||||
|
||||
break;
|
||||
|
||||
} // end, raw mouse position
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_LEFT_DRAG:
|
||||
case GameMessage::MSG_RAW_MOUSE_MIDDLE_DRAG:
|
||||
case GameMessage::MSG_RAW_MOUSE_RIGHT_DRAG:
|
||||
{
|
||||
// all window events have the position of the mouse as arg 0
|
||||
ICoord2D mousePos = msg->getArgument( 0 )->pixel;
|
||||
|
||||
// get delta for drag
|
||||
ICoord2D delta = msg->getArgument( 1 )->pixel;
|
||||
|
||||
// process drag event
|
||||
GameWindowMessage gwm = rawMouseToWindowMessage( msg );
|
||||
if( TheWindowManager )
|
||||
returnCode = TheWindowManager->winProcessMouseEvent( gwm, &mousePos, &delta );
|
||||
|
||||
if( TheShell && TheShell->isShellActive() )
|
||||
returnCode = WIN_INPUT_USED;
|
||||
|
||||
if ( TheInGameUI && TheInGameUI->getInputEnabled() == FALSE )
|
||||
returnCode = WIN_INPUT_USED;
|
||||
|
||||
break;
|
||||
|
||||
} // end drag mouse
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_MOUSE_WHEEL:
|
||||
{
|
||||
// all window events have the position of the mouse as arg 0
|
||||
ICoord2D mousePos = msg->getArgument( 0 )->pixel;
|
||||
|
||||
// get wheel position
|
||||
Int wheelPos = msg->getArgument( 1 )->integer;
|
||||
|
||||
// process wheel event
|
||||
GameWindowMessage gwm = rawMouseToWindowMessage( msg );
|
||||
if( TheWindowManager )
|
||||
returnCode = TheWindowManager->winProcessMouseEvent( gwm, &mousePos,
|
||||
&wheelPos );
|
||||
|
||||
if( TheShell && TheShell->isShellActive() )
|
||||
returnCode = WIN_INPUT_USED;
|
||||
|
||||
if ( TheInGameUI && TheInGameUI->getInputEnabled() == FALSE )
|
||||
returnCode = WIN_INPUT_USED;
|
||||
|
||||
break;
|
||||
|
||||
} // end mouse wheel
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GameMessage::MSG_RAW_KEY_DOWN:
|
||||
case GameMessage::MSG_RAW_KEY_UP:
|
||||
{
|
||||
// get key and state from args
|
||||
UnsignedByte key = msg->getArgument( 0 )->integer;
|
||||
UnsignedByte state = msg->getArgument( 1 )->integer;
|
||||
|
||||
// process event through window system
|
||||
if( TheWindowManager )
|
||||
returnCode = TheWindowManager->winProcessKey( key, state );
|
||||
|
||||
|
||||
// If we're in a movie, we want to be able to escape out of it
|
||||
if(returnCode != WIN_INPUT_USED
|
||||
&& (key == KEY_ESC)
|
||||
&& (BitTest( state, KEY_STATE_UP ))
|
||||
&& TheDisplay->isMoviePlaying()
|
||||
&& TheGlobalData->m_allowExitOutOfMovies == TRUE )
|
||||
{
|
||||
TheDisplay->stopMovie();
|
||||
returnCode = WIN_INPUT_USED;
|
||||
}
|
||||
|
||||
if(returnCode != WIN_INPUT_USED
|
||||
&& (key == KEY_ESC)
|
||||
&& (BitTest( state, KEY_STATE_UP ))
|
||||
&& (TheInGameUI && (TheInGameUI->getInputEnabled() == FALSE)) )
|
||||
{
|
||||
returnCode = WIN_INPUT_USED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end key messages
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
break;
|
||||
|
||||
} // end switch( msg->getType() )
|
||||
|
||||
// remove event from the stream if the return code specifies to do so
|
||||
// If TheShell doesn't exist, then well, we're not in RTS, we're in GUIEdit
|
||||
if( returnCode == WIN_INPUT_USED && !forceKeepMessage )// || (TheShell && TheShell->isShellActive()))
|
||||
{
|
||||
disp = DESTROY_MESSAGE;
|
||||
}
|
||||
|
||||
return disp;
|
||||
|
||||
}
|
Reference in a new issue