1240 lines
34 KiB
C++
1240 lines
34 KiB
C++
/*
|
|
** Command & Conquer Generals Zero Hour(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. //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// MessageStream.cpp
|
|
// Implementation of the message stream
|
|
// Author: Michael S. Booth, February 2001
|
|
|
|
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
|
|
|
#include "Common/MessageStream.h"
|
|
#include "Common/Player.h"
|
|
#include "Common/PlayerList.h"
|
|
#include "Common/Recorder.h"
|
|
|
|
#include "GameClient/InGameUI.h"
|
|
#include "GameLogic/GameLogic.h"
|
|
|
|
/// The singleton message stream for messages going to TheGameLogic
|
|
MessageStream *TheMessageStream = NULL;
|
|
CommandList *TheCommandList = NULL;
|
|
|
|
|
|
|
|
#ifdef _INTERNAL
|
|
// for occasional debugging...
|
|
//#pragma optimize("", off)
|
|
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
|
#endif
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
// GameMessage
|
|
//
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
GameMessage::GameMessage( GameMessage::Type type )
|
|
{
|
|
m_playerIndex = ThePlayerList->getLocalPlayer()->getPlayerIndex();
|
|
m_type = type;
|
|
m_argList = NULL;
|
|
m_argTail = NULL;
|
|
m_argCount = 0;
|
|
m_list = 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
GameMessage::~GameMessage( )
|
|
{
|
|
// free all arguments
|
|
GameMessageArgument *arg, *nextArg;
|
|
|
|
for( arg = m_argList; arg; arg=nextArg )
|
|
{
|
|
nextArg = arg->m_next;
|
|
arg->deleteInstance();
|
|
}
|
|
|
|
// detach message from list
|
|
if (m_list)
|
|
m_list->removeMessage( this );
|
|
}
|
|
|
|
/**
|
|
* Return the given argument union.
|
|
* @todo This should be a more list-like interface. Very inefficient.
|
|
*/
|
|
const GameMessageArgumentType *GameMessage::getArgument( Int argIndex ) const
|
|
{
|
|
static const GameMessageArgumentType junk = { 0 };
|
|
|
|
int i=0;
|
|
for( GameMessageArgument *a = m_argList; a; a=a->m_next, i++ )
|
|
if (i == argIndex)
|
|
return &a->m_data;
|
|
|
|
DEBUG_CRASH(("argument not found"));
|
|
return &junk;
|
|
}
|
|
|
|
/**
|
|
* Return the given argument data type
|
|
*/
|
|
GameMessageArgumentDataType GameMessage::getArgumentDataType( Int argIndex )
|
|
{
|
|
if (argIndex >= m_argCount) {
|
|
return ARGUMENTDATATYPE_UNKNOWN;
|
|
}
|
|
int i=0;
|
|
for (GameMessageArgument *a = m_argList; a && (i < argIndex); a=a->m_next, ++i );
|
|
|
|
if (a != NULL)
|
|
{
|
|
return a->m_type;
|
|
}
|
|
return ARGUMENTDATATYPE_UNKNOWN;
|
|
}
|
|
|
|
/**
|
|
* Allocate a new argument, add it to the argument list, and increment the total arg count
|
|
*/
|
|
GameMessageArgument *GameMessage::allocArg( void )
|
|
{
|
|
// allocate a new argument
|
|
GameMessageArgument *arg = newInstance(GameMessageArgument);
|
|
|
|
// add to end of argument list
|
|
if (m_argTail)
|
|
m_argTail->m_next = arg;
|
|
else
|
|
{
|
|
m_argList = arg;
|
|
m_argTail = arg;
|
|
}
|
|
|
|
arg->m_next = NULL;
|
|
m_argTail = arg;
|
|
|
|
m_argCount++;
|
|
|
|
return arg;
|
|
}
|
|
|
|
/**
|
|
* Append an integer argument
|
|
*/
|
|
void GameMessage::appendIntegerArgument( Int arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.integer = arg;
|
|
a->m_type = ARGUMENTDATATYPE_INTEGER;
|
|
}
|
|
|
|
void GameMessage::appendRealArgument( Real arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.real = arg;
|
|
a->m_type = ARGUMENTDATATYPE_REAL;
|
|
}
|
|
|
|
void GameMessage::appendBooleanArgument( Bool arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.boolean = arg;
|
|
a->m_type = ARGUMENTDATATYPE_BOOLEAN;
|
|
}
|
|
|
|
void GameMessage::appendObjectIDArgument( ObjectID arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.objectID = arg;
|
|
a->m_type = ARGUMENTDATATYPE_OBJECTID;
|
|
}
|
|
|
|
void GameMessage::appendDrawableIDArgument( DrawableID arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.drawableID = arg;
|
|
a->m_type = ARGUMENTDATATYPE_DRAWABLEID;
|
|
}
|
|
|
|
void GameMessage::appendTeamIDArgument( UnsignedInt arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.teamID = arg;
|
|
a->m_type = ARGUMENTDATATYPE_TEAMID;
|
|
}
|
|
|
|
void GameMessage::appendLocationArgument( const Coord3D& arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.location = arg;
|
|
a->m_type = ARGUMENTDATATYPE_LOCATION;
|
|
}
|
|
|
|
void GameMessage::appendPixelArgument( const ICoord2D& arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.pixel = arg;
|
|
a->m_type = ARGUMENTDATATYPE_PIXEL;
|
|
}
|
|
|
|
void GameMessage::appendPixelRegionArgument( const IRegion2D& arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.pixelRegion = arg;
|
|
a->m_type = ARGUMENTDATATYPE_PIXELREGION;
|
|
}
|
|
|
|
void GameMessage::appendTimestampArgument( UnsignedInt arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.timestamp = arg;
|
|
a->m_type = ARGUMENTDATATYPE_TIMESTAMP;
|
|
}
|
|
|
|
void GameMessage::appendWideCharArgument( const WideChar& arg )
|
|
{
|
|
GameMessageArgument *a = allocArg();
|
|
a->m_data.wChar = arg;
|
|
a->m_type = ARGUMENTDATATYPE_WIDECHAR;
|
|
}
|
|
|
|
AsciiString GameMessage::getCommandAsAsciiString( void )
|
|
{
|
|
return getCommandTypeAsAsciiString(m_type);
|
|
}
|
|
|
|
AsciiString GameMessage::getCommandTypeAsAsciiString(GameMessage::Type t)
|
|
{
|
|
#define CHECK_IF(x) if (t == x) { return #x; }
|
|
AsciiString commandName = "UnknownMessage";
|
|
if (t >= GameMessage::MSG_COUNT)
|
|
{
|
|
commandName = "Invalid command";
|
|
}
|
|
CHECK_IF(MSG_INVALID)
|
|
CHECK_IF(MSG_FRAME_TICK)
|
|
CHECK_IF(MSG_RAW_MOUSE_BEGIN)
|
|
CHECK_IF(MSG_RAW_MOUSE_POSITION)
|
|
CHECK_IF(MSG_RAW_MOUSE_LEFT_BUTTON_DOWN)
|
|
CHECK_IF(MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK)
|
|
CHECK_IF(MSG_RAW_MOUSE_LEFT_BUTTON_UP)
|
|
CHECK_IF(MSG_RAW_MOUSE_LEFT_CLICK)
|
|
CHECK_IF(MSG_RAW_MOUSE_LEFT_DRAG)
|
|
CHECK_IF(MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN)
|
|
CHECK_IF(MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK)
|
|
CHECK_IF(MSG_RAW_MOUSE_MIDDLE_BUTTON_UP)
|
|
CHECK_IF(MSG_RAW_MOUSE_MIDDLE_DRAG)
|
|
CHECK_IF(MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN)
|
|
CHECK_IF(MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK)
|
|
CHECK_IF(MSG_RAW_MOUSE_RIGHT_BUTTON_UP)
|
|
CHECK_IF(MSG_RAW_MOUSE_RIGHT_DRAG)
|
|
CHECK_IF(MSG_RAW_MOUSE_WHEEL)
|
|
CHECK_IF(MSG_RAW_MOUSE_END)
|
|
CHECK_IF(MSG_RAW_KEY_DOWN)
|
|
CHECK_IF(MSG_RAW_KEY_UP)
|
|
CHECK_IF(MSG_MOUSE_LEFT_CLICK)
|
|
CHECK_IF(MSG_MOUSE_LEFT_DOUBLE_CLICK)
|
|
CHECK_IF(MSG_MOUSE_MIDDLE_CLICK)
|
|
CHECK_IF(MSG_MOUSE_MIDDLE_DOUBLE_CLICK)
|
|
CHECK_IF(MSG_MOUSE_RIGHT_CLICK)
|
|
CHECK_IF(MSG_MOUSE_RIGHT_DOUBLE_CLICK)
|
|
CHECK_IF(MSG_CLEAR_GAME_DATA)
|
|
CHECK_IF(MSG_NEW_GAME)
|
|
CHECK_IF(MSG_BEGIN_META_MESSAGES)
|
|
CHECK_IF(MSG_META_SAVE_VIEW1)
|
|
CHECK_IF(MSG_META_SAVE_VIEW2)
|
|
CHECK_IF(MSG_META_SAVE_VIEW3)
|
|
CHECK_IF(MSG_META_SAVE_VIEW4)
|
|
CHECK_IF(MSG_META_SAVE_VIEW5)
|
|
CHECK_IF(MSG_META_SAVE_VIEW6)
|
|
CHECK_IF(MSG_META_SAVE_VIEW7)
|
|
CHECK_IF(MSG_META_SAVE_VIEW8)
|
|
CHECK_IF(MSG_META_VIEW_VIEW1)
|
|
CHECK_IF(MSG_META_VIEW_VIEW2)
|
|
CHECK_IF(MSG_META_VIEW_VIEW3)
|
|
CHECK_IF(MSG_META_VIEW_VIEW4)
|
|
CHECK_IF(MSG_META_VIEW_VIEW5)
|
|
CHECK_IF(MSG_META_VIEW_VIEW6)
|
|
CHECK_IF(MSG_META_VIEW_VIEW7)
|
|
CHECK_IF(MSG_META_VIEW_VIEW8)
|
|
CHECK_IF(MSG_META_CREATE_TEAM0)
|
|
CHECK_IF(MSG_META_CREATE_TEAM1)
|
|
CHECK_IF(MSG_META_CREATE_TEAM2)
|
|
CHECK_IF(MSG_META_CREATE_TEAM3)
|
|
CHECK_IF(MSG_META_CREATE_TEAM4)
|
|
CHECK_IF(MSG_META_CREATE_TEAM5)
|
|
CHECK_IF(MSG_META_CREATE_TEAM6)
|
|
CHECK_IF(MSG_META_CREATE_TEAM7)
|
|
CHECK_IF(MSG_META_CREATE_TEAM8)
|
|
CHECK_IF(MSG_META_CREATE_TEAM9)
|
|
CHECK_IF(MSG_META_SELECT_TEAM0)
|
|
CHECK_IF(MSG_META_SELECT_TEAM1)
|
|
CHECK_IF(MSG_META_SELECT_TEAM2)
|
|
CHECK_IF(MSG_META_SELECT_TEAM3)
|
|
CHECK_IF(MSG_META_SELECT_TEAM4)
|
|
CHECK_IF(MSG_META_SELECT_TEAM5)
|
|
CHECK_IF(MSG_META_SELECT_TEAM6)
|
|
CHECK_IF(MSG_META_SELECT_TEAM7)
|
|
CHECK_IF(MSG_META_SELECT_TEAM8)
|
|
CHECK_IF(MSG_META_SELECT_TEAM9)
|
|
CHECK_IF(MSG_META_ADD_TEAM0)
|
|
CHECK_IF(MSG_META_ADD_TEAM1)
|
|
CHECK_IF(MSG_META_ADD_TEAM2)
|
|
CHECK_IF(MSG_META_ADD_TEAM3)
|
|
CHECK_IF(MSG_META_ADD_TEAM4)
|
|
CHECK_IF(MSG_META_ADD_TEAM5)
|
|
CHECK_IF(MSG_META_ADD_TEAM6)
|
|
CHECK_IF(MSG_META_ADD_TEAM7)
|
|
CHECK_IF(MSG_META_ADD_TEAM8)
|
|
CHECK_IF(MSG_META_ADD_TEAM9)
|
|
CHECK_IF(MSG_META_VIEW_TEAM0)
|
|
CHECK_IF(MSG_META_VIEW_TEAM1)
|
|
CHECK_IF(MSG_META_VIEW_TEAM2)
|
|
CHECK_IF(MSG_META_VIEW_TEAM3)
|
|
CHECK_IF(MSG_META_VIEW_TEAM4)
|
|
CHECK_IF(MSG_META_VIEW_TEAM5)
|
|
CHECK_IF(MSG_META_VIEW_TEAM6)
|
|
CHECK_IF(MSG_META_VIEW_TEAM7)
|
|
CHECK_IF(MSG_META_VIEW_TEAM8)
|
|
CHECK_IF(MSG_META_VIEW_TEAM9)
|
|
CHECK_IF(MSG_META_SELECT_MATCHING_UNITS)
|
|
CHECK_IF(MSG_META_SELECT_NEXT_UNIT)
|
|
CHECK_IF(MSG_META_SELECT_PREV_UNIT)
|
|
CHECK_IF(MSG_META_SELECT_NEXT_WORKER)
|
|
CHECK_IF(MSG_META_SELECT_PREV_WORKER)
|
|
CHECK_IF(MSG_META_VIEW_COMMAND_CENTER)
|
|
CHECK_IF(MSG_META_VIEW_LAST_RADAR_EVENT)
|
|
CHECK_IF(MSG_META_SELECT_HERO)
|
|
CHECK_IF(MSG_META_SELECT_ALL)
|
|
CHECK_IF(MSG_META_SELECT_ALL_AIRCRAFT)
|
|
CHECK_IF(MSG_META_SCATTER)
|
|
CHECK_IF(MSG_META_STOP)
|
|
CHECK_IF(MSG_META_DEPLOY)
|
|
CHECK_IF(MSG_META_CREATE_FORMATION)
|
|
CHECK_IF(MSG_META_FOLLOW)
|
|
CHECK_IF(MSG_META_CHAT_PLAYERS)
|
|
CHECK_IF(MSG_META_CHAT_ALLIES)
|
|
CHECK_IF(MSG_META_CHAT_EVERYONE)
|
|
CHECK_IF(MSG_META_DIPLOMACY)
|
|
CHECK_IF(MSG_META_OPTIONS)
|
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
|
CHECK_IF(MSG_META_HELP)
|
|
#endif
|
|
CHECK_IF(MSG_META_TOGGLE_LOWER_DETAILS)
|
|
CHECK_IF(MSG_META_TOGGLE_CONTROL_BAR)
|
|
CHECK_IF(MSG_META_BEGIN_PATH_BUILD)
|
|
CHECK_IF(MSG_META_END_PATH_BUILD)
|
|
CHECK_IF(MSG_META_BEGIN_FORCEATTACK)
|
|
CHECK_IF(MSG_META_END_FORCEATTACK)
|
|
CHECK_IF(MSG_META_BEGIN_FORCEMOVE)
|
|
CHECK_IF(MSG_META_END_FORCEMOVE)
|
|
CHECK_IF(MSG_META_BEGIN_WAYPOINTS)
|
|
CHECK_IF(MSG_META_END_WAYPOINTS)
|
|
CHECK_IF(MSG_META_BEGIN_PREFER_SELECTION)
|
|
CHECK_IF(MSG_META_END_PREFER_SELECTION)
|
|
CHECK_IF(MSG_META_TAKE_SCREENSHOT)
|
|
CHECK_IF(MSG_META_ALL_CHEER)
|
|
CHECK_IF(MSG_META_TOGGLE_ATTACKMOVE)
|
|
CHECK_IF(MSG_META_BEGIN_CAMERA_ROTATE_LEFT)
|
|
CHECK_IF(MSG_META_END_CAMERA_ROTATE_LEFT)
|
|
CHECK_IF(MSG_META_BEGIN_CAMERA_ROTATE_RIGHT)
|
|
CHECK_IF(MSG_META_END_CAMERA_ROTATE_RIGHT)
|
|
CHECK_IF(MSG_META_BEGIN_CAMERA_ZOOM_IN)
|
|
CHECK_IF(MSG_META_END_CAMERA_ZOOM_IN)
|
|
CHECK_IF(MSG_META_BEGIN_CAMERA_ZOOM_OUT)
|
|
CHECK_IF(MSG_META_END_CAMERA_ZOOM_OUT)
|
|
CHECK_IF(MSG_META_CAMERA_RESET)
|
|
CHECK_IF(MSG_META_TOGGLE_CAMERA_TRACKING_DRAWABLE)
|
|
CHECK_IF(MSG_META_DEMO_INSTANT_QUIT)
|
|
|
|
|
|
#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT1)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT2)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT3)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT4)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT5)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT6)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT7)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT8)
|
|
CHECK_IF(MSG_CHEAT_RUNSCRIPT9)
|
|
CHECK_IF(MSG_CHEAT_TOGGLE_SPECIAL_POWER_DELAYS)
|
|
CHECK_IF(MSG_CHEAT_SWITCH_TEAMS)
|
|
CHECK_IF(MSG_CHEAT_KILL_SELECTION)
|
|
CHECK_IF(MSG_CHEAT_TOGGLE_HAND_OF_GOD_MODE)
|
|
CHECK_IF(MSG_CHEAT_INSTANT_BUILD)
|
|
CHECK_IF(MSG_CHEAT_DESHROUD)
|
|
CHECK_IF(MSG_CHEAT_ADD_CASH)
|
|
CHECK_IF(MSG_CHEAT_GIVE_ALL_SCIENCES)
|
|
CHECK_IF(MSG_CHEAT_GIVE_SCIENCEPURCHASEPOINTS)
|
|
CHECK_IF(MSG_CHEAT_SHOW_HEALTH)
|
|
CHECK_IF(MSG_CHEAT_TOGGLE_MESSAGE_TEXT)
|
|
|
|
|
|
#endif
|
|
CHECK_IF(MSG_META_TOGGLE_FAST_FORWARD_REPLAY)
|
|
|
|
|
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_BEHIND_BUILDINGS)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_LETTERBOX)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_MESSAGE_TEXT)
|
|
CHECK_IF(MSG_META_DEMO_LOD_DECREASE)
|
|
CHECK_IF(MSG_META_DEMO_LOD_INCREASE)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_ZOOM_LOCK)
|
|
CHECK_IF(MSG_META_DEMO_PLAY_CAMEO_MOVIE)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_SPECIAL_POWER_DELAYS)
|
|
CHECK_IF(MSG_META_DEMO_BATTLE_CRY)
|
|
CHECK_IF(MSG_META_DEMO_SWITCH_TEAMS)
|
|
CHECK_IF(MSG_META_DEMO_SWITCH_TEAMS_BETWEEN_CHINA_USA)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_PARTICLEDEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_SHADOW_VOLUMES)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_FOGOFWAR)
|
|
CHECK_IF(MSG_META_DEMO_KILL_ALL_ENEMIES)
|
|
CHECK_IF(MSG_META_DEMO_KILL_SELECTION)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_HURT_ME_MODE)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_HAND_OF_GOD_MODE)
|
|
CHECK_IF(MSG_META_DEMO_DEBUG_SELECTION)
|
|
CHECK_IF(MSG_META_DEMO_LOCK_CAMERA_TO_SELECTION)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_SOUND)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_TRACKMARKS)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_WATERPLANE)
|
|
CHECK_IF(MSG_META_DEMO_TIME_OF_DAY)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_MUSIC)
|
|
CHECK_IF(MSG_META_DEMO_MUSIC_NEXT_TRACK)
|
|
CHECK_IF(MSG_META_DEMO_MUSIC_PREV_TRACK)
|
|
CHECK_IF(MSG_META_DEMO_NEXT_OBJECTIVE_MOVIE)
|
|
CHECK_IF(MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE1)
|
|
CHECK_IF(MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE2)
|
|
CHECK_IF(MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE3)
|
|
CHECK_IF(MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE4)
|
|
CHECK_IF(MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE5)
|
|
CHECK_IF(MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE6)
|
|
CHECK_IF(MSG_META_DEMO_BEGIN_ADJUST_PITCH)
|
|
CHECK_IF(MSG_META_DEMO_END_ADJUST_PITCH)
|
|
CHECK_IF(MSG_META_DEMO_BEGIN_ADJUST_FOV)
|
|
CHECK_IF(MSG_META_DEMO_END_ADJUST_FOV)
|
|
CHECK_IF(MSG_META_DEMO_LOCK_CAMERA_TO_PLANES)
|
|
CHECK_IF(MSG_META_DEMO_REMOVE_PREREQ)
|
|
CHECK_IF(MSG_META_DEMO_INSTANT_BUILD)
|
|
CHECK_IF(MSG_META_DEMO_FREE_BUILD)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT1)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT2)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT3)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT4)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT5)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT6)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT7)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT8)
|
|
CHECK_IF(MSG_META_DEMO_RUNSCRIPT9)
|
|
CHECK_IF(MSG_META_DEMO_ENSHROUD)
|
|
CHECK_IF(MSG_META_DEMO_DESHROUD)
|
|
CHECK_IF(MSG_META_DEBUG_SHOW_EXTENTS)
|
|
CHECK_IF(MSG_META_DEBUG_SHOW_AUDIO_LOCATIONS)
|
|
CHECK_IF(MSG_META_DEBUG_SHOW_HEALTH)
|
|
CHECK_IF(MSG_META_DEBUG_GIVE_VETERANCY)
|
|
CHECK_IF(MSG_META_DEBUG_TAKE_VETERANCY)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_AI_DEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_SUPPLY_CENTER_PLACEMENT)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_CAMERA_DEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_AVI)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_BW_VIEW)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_RED_VIEW)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_GREEN_VIEW)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_MOTION_BLUR_ZOOM)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_MILITARY_SUBTITLES)
|
|
CHECK_IF(MSG_META_DEMO_ADD_CASH)
|
|
#ifdef ALLOW_SURRENDER
|
|
CHECK_IF(MSG_META_DEMO_TEST_SURRENDER)
|
|
#endif
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_RENDER)
|
|
CHECK_IF(MSG_META_DEMO_KILL_AREA_SELECTION)
|
|
CHECK_IF(MSG_META_DEMO_CYCLE_LOD_LEVEL)
|
|
CHECK_IF(MSG_META_DEBUG_INCR_ANIM_SKATE_SPEED)
|
|
CHECK_IF(MSG_META_DEBUG_DECR_ANIM_SKATE_SPEED)
|
|
CHECK_IF(MSG_META_DEBUG_CYCLE_EXTENT_TYPE)
|
|
CHECK_IF(MSG_META_DEBUG_INCREASE_EXTENT_MAJOR)
|
|
CHECK_IF(MSG_META_DEBUG_INCREASE_EXTENT_MAJOR_BIG)
|
|
CHECK_IF(MSG_META_DEBUG_DECREASE_EXTENT_MAJOR)
|
|
CHECK_IF(MSG_META_DEBUG_DECREASE_EXTENT_MAJOR_BIG)
|
|
CHECK_IF(MSG_META_DEBUG_INCREASE_EXTENT_MINOR)
|
|
CHECK_IF(MSG_META_DEBUG_INCREASE_EXTENT_MINOR_BIG)
|
|
CHECK_IF(MSG_META_DEBUG_DECREASE_EXTENT_MINOR)
|
|
CHECK_IF(MSG_META_DEBUG_DECREASE_EXTENT_MINOR_BIG)
|
|
CHECK_IF(MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT)
|
|
CHECK_IF(MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT_BIG)
|
|
CHECK_IF(MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT)
|
|
CHECK_IF(MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT_BIG)
|
|
CHECK_IF(MSG_META_DEBUG_VTUNE_ON)
|
|
CHECK_IF(MSG_META_DEBUG_VTUNE_OFF)
|
|
CHECK_IF(MSG_META_DEBUG_TOGGLE_FEATHER_WATER)
|
|
CHECK_IF(MSG_META_DEBUG_DUMP_ASSETS)
|
|
CHECK_IF(MSG_NO_DRAW)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_METRICS)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_PROJECTILEDEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_VISIONDEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_THREATDEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_CASHMAPDEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_GRAPHICALFRAMERATEBAR)
|
|
CHECK_IF(MSG_META_DEMO_GIVE_ALL_SCIENCES)
|
|
CHECK_IF(MSG_META_DEMO_GIVE_RANKLEVEL)
|
|
CHECK_IF(MSG_META_DEMO_TAKE_RANKLEVEL)
|
|
CHECK_IF(MSG_META_DEMO_GIVE_SCIENCEPURCHASEPOINTS)
|
|
CHECK_IF(MSG_META_DEBUG_TOGGLE_NETWORK)
|
|
CHECK_IF(MSG_META_DEBUG_DUMP_PLAYER_OBJECTS)
|
|
CHECK_IF(MSG_META_DEBUG_DUMP_ALL_PLAYER_OBJECTS)
|
|
CHECK_IF(MSG_META_DEBUG_OBJECT_ID_PERFORMANCE)
|
|
CHECK_IF(MSG_META_DEBUG_DRAWABLE_ID_PERFORMANCE)
|
|
CHECK_IF(MSG_META_DEBUG_SLEEPY_UPDATE_PERFORMANCE)
|
|
CHECK_IF(MSG_META_DEBUG_WIN)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_DEBUG_STATS)
|
|
#endif // defined(_DEBUG) || defined(_INTERNAL)
|
|
|
|
|
|
#if defined(_INTERNAL) || defined(_DEBUG)
|
|
CHECK_IF(MSG_META_DEMO_TOGGLE_AUDIODEBUG)
|
|
#endif//defined(_INTERNAL) || defined(_DEBUG)
|
|
#ifdef DUMP_PERF_STATS
|
|
CHECK_IF(MSG_META_DEMO_PERFORM_STATISTICAL_DUMP)
|
|
#endif//DUMP_PERF_STATS
|
|
CHECK_IF(MSG_META_PLACE_BEACON)
|
|
CHECK_IF(MSG_META_REMOVE_BEACON)
|
|
CHECK_IF(MSG_END_META_MESSAGES)
|
|
CHECK_IF(MSG_MOUSEOVER_DRAWABLE_HINT)
|
|
CHECK_IF(MSG_MOUSEOVER_LOCATION_HINT)
|
|
CHECK_IF(MSG_VALID_GUICOMMAND_HINT)
|
|
CHECK_IF(MSG_INVALID_GUICOMMAND_HINT)
|
|
CHECK_IF(MSG_AREA_SELECTION_HINT)
|
|
CHECK_IF(MSG_DO_ATTACK_OBJECT_HINT)
|
|
CHECK_IF(MSG_DO_ATTACK_OBJECT_AFTER_MOVING_HINT)
|
|
CHECK_IF(MSG_DO_FORCE_ATTACK_OBJECT_HINT)
|
|
CHECK_IF(MSG_DO_FORCE_ATTACK_GROUND_HINT)
|
|
CHECK_IF(MSG_GET_REPAIRED_HINT)
|
|
CHECK_IF(MSG_GET_HEALED_HINT)
|
|
CHECK_IF(MSG_DO_REPAIR_HINT)
|
|
CHECK_IF(MSG_RESUME_CONSTRUCTION_HINT)
|
|
CHECK_IF(MSG_ENTER_HINT)
|
|
CHECK_IF(MSG_DOCK_HINT)
|
|
CHECK_IF(MSG_DO_MOVETO_HINT)
|
|
CHECK_IF(MSG_DO_ATTACKMOVETO_HINT)
|
|
CHECK_IF(MSG_ADD_WAYPOINT_HINT)
|
|
CHECK_IF(MSG_HIJACK_HINT)
|
|
CHECK_IF(MSG_SABOTAGE_HINT)
|
|
CHECK_IF(MSG_FIREBOMB_HINT)
|
|
CHECK_IF(MSG_CONVERT_TO_CARBOMB_HINT)
|
|
CHECK_IF(MSG_CAPTUREBUILDING_HINT)
|
|
CHECK_IF(MSG_HACK_HINT)
|
|
#ifdef ALLOW_SURRENDER
|
|
CHECK_IF(MSG_PICK_UP_PRISONER_HINT)
|
|
#endif
|
|
CHECK_IF(MSG_SNIPE_VEHICLE_HINT)
|
|
CHECK_IF(MSG_DEFECTOR_HINT)
|
|
CHECK_IF(MSG_SET_RALLY_POINT_HINT)
|
|
CHECK_IF(MSG_DO_SALVAGE_HINT)
|
|
CHECK_IF(MSG_DO_INVALID_HINT)
|
|
CHECK_IF(MSG_BEGIN_NETWORK_MESSAGES)
|
|
CHECK_IF(MSG_CREATE_SELECTED_GROUP)
|
|
CHECK_IF(MSG_CREATE_SELECTED_GROUP_NO_SOUND)
|
|
CHECK_IF(MSG_DESTROY_SELECTED_GROUP)
|
|
CHECK_IF(MSG_REMOVE_FROM_SELECTED_GROUP)
|
|
CHECK_IF(MSG_SELECTED_GROUP_COMMAND)
|
|
CHECK_IF(MSG_CREATE_TEAM0)
|
|
CHECK_IF(MSG_CREATE_TEAM1)
|
|
CHECK_IF(MSG_CREATE_TEAM2)
|
|
CHECK_IF(MSG_CREATE_TEAM3)
|
|
CHECK_IF(MSG_CREATE_TEAM4)
|
|
CHECK_IF(MSG_CREATE_TEAM5)
|
|
CHECK_IF(MSG_CREATE_TEAM6)
|
|
CHECK_IF(MSG_CREATE_TEAM7)
|
|
CHECK_IF(MSG_CREATE_TEAM8)
|
|
CHECK_IF(MSG_CREATE_TEAM9)
|
|
CHECK_IF(MSG_SELECT_TEAM0)
|
|
CHECK_IF(MSG_SELECT_TEAM1)
|
|
CHECK_IF(MSG_SELECT_TEAM2)
|
|
CHECK_IF(MSG_SELECT_TEAM3)
|
|
CHECK_IF(MSG_SELECT_TEAM4)
|
|
CHECK_IF(MSG_SELECT_TEAM5)
|
|
CHECK_IF(MSG_SELECT_TEAM6)
|
|
CHECK_IF(MSG_SELECT_TEAM7)
|
|
CHECK_IF(MSG_SELECT_TEAM8)
|
|
CHECK_IF(MSG_SELECT_TEAM9)
|
|
CHECK_IF(MSG_ADD_TEAM0)
|
|
CHECK_IF(MSG_ADD_TEAM1)
|
|
CHECK_IF(MSG_ADD_TEAM2)
|
|
CHECK_IF(MSG_ADD_TEAM3)
|
|
CHECK_IF(MSG_ADD_TEAM4)
|
|
CHECK_IF(MSG_ADD_TEAM5)
|
|
CHECK_IF(MSG_ADD_TEAM6)
|
|
CHECK_IF(MSG_ADD_TEAM7)
|
|
CHECK_IF(MSG_ADD_TEAM8)
|
|
CHECK_IF(MSG_ADD_TEAM9)
|
|
CHECK_IF(MSG_DO_ATTACKSQUAD)
|
|
CHECK_IF(MSG_DO_WEAPON)
|
|
CHECK_IF(MSG_DO_WEAPON_AT_LOCATION)
|
|
CHECK_IF(MSG_DO_WEAPON_AT_OBJECT)
|
|
CHECK_IF(MSG_DO_SPECIAL_POWER)
|
|
CHECK_IF(MSG_DO_SPECIAL_POWER_AT_LOCATION)
|
|
CHECK_IF(MSG_DO_SPECIAL_POWER_AT_OBJECT)
|
|
CHECK_IF(MSG_SET_RALLY_POINT)
|
|
CHECK_IF(MSG_PURCHASE_SCIENCE)
|
|
CHECK_IF(MSG_QUEUE_UPGRADE)
|
|
CHECK_IF(MSG_CANCEL_UPGRADE)
|
|
CHECK_IF(MSG_QUEUE_UNIT_CREATE)
|
|
CHECK_IF(MSG_CANCEL_UNIT_CREATE)
|
|
CHECK_IF(MSG_DOZER_CONSTRUCT)
|
|
CHECK_IF(MSG_DOZER_CONSTRUCT_LINE)
|
|
CHECK_IF(MSG_DOZER_CANCEL_CONSTRUCT)
|
|
CHECK_IF(MSG_SELL)
|
|
CHECK_IF(MSG_EXIT)
|
|
CHECK_IF(MSG_EVACUATE)
|
|
CHECK_IF(MSG_EXECUTE_RAILED_TRANSPORT)
|
|
CHECK_IF(MSG_COMBATDROP_AT_LOCATION)
|
|
CHECK_IF(MSG_COMBATDROP_AT_OBJECT)
|
|
CHECK_IF(MSG_AREA_SELECTION)
|
|
CHECK_IF(MSG_DO_ATTACK_OBJECT)
|
|
CHECK_IF(MSG_DO_FORCE_ATTACK_OBJECT)
|
|
CHECK_IF(MSG_DO_FORCE_ATTACK_GROUND)
|
|
CHECK_IF(MSG_GET_REPAIRED)
|
|
CHECK_IF(MSG_GET_HEALED)
|
|
CHECK_IF(MSG_DO_REPAIR)
|
|
CHECK_IF(MSG_RESUME_CONSTRUCTION)
|
|
CHECK_IF(MSG_ENTER)
|
|
CHECK_IF(MSG_DOCK)
|
|
CHECK_IF(MSG_DO_MOVETO)
|
|
CHECK_IF(MSG_DO_ATTACKMOVETO)
|
|
CHECK_IF(MSG_DO_FORCEMOVETO)
|
|
CHECK_IF(MSG_ADD_WAYPOINT)
|
|
CHECK_IF(MSG_DO_GUARD_POSITION)
|
|
CHECK_IF(MSG_DO_GUARD_OBJECT)
|
|
CHECK_IF(MSG_DO_STOP)
|
|
CHECK_IF(MSG_DO_SCATTER)
|
|
CHECK_IF(MSG_INTERNET_HACK)
|
|
CHECK_IF(MSG_DO_CHEER)
|
|
#ifdef ALLOW_SURRENDER
|
|
CHECK_IF(MSG_DO_SURRENDER)
|
|
#endif
|
|
CHECK_IF(MSG_TOGGLE_OVERCHARGE)
|
|
#ifdef ALLOW_SURRENDER
|
|
CHECK_IF(MSG_RETURN_TO_PRISON)
|
|
#endif
|
|
CHECK_IF(MSG_SWITCH_WEAPONS)
|
|
CHECK_IF(MSG_CONVERT_TO_CARBOMB)
|
|
CHECK_IF(MSG_CAPTUREBUILDING)
|
|
CHECK_IF(MSG_DISABLEVEHICLE_HACK)
|
|
CHECK_IF(MSG_STEALCASH_HACK)
|
|
CHECK_IF(MSG_DISABLEBUILDING_HACK)
|
|
CHECK_IF(MSG_SNIPE_VEHICLE)
|
|
#ifdef ALLOW_SURRENDER
|
|
CHECK_IF(MSG_PICK_UP_PRISONER)
|
|
#endif
|
|
CHECK_IF(MSG_DO_SALVAGE)
|
|
CHECK_IF(MSG_CLEAR_INGAME_POPUP_MESSAGE)
|
|
CHECK_IF(MSG_PLACE_BEACON)
|
|
CHECK_IF(MSG_REMOVE_BEACON)
|
|
CHECK_IF(MSG_SET_BEACON_TEXT)
|
|
CHECK_IF(MSG_SET_REPLAY_CAMERA)
|
|
CHECK_IF(MSG_SELF_DESTRUCT)
|
|
CHECK_IF(MSG_CREATE_FORMATION)
|
|
CHECK_IF(MSG_LOGIC_CRC)
|
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
|
CHECK_IF(MSG_DEBUG_KILL_SELECTION)
|
|
CHECK_IF(MSG_DEBUG_HURT_OBJECT)
|
|
CHECK_IF(MSG_DEBUG_KILL_OBJECT)
|
|
#endif
|
|
|
|
CHECK_IF(MSG_END_NETWORK_MESSAGES)
|
|
CHECK_IF(MSG_TIMESTAMP)
|
|
CHECK_IF(MSG_OBJECT_CREATED)
|
|
CHECK_IF(MSG_OBJECT_DESTROYED)
|
|
CHECK_IF(MSG_OBJECT_POSITION)
|
|
CHECK_IF(MSG_OBJECT_ORIENTATION)
|
|
CHECK_IF(MSG_OBJECT_JOINED_TEAM)
|
|
CHECK_IF(MSG_SET_MINE_CLEARING_DETAIL)
|
|
CHECK_IF(MSG_ENABLE_RETALIATION_MODE)
|
|
return commandName;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
// GameMessageList
|
|
//
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
GameMessageList::GameMessageList( void )
|
|
{
|
|
m_firstMessage = 0;
|
|
m_lastMessage = 0;
|
|
}
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
GameMessageList::~GameMessageList()
|
|
{
|
|
// destroy all messages currently on the list
|
|
GameMessage *msg, *nextMsg;
|
|
for( msg = m_firstMessage; msg; msg = nextMsg )
|
|
{
|
|
nextMsg = msg->next();
|
|
// set list ptr to null to avoid it trying to remove itself from the list
|
|
// that we are in the process of nuking...
|
|
msg->friend_setList(NULL);
|
|
msg->deleteInstance();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Append message to end of message list
|
|
*/
|
|
void GameMessageList::appendMessage( GameMessage *msg )
|
|
{
|
|
msg->friend_setNext(NULL);
|
|
|
|
if (m_lastMessage)
|
|
{
|
|
m_lastMessage->friend_setNext(msg);
|
|
msg->friend_setPrev(m_lastMessage);
|
|
m_lastMessage = msg;
|
|
}
|
|
else
|
|
{
|
|
// first message
|
|
m_firstMessage = msg;
|
|
m_lastMessage = msg;
|
|
msg->friend_setPrev(NULL);
|
|
}
|
|
|
|
// note containment within message itself
|
|
msg->friend_setList(this);
|
|
}
|
|
|
|
/**
|
|
* Inserts the msg after messageToInsertAfter.
|
|
*/
|
|
void GameMessageList::insertMessage( GameMessage *msg, GameMessage *messageToInsertAfter )
|
|
{
|
|
// First, set msg's next to be messageToInsertAfter's next.
|
|
msg->friend_setNext(messageToInsertAfter->next());
|
|
|
|
// Next, set msg's prev to be messageToInsertAfter
|
|
msg->friend_setPrev(messageToInsertAfter);
|
|
|
|
// Now update the next message's prev to be msg
|
|
if (msg->next())
|
|
msg->next()->friend_setPrev(msg);
|
|
else // if the friend wasn't there, then messageToInsertAfter is the last message. Update it to be msg.
|
|
m_lastMessage = msg;
|
|
|
|
// Finally, update the messageToInsertAfter's next to be msg
|
|
messageToInsertAfter->friend_setNext(msg);
|
|
|
|
// note containment within the message itself
|
|
msg->friend_setList(this);
|
|
}
|
|
|
|
/**
|
|
* Remove given message from the list.
|
|
*/
|
|
void GameMessageList::removeMessage( GameMessage *msg )
|
|
{
|
|
if (msg->next())
|
|
msg->next()->friend_setPrev(msg->prev());
|
|
else
|
|
m_lastMessage = msg->prev();
|
|
|
|
if (msg->prev())
|
|
msg->prev()->friend_setNext(msg->next());
|
|
else
|
|
m_firstMessage = msg->next();
|
|
|
|
msg->friend_setList(NULL);
|
|
}
|
|
|
|
/**
|
|
* Return whether or not a message of the given type is in the message list
|
|
*/
|
|
Bool GameMessageList::containsMessageOfType( GameMessage::Type type )
|
|
{
|
|
GameMessage *msg = getFirstMessage();
|
|
while (msg) {
|
|
if (msg->getType() == type) {
|
|
return true;
|
|
}
|
|
msg = msg->next();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
// MessageStream
|
|
//
|
|
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
MessageStream::MessageStream( void )
|
|
{
|
|
m_firstTranslator = 0;
|
|
m_nextTranslatorID = 1;
|
|
}
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
MessageStream::~MessageStream()
|
|
{
|
|
// destroy all translators
|
|
TranslatorData *trans, *nextTrans;
|
|
for( trans=m_firstTranslator; trans; trans=nextTrans )
|
|
{
|
|
nextTrans = trans->m_next;
|
|
delete trans;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Init
|
|
*/
|
|
void MessageStream::init( void )
|
|
{
|
|
// extend
|
|
GameMessageList::init();
|
|
}
|
|
|
|
/**
|
|
* Reset
|
|
*/
|
|
void MessageStream::reset( void )
|
|
{
|
|
|
|
/// @todo Reset the MessageStream
|
|
|
|
// extend
|
|
GameMessageList::reset();
|
|
|
|
}
|
|
|
|
/**
|
|
* Update
|
|
*/
|
|
void MessageStream::update( void )
|
|
{
|
|
// extend
|
|
GameMessageList::update();
|
|
|
|
}
|
|
|
|
/**
|
|
* Create a new message of the given message type and append it
|
|
* to this message stream. Return the message such that any data
|
|
* associated with this message can be attached to it.
|
|
*/
|
|
GameMessage *MessageStream::appendMessage( GameMessage::Type type )
|
|
{
|
|
GameMessage *msg = newInstance(GameMessage)( type );
|
|
|
|
// add message to list
|
|
GameMessageList::appendMessage( msg );
|
|
|
|
return msg;
|
|
}
|
|
|
|
/**
|
|
* Create a new message of the given message type and insert it
|
|
* in the stream after messageToInsertAfter, which must not be NULL.
|
|
*/
|
|
GameMessage *MessageStream::insertMessage( GameMessage::Type type, GameMessage *messageToInsertAfter )
|
|
{
|
|
GameMessage *msg = newInstance(GameMessage)(type);
|
|
|
|
GameMessageList::insertMessage(msg, messageToInsertAfter);
|
|
|
|
return msg;
|
|
}
|
|
|
|
/**
|
|
* Attach the given Translator to the message stream, and return a
|
|
* unique TranslatorID identifying it.
|
|
* Translators are placed on a list, sorted by priority order. If two
|
|
* Translators share a priority, they are kept in the same order they
|
|
* were attached.
|
|
*/
|
|
TranslatorID MessageStream::attachTranslator( GameMessageTranslator *translator,
|
|
UnsignedInt priority)
|
|
{
|
|
MessageStream::TranslatorData *newSS = NEW MessageStream::TranslatorData;
|
|
MessageStream::TranslatorData *ss;
|
|
|
|
newSS->m_translator = translator;
|
|
newSS->m_priority = priority;
|
|
newSS->m_id = m_nextTranslatorID++;
|
|
|
|
if (m_firstTranslator == NULL)
|
|
{
|
|
// first Translator to be attached
|
|
newSS->m_prev = NULL;
|
|
newSS->m_next = NULL;
|
|
m_firstTranslator = newSS;
|
|
m_lastTranslator = newSS;
|
|
return newSS->m_id;
|
|
}
|
|
|
|
// seach the Translator list for our priority location
|
|
for( ss=m_firstTranslator; ss; ss=ss->m_next )
|
|
if (ss->m_priority > newSS->m_priority)
|
|
break;
|
|
|
|
if (ss)
|
|
{
|
|
// insert new Translator just BEFORE this one,
|
|
// therefore, m_lastTranslator cannot be affected
|
|
if (ss->m_prev)
|
|
{
|
|
ss->m_prev->m_next = newSS;
|
|
newSS->m_prev = ss->m_prev;
|
|
newSS->m_next = ss;
|
|
ss->m_prev = newSS;
|
|
}
|
|
else
|
|
{
|
|
// insert at head of list
|
|
newSS->m_prev = NULL;
|
|
newSS->m_next = m_firstTranslator;
|
|
m_firstTranslator->m_prev = newSS;
|
|
m_firstTranslator = newSS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// append Translator to end of list
|
|
m_lastTranslator->m_next = newSS;
|
|
newSS->m_prev = m_lastTranslator;
|
|
newSS->m_next = NULL;
|
|
m_lastTranslator = newSS;
|
|
}
|
|
|
|
return newSS->m_id;
|
|
}
|
|
|
|
/**
|
|
* Find a translator attached to this message stream given the ID
|
|
*/
|
|
GameMessageTranslator* MessageStream::findTranslator( TranslatorID id )
|
|
{
|
|
MessageStream::TranslatorData *translatorData;
|
|
|
|
for( translatorData = m_firstTranslator; translatorData; translatorData = translatorData->m_next )
|
|
{
|
|
|
|
if( translatorData->m_id == id )
|
|
return translatorData->m_translator;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/**
|
|
* Remove a previously attached translator.
|
|
*/
|
|
void MessageStream::removeTranslator( TranslatorID id )
|
|
{
|
|
MessageStream::TranslatorData *ss;
|
|
|
|
for( ss=m_firstTranslator; ss; ss=ss->m_next )
|
|
if (ss->m_id == id)
|
|
{
|
|
// found the translator - remove it
|
|
if (ss->m_prev)
|
|
ss->m_prev->m_next = ss->m_next;
|
|
else
|
|
m_firstTranslator = ss->m_next;
|
|
|
|
if (ss->m_next)
|
|
ss->m_next->m_prev = ss->m_prev;
|
|
else
|
|
m_lastTranslator = ss->m_prev;
|
|
|
|
// delete the translator data
|
|
delete ss;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// ------------------------------------------------------------------------------------------------
|
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
|
|
|
Bool isInvalidDebugCommand( GameMessage::Type t )
|
|
{
|
|
// see if this is something that should be prevented in multiplayer games
|
|
// Don't reject this stuff in skirmish games.
|
|
if (TheGameLogic && !TheGameLogic->isInSkirmishGame() &&
|
|
(TheRecorder && TheRecorder->isMultiplayer() && TheRecorder->getMode() == RECORDERMODETYPE_RECORD))
|
|
{
|
|
switch (t)
|
|
{
|
|
case GameMessage::MSG_META_DEMO_SWITCH_TEAMS:
|
|
case GameMessage::MSG_META_DEMO_SWITCH_TEAMS_BETWEEN_CHINA_USA:
|
|
case GameMessage::MSG_META_DEMO_KILL_ALL_ENEMIES:
|
|
case GameMessage::MSG_META_DEMO_KILL_SELECTION:
|
|
case GameMessage::MSG_META_DEMO_TOGGLE_HURT_ME_MODE:
|
|
case GameMessage::MSG_META_DEMO_TOGGLE_HAND_OF_GOD_MODE:
|
|
case GameMessage::MSG_META_DEMO_TOGGLE_SPECIAL_POWER_DELAYS:
|
|
case GameMessage::MSG_META_DEMO_TIME_OF_DAY:
|
|
case GameMessage::MSG_META_DEMO_LOCK_CAMERA_TO_PLANES:
|
|
case GameMessage::MSG_META_DEMO_REMOVE_PREREQ:
|
|
case GameMessage::MSG_META_DEMO_INSTANT_BUILD:
|
|
case GameMessage::MSG_META_DEMO_FREE_BUILD:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT1:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT2:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT3:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT4:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT5:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT6:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT7:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT8:
|
|
case GameMessage::MSG_META_DEMO_RUNSCRIPT9:
|
|
case GameMessage::MSG_META_DEMO_ENSHROUD:
|
|
case GameMessage::MSG_META_DEMO_DESHROUD:
|
|
case GameMessage::MSG_META_DEBUG_GIVE_VETERANCY:
|
|
case GameMessage::MSG_META_DEBUG_TAKE_VETERANCY:
|
|
//#pragma MESSAGE ("WARNING - DEBUG key in multiplayer!")
|
|
case GameMessage::MSG_META_DEMO_ADD_CASH:
|
|
case GameMessage::MSG_META_DEBUG_INCR_ANIM_SKATE_SPEED:
|
|
case GameMessage::MSG_META_DEBUG_DECR_ANIM_SKATE_SPEED:
|
|
case GameMessage::MSG_META_DEBUG_CYCLE_EXTENT_TYPE:
|
|
case GameMessage::MSG_META_DEMO_TOGGLE_RENDER:
|
|
case GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MAJOR:
|
|
case GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MAJOR_BIG:
|
|
case GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MAJOR:
|
|
case GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MAJOR_BIG:
|
|
case GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MINOR:
|
|
case GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_MINOR_BIG:
|
|
case GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MINOR:
|
|
case GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_MINOR_BIG:
|
|
case GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT:
|
|
case GameMessage::MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT_BIG:
|
|
case GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT:
|
|
case GameMessage::MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT_BIG:
|
|
case GameMessage::MSG_META_DEMO_KILL_AREA_SELECTION:
|
|
case GameMessage::MSG_DEBUG_KILL_SELECTION:
|
|
case GameMessage::MSG_DEBUG_HURT_OBJECT:
|
|
case GameMessage::MSG_DEBUG_KILL_OBJECT:
|
|
case GameMessage::MSG_META_DEMO_GIVE_SCIENCEPURCHASEPOINTS:
|
|
case GameMessage::MSG_META_DEMO_GIVE_ALL_SCIENCES:
|
|
case GameMessage::MSG_META_DEMO_GIVE_RANKLEVEL:
|
|
case GameMessage::MSG_META_DEMO_TAKE_RANKLEVEL:
|
|
case GameMessage::MSG_META_DEBUG_WIN:
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Propagate messages thru attached Translators, invoking each Translator's
|
|
* callback for each message in the stream.
|
|
* Once all Translators have evaluated the message stream, all messages
|
|
* in the stream are destroyed.
|
|
*/
|
|
void MessageStream::propagateMessages( void )
|
|
{
|
|
MessageStream::TranslatorData *ss;
|
|
GameMessage *msg, *next;
|
|
|
|
// process each Translator
|
|
for( ss=m_firstTranslator; ss; ss=ss->m_next )
|
|
{
|
|
for( msg=m_firstMessage; msg; msg=next )
|
|
{
|
|
if (ss->m_translator
|
|
#if defined(_DEBUG) || defined(_INTERNAL)
|
|
&& !isInvalidDebugCommand(msg->getType())
|
|
#endif
|
|
)
|
|
{
|
|
GameMessageDisposition disp = ss->m_translator->translateGameMessage(msg);
|
|
next = msg->next();
|
|
if (disp == DESTROY_MESSAGE)
|
|
{
|
|
msg->deleteInstance();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
next = msg->next();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// transfer all messages that reached the end of the stream to TheCommandList
|
|
TheCommandList->appendMessageList( m_firstMessage );
|
|
|
|
// clear the stream
|
|
m_firstMessage = NULL;
|
|
m_lastMessage = NULL;
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
// CommandList
|
|
//
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
CommandList::CommandList( void )
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
CommandList::~CommandList()
|
|
{
|
|
destroyAllMessages();
|
|
}
|
|
|
|
/**
|
|
* Init
|
|
*/
|
|
void CommandList::init( void )
|
|
{
|
|
|
|
// extend
|
|
GameMessageList::init();
|
|
|
|
}
|
|
|
|
/**
|
|
* Destroy all messages on the list, and reset list to empty
|
|
*/
|
|
void CommandList::reset( void )
|
|
{
|
|
|
|
// extend
|
|
GameMessageList::reset();
|
|
|
|
// destroy all messages
|
|
destroyAllMessages();
|
|
|
|
}
|
|
|
|
/**
|
|
* Update
|
|
*/
|
|
void CommandList::update( void )
|
|
{
|
|
|
|
// extend
|
|
GameMessageList::update();
|
|
|
|
}
|
|
|
|
/**
|
|
* Destroy all messages on the command list, this will get called from the
|
|
* destructor and reset methods, DO NOT throw exceptions
|
|
*/
|
|
void CommandList::destroyAllMessages( void )
|
|
{
|
|
GameMessage *msg, *next;
|
|
|
|
for( msg=m_firstMessage; msg; msg=next )
|
|
{
|
|
next = msg->next();
|
|
msg->deleteInstance();
|
|
}
|
|
|
|
m_firstMessage = NULL;
|
|
m_lastMessage = NULL;
|
|
|
|
}
|
|
|
|
/**
|
|
* Adds messages to the end of TheCommandList.
|
|
* Primarily used by TheMessageStream to put the final messages that reach the end of the
|
|
* stream on TheCommandList. Since TheGameClient will update faster than TheNetwork
|
|
* and TheGameLogic, messages will accumulate on this list.
|
|
*/
|
|
void CommandList::appendMessageList( GameMessage *list )
|
|
{
|
|
GameMessage *msg, *next;
|
|
|
|
for( msg = list; msg; msg = next )
|
|
{
|
|
next = msg->next();
|
|
appendMessage( msg );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* Given an "anchor" point and the current mouse position (dest),
|
|
* construct a valid 2D bounding region.
|
|
*/
|
|
void buildRegion( const ICoord2D *anchor, const ICoord2D *dest, IRegion2D *region )
|
|
{
|
|
// build rectangular region defined by the drag selection
|
|
if (anchor->x < dest->x)
|
|
{
|
|
region->lo.x = anchor->x;
|
|
region->hi.x = dest->x;
|
|
}
|
|
else
|
|
{
|
|
region->lo.x = dest->x;
|
|
region->hi.x = anchor->x;
|
|
}
|
|
|
|
if (anchor->y < dest->y)
|
|
{
|
|
region->lo.y = anchor->y;
|
|
region->hi.y = dest->y;
|
|
}
|
|
else
|
|
{
|
|
region->lo.y = dest->y;
|
|
region->hi.y = anchor->y;
|
|
}
|
|
}
|