799 lines
43 KiB
C++

/*
** 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: MessageStream.h //////////////////////////////////////////////////////
// The message stream propagates all messages thru a series of "translators"
// Author: Michael S. Booth, February 2001
#pragma once
#ifndef _MESSAGE_STREAM_H_
#define _MESSAGE_STREAM_H_
#include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
#include "Common/SubsystemInterface.h"
#include "Lib/BaseType.h"
#include "Common/GameMemory.h"
enum { TRANSLATOR_ID_INVALID = -1 };
// how far the the cursor moves before a click becomes a drag
typedef UnsignedInt TranslatorID; ///< Unique identifiers for message stream translators
class Drawable;
class GameMessageList;
enum ObjectID;
enum DrawableID;
union GameMessageArgumentType ///< Union of possible data for given message type
{
Int integer;
Real real;
Bool boolean;
ObjectID objectID;
DrawableID drawableID;
UnsignedInt teamID;
UnsignedInt squadID;
Coord3D location;
ICoord2D pixel;
IRegion2D pixelRegion;
UnsignedInt timestamp;
WideChar wChar;
};
enum GameMessageArgumentDataType
{
ARGUMENTDATATYPE_INTEGER,
ARGUMENTDATATYPE_REAL,
ARGUMENTDATATYPE_BOOLEAN,
ARGUMENTDATATYPE_OBJECTID,
ARGUMENTDATATYPE_DRAWABLEID,
ARGUMENTDATATYPE_TEAMID,
ARGUMENTDATATYPE_LOCATION,
ARGUMENTDATATYPE_PIXEL,
ARGUMENTDATATYPE_PIXELREGION,
ARGUMENTDATATYPE_TIMESTAMP,
ARGUMENTDATATYPE_WIDECHAR,
ARGUMENTDATATYPE_UNKNOWN
};
class GameMessageArgument : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessageArgument, "GameMessageArgument")
public:
GameMessageArgument* m_next; ///< The next argument
GameMessageArgumentType m_data; ///< The data storage of an argument
GameMessageArgumentDataType m_type; ///< The type of the argument.
};
EMPTY_DTOR(GameMessageArgument)
/**
* A game message that either lives on TheMessageStream or TheCommandList.
* Messages consist of a type, defining what the message is, and zero or more arguments
* of various data types. The user of a message must know how many and what type of
* arguments are valid for a given message type.
*/
class GameMessage : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessage, "GameMessage")
public:
/// The various messages which can be sent in a MessageStream
/// @todo Replace this hardcoded enum with a generalized system that can be easily changed and updated
/** @todo Because the Client will run faster than Logic, we'll need "superceding" messages for events
such as mouse movements so we only send the latest one over the net */
/** @todo Create two classes of message: raw input messages, and command messages. Raw input messages
will be destroyed when they reach the end of the stream, whereas command messages will be
transferred to TheCommandList */
enum Type
{
MSG_INVALID, ///< (none) this msg should never actually occur
MSG_FRAME_TICK, ///< (timestamp) once each frame this message is sent thru the stream
// Client to Server messages
// Note: Please keep MSG_RAW_MOUSE between MSG_RAW_MOUSE_BEGIN and MSG_RAW_MOUSE_END
MSG_RAW_MOUSE_BEGIN,
MSG_RAW_MOUSE_POSITION, ///< (pixel) the cursor's position
MSG_RAW_MOUSE_LEFT_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_WHEEL, ///< (Int spin, + is away, - is toward user)
MSG_RAW_MOUSE_END,
MSG_RAW_KEY_DOWN, ///< (KeyDefType) the given key was pressed (uses Microsoft VK_ codes)
MSG_RAW_KEY_UP, ///< (KeyDefType) the given key was released
// Refined Mouse messages
// NOTE: All processing should attempt to use these refined mouse messages, rather than the
// RAW_* variants. (Please.) :-) jkmcd
MSG_MOUSE_LEFT_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_LEFT_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_MIDDLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_MIDDLE_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_RIGHT_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
// End Refined Mouse Messages
MSG_CLEAR_GAME_DATA, ///< Clear all game data in memory
MSG_NEW_GAME, ///< Start a new game
// "meta" messages should be thought of as "virtual keystrokes" -- they exist
// solely to provide an abstraction layer useful for keyboard/mouse remapping.
// they should NEVER be sent over the network.
MSG_BEGIN_META_MESSAGES, ///< Marker to delineate "meta" messages
MSG_META_SAVE_VIEW1, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW2, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW3, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW4, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW5, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW6, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW7, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW8, ///< save current view as the given user-defined view
MSG_META_VIEW_VIEW1, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW2, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW3, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW4, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW5, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW6, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW7, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW8, ///< center view on the given user-defined view
MSG_META_CREATE_TEAM0, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM1, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM2, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM3, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM4, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM5, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM6, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM7, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM8, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM9, ///< create user-defined team from the selected objects
MSG_META_SELECT_TEAM0, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM1, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM2, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM3, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM4, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM5, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM6, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM7, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM8, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM9, ///< deselect all, then select all units in the given user-defined team
MSG_META_ADD_TEAM0, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM1, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM2, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM3, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM4, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM5, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM6, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM7, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM8, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM9, ///< add the user-defined team to the current selection
MSG_META_VIEW_TEAM0, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM1, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM2, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM3, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM4, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM5, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM6, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM7, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM8, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM9, ///< center view on given user-defined team (but do not affect selection)
MSG_META_SELECT_MATCHING_UNITS, ///< selects mathcing units, used for both on screen and across map
MSG_META_SELECT_NEXT_UNIT, ///< select 'next' unit
MSG_META_SELECT_PREV_UNIT, ///< select 'prev' unit
MSG_META_SELECT_NEXT_WORKER, ///< select 'next' worker
MSG_META_SELECT_PREV_WORKER, ///< select 'prev' worker
MSG_META_VIEW_COMMAND_CENTER, ///< center view on command center
MSG_META_VIEW_LAST_RADAR_EVENT, ///< center view on last radar event
MSG_META_SELECT_HERO, ///< selects player's hero character, if exists...
MSG_META_SELECT_ALL, ///< selects all units across screen
MSG_META_SCATTER, ///< selected units scatter
MSG_META_STOP, ///< selected units stop
MSG_META_DEPLOY, ///< selected units 'deploy'
MSG_META_CREATE_FORMATION, ///< selected units become a formation
MSG_META_FOLLOW, ///< selected units 'follow'
MSG_META_CHAT_PLAYERS, ///< send chat msg to all players
MSG_META_CHAT_ALLIES, ///< send chat msg to allied players
MSG_META_CHAT_EVERYONE, ///< send chat msg to everyone (incl. observers)
MSG_META_DIPLOMACY, ///< bring up diplomacy screen
MSG_META_OPTIONS, ///< bring up options screen
#if defined(_DEBUG) || defined(_INTERNAL)
MSG_META_HELP, ///< bring up help screen
#endif
MSG_META_TOGGLE_LOWER_DETAILS, ///< toggles graphics options to crappy mode instantly
MSG_META_TOGGLE_CONTROL_BAR, ///< show/hide controlbar
MSG_META_BEGIN_PATH_BUILD, ///< enter path-building mode
MSG_META_END_PATH_BUILD, ///< exit path-building mode
MSG_META_BEGIN_FORCEATTACK, ///< enter force-attack mode
MSG_META_END_FORCEATTACK, ///< exit force-attack mode
MSG_META_BEGIN_FORCEMOVE, ///< enter force-move mode
MSG_META_END_FORCEMOVE, ///< exit force-move mode
MSG_META_BEGIN_WAYPOINTS, ///< enter waypoint mode
MSG_META_END_WAYPOINTS, ///< exit waypoint mode
MSG_META_BEGIN_PREFER_SELECTION, ///< The Shift key has been depressed alone
MSG_META_END_PREFER_SELECTION, ///< The Shift key has been released.
MSG_META_TAKE_SCREENSHOT, ///< take screenshot
MSG_META_ALL_CHEER, ///< Yay! :)
MSG_META_TOGGLE_ATTACKMOVE, ///< enter attack-move mode
MSG_META_BEGIN_CAMERA_ROTATE_LEFT,
MSG_META_END_CAMERA_ROTATE_LEFT,
MSG_META_BEGIN_CAMERA_ROTATE_RIGHT,
MSG_META_END_CAMERA_ROTATE_RIGHT,
MSG_META_BEGIN_CAMERA_ZOOM_IN,
MSG_META_END_CAMERA_ZOOM_IN,
MSG_META_BEGIN_CAMERA_ZOOM_OUT,
MSG_META_END_CAMERA_ZOOM_OUT,
MSG_META_CAMERA_RESET,
// META items that are really for debug/demo/development use only...
// They do not get built into RELEASE builds.
#if defined(_DEBUG) || defined(_INTERNAL)
MSG_META_DEMO_TOGGLE_BEHIND_BUILDINGS, ///< Toggles showing units behind buildings or not
MSG_META_DEMO_TOGGLE_LETTERBOX, ///< enable/disable letterbox mode
MSG_META_DEMO_TOGGLE_MESSAGE_TEXT, ///< toggle the text from the UI messages
MSG_META_DEMO_LOD_DECREASE, ///< decrease LOD by 1
MSG_META_DEMO_LOD_INCREASE, ///< increase LOD by 1
MSG_META_DEMO_TOGGLE_ZOOM_LOCK, ///< Toggle the camera zoom lock on/off
MSG_META_DEMO_PLAY_CAMEO_MOVIE, ///< Play a movie in the cameo spot
MSG_META_DEMO_INSTANT_QUIT, ///< bail out of game immediately
MSG_META_DEMO_TOGGLE_SPECIAL_POWER_DELAYS, ///< Toggle special power delays on/off
MSG_META_DEMO_BATTLE_CRY, ///< battle cry
MSG_META_DEMO_SWITCH_TEAMS, ///< switch local control to another team
MSG_META_DEMO_SWITCH_TEAMS_BETWEEN_CHINA_USA, ///< switch the local player between china and usa
MSG_META_DEMO_TOGGLE_PARTICLEDEBUG, ///< show/hide the particle system debug info
MSG_META_DEMO_TOGGLE_SHADOW_VOLUMES, ///< show/hide shadow volumes
MSG_META_DEMO_TOGGLE_FOGOFWAR,
MSG_META_DEMO_KILL_ALL_ENEMIES, ///< kill ALL ENEMIES! (yeah!)
MSG_META_DEMO_KILL_SELECTION, ///< kill the selected units (yeah!)
MSG_META_DEMO_TOGGLE_HURT_ME_MODE, ///< do 10% damage to the selected units (yeah!)
MSG_META_DEMO_TOGGLE_HAND_OF_GOD_MODE, ///< do 100% damage to the selected units (w00t!)
MSG_META_DEMO_DEBUG_SELECTION, ///< select a given unit for state-machine debugging
MSG_META_DEMO_LOCK_CAMERA_TO_SELECTION, ///< lock the view camera to the selected object
MSG_META_DEMO_TOGGLE_SOUND, ///< toggle sound/video on/off
MSG_META_DEMO_TOGGLE_TRACKMARKS, ///< toggle tank tread marks on/off
MSG_META_DEMO_TOGGLE_WATERPLANE, ///< toggle waterplane on/off
MSG_META_DEMO_TIME_OF_DAY, ///< change time-of-day lighting
MSG_META_DEMO_TOGGLE_MUSIC, ///< turn background music on/off
MSG_META_DEMO_MUSIC_NEXT_TRACK, ///< play next track
MSG_META_DEMO_MUSIC_PREV_TRACK, ///< play prev track
MSG_META_DEMO_NEXT_OBJECTIVE_MOVIE, ///< play next "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE1, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE2, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE3, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE4, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE5, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE6, ///< play specific "Objective" movie
MSG_META_DEMO_BEGIN_ADJUST_PITCH, ///< enter adjust-pitch mode
MSG_META_DEMO_END_ADJUST_PITCH, ///< exit adjust-pitch mode
MSG_META_DEMO_BEGIN_ADJUST_FOV, ///< enter adjust-FOV mode
MSG_META_DEMO_END_ADJUST_FOV, ///< exit adjust-FOV mode
MSG_META_DEMO_LOCK_CAMERA_TO_PLANES, ///< lock camera to airborne thingies
MSG_META_DEMO_REMOVE_PREREQ, ///< Turn of Prerequisite checks in building legality
MSG_META_DEMO_INSTANT_BUILD, ///< All building is with a timer of 1
MSG_META_DEMO_FREE_BUILD, ///< All building is for 0 money
MSG_META_DEMO_RUNSCRIPT1, ///< run script named "KEY_F1"
MSG_META_DEMO_RUNSCRIPT2, ///< run script named "KEY_F2"
MSG_META_DEMO_RUNSCRIPT3, ///< run script named "KEY_F3"
MSG_META_DEMO_RUNSCRIPT4, ///< run script named "KEY_F4"
MSG_META_DEMO_RUNSCRIPT5, ///< run script named "KEY_F5"
MSG_META_DEMO_RUNSCRIPT6, ///< run script named "KEY_F6"
MSG_META_DEMO_RUNSCRIPT7, ///< run script named "KEY_F7"
MSG_META_DEMO_RUNSCRIPT8, ///< run script named "KEY_F8"
MSG_META_DEMO_RUNSCRIPT9, ///< run script named "KEY_F9"
MSG_META_DEMO_ENSHROUD, ///< re-shroud the world for the local player
MSG_META_DEMO_DESHROUD, ///< de-shroud the world for the local player
MSG_META_DEBUG_SHOW_EXTENTS, ///< show object extents
MSG_META_DEBUG_SHOW_HEALTH, ///< show object health
MSG_META_DEBUG_GIVE_VETERANCY, ///< give a veterancy level to selected objects
MSG_META_DEBUG_TAKE_VETERANCY, ///< take a veterancy level from selected objects
MSG_META_DEMO_TOGGLE_AI_DEBUG, ///< show/hide the ai debug stats
MSG_META_DEMO_TOGGLE_CAMERA_DEBUG, ///< show/hide the camera debug stats
MSG_META_DEMO_TOGGLE_AVI, ///< start capturing video
MSG_META_DEMO_TOGGLE_BW_VIEW, ///< enable/disable black & white camera mode
MSG_META_DEMO_TOGGLE_RED_VIEW, ///< enable/disable red tinted view
MSG_META_DEMO_TOGGLE_GREEN_VIEW, ///< enable/disable green view
MSG_META_DEMO_TOGGLE_MOTION_BLUR_ZOOM, ///< enable/disable green view
MSG_META_DEMO_TOGGLE_MILITARY_SUBTITLES, ///< enable/disable military subtitles
MSG_META_DEMO_ADD_CASH, ///< adds 10000 cash to the player
#ifdef ALLOW_SURRENDER
MSG_META_DEMO_TEST_SURRENDER, ///< Test key to show surrender animation in game.
#endif
MSG_META_DEMO_TOGGLE_RENDER, ///< toggle rendering on/off
MSG_META_DEMO_KILL_AREA_SELECTION, ///< (teamID, objectID1, objectID2, ... objectIDN)
MSG_META_DEMO_CYCLE_LOD_LEVEL, ///< cycles through dynamic game detail levels.
MSG_META_DEBUG_INCR_ANIM_SKATE_SPEED, ///< for debugging anim skate speeds
MSG_META_DEBUG_DECR_ANIM_SKATE_SPEED, ///< for debugging anim skate speeds
MSG_META_DEBUG_CYCLE_EXTENT_TYPE, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MAJOR, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MAJOR_BIG, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MAJOR, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MAJOR_BIG, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MINOR, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MINOR_BIG, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MINOR, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MINOR_BIG, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT_BIG, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT_BIG, ///< change extent
MSG_META_DEBUG_VTUNE_ON, ///< turn on/off Vtune
MSG_META_DEBUG_VTUNE_OFF, ///< turn on/off Vtune
MSG_META_DEBUG_TOGGLE_FEATHER_WATER, ///< toggle lorenzen's feather water
MSG_META_DEBUG_DUMP_ASSETS, ///< dumps currently used map assets to a file.
MSG_NO_DRAW, ///< show/hide all objects to test Drawing code
MSG_META_DEMO_TOGGLE_METRICS, ///< Toggle the metrics on/off
MSG_META_DEMO_TOGGLE_PROJECTILEDEBUG, ///< Toggles bezier curves on projectiles on/off
MSG_META_DEMO_TOGGLE_VISIONDEBUG, ///< Toggles vision debug circles on/off
MSG_META_DEMO_TOGGLE_THREATDEBUG, ///< Toggle the threat debugger on/off
MSG_META_DEMO_TOGGLE_CASHMAPDEBUG, ///< Toggle the cash map debugger on/off
MSG_META_DEMO_TOGGLE_GRAPHICALFRAMERATEBAR, ///< Toggle the graphical framerate bar on/off
MSG_META_DEMO_GIVE_ALL_SCIENCES, ///< grant all grantable sciences
MSG_META_DEMO_GIVE_RANKLEVEL, ///< up one RankLevel
MSG_META_DEMO_TAKE_RANKLEVEL, ///< up one RankLevel
MSG_META_DEMO_GIVE_SCIENCEPURCHASEPOINTS, ///< give yourself an SPP (but no rank change)
MSG_META_DEBUG_TOGGLE_NETWORK, ///< toggle between having and not having network traffic.
MSG_META_DEBUG_DUMP_PLAYER_OBJECTS, ///< Dump numbers of objects owned by each player to the script debug window
MSG_META_DEBUG_DUMP_ALL_PLAYER_OBJECTS, ///< Dump numbers of objects owned by each player to the script debug window, and additional object info
MSG_META_DEBUG_WIN, ///< Instant Win
MSG_META_DEMO_TOGGLE_DEBUG_STATS, ///< show/hide the debug stats
/// @todo END section to REMOVE (not disable) for release
#endif // defined(_DEBUG) || defined(_INTERNAL)
#if defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
MSG_META_DEMO_TOGGLE_AUDIODEBUG, ///< show/hide the audio debug info
#endif//defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
#ifdef DUMP_PERF_STATS
MSG_META_DEMO_PERFORM_STATISTICAL_DUMP, ///< dump performance stats for this frame to StatisticsDump.txt
#endif//DUMP_PERF_STATS
MSG_META_PLACE_BEACON,
MSG_META_REMOVE_BEACON,
MSG_END_META_MESSAGES, ///< Marker to delineate "meta" messages
MSG_MOUSEOVER_DRAWABLE_HINT, ///< (drawableid) the given drawable is under the mouse, regardless of button states
MSG_MOUSEOVER_LOCATION_HINT, ///< (location) The cursor is not over a drawable, but is here.
MSG_VALID_GUICOMMAND_HINT, ///< posted when the gui command is valid if the user clicked to execute it.
MSG_INVALID_GUICOMMAND_HINT, ///< posted when the gui command is not valid if the user were to click to attempt to execute it.
MSG_AREA_SELECTION_HINT, ///< (pixelRegion) rectangular selection area under construction, not confirmed
//Command hints
MSG_DO_ATTACK_OBJECT_HINT, ///< (victim objectID) If clicked, an attack would be ordered, "Current Selection" is assumed
MSG_IMPOSSIBLE_ATTACK_HINT, ///< we can't do anything, and target is out of range.
MSG_DO_FORCE_ATTACK_OBJECT_HINT, ///< (victim objectID) If clicked, an attack would be ordered, "Current Selection" is assumed
MSG_DO_FORCE_ATTACK_GROUND_HINT, ///< (victim objectID) If clicked, an attack would be ordered, "Current Selection" is assumed
MSG_GET_REPAIRED_HINT, ///< If clicked, selected unit will go get repaired at clicked object
MSG_GET_HEALED_HINT, ///< If clicked, selected unit will go get healed at clicked object
MSG_DO_REPAIR_HINT, ///< if clicked, dozer will go repair the clicked target
MSG_RESUME_CONSTRUCTION_HINT, ///< if clicked, dozer will go construct a partially constructed building
MSG_ENTER_HINT, ///< if clicked, selected unit(s) will attempt to enter clicked object
MSG_DOCK_HINT, ///< If clicked, selected unit(s) will dock
MSG_DO_MOVETO_HINT, ///< (location) If clicked, a move would be ordered, "Current Selection" is assumed
MSG_DO_ATTACKMOVETO_HINT, ///< (location) If clicked, a move would be ordered, "Current Selection" is assumed
MSG_ADD_WAYPOINT_HINT, ///< (location) If clicked, a waypoint will be added for currently selected units.
//Context command hints
MSG_HIJACK_HINT, ///< if clicked, selected unit(s) will attempt to take over vehicle.
MSG_FIREBOMB_HINT, ///< throw a molotov cocktail
MSG_CONVERT_TO_CARBOMB_HINT, ///< if clicked, selected unit(s) will attempt to convert clicked object into a carbomb.
MSG_CAPTUREBUILDING_HINT,
#ifdef ALLOW_SURRENDER
MSG_PICK_UP_PRISONER_HINT,
#endif
MSG_SNIPE_VEHICLE_HINT,
MSG_DEFECTOR_HINT,
MSG_SET_RALLY_POINT_HINT, ///< (location) if clicked, we will place a rally point here.
MSG_DO_SPECIAL_POWER_OVERRIDE_DESTINATION_HINT,
MSG_DO_SALVAGE_HINT,
MSG_DO_INVALID_HINT, ///< Display invalid cursor because no real command can be done in this context.
MSG_DO_ATTACK_OBJECT_AFTER_MOVING_HINT,
MSG_HACK_HINT,
//*********************************************************************************************************
//*********************************************************************************************************
/*
Note that we start this at a fixed value, so that (regardless of ifdefs upstream from us) we have the same
numeric values for all enums that are saved in replay files. This helps improve compatibility between
replay files created in internal vs. release builds (though they will still generate sync errors in
some situations due to other reasons, e.g., DEBUG_LOG using the FPU and thus changing its state).
there should be NO IFDEFS OF ANY KIND FROM HERE UNTIL MSG_END_NETWORK_MESSAGES.
there should be NO IFDEFS OF ANY KIND FROM HERE UNTIL MSG_END_NETWORK_MESSAGES.
there should be NO IFDEFS OF ANY KIND FROM HERE UNTIL MSG_END_NETWORK_MESSAGES.
*/
MSG_BEGIN_NETWORK_MESSAGES = 1000, ///< MARKER TO DELINEATE MESSAGES THAT GO OVER THE NETWORK
//*********************************************************************************************************
MSG_CREATE_SELECTED_GROUP, /**< (Bool createNewGroup, objectID1, objectID2, ... objectIDN)
* The selected team is created/augmented with the given team members
*/
MSG_CREATE_SELECTED_GROUP_NO_SOUND, /**< (Bool createNewGroup, objectID1, objectID2, ... objectIDN)
* The selected team is created/augmented with the given team members.
* Do not play their selection sounds.
*/
MSG_DESTROY_SELECTED_GROUP, ///< (teamID) the given team is no longer valid
MSG_REMOVE_FROM_SELECTED_GROUP, /**< (objectID1, objectID2, ... objectIDN)
* Remove these units from the selected group. (N should almost always be 1)
*/
MSG_SELECTED_GROUP_COMMAND, ///< (teamID) the NEXT COMMAND acts upon all members of this team
MSG_CREATE_TEAM0, ///< Creates a hotkey squad from the currently selected units.
MSG_CREATE_TEAM1,
MSG_CREATE_TEAM2,
MSG_CREATE_TEAM3,
MSG_CREATE_TEAM4,
MSG_CREATE_TEAM5,
MSG_CREATE_TEAM6,
MSG_CREATE_TEAM7,
MSG_CREATE_TEAM8,
MSG_CREATE_TEAM9,
MSG_SELECT_TEAM0, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM1, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM2, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM3, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM4, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM5, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM6, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM7, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM8, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM9, ///< Set a hotkey squad to be the currently selected units.
MSG_ADD_TEAM0, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM1, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM2, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM3, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM4, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM5, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM6, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM7, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM8, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM9, ///< Add hotkey squad to the currently selected units.
MSG_DO_ATTACKSQUAD, ///< (numObjects) (numObjects * objectID)
MSG_DO_WEAPON, ///< fire specific weapon
MSG_DO_WEAPON_AT_LOCATION, ///< fire a specific weapon at location
MSG_DO_WEAPON_AT_OBJECT, ///< fire a specific weapon at a target object
MSG_DO_SPECIAL_POWER, ///< do special
MSG_DO_SPECIAL_POWER_AT_LOCATION, ///< do special with target location
MSG_DO_SPECIAL_POWER_AT_OBJECT, ///< do special at with target object
MSG_SET_RALLY_POINT, ///< (objectID, location)
MSG_PURCHASE_SCIENCE, ///< purchase a science
MSG_QUEUE_UPGRADE, ///< queue the "research" of an upgrade
MSG_CANCEL_UPGRADE, ///< cancel the "research" of an upgrade
MSG_QUEUE_UNIT_CREATE, ///< clicked on a button to queue the production of a unit
MSG_CANCEL_UNIT_CREATE, ///< clicked on UI button to cancel production of a unit
MSG_DOZER_CONSTRUCT, /**< building things requires clicking on a dozer
selecting what to build, selecting where to
build it ... this construct message will
start the actual build process */
MSG_DOZER_CONSTRUCT_LINE, ///< Like MSG_CONSTRUCT, but for build procesess that occur in a line (like walls)
MSG_DOZER_CANCEL_CONSTRUCT, ///< cancel construction of a building
MSG_SELL, ///< sell a structure
MSG_EXIT, ///< WE want to exit from whatever WE are inside of
MSG_EVACUATE, ///< Dump out all of OUR contained objects
MSG_EXECUTE_RAILED_TRANSPORT, ///< Execute railed transport sequence
MSG_COMBATDROP_AT_LOCATION, ///< dump out all rappellers
MSG_COMBATDROP_AT_OBJECT, ///< dump out all rappellers
MSG_AREA_SELECTION, ///< (pixelRegion) rectangular selection area
MSG_DO_ATTACK_OBJECT, ///< (objectID, victim objectID)
MSG_DO_FORCE_ATTACK_OBJECT, ///< force attack the given object if picked
MSG_DO_FORCE_ATTACK_GROUND, ///< (locationID) bombard the given location if picked
MSG_GET_REPAIRED, ///< selected unit will go get repaired at clicked object
MSG_GET_HEALED, ///< selected unit will go get healed at clicked object
MSG_DO_REPAIR, ///< dozer will go repair the clicked target
MSG_RESUME_CONSTRUCTION, ///< resume construction on a structure
MSG_ENTER, ///< Enter object
MSG_DOCK, ///< Dock with this object
MSG_DO_MOVETO, ///< location
MSG_DO_ATTACKMOVETO, ///< location
MSG_DO_FORCEMOVETO, ///< location
MSG_ADD_WAYPOINT, ///< location
MSG_DO_GUARD_POSITION, ///< Guard with the currently selected group
MSG_DO_GUARD_OBJECT, ///< Guard with the currently selected group
MSG_DO_STOP, ///< Stop with the currently selected group
MSG_DO_SCATTER, ///< Scatter the currently selected group
MSG_INTERNET_HACK, ///< Begin a persistent internet hack (free slow income)
MSG_DO_CHEER, ///< Orders selected units to play cheer animation (if possible)
MSG_TOGGLE_OVERCHARGE, ///< Toggle overcharge status of a power plant
MSG_SWITCH_WEAPONS, ///< Switches which weapon slot to use for an object
MSG_CONVERT_TO_CARBOMB,
MSG_CAPTUREBUILDING,
MSG_DISABLEVEHICLE_HACK,
MSG_STEALCASH_HACK,
MSG_DISABLEBUILDING_HACK,
MSG_SNIPE_VEHICLE,
MSG_DO_SPECIAL_POWER_OVERRIDE_DESTINATION,
MSG_DO_SALVAGE,
MSG_CLEAR_INGAME_POPUP_MESSAGE, ///< If we want a replay to work with the popup messages then we need it to be passed
MSG_PLACE_BEACON,
MSG_REMOVE_BEACON,
MSG_SET_BEACON_TEXT,
MSG_SET_REPLAY_CAMERA, ///< Track camera pos for replays
MSG_SELF_DESTRUCT, ///< Destroys a player's units (for copy protection or to quit to observer)
MSG_CREATE_FORMATION, ///< Creates a formation.
MSG_LOGIC_CRC, ///< CRC from the logic passed around in a network game :)
MSG_SET_MINE_CLEARING_DETAIL, ///< CRC from the logic passed around in a network game :)
MSG_BEGIN_DEBUG_NETWORK_MESSAGES = 1900, ///< network messages that exist only in debug/internal builds. all grouped separately.
#if defined(_DEBUG) || defined(_INTERNAL)
// all debug/internal-only messages must go here.
MSG_DEBUG_KILL_SELECTION,
MSG_DEBUG_HURT_OBJECT,
MSG_DEBUG_KILL_OBJECT,
#endif
//*********************************************************************************************************
MSG_END_NETWORK_MESSAGES = 1999, ///< MARKER TO DELINEATE MESSAGES THAT GO OVER THE NETWORK
//*********************************************************************************************************
//*********************************************************************************************************
// Server to Client messages
MSG_TIMESTAMP, ///< The current frame number
MSG_OBJECT_CREATED, ///< (objectID, Int type) Cause a drawable to be created and bound to this ID
MSG_OBJECT_DESTROYED, ///< (objectID) Free bound drawable
MSG_OBJECT_POSITION, ///< (objectID, location) New position of object
MSG_OBJECT_ORIENTATION, ///< (objectID, angle) New orientation of object
MSG_OBJECT_JOINED_TEAM, ///< (objectID) New team affiliation of object
MSG_COUNT
};
GameMessage( Type type );
GameMessage *next( void ) { return m_next; } ///< Return next message in the stream
GameMessage *prev( void ) { return m_prev; } ///< Return prev message in the stream
Type getType( void ) const { return m_type; } ///< Return the message type
UnsignedByte getArgumentCount( void ) const { return m_argCount; } ///< Return the number of arguments for this msg
AsciiString getCommandAsAsciiString( void ); ///< returns a string representation of the command type.
static AsciiString getCommandTypeAsAsciiString(GameMessage::Type t);
Int getPlayerIndex( void ) const { return m_playerIndex; } ///< Return the originating player
// access methods for GameMessageArgumentType enum
void appendIntegerArgument( Int arg );
void appendRealArgument( Real arg );
void appendBooleanArgument( Bool arg );
void appendDrawableIDArgument( DrawableID arg );
void appendObjectIDArgument( ObjectID arg );
void appendTeamIDArgument( UnsignedInt arg );
void appendLocationArgument( const Coord3D& arg );
void appendPixelArgument( const ICoord2D& arg );
void appendPixelRegionArgument( const IRegion2D& arg );
void appendWideCharArgument( const WideChar& arg );
void appendTimestampArgument( UnsignedInt arg );
/**
* Return the given argument union.
* @todo This should be a more list-like interface. Very inefficient.
*/
const GameMessageArgumentType *getArgument( Int argIndex ) const;
GameMessageArgumentDataType getArgumentDataType( Int argIndex );
void friend_setNext(GameMessage* m) { m_next = m; }
void friend_setPrev(GameMessage* m) { m_prev = m; }
void friend_setList(GameMessageList* m) { m_list = m; }
void friend_setPlayerIndex(Int i) { m_playerIndex = i; }
private:
// friend classes are bad. don't use them. no, really.
// if for no other reason than the fact that they subvert MemoryPoolObject. (srj)
GameMessage *m_next, *m_prev; ///< List links for message list
GameMessageList *m_list; ///< The list this message is on
Type m_type; ///< The type of this message
Int m_playerIndex; ///< The Player who issued the command
/// @todo If a GameMessage needs more than 255 arguments, it needs to be split up into multiple GameMessage's.
UnsignedByte m_argCount; ///< The number of arguments of this message
GameMessageArgument *m_argList, *m_argTail; ///< This message's arguments
/// allocate a new argument, add it to list, return pointer to its data
GameMessageArgument *allocArg( void );
};
/**
* The GameMessageList class encapsulates the manipulation of lists of GameMessages.
* Both MessageStream and CommandList derive from this class.
*/
class GameMessageList : public SubsystemInterface
{
public:
GameMessageList( void );
virtual ~GameMessageList();
virtual void init( void ) { }; ///< Initialize system
virtual void reset( void ) { }; ///< Reset system
virtual void update( void ) { }; ///< Update system
GameMessage *getFirstMessage( void ) { return m_firstMessage; } ///< Return the first message
virtual void appendMessage( GameMessage *msg ); ///< Add message to end of the list
virtual void insertMessage( GameMessage *msg, GameMessage *messageToInsertAfter ); // Insert message after messageToInsertAfter.
virtual void removeMessage( GameMessage *msg ); ///< Remove message from the list
virtual Bool containsMessageOfType( GameMessage::Type type ); ///< Return true if a message of type is in the message stream
protected:
GameMessage *m_firstMessage; ///< The first message on the list
GameMessage *m_lastMessage; ///< The last message on the list
};
/**
What to do with a GameMessage after a translator has handled it.
Use a custom enum (rather than a Bool) to make the code more obvious.
*/
enum GameMessageDisposition
{
KEEP_MESSAGE, ///< continue processing this message thru other translators
DESTROY_MESSAGE ///< destroy this message immediately and don't hand it to any other translators
};
class GameMessageTranslator
{
public:
virtual GameMessageDisposition translateGameMessage(const GameMessage *msg) = 0;
virtual ~GameMessageTranslator() { }
};
/**
* A MessageStream contains an ordered list of messages which can have one or more
* prioritized message handler functions ("translators") attached to it.
*/
class MessageStream : public GameMessageList
{
public:
MessageStream( void );
virtual ~MessageStream();
// Inherited Methods ----------------------------------------------------------------------------
virtual void init( void );
virtual void reset( void );
virtual void update( void );
virtual GameMessage *appendMessage( GameMessage::Type type ); ///< Append a message to the end of the stream
virtual GameMessage *insertMessage( GameMessage::Type type, GameMessage *messageToInsertAfter ); // Insert message after messageToInsertAfter.
// Methods NOT Inherited ------------------------------------------------------------------------
void propagateMessages( void ); ///< Propagate messages through attached translators
/**
Attach a translator function to the stream at a priority value. Lower priorities are executed first.
Note that MessageStream assumes ownership of the translator, and is responsible for freeing it!
*/
TranslatorID attachTranslator( GameMessageTranslator *translator, UnsignedInt priority);
GameMessageTranslator* findTranslator( TranslatorID id );
void removeTranslator( TranslatorID ); ///< Remove a previously attached translator
protected:
struct TranslatorData
{
TranslatorData *m_next, *m_prev; ///< List links for list of translators
TranslatorID m_id; ///< The unique ID of this translator
GameMessageTranslator *m_translator; ///< The translor's interface function
UnsignedInt m_priority; ///< The priority level of this translator
TranslatorData() : m_next(0), m_prev(0), m_id(0), m_translator(0), m_priority(0)
{
}
~TranslatorData()
{
delete m_translator;
}
};
TranslatorData *m_firstTranslator; ///< List of registered translators, in order of priority
TranslatorData *m_lastTranslator;
TranslatorID m_nextTranslatorID; ///< For issuing unique translator ID's
};
/**
* The CommandList is the final set of messages that have made their way through
* all of the Translators of the MessageStream, and reached the end.
* This set of commands will be executed by the GameLogic on its next iteration.
*/
class CommandList : public GameMessageList
{
public:
CommandList( void );
virtual ~CommandList();
virtual void init( void ); ///< Init command list
virtual void reset( void ); ///< Destroy all messages and reset list to empty
virtual void update( void ); ///< Update hook
void appendMessageList( GameMessage *list ); ///< Adds messages to the end of the command list
protected:
void destroyAllMessages( void ); ///< The meat of a reset and a shutdown
};
//
// The message stream that filters client input into game commands
//
extern MessageStream *TheMessageStream;
//
// The list of commands awaiting execution by the GameLogic
//
extern CommandList *TheCommandList;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Functions used in multiple translators should go here.
//
/**
* Given an "anchor" point and the current mouse position (dest),
* construct a valid 2D bounding region.
*/
extern void buildRegion( const ICoord2D *anchor, const ICoord2D *dest, IRegion2D *region );
#endif // _MESSAGE_STREAM_H_