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"
@@ -174,7 +175,9 @@ static const LookupListRec GameMessageMetaTypeNames[] =
174175 { " CAMERA_RESET" , GameMessage::MSG_META_CAMERA_RESET },
175176 { " TOGGLE_FAST_FORWARD_REPLAY" , GameMessage::MSG_META_TOGGLE_FAST_FORWARD_REPLAY },
176177 { " TOGGLE_PAUSE" , GameMessage::MSG_META_TOGGLE_PAUSE },
178+ { " TOGGLE_PAUSE_ALT" , GameMessage::MSG_META_TOGGLE_PAUSE_ALT },
177179 { " STEP_FRAME" , GameMessage::MSG_META_STEP_FRAME },
180+ { " STEP_FRAME_ALT" , GameMessage::MSG_META_STEP_FRAME_ALT },
178181
179182#if defined(RTS_DEBUG)
180183 { " HELP" , GameMessage::MSG_META_HELP },
@@ -362,6 +365,33 @@ static const char * findGameMessageNameByType(GameMessage::Type type)
362365 return " ???" ;
363366}
364367
368+ // -------------------------------------------------------------------------------------------------
369+ static Bool isMessageUsable (CommandUsableInType usableIn)
370+ {
371+ // We will ignore all commands if the game client has not yet incremented to frame 1.
372+ // It prevents the user from doing commands during a map load, which throws the input
373+ // system into whack because there isn't a client frame for the input event, and in
374+ // the case of a command that pauses the game, like the quit menu, the client frame
375+ // will never get beyond 0 and we lose the ability to process any input.
376+ if (TheGameClient->getFrame () == 0 )
377+ return false ;
378+
379+ const Bool usableInShell = (usableIn & COMMANDUSABLE_SHELL);
380+ const Bool usableInGame = (usableIn & COMMANDUSABLE_GAME);
381+ const Bool usableAsObserver = (usableIn & COMMANDUSABLE_OBSERVER);
382+
383+ if (usableInShell && TheShell && TheShell->isShellActive ())
384+ return true ;
385+
386+ if (usableInGame && (!TheShell || !TheShell->isShellActive ()))
387+ return true ;
388+
389+ if (usableAsObserver && rts::localPlayerIsObserving ())
390+ return true ;
391+
392+ return false ;
393+ }
394+
365395// -------------------------------------------------------------------------------------------------
366396GameMessageDisposition MetaEventTranslator::translateGameMessage (const GameMessage *msg)
367397{
@@ -397,23 +427,7 @@ GameMessageDisposition MetaEventTranslator::translateGameMessage(const GameMessa
397427 DEBUG_ASSERTCRASH (map->m_meta > GameMessage::MSG_BEGIN_META_MESSAGES &&
398428 map->m_meta < GameMessage::MSG_END_META_MESSAGES, (" hmm, expected only meta-msgs here" ));
399429
400- //
401- // if this command is *only* usable in the game, we will ignore it if the game client
402- // has not yet incremented to frame 1 (keeps us from doing in-game commands during
403- // a map load, which throws the input system into wack because there isn't a
404- // client frame for the input event, and in the case of a command that pauses the
405- // game, like the quit menu, the client frame will never get beyond 0 and we
406- // lose the ability to process any input
407- //
408- if ( map->m_usableIn == COMMANDUSABLE_GAME && TheGameClient->getFrame () < 1 )
409- continue ;
410-
411- // if the shell is active, and this command is not usable in shell, continue
412- if (TheShell && TheShell->isShellActive () && !(map->m_usableIn & COMMANDUSABLE_SHELL) )
413- continue ;
414-
415- // if the shell is not active and this command is not usable in the game, continue
416- if (TheShell && !TheShell->isShellActive () && !(map->m_usableIn & COMMANDUSABLE_GAME) )
430+ if (!isMessageUsable (map->m_usableIn ))
417431 continue ;
418432
419433 // check for the special case of mods-only-changed.
@@ -719,7 +733,7 @@ MetaMapRec *MetaMap::getMetaMapRec(GameMessage::Type t)
719733 map->m_key = MK_F;
720734 map->m_transition = DOWN;
721735 map->m_modState = NONE;
722- map->m_usableIn = COMMANDUSABLE_GAME;
736+ map->m_usableIn = COMMANDUSABLE_GAME; // @todo COMMANDUSABLE_OBSERVER
723737 }
724738 }
725739 {
@@ -730,7 +744,18 @@ MetaMapRec *MetaMap::getMetaMapRec(GameMessage::Type t)
730744 map->m_key = MK_P;
731745 map->m_transition = DOWN;
732746 map->m_modState = NONE;
733- map->m_usableIn = COMMANDUSABLE_GAME;
747+ map->m_usableIn = COMMANDUSABLE_OBSERVER;
748+ }
749+ }
750+ {
751+ // Is useful for Generals and Zero Hour.
752+ MetaMapRec *map = TheMetaMap->getMetaMapRec (GameMessage::MSG_META_TOGGLE_PAUSE_ALT);
753+ if (map->m_key == MK_NONE)
754+ {
755+ map->m_key = MK_P;
756+ map->m_transition = DOWN;
757+ map->m_modState = SHIFT; // Requires modifier to avoid key conflicts as a player.
758+ map->m_usableIn = COMMANDUSABLE_EVERYWHERE;
734759 }
735760 }
736761 {
@@ -741,7 +766,18 @@ MetaMapRec *MetaMap::getMetaMapRec(GameMessage::Type t)
741766 map->m_key = MK_O;
742767 map->m_transition = DOWN;
743768 map->m_modState = NONE;
744- map->m_usableIn = COMMANDUSABLE_GAME;
769+ map->m_usableIn = COMMANDUSABLE_OBSERVER;
770+ }
771+ }
772+ {
773+ // Is useful for Generals and Zero Hour.
774+ MetaMapRec *map = TheMetaMap->getMetaMapRec (GameMessage::MSG_META_STEP_FRAME_ALT);
775+ if (map->m_key == MK_NONE)
776+ {
777+ map->m_key = MK_O;
778+ map->m_transition = DOWN;
779+ map->m_modState = SHIFT; // Requires modifier to avoid key conflicts as a player.
780+ map->m_usableIn = COMMANDUSABLE_EVERYWHERE;
745781 }
746782 }
747783 {
0 commit comments