3030// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
3131#include " PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
3232
33+ #include " Common/GameUtility.h"
3334#include " Common/INI.h"
3435#include " Common/MessageStream.h"
3536#include " Common/Player.h"
@@ -183,8 +184,10 @@ static const LookupListRec GameMessageMetaTypeNames[] =
183184 { " TOGGLE_CAMERA_TRACKING_DRAWABLE" , GameMessage::MSG_META_TOGGLE_CAMERA_TRACKING_DRAWABLE },
184185 { " TOGGLE_FAST_FORWARD_REPLAY" , GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY },
185186 { " TOGGLE_PAUSE" , GameMessage::MSG_META_TOGGLE_PAUSE },
187+ { " TOGGLE_PAUSE_ALT" , GameMessage::MSG_META_TOGGLE_PAUSE_ALT },
186188 { " STEP_FRAME" , GameMessage::MSG_META_STEP_FRAME },
187- { " DEMO_INSTANT_QUIT" , GameMessage::MSG_META_DEMO_INSTANT_QUIT },
189+ { " STEP_FRAME_ALT" , GameMessage::MSG_META_STEP_FRAME_ALT },
190+ { " DEMO_INSTANT_QUIT" , GameMessage::MSG_META_DEMO_INSTANT_QUIT },
188191
189192#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)// may be defined in GameCommon.h
190193 { " CHEAT_RUNSCRIPT1" , GameMessage::MSG_CHEAT_RUNSCRIPT1 },
@@ -400,6 +403,33 @@ static const char * findGameMessageNameByType(GameMessage::Type type)
400403 return " ???" ;
401404}
402405
406+ // -------------------------------------------------------------------------------------------------
407+ static Bool isMessageUsable (CommandUsableInType usableIn)
408+ {
409+ // We will ignore all commands if the game client has not yet incremented to frame 1.
410+ // It prevents the user from doing commands during a map load, which throws the input
411+ // system into whack because there isn't a client frame for the input event, and in
412+ // the case of a command that pauses the game, like the quit menu, the client frame
413+ // will never get beyond 0 and we lose the ability to process any input.
414+ if (TheGameClient->getFrame () == 0 )
415+ return false ;
416+
417+ const Bool usableInShell = (usableIn & COMMANDUSABLE_SHELL);
418+ const Bool usableInGame = (usableIn & COMMANDUSABLE_GAME);
419+ const Bool usableAsObserver = (usableIn & COMMANDUSABLE_OBSERVER);
420+
421+ if (usableInShell && TheShell && TheShell->isShellActive ())
422+ return true ;
423+
424+ if (usableInGame && (!TheShell || !TheShell->isShellActive ()))
425+ return true ;
426+
427+ if (usableAsObserver && rts::localPlayerIsObserving ())
428+ return true ;
429+
430+ return false ;
431+ }
432+
403433// -------------------------------------------------------------------------------------------------
404434GameMessageDisposition MetaEventTranslator::translateGameMessage (const GameMessage *msg)
405435{
@@ -431,34 +461,14 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
431461 }
432462
433463
434- for (const MetaMapRec *map = TheMetaMap->getFirstMetaMapRec (); map; map = map->m_next )
464+ for (const MetaMapRec *map = TheMetaMap->getFirstMetaMapRec (); map; map = map->m_next )
435465 {
436466 DEBUG_ASSERTCRASH (map->m_meta > GameMessage::MSG_BEGIN_META_MESSAGES &&
437467 map->m_meta < GameMessage::MSG_END_META_MESSAGES, (" hmm, expected only meta-msgs here" ));
438468
439- //
440- // if this command is *only* usable in the game, we will ignore it if the game client
441- // has not yet incremented to frame 1 (keeps us from doing in-game commands during
442- // a map load, which throws the input system into wack because there isn't a
443- // client frame for the input event, and in the case of a command that pauses the
444- // game, like the quit menu, the client frame will never get beyond 0 and we
445- // lose the ability to process any input
446- //
447- if ( map->m_usableIn == COMMANDUSABLE_GAME && TheGameClient->getFrame () < 1 )
469+ if (!isMessageUsable (map->m_usableIn ))
448470 continue ;
449471
450- // if the shell is active, and this command is not usable in shell, continue
451- if (TheShell && TheShell->isShellActive () && !(map->m_usableIn & COMMANDUSABLE_SHELL) )
452- continue ;
453-
454- // if the shell is not active and this command is not usable in the game, continue
455- if (TheShell && !TheShell->isShellActive () && !(map->m_usableIn & COMMANDUSABLE_GAME) )
456- continue ;
457-
458-
459-
460-
461-
462472 // check for the special case of mods-only-changed.
463473 if (
464474 map->m_key == MK_NONE &&
@@ -781,7 +791,7 @@ MetaMapRec *MetaMap::getMetaMapRec(GameMessage::Type t)
781791 map->m_key = MK_F;
782792 map->m_transition = DOWN;
783793 map->m_modState = NONE;
784- map->m_usableIn = COMMANDUSABLE_GAME;
794+ map->m_usableIn = COMMANDUSABLE_GAME; // @todo COMMANDUSABLE_OBSERVER
785795 }
786796 }
787797 {
@@ -792,7 +802,18 @@ MetaMapRec *MetaMap::getMetaMapRec(GameMessage::Type t)
792802 map->m_key = MK_P;
793803 map->m_transition = DOWN;
794804 map->m_modState = NONE;
795- map->m_usableIn = COMMANDUSABLE_GAME;
805+ map->m_usableIn = COMMANDUSABLE_OBSERVER;
806+ }
807+ }
808+ {
809+ // Is useful for Generals and Zero Hour.
810+ MetaMapRec *map = TheMetaMap->getMetaMapRec (GameMessage::MSG_META_TOGGLE_PAUSE_ALT);
811+ if (map->m_key == MK_NONE)
812+ {
813+ map->m_key = MK_P;
814+ map->m_transition = DOWN;
815+ map->m_modState = SHIFT; // Requires modifier to avoid key conflicts as a player.
816+ map->m_usableIn = COMMANDUSABLE_EVERYWHERE;
796817 }
797818 }
798819 {
@@ -803,7 +824,18 @@ MetaMapRec *MetaMap::getMetaMapRec(GameMessage::Type t)
803824 map->m_key = MK_O;
804825 map->m_transition = DOWN;
805826 map->m_modState = NONE;
806- map->m_usableIn = COMMANDUSABLE_GAME;
827+ map->m_usableIn = COMMANDUSABLE_OBSERVER;
828+ }
829+ }
830+ {
831+ // Is useful for Generals and Zero Hour.
832+ MetaMapRec *map = TheMetaMap->getMetaMapRec (GameMessage::MSG_META_STEP_FRAME_ALT);
833+ if (map->m_key == MK_NONE)
834+ {
835+ map->m_key = MK_O;
836+ map->m_transition = DOWN;
837+ map->m_modState = SHIFT; // Requires modifier to avoid key conflicts as a player.
838+ map->m_usableIn = COMMANDUSABLE_EVERYWHERE;
807839 }
808840 }
809841 {
0 commit comments