forked from Mirrors/openclonk
Moving controls to script...
parent
ff15ca7441
commit
ce6d73b92a
|
@ -118,6 +118,7 @@
|
|||
#define C4CFN_Teams "Teams.txt"
|
||||
#define C4CFN_Parameters "Parameters.txt"
|
||||
#define C4CFN_RoundResults "RoundResults.txt"
|
||||
#define C4CFN_PlayerControls "PlayerControls.txt"
|
||||
|
||||
#define C4CFN_MapFolderData "FolderMap.txt"
|
||||
#define C4CFN_MapFolderBG "FolderMap"
|
||||
|
|
|
@ -173,6 +173,37 @@ public:
|
|||
DECLARE_C4CONTROL_VIRTUALS
|
||||
};
|
||||
|
||||
class C4ControlPlayerControl2 : public C4ControlPacket // sync
|
||||
{
|
||||
public:
|
||||
C4ControlPlayerControl2() : iPlr(-1), fRelease(false) {}
|
||||
C4ControlPlayerControl2(int32_t iPlr, bool fRelease, const C4KeyEventData &rExtraData)
|
||||
: iPlr(iPlr), fRelease(fRelease), ExtraData(rExtraData) { }
|
||||
|
||||
struct ControlItem
|
||||
{
|
||||
int32_t iControl;
|
||||
int32_t iTriggerMode;
|
||||
ControlItem() : iControl(-1), iTriggerMode(0) {}
|
||||
ControlItem(int32_t iControl, int32_t iTriggerMode) : iControl(iControl), iTriggerMode(iTriggerMode) {}
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool operator ==(const struct ControlItem &cmp) const { return iControl==cmp.iControl && iTriggerMode == cmp.iTriggerMode; }
|
||||
};
|
||||
typedef std::vector<ControlItem> ControlItemVec;
|
||||
protected:
|
||||
int32_t iPlr;
|
||||
bool fRelease;
|
||||
C4KeyEventData ExtraData;
|
||||
ControlItemVec ControlItems;
|
||||
public:
|
||||
DECLARE_C4CONTROL_VIRTUALS
|
||||
void AddControl(int32_t iControl, int32_t iTriggerMode)
|
||||
{ ControlItems.push_back(ControlItem(iControl, iTriggerMode)); }
|
||||
const ControlItemVec &GetControlItems() const { return ControlItems; }
|
||||
bool IsReleaseControl() const { return fRelease; }
|
||||
const C4KeyEventData &GetExtraData() const { return ExtraData; }
|
||||
};
|
||||
|
||||
class C4ControlPlayerCommand : public C4ControlPacket // sync
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -58,9 +58,10 @@
|
|||
#include <C4Network2Reference.h>
|
||||
#include <C4VideoPlayback.h>
|
||||
#include <C4RoundResults.h>
|
||||
#include <C4PlayerControl.h>
|
||||
|
||||
class C4Game
|
||||
{
|
||||
{
|
||||
private:
|
||||
// used as StdCompiler-parameter
|
||||
struct CompileSettings
|
||||
|
@ -81,13 +82,13 @@ class C4Game
|
|||
C4KeySetCtrl(int32_t iKeySet, int32_t iCtrl) : iKeySet(iKeySet), iCtrl(iCtrl) {}
|
||||
};
|
||||
|
||||
public:
|
||||
C4Game();
|
||||
public:
|
||||
C4Game();
|
||||
~C4Game();
|
||||
public:
|
||||
C4DefList Defs;
|
||||
C4TextureMap TextureMap;
|
||||
C4RankSystem Rank;
|
||||
C4DefList Defs;
|
||||
C4TextureMap TextureMap;
|
||||
C4RankSystem Rank;
|
||||
C4GraphicsSystem GraphicsSystem;
|
||||
C4MessageInput MessageInput;
|
||||
C4GraphicsResource GraphicsResource;
|
||||
|
@ -100,13 +101,13 @@ class C4Game
|
|||
C4RoundResults RoundResults;
|
||||
C4GameMessageList Messages;
|
||||
C4MouseControl MouseControl;
|
||||
C4Weather Weather;
|
||||
C4Weather Weather;
|
||||
C4MaterialMap Material;
|
||||
C4GameObjects Objects;
|
||||
C4ObjectList BackObjects; // objects in background (C4D_Background)
|
||||
C4ObjectList ForeObjects; // objects in foreground (C4D_Foreground)
|
||||
C4Landscape Landscape;
|
||||
C4Scenario C4S;
|
||||
C4Landscape Landscape;
|
||||
C4Scenario C4S;
|
||||
C4ComponentHost Info;
|
||||
C4ComponentHost Title;
|
||||
C4ComponentHost Names;
|
||||
|
@ -114,7 +115,7 @@ class C4Game
|
|||
C4AulScriptEngine ScriptEngine;
|
||||
C4GameScriptHost Script;
|
||||
C4LangStringTable MainSysLangStringTable, ScenarioLangStringTable, ScenarioSysLangStringTable;
|
||||
C4MassMoverSet MassMover;
|
||||
C4MassMoverSet MassMover;
|
||||
C4PXSSystem PXS;
|
||||
C4ParticleSystem Particles;
|
||||
C4PlayerList Players;
|
||||
|
@ -124,13 +125,15 @@ class C4Game
|
|||
|
||||
C4PathFinder PathFinder;
|
||||
C4TransferZones TransferZones;
|
||||
C4Group ScenarioFile;
|
||||
C4Group ScenarioFile;
|
||||
C4GroupSet GroupSet;
|
||||
C4Group *pParentGroup;
|
||||
C4Extra Extra;
|
||||
C4GUIScreen *pGUI;
|
||||
C4ScenarioSection *pScenarioSections, *pCurrentScenarioSection;
|
||||
C4Effect *pGlobalEffects;
|
||||
C4PlayerControlDefs PlayerControlDefs;
|
||||
C4PlayerControlAssignmentSets PlayerControlAssignmentSets;
|
||||
#ifndef USE_CONSOLE
|
||||
// We don't need fonts when we don't have graphics
|
||||
C4FontLoader FontLoader;
|
||||
|
@ -142,8 +145,8 @@ class C4Game
|
|||
class C4FileMonitor *pFileMonitor;
|
||||
class C4GameSec1Timer *pSec1Timer;
|
||||
|
||||
char CurrentScenarioSection[C4MaxName+1];
|
||||
char ScenarioFilename[_MAX_PATH+1];
|
||||
char CurrentScenarioSection[C4MaxName+1];
|
||||
char ScenarioFilename[_MAX_PATH+1];
|
||||
StdCopyStrBuf ScenarioTitle;
|
||||
char PlayerFilenames[20*_MAX_PATH+1];
|
||||
char DefinitionFilenames[20*_MAX_PATH+1];
|
||||
|
@ -152,13 +155,13 @@ class C4Game
|
|||
int32_t StartupPlayerCount;
|
||||
int32_t FPS,cFPS;
|
||||
int32_t HaltCount;
|
||||
bool GameOver;
|
||||
bool Evaluated;
|
||||
bool GameOver;
|
||||
bool Evaluated;
|
||||
bool GameOverDlgShown;
|
||||
bool fScriptCreatedObjects;
|
||||
bool fLobby;
|
||||
int32_t iLobbyTimeout;
|
||||
bool fObserve;
|
||||
bool fObserve;
|
||||
bool fReferenceDefinitionOverride;
|
||||
bool NetworkActive;
|
||||
bool Record;
|
||||
|
@ -192,27 +195,27 @@ class C4Game
|
|||
// next mission to be played after this one
|
||||
StdCopyStrBuf NextMission, NextMissionText, NextMissionDesc;
|
||||
|
||||
public:
|
||||
// Init and execution
|
||||
public:
|
||||
// Init and execution
|
||||
void Default();
|
||||
void Clear();
|
||||
void Abort(bool fApproved = false); // hard-quit on Esc+Y (/J/O)
|
||||
void Evaluate();
|
||||
void Evaluate();
|
||||
void ShowGameOverDlg();
|
||||
bool DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType eEventType, bool fAlt, bool fCtrl, bool fShift, bool fRepeated, class C4GUI::Dialog *pForDialog=NULL, bool fPlrCtrlOnly=false);
|
||||
void DrawCursors(C4TargetFacet &cgo, int32_t iPlayer);
|
||||
bool LocalControlKey(C4KeyCodeEx key, C4KeySetCtrl Ctrl);
|
||||
bool LocalControlKeyUp(C4KeyCodeEx key, C4KeySetCtrl Ctrl);
|
||||
void LocalPlayerControl(int32_t iPlayer, int32_t iCom);
|
||||
void FixRandom(int32_t iSeed);
|
||||
void LocalPlayerControl(int32_t iPlayer, int32_t iCom);
|
||||
void FixRandom(int32_t iSeed);
|
||||
bool Init();
|
||||
bool PreInit();
|
||||
void ParseCommandLine(const char *szCmdLine);
|
||||
BOOL Execute();
|
||||
class C4Player *JoinPlayer(const char *szFilename, int32_t iAtClient, const char *szAtClientName, C4PlayerInfo *pInfo);
|
||||
BOOL DoGameOver();
|
||||
void ParseCommandLine(const char *szCmdLine);
|
||||
BOOL Execute();
|
||||
class C4Player *JoinPlayer(const char *szFilename, int32_t iAtClient, const char *szAtClientName, C4PlayerInfo *pInfo);
|
||||
BOOL DoGameOver();
|
||||
bool CanQuickSave();
|
||||
BOOL QuickSave(const char *strFilename, const char *strTitle, bool fForceSave=false);
|
||||
BOOL QuickSave(const char *strFilename, const char *strTitle, bool fForceSave=false);
|
||||
void SetInitProgress(float fToProgress);
|
||||
void OnResolutionChanged(unsigned int iXRes, unsigned int iYRes); // update anything that's dependant on screen resolution
|
||||
void InitFullscreenComponents(bool fRunning);
|
||||
|
@ -223,58 +226,58 @@ class C4Game
|
|||
bool Unpause();
|
||||
bool IsPaused();
|
||||
// Network
|
||||
void Synchronize(BOOL fSavePlayerFiles);
|
||||
void SyncClearance();
|
||||
void Synchronize(BOOL fSavePlayerFiles);
|
||||
void SyncClearance();
|
||||
BOOL ReSync();
|
||||
void SyncCheckFiles(); // check if files are in sync
|
||||
// Editing
|
||||
// Editing
|
||||
BOOL DropFile(const char *szFilename, float iX, float iY);
|
||||
BOOL CreateViewport(int32_t iPlayer, bool fSilent=false);
|
||||
BOOL DropDef(C4ID id, float iX, float iY);
|
||||
BOOL LoadDef(const char *szFilename);
|
||||
BOOL ReloadFile(const char *szPath);
|
||||
BOOL ReloadDef(C4ID id);
|
||||
BOOL DropDef(C4ID id, float iX, float iY);
|
||||
BOOL LoadDef(const char *szFilename);
|
||||
BOOL ReloadFile(const char *szPath);
|
||||
BOOL ReloadDef(C4ID id);
|
||||
BOOL ReloadParticle(const char *szName);
|
||||
// Object functions
|
||||
void ClearPointers(C4Object *cobj);
|
||||
C4Object *CreateObject(C4ID type, C4Object *pCreator, int32_t owner=NO_OWNER,
|
||||
int32_t x=50, int32_t y=50, int32_t r=0,
|
||||
FIXED xdir=Fix0, FIXED ydir=Fix0, FIXED rdir=Fix0, int32_t iController=NO_OWNER);
|
||||
C4Object *CreateObjectConstruction(C4ID type,
|
||||
C4Object *pCreator,
|
||||
int32_t owner,
|
||||
int32_t ctx=0, int32_t bty=0,
|
||||
int32_t con=1, BOOL terrain=FALSE);
|
||||
C4Object *CreateInfoObject(C4ObjectInfo *cinf, int32_t owner,
|
||||
int32_t tx=50, int32_t ty=50);
|
||||
void BlastObjects(int32_t tx, int32_t ty, int32_t level, C4Object *inobj, int32_t iCausedBy, C4Object *pByObj);
|
||||
// Object functions
|
||||
void ClearPointers(C4Object *cobj);
|
||||
C4Object *CreateObject(C4ID type, C4Object *pCreator, int32_t owner=NO_OWNER,
|
||||
int32_t x=50, int32_t y=50, int32_t r=0,
|
||||
FIXED xdir=Fix0, FIXED ydir=Fix0, FIXED rdir=Fix0, int32_t iController=NO_OWNER);
|
||||
C4Object *CreateObjectConstruction(C4ID type,
|
||||
C4Object *pCreator,
|
||||
int32_t owner,
|
||||
int32_t ctx=0, int32_t bty=0,
|
||||
int32_t con=1, BOOL terrain=FALSE);
|
||||
C4Object *CreateInfoObject(C4ObjectInfo *cinf, int32_t owner,
|
||||
int32_t tx=50, int32_t ty=50);
|
||||
void BlastObjects(int32_t tx, int32_t ty, int32_t level, C4Object *inobj, int32_t iCausedBy, C4Object *pByObj);
|
||||
void ShakeObjects(int32_t tx, int32_t ry, int32_t range);
|
||||
C4Object *OverlapObject(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt,
|
||||
int32_t category);
|
||||
C4Object *FindObject(C4ID id,
|
||||
int32_t iX=0, int32_t iY=0, int32_t iWdt=0, int32_t iHgt=0,
|
||||
DWORD ocf=OCF_All,
|
||||
const char *szAction=NULL, C4Object *pActionTarget=NULL,
|
||||
C4Object *pExclude=NULL,
|
||||
C4Object *pContainer=NULL,
|
||||
int32_t iOwner=ANY_OWNER,
|
||||
C4Object *pFindNext=NULL);
|
||||
C4Object *OverlapObject(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt,
|
||||
int32_t category);
|
||||
C4Object *FindObject(C4ID id,
|
||||
int32_t iX=0, int32_t iY=0, int32_t iWdt=0, int32_t iHgt=0,
|
||||
DWORD ocf=OCF_All,
|
||||
const char *szAction=NULL, C4Object *pActionTarget=NULL,
|
||||
C4Object *pExclude=NULL,
|
||||
C4Object *pContainer=NULL,
|
||||
int32_t iOwner=ANY_OWNER,
|
||||
C4Object *pFindNext=NULL);
|
||||
C4Object *FindVisObject( // find object in view at pos, regarding parallaxity and visibility (but not distance)
|
||||
float tx, float ty, int32_t iPlr, const C4Facet &fctViewport,
|
||||
float iX=0, float iY=0, float iWdt=0, float iHgt=0,
|
||||
DWORD ocf=OCF_All,
|
||||
C4Object *pExclude=NULL,
|
||||
int32_t iOwner=ANY_OWNER,
|
||||
C4Object *pFindNext=NULL);
|
||||
int32_t ObjectCount(C4ID id,
|
||||
int32_t x=0, int32_t y=0, int32_t wdt=0, int32_t hgt=0,
|
||||
DWORD ocf=OCF_All,
|
||||
const char *szAction=NULL, C4Object *pActionTarget=NULL,
|
||||
C4Object *pExclude=NULL,
|
||||
C4Object *pContainer=NULL,
|
||||
int32_t iOwner=ANY_OWNER);
|
||||
C4Object *FindBase(int32_t iPlayer, int32_t iIndex);
|
||||
C4Object *FindFriendlyBase(int32_t iPlayer, int32_t iIndex);
|
||||
float tx, float ty, int32_t iPlr, const C4Facet &fctViewport,
|
||||
float iX=0, float iY=0, float iWdt=0, float iHgt=0,
|
||||
DWORD ocf=OCF_All,
|
||||
C4Object *pExclude=NULL,
|
||||
int32_t iOwner=ANY_OWNER,
|
||||
C4Object *pFindNext=NULL);
|
||||
int32_t ObjectCount(C4ID id,
|
||||
int32_t x=0, int32_t y=0, int32_t wdt=0, int32_t hgt=0,
|
||||
DWORD ocf=OCF_All,
|
||||
const char *szAction=NULL, C4Object *pActionTarget=NULL,
|
||||
C4Object *pExclude=NULL,
|
||||
C4Object *pContainer=NULL,
|
||||
int32_t iOwner=ANY_OWNER);
|
||||
C4Object *FindBase(int32_t iPlayer, int32_t iIndex);
|
||||
C4Object *FindFriendlyBase(int32_t iPlayer, int32_t iIndex);
|
||||
C4Object *FindObjectByCommand(int32_t iCommand, C4Object *pTarget=NULL, C4Value iTx=C4VNull, int32_t iTy=0, C4Object *pTarget2=NULL, C4Object *pFindNext=NULL);
|
||||
void CastObjects(C4ID id, C4Object *pCreator, int32_t num, int32_t level, int32_t tx, int32_t ty, int32_t iOwner=NO_OWNER, int32_t iController=NO_OWNER);
|
||||
void BlastCastObjects(C4ID id, C4Object *pCreator, int32_t num, int32_t tx, int32_t ty, int32_t iController=NO_OWNER);
|
||||
|
@ -282,14 +285,16 @@ class C4Game
|
|||
C4Object *PlaceAnimal(C4ID idAnimal);
|
||||
|
||||
BOOL LoadScenarioSection(const char *szSection, DWORD dwFlags);
|
||||
BOOL SaveDesc(C4Group &hGroup, BOOL fSaveGame=FALSE, BOOL fReference=FALSE, BOOL fLobby=FALSE, BOOL fUnregistered=FALSE, BOOL fRecord=FALSE);
|
||||
BOOL SaveDesc(C4Group &hGroup, BOOL fSaveGame=FALSE, BOOL fReference=FALSE, BOOL fLobby=FALSE, BOOL fUnregistered=FALSE, BOOL fRecord=FALSE);
|
||||
|
||||
bool DrawTextSpecImage(C4FacetSurface &fctTarget, const char *szSpec, uint32_t dwClr=0xff);
|
||||
bool SpeedUp();
|
||||
bool SlowDown();
|
||||
bool InitKeyboard(); // register main keyboard input functions
|
||||
void UpdateLanguage();
|
||||
bool InitPlayerControlSettings();
|
||||
|
||||
protected:
|
||||
protected:
|
||||
bool InitSystem();
|
||||
void InitInEarth();
|
||||
void InitVegetation();
|
||||
|
|
|
@ -202,6 +202,7 @@
|
|||
#include "C4PathFinder.h"
|
||||
#include "C4Physics.h"
|
||||
#include "C4Player.h"
|
||||
#include "C4PlayerControl.h"
|
||||
#include "C4PlayerInfo.h"
|
||||
#include "C4PlayerInfoListBox.h"
|
||||
#include "C4PlayerList.h"
|
||||
|
|
|
@ -167,7 +167,17 @@ struct C4KeyCodeEx
|
|||
C4KeyCodeEx(C4KeyCode Key = KEY_Default, C4KeyShiftState Shift = KEYS_None, bool fIsRepeated = false)
|
||||
: Key(Key), dwShift(Shift), fRepeated(fIsRepeated) {}
|
||||
|
||||
bool IsRepeated() { return fRepeated; }
|
||||
bool IsRepeated() const { return fRepeated; }
|
||||
};
|
||||
|
||||
// extra data associated with a key event
|
||||
struct C4KeyEventData
|
||||
{
|
||||
int32_t iStrength; // pressure between 0 and 100 (100 for nomal keypress)
|
||||
int32_t x,y; // position for mouse event
|
||||
C4KeyEventData() : iStrength(0), x(0), y(0) {}
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool operator ==(const struct C4KeyEventData &cmp) const;
|
||||
};
|
||||
|
||||
// callback interface
|
||||
|
@ -392,6 +402,7 @@ class C4KeyboardInput
|
|||
// mapping of all keys by code and name
|
||||
KeyCodeMap KeysByCode;
|
||||
KeyNameMap KeysByName;
|
||||
C4KeyEventData LastKeyExtraData;
|
||||
|
||||
public:
|
||||
static bool IsValid; // global var to fix any deinitialization orders of key map and static keys
|
||||
|
@ -417,6 +428,7 @@ class C4KeyboardInput
|
|||
|
||||
C4CustomKey *GetKeyByName(const char *szKeyName);
|
||||
StdStrBuf GetKeyCodeNameByKeyName(const char *szKeyName, bool fShort = false, int32_t iIndex = 0);
|
||||
const C4KeyEventData &GetLastKeyExtraData() const { return LastKeyExtraData; }
|
||||
};
|
||||
|
||||
// keyboardinput-initializer-helper
|
||||
|
|
|
@ -159,6 +159,7 @@ enum C4PacketType
|
|||
CID_PlrControl = CID_First | 0x21,
|
||||
CID_PlrCommand = CID_First | 0x22,
|
||||
CID_Message = CID_First | 0x23,
|
||||
CID_PlrControl2 = CID_First | 0x24,
|
||||
|
||||
CID_EMMoveObj = CID_First | 0x30,
|
||||
CID_EMDrawTool = CID_First | 0x31,
|
||||
|
|
|
@ -30,12 +30,25 @@ class C4PlayerControlDef
|
|||
StdCopyStrBuf sIdentifier; // name as seen in script and config
|
||||
StdCopyStrBuf sGUIName; // name as displayed to player
|
||||
StdCopyStrBuf sGUIDesc; // key description displayed to player in config dialog
|
||||
bool fGlobal; // if true, control can be bound to the global player only
|
||||
bool fIsHoldKey; // if true, the control can be in down and up state
|
||||
int32_t iRepeat; // if >0, the key will generate successive events when held down
|
||||
int32_t iRepeatDelay; // if >0, the key will generate successive events when held down
|
||||
int32_t iInitialRepeatDelay; // delay after which KeyRepeat will be enabled
|
||||
bool fDefaultDisabled; // if true, the control is disabled by default and needs to be enabled by script
|
||||
C4ID idControlExtraData; // extra data to be passed to script function
|
||||
public:
|
||||
enum Actions //action to be performed when control is triggered
|
||||
{
|
||||
CDA_None=0, // do nothing
|
||||
CDA_Script, // default: Script callback
|
||||
CDA_Menu, // open player menu (async)
|
||||
CDA_MenuOK, CDA_MenuCancel, CDA_MenuLeft, CDA_MenuUp, CDA_MenuRight, CDA_MenuDown, // player menu controls (async)
|
||||
};
|
||||
private:
|
||||
Actions eAction;
|
||||
|
||||
public:
|
||||
C4PlayerControlDef() : fIsHoldKey(false), fDefaultDisabled(false) {}
|
||||
C4PlayerControlDef() : fIsHoldKey(false), fDefaultDisabled(false), eAction(CDA_Script), fGlobal(false), idControlExtraData(C4ID_None) {}
|
||||
~C4PlayerControlDef() {};
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
@ -43,9 +56,18 @@ class C4PlayerControlDef
|
|||
const char *GetIdentifier() const { return sIdentifier.getData(); }
|
||||
const char *GetGUIName() const { return sGUIName.getData(); }
|
||||
const char *GetGUIDesc() const { return sGUIDesc.getData(); }
|
||||
Actions GetAction() const { return eAction; }
|
||||
bool IsHoldKey() const { return fIsHoldKey; }
|
||||
C4ID GetExtraData() const { return idControlExtraData; }
|
||||
bool IsGlobal() const { return fGlobal; }
|
||||
|
||||
//C4PlayerControlDef &operator =(const C4PlayerControlDef &src);
|
||||
bool operator ==(const C4PlayerControlDef &cmp) const;
|
||||
|
||||
bool Execute(bool fUp, const C4KeyEventData &rKeyExtraData); // key was triggered - execute and return if handled
|
||||
bool IsAsync() const { return eAction != CDA_None && eAction != CDA_Script; } // true if to be executed directly when triggered
|
||||
bool IsSync() const { return eAction == CDA_Script; } // true if to be executed via control queue
|
||||
bool IsValid() const { return eAction != CDA_None; }
|
||||
};
|
||||
|
||||
// CON_* constants are indices into the C4PlayerControlDefs list
|
||||
|
@ -59,11 +81,17 @@ class C4PlayerControlDefs
|
|||
DefVecImpl Defs;
|
||||
|
||||
public:
|
||||
C4PlayerControlDefs() {}
|
||||
~C4PlayerControlDefs() {}
|
||||
void Clear();
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
void MergeFrom(const C4PlayerControlDefs &Src); // copy all defs from source file; overwrite defs of same name if found
|
||||
|
||||
C4PlayerControlDef *GetControlByIndex(int32_t idx);
|
||||
int32_t GetControlIndexByIdentifier(const char *szIdentifier) const; // return CON_None for not found
|
||||
|
||||
bool operator ==(const C4PlayerControlDefs &cmp) const { return Defs == cmp.Defs; }
|
||||
};
|
||||
|
||||
// a key/mouse/gamepad assignment to a PlayerControlDef
|
||||
|
@ -89,47 +117,73 @@ class C4PlayerControlAssignment
|
|||
|
||||
StdCopyStrBuf sControlName; // name of the control to be executed on this key
|
||||
int32_t iControl; // the control to be executed on this key, i.e. the resolved sControlName
|
||||
bool fAlwaysUnhandled; // if true, the key will not block handling of other keys even if it got handled
|
||||
int32_t iPriority; // higher priority assignments get handled first
|
||||
|
||||
public:
|
||||
// action to be performed on the control upon this key
|
||||
enum TriggerModes
|
||||
{
|
||||
CTM_Default=0, // standard behaviour: The control will be triggered
|
||||
CTM_Hold, // the control will be put into "down"-mode
|
||||
CTM_Release, // the hold mode of the control will be released
|
||||
} eTriggerMode;
|
||||
CTM_Default=0, // standard behaviour: The control will be triggered
|
||||
CTM_Hold= 1<<0, // the control will be put into "down"-mode
|
||||
CTM_Release= 1<<1, // the hold mode of the control will be released
|
||||
CTM_AlwaysUnhandled= 1<<2, // the key will not block handling of other keys even if it got handled
|
||||
};
|
||||
|
||||
private:
|
||||
int32_t iTriggerMode;
|
||||
|
||||
bool fRefsResolved; // set to true after sControlName and sKeyNames have been resolved to runtime values
|
||||
|
||||
public:
|
||||
C4PlayerControlAssignment() : TriggerKey(), iControl(CON_None), fAlwaysUnhandled(false), eTriggerMode(CTM_Default) {}
|
||||
~C4PlayerControlAssignment();
|
||||
C4PlayerControlAssignment() : TriggerKey(), iControl(CON_None), iTriggerMode(CTM_Default), iPriority(0), fRefsResolved(false) {}
|
||||
~C4PlayerControlAssignment() {}
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
void ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
|
||||
bool ResolveRefs(class C4PlayerControlAssignmentSet *pParentSet, C4PlayerControlDefs *pControlDefs); // resolve references between assignments
|
||||
|
||||
bool operator ==(const C4PlayerControlAssignment &cmp) const; // doesn't compare resolved TriggerKey/iControl
|
||||
bool operator <(const C4PlayerControlAssignment &cmp) const { return iPriority < cmp.iPriority; }
|
||||
const char *GetControlName() const { return sControlName.getData(); }
|
||||
int32_t GetControl() const { return iControl; }
|
||||
bool IsRefsResolved() const { return fRefsResolved; }
|
||||
bool IsAlwaysUnhandled() const { return iTriggerMode & CTM_AlwaysUnhandled; }
|
||||
int32_t GetTriggerMode() const { return iTriggerMode; }
|
||||
};
|
||||
|
||||
typedef std::vector<C4PlayerControlAssignment> C4PlayerControlAssignmentVec;
|
||||
|
||||
struct C4PlayerControlRecentKey
|
||||
{
|
||||
C4KeyCodeEx Key;
|
||||
int32_t iFrame;
|
||||
C4PlayerControlRecentKey(const C4KeyCodeEx &Key, int32_t iFrame) : Key(Key), iFrame(iFrame) {}
|
||||
bool operator ==(const C4PlayerControlRecentKey &cmp) { return Key==cmp.Key; } // comparison op for finding items in lists: Search for the key only
|
||||
};
|
||||
|
||||
typedef std::list<C4PlayerControlRecentKey> C4PlayerControlRecentKeyList;
|
||||
|
||||
// a set of key/mouse/gamepad assignments to all controls
|
||||
class C4PlayerControlAssignmentSet
|
||||
{
|
||||
private:
|
||||
StdCopyStrBuf sName;
|
||||
typedef std::vector<C4PlayerControlAssignment> AssignmentsVec;
|
||||
AssignmentsVec Assignments;
|
||||
C4PlayerControlAssignmentVec Assignments;
|
||||
|
||||
public:
|
||||
C4PlayerControlAssignmentSet() {}
|
||||
~C4PlayerControlAssignmentSet() {}
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
void ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
|
||||
bool ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
|
||||
|
||||
void MergeFrom(const C4PlayerControlAssignmentSet &Src, bool fLowPrio); // take over all assignments defined in Src
|
||||
|
||||
const char *GetName() const { return sName.getData(); }
|
||||
|
||||
C4PlayerControlAssignment *GetAssignmentByControlName(const char *szControlName) const;
|
||||
C4PlayerControlAssignment *GetAssignmentByControlName(const char *szControlName);
|
||||
void GetAssignmentsByKey(const C4KeyCodeEx &key, bool fHoldKeysOnly, C4PlayerControlAssignmentVec *pOutVec, const C4PlayerControlRecentKeyList &DownKeys, const C4PlayerControlRecentKeyList &RecentKeys); // match only by TriggerKey (last key of Combo) if fHoldKeysOnly
|
||||
|
||||
bool operator ==(const C4PlayerControlAssignmentSet &cmp) const;
|
||||
};
|
||||
|
||||
// list of C4PlayerControlAssignmentSet
|
||||
|
@ -137,26 +191,34 @@ class C4PlayerControlAssignmentSets
|
|||
{
|
||||
private:
|
||||
typedef std::list<C4PlayerControlAssignmentSet> AssignmentSetList;
|
||||
AssignmentSetList Sets;
|
||||
|
||||
public:
|
||||
C4PlayerControlAssignmentSets() {}
|
||||
~C4PlayerControlAssignmentSets() {}
|
||||
void Clear();
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
|
||||
|
||||
void MergeFrom(const C4PlayerControlAssignmentSets &Src, bool fLowPrio); // take over all assignments in known sets and new sets defined in Src
|
||||
|
||||
C4PlayerControlAssignmentSet *GetSetByName(const char *szName);
|
||||
};
|
||||
|
||||
// contents of one PlayerControls.txt file
|
||||
class C4PlayerControlFile
|
||||
{
|
||||
private:
|
||||
C4PlayerControlDef ControlDefs;
|
||||
C4PlayerControlDefs ControlDefs;
|
||||
C4PlayerControlAssignmentSets AssignmentSets;
|
||||
public:
|
||||
bool Load(C4Group &hGroup, const char *szFilename);
|
||||
void Clear();
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool Load(C4Group &hGroup, const char *szFilename, C4LangStringTable *pLang);
|
||||
bool Save(C4Group &hGroup, const char *szFilename);
|
||||
|
||||
const C4PlayerControlDef &GetControlDefs() const { return ControlDefs; }
|
||||
const C4PlayerControlDefs &GetControlDefs() const { return ControlDefs; }
|
||||
const C4PlayerControlAssignmentSets &GetAssignmentSets() const { return AssignmentSets; }
|
||||
};
|
||||
|
||||
|
@ -164,40 +226,69 @@ class C4PlayerControlFile
|
|||
class C4PlayerControl
|
||||
{
|
||||
private:
|
||||
struct RecentKey
|
||||
{
|
||||
C4KeyCodeEx Key;
|
||||
int32_t iFrame;
|
||||
};
|
||||
// shortcut
|
||||
C4PlayerControlDefs &ControlDefs;
|
||||
C4PlayerControlDefs &ControlDefs; // shortcut
|
||||
|
||||
// owner
|
||||
int32_t iPlr;
|
||||
|
||||
// async values
|
||||
C4PlayerControlAssignmentSet *pControlSet; // the control set used by this player
|
||||
std::list<C4KeyBinding *> KeyBindings; // keys registered into Game.KeyboardInput
|
||||
std::list<RecentKey> RecentKeys; // keys pressed recently; for combinations
|
||||
std::vector<C4KeyCodeEx> DownKeys; // keys currently held down
|
||||
C4PlayerControlRecentKeyList RecentKeys; // keys pressed recently; for combinations
|
||||
C4PlayerControlRecentKeyList DownKeys; // keys currently held down
|
||||
|
||||
// sync values
|
||||
struct
|
||||
struct CSync
|
||||
{
|
||||
std::vector<int32_t> ControlDownStates; // indexed by C4PlayerControlID: Down-state of a control. 0=up, 100=down; values inbetween e.g. for gamepad sticks
|
||||
std::vector<int32_t> ControlDisableStates; // indexed by C4PlayerControlID: Disable-states of controls. >0 is disabled.
|
||||
struct ControlDownState
|
||||
{
|
||||
C4KeyEventData DownState; // control is down if DownState.iStrength>0
|
||||
int32_t iDownFrame; // frame when control was pressed
|
||||
bool fDownByUser; // if true, the key is actually pressed. Otherwise, it's triggered as down by another key
|
||||
ControlDownState(const C4KeyEventData &rDownState, int32_t iDownFrame, bool fDownByUser)
|
||||
: DownState(rDownState), iDownFrame(iDownFrame), fDownByUser(fDownByUser) {}
|
||||
};
|
||||
typedef std::vector<int32_t> DownStateVec;
|
||||
DownStateVec ControlDownStates; // indexed by C4PlayerControlID: Down-state of a control. 0=up, 100=down; values inbetween e.g. for gamepad sticks
|
||||
typedef std::vector<int32_t> DisableStateVec;
|
||||
DisableStateVec ControlDisableStates; // indexed by C4PlayerControlID: Disable-states of controls. >0 is disabled.
|
||||
|
||||
const ControlDownState *GetControlDownState(int32_t iControl) const;
|
||||
int32_t GetControlDisabled(int32_t iControl) const;
|
||||
bool IsControlDisabled(int32_t iControl) const { return GetControlDisabled(iControl)>0; }
|
||||
void SetControlDownState(int32_t iControl, const C4KeyEventData &rDownState, int32_t iDownFrame, bool fDownByUser);
|
||||
void SetControlDisabled(int32_t iControl, int32_t iVal);
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool operator ==(const CSync &cmp) const;
|
||||
} Sync;
|
||||
|
||||
// callbacks from Game.KeyboardInput
|
||||
bool ProcessKeyPress(C4KeyCodeEx key, int32_t iKeyIndex);
|
||||
bool ProcessKeyDown(C4KeyCodeEx key, int32_t iKeyIndex);
|
||||
bool ProcessKeyUp(C4KeyCodeEx key, int32_t iKeyIndex);
|
||||
bool ProcessKeyEvent(const C4KeyCodeEx &key, bool fUp, const C4KeyEventData &rKeyExtraData);
|
||||
bool ProcessKeyDown(const C4KeyCodeEx &key);
|
||||
bool ProcessKeyUp(const C4KeyCodeEx &key);
|
||||
|
||||
// execute single control. return if handled.
|
||||
bool ExecuteControl(int32_t iControl, bool fUp, const C4KeyEventData &rKeyExtraData, int32_t iTriggerMode, bool fRepeated);
|
||||
bool ExecuteControlAction(int32_t iControl, C4PlayerControlDef::Actions eAction, C4ID idControlExtraData, bool fUp, const C4KeyEventData &rKeyExtraData, bool fRepeated);
|
||||
bool ExecuteControlScript(int32_t iControl, C4ID idControlExtraData, bool fUp, const C4KeyEventData &rKeyExtraData, bool fRepeated);
|
||||
|
||||
// sync execution: Do keyrepeat, etc.
|
||||
void Execute();
|
||||
|
||||
public:
|
||||
C4PlayerControl();
|
||||
~C4PlayerControl() { Clear(); }
|
||||
void Clear();
|
||||
|
||||
void RegisterKeyset(C4PlayerControlAssignmentSet *pKeyset); // register all keys into Game.KeyboardInput creating KeyBindings
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
||||
void RegisterKeyset(int32_t iPlr, C4PlayerControlAssignmentSet *pKeyset); // register all keys into Game.KeyboardInput creating KeyBindings
|
||||
|
||||
bool IsGlobal() const { return iPlr==-1; }
|
||||
|
||||
// callback from control queue
|
||||
void ExecuteControlPacket(const class C4ControlPlayerControl2 *pCtrl);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -150,6 +150,8 @@ void InitFunctionMap(C4AulScriptEngine *pEngine); // add functions to engine
|
|||
#define PSF_OnHostilityChange "~OnHostilityChange" // int iPlr1, int iPlr2, bool fNewHostility, bool fOldHostility
|
||||
#define PSF_OnTeamSwitch "~OnTeamSwitch" // int iPlr1, int idNewTeam, int idOldTeam
|
||||
#define PSF_OnOwnerRemoved "~OnOwnerRemoved"
|
||||
#define PSF_PlayerControl "~PlayerControl" // int iControl, C4ID idControlExtraData, int x, int y, int iStrength, bool fRepeated
|
||||
#define PSF_PlayerControlRelease "~PlayerControlRelease" // int iControl, C4ID idControlExtraData, int x, int y
|
||||
|
||||
// Fx%s is automatically prefixed
|
||||
#define PSFS_FxAdd "Add" // C4Object *pTarget, int iEffectNumber, C4String *szNewEffect, int iNewTimer, C4Value vNewEffectVar1, C4Value vNewEffectVar2, C4Value vNewEffectVar3, C4Value vNewEffectVar4
|
||||
|
|
|
@ -376,6 +376,45 @@ void C4ControlPlayerControl::CompileFunc(StdCompiler *pComp)
|
|||
C4ControlPacket::CompileFunc(pComp);
|
||||
}
|
||||
|
||||
|
||||
// *** C4ControlPlayerControl2
|
||||
|
||||
void C4ControlPlayerControl2::Execute() const
|
||||
{
|
||||
C4PlayerControl *pTargetCtrl = NULL;
|
||||
if (iPlr == -1)
|
||||
{
|
||||
// neutral control packet: Execute in global control
|
||||
}
|
||||
else
|
||||
{
|
||||
// player-based control: Execute on control owned by player
|
||||
C4Player *pPlr=Game.Players.Get(iPlr);
|
||||
if (pPlr)
|
||||
{
|
||||
//pPlr->CountControl(C4Player::PCID_DirectCom, iCom*10000+iData);
|
||||
}
|
||||
}
|
||||
if (pTargetCtrl) pTargetCtrl->ExecuteControlPacket(this);
|
||||
}
|
||||
|
||||
void C4ControlPlayerControl2::ControlItem::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(iControl);
|
||||
pComp->Seperator();
|
||||
pComp->Value(iTriggerMode);
|
||||
}
|
||||
|
||||
void C4ControlPlayerControl2::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkIntPackAdapt(iPlr), "Player", -1));
|
||||
pComp->Value(mkNamingAdapt(fRelease, "Release", false));
|
||||
pComp->Value(mkNamingAdapt(ExtraData, "ExtraData", C4KeyEventData()));
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(ControlItems), "Controls", ControlItemVec()));
|
||||
C4ControlPacket::CompileFunc(pComp);
|
||||
}
|
||||
|
||||
|
||||
// *** C4ControlPlayerCommand
|
||||
|
||||
C4ControlPlayerCommand::C4ControlPlayerCommand(int32_t iPlr, int32_t iCmd, int32_t iX, int32_t iY,
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <C4ObjectMenu.h>
|
||||
#include <C4GameLobby.h>
|
||||
#include <C4ChatDlg.h>
|
||||
#include <C4PlayerControl.h>
|
||||
#endif
|
||||
|
||||
#include <StdFile.h>
|
||||
|
@ -572,6 +573,8 @@ void C4Game::Clear()
|
|||
KeyboardInput.Clear();
|
||||
SetMusicLevel(100);
|
||||
PlayList.Clear();
|
||||
PlayerControlAssignmentSets.Clear();
|
||||
PlayerControlDefs.Clear();
|
||||
|
||||
// global fullscreen class is not cleared, because it holds the carrier window
|
||||
// but the menu must be cleared (maybe move Fullscreen.Menu somewhere else?)
|
||||
|
@ -2443,9 +2446,6 @@ BOOL C4Game::InitScriptEngine()
|
|||
{ LogFatal(LoadResStr("IDS_ERR_INVALIDSYSGRP")); return FALSE; }
|
||||
C4Group &File = Application.SystemGroup;
|
||||
|
||||
// Load string table
|
||||
MainSysLangStringTable.LoadEx("StringTbl", File, C4CFN_ScriptStringTbl, Config.General.LanguageEx);
|
||||
|
||||
// get scripts
|
||||
char fn[_MAX_FNAME+1] = { 0 };
|
||||
File.ResetSearch();
|
||||
|
@ -3238,12 +3238,34 @@ bool C4Game::InitSystem()
|
|||
// init keyboard input (default keys, plus overloads)
|
||||
if (!InitKeyboard())
|
||||
{ LogFatal(LoadResStr("IDS_ERR_NOKEYBOARD")); return false; }
|
||||
// Load string table
|
||||
UpdateLanguage();
|
||||
// Player keyboard input: Key definitions and default sets
|
||||
if (!InitPlayerControlSettings()) return false;
|
||||
// Rank system
|
||||
Rank.Init(Config.GetSubkeyPath("ClonkRanks"), LoadResStr("IDS_GAME_DEFRANKS"), 1000);
|
||||
// done, success
|
||||
return true;
|
||||
}
|
||||
|
||||
void C4Game::UpdateLanguage()
|
||||
{
|
||||
// Reload System.c4g string table
|
||||
MainSysLangStringTable.LoadEx("StringTbl", Application.SystemGroup, C4CFN_ScriptStringTbl, Config.General.LanguageEx);
|
||||
}
|
||||
|
||||
bool C4Game::InitPlayerControlSettings()
|
||||
{
|
||||
C4PlayerControlFile PlayerControlFile;
|
||||
if (!PlayerControlFile.Load(Application.SystemGroup, C4CFN_PlayerControls, &MainSysLangStringTable)) { LogFatal("[!]Error loading player controls"); return false; }
|
||||
PlayerControlDefs = PlayerControlFile.GetControlDefs();
|
||||
PlayerControlAssignmentSets = PlayerControlFile.GetAssignmentSets();
|
||||
PlayerControlAssignmentSets.ResolveRefs(&PlayerControlDefs);
|
||||
// And overwrites from config
|
||||
//PlayerControlAssignmentSets.MergeFrom(Config.Controls.Assignments);
|
||||
return true;
|
||||
}
|
||||
|
||||
C4Player *C4Game::JoinPlayer(const char *szFilename, int32_t iAtClient, const char *szAtClientName, C4PlayerInfo *pInfo)
|
||||
{
|
||||
assert(pInfo);
|
||||
|
|
|
@ -494,6 +494,21 @@ void C4KeyCodeEx::CompileFunc(StdCompiler *pComp, StdStrBuf *pOutBufIfUndefined)
|
|||
}
|
||||
}
|
||||
|
||||
void C4KeyEventData::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(iStrength);
|
||||
pComp->Seperator();
|
||||
pComp->Value(x);
|
||||
pComp->Seperator();
|
||||
pComp->Value(y);
|
||||
}
|
||||
|
||||
bool C4KeyEventData::operator ==(const struct C4KeyEventData &cmp) const
|
||||
{
|
||||
return iStrength == cmp.iStrength
|
||||
&& x == cmp.x && y == cmp.y;
|
||||
}
|
||||
|
||||
/* ----------------- C4CustomKey------------------ */
|
||||
|
||||
C4CustomKey::C4CustomKey(C4KeyCodeEx DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority)
|
||||
|
@ -640,6 +655,7 @@ bool C4KeyboardInput::IsValid = false;
|
|||
|
||||
void C4KeyboardInput::Clear()
|
||||
{
|
||||
LastKeyExtraData = C4KeyEventData();
|
||||
// release all keys - name map is guarantueed to contain them all
|
||||
for (KeyNameMap::const_iterator i = KeysByName.begin(); i != KeysByName.end(); ++i)
|
||||
i->second->Deref();
|
||||
|
|
|
@ -24,13 +24,28 @@
|
|||
|
||||
void C4PlayerControlDef::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
if (!pComp->Name("ControlDef")) pComp->excNotFound("ControlDef");
|
||||
if (!pComp->Name("ControlDef")) { pComp->NameEnd(); pComp->excNotFound("ControlDef"); }
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(sIdentifier, StdCompiler::RCT_Idtf), "Identifier", "None"));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(sGUIName, StdCompiler::RCT_All), "GUIName", "undefined"));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(sGUIDesc, StdCompiler::RCT_All), "GUIDesc", ""));
|
||||
pComp->Value(mkNamingAdapt(fIsHoldKey, "IsHoldKey", false));
|
||||
pComp->Value(mkNamingAdapt(iRepeat, "Repeat", 0));
|
||||
pComp->Value(mkNamingAdapt(fGlobal, "Global", false));
|
||||
pComp->Value(mkNamingAdapt(fIsHoldKey, "Hold", false));
|
||||
pComp->Value(mkNamingAdapt(iRepeatDelay, "RepeatDelay", 0));
|
||||
pComp->Value(mkNamingAdapt(iInitialRepeatDelay, "InitialRepeatDelay", 0));
|
||||
pComp->Value(mkNamingAdapt(fDefaultDisabled, "DefaultDisabled", false));
|
||||
pComp->Value(mkNamingAdapt(mkC4IDAdapt(idControlExtraData), "ExtraData", C4ID_None));
|
||||
const StdEnumEntry<Actions> ActionNames[] = {
|
||||
{ "None", CDA_None },
|
||||
{ "Script", CDA_Script },
|
||||
{ "Menu", CDA_Menu },
|
||||
{ "MenuOK", CDA_MenuOK },
|
||||
{ "MenuCancel", CDA_MenuCancel },
|
||||
{ "MenuLeft", CDA_MenuLeft },
|
||||
{ "MenuUp", CDA_MenuUp },
|
||||
{ "MenuRight", CDA_MenuRight },
|
||||
{ "MenuDown", CDA_MenuDown },
|
||||
{ NULL, CDA_None } };
|
||||
pComp->Value(mkNamingAdapt(mkEnumAdapt<Actions, int32_t>(eAction, ActionNames), "Action", CDA_Script));
|
||||
pComp->NameEnd();
|
||||
}
|
||||
|
||||
|
@ -39,14 +54,23 @@ bool C4PlayerControlDef::operator ==(const C4PlayerControlDef &cmp) const
|
|||
return sIdentifier == cmp.sIdentifier
|
||||
&& sGUIName == cmp.sGUIName
|
||||
&& sGUIDesc == cmp.sGUIDesc
|
||||
&& fGlobal == cmp.fGlobal
|
||||
&& fIsHoldKey == cmp.fIsHoldKey
|
||||
&& iRepeat == cmp.iRepeat
|
||||
&& fDefaultDisabled == cmp.fDefaultDisabled;
|
||||
&& iRepeatDelay == cmp.iRepeatDelay
|
||||
&& iInitialRepeatDelay == cmp.iInitialRepeatDelay
|
||||
&& fDefaultDisabled == cmp.fDefaultDisabled
|
||||
&& idControlExtraData == cmp.idControlExtraData
|
||||
&& eAction == cmp.eAction;
|
||||
}
|
||||
|
||||
|
||||
/* C4PlayerControlDefs */
|
||||
|
||||
void C4PlayerControlDefs::Clear()
|
||||
{
|
||||
Defs.clear();
|
||||
}
|
||||
|
||||
void C4PlayerControlDefs::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Defs, StdCompiler::SEP_NONE), "ControlDefs", DefVecImpl()));
|
||||
|
@ -113,17 +137,68 @@ void C4PlayerControlAssignment::KeyComboItem::CompileFunc(StdCompiler *pComp)
|
|||
|
||||
void C4PlayerControlAssignment::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
if (!pComp->Name("ControlAssignment")) pComp->excNotFound("ControlAssignment");
|
||||
if (!pComp->Name("Assignment")) { pComp->NameEnd(); pComp->excNotFound("Assignment"); }
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(KeyCombo), "Key", KeyComboVec()));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(sControlName, StdCompiler::RCT_Idtf), "Control", "None"));
|
||||
pComp->Value(mkNamingAdapt(fAlwaysUnhandled, "AlwaysUnhandled", false));
|
||||
const StdEnumEntry<TriggerModes> TriggerModeNames[] = {
|
||||
pComp->Value(mkNamingAdapt(iPriority, "Priority", 0));
|
||||
const StdBitfieldEntry<int32_t> TriggerModeNames[] = {
|
||||
{ "Default", CTM_Default },
|
||||
{ "Hold", CTM_Hold },
|
||||
{ "Release", CTM_Release },
|
||||
{ NULL, CTM_Default } };
|
||||
pComp->Value(mkNamingAdapt(mkEnumAdapt<TriggerModes, int32_t>(eTriggerMode, TriggerModeNames), "TriggerMode", CTM_Default));
|
||||
{ "AlwaysUnhandled", CTM_AlwaysUnhandled },
|
||||
{ NULL, 0 } };
|
||||
pComp->Value(mkNamingAdapt(mkBitfieldAdapt< int32_t>(iTriggerMode, TriggerModeNames), "TriggerMode", CTM_Default));
|
||||
pComp->NameEnd();
|
||||
// newly loaded structures are not resolved
|
||||
if (pComp->isCompiler()) fRefsResolved = false;
|
||||
}
|
||||
|
||||
bool C4PlayerControlAssignment::ResolveRefs(C4PlayerControlAssignmentSet *pParentSet, C4PlayerControlDefs *pControlDefs)
|
||||
{
|
||||
// avoid circular chains
|
||||
static C4PlayerControlAssignment *pCircularDetect = NULL;
|
||||
if (!pCircularDetect) pCircularDetect = this; else if (pCircularDetect == this)
|
||||
{
|
||||
LogFatal(FormatString("Circular reference chain detected in player control assignments of set %s in assignment for key %s!", pParentSet->GetName(), GetControlName()).getData());
|
||||
return false;
|
||||
}
|
||||
// resolve control name
|
||||
iControl = pControlDefs->GetControlIndexByIdentifier(sControlName.getData());
|
||||
// resolve keys
|
||||
KeyComboVec NewCombo;
|
||||
for (KeyComboVec::iterator i = KeyCombo.begin(); i != KeyCombo.end(); ++i)
|
||||
{
|
||||
KeyComboItem &rKeyComboItem = *i;
|
||||
if (rKeyComboItem.Key == KEY_Default && rKeyComboItem.sKeyName.getLength())
|
||||
{
|
||||
// this is a key reference - find it
|
||||
C4PlayerControlAssignment *pRefAssignment = pParentSet->GetAssignmentByControlName(rKeyComboItem.sKeyName.getData());
|
||||
if (pRefAssignment)
|
||||
{
|
||||
// resolve itself if necessary
|
||||
if (!pRefAssignment->IsRefsResolved()) if (!pRefAssignment->ResolveRefs(pParentSet, pControlDefs)) return false;
|
||||
// insert all keys of that combo into own combo
|
||||
NewCombo.insert(NewCombo.end(), pRefAssignment->KeyCombo.begin(), pRefAssignment->KeyCombo.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
// undefined reference? Not fatal, but inform user
|
||||
LogF("WARNING: Control %s of set %s contains reference to unassigned control %s.", GetControlName(), pParentSet->GetName(), rKeyComboItem.sKeyName.getData());
|
||||
NewCombo.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NewCombo.push_back(rKeyComboItem);
|
||||
}
|
||||
}
|
||||
KeyCombo = NewCombo;
|
||||
// the trigger key is always last of the chain
|
||||
if (KeyCombo.size()) TriggerKey = KeyCombo.back().Key; else TriggerKey = C4KeyCodeEx();
|
||||
// done
|
||||
fRefsResolved = true;
|
||||
if (pCircularDetect == this) pCircularDetect = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4PlayerControlAssignment::operator ==(const C4PlayerControlAssignment &cmp) const
|
||||
|
@ -131,8 +206,8 @@ bool C4PlayerControlAssignment::operator ==(const C4PlayerControlAssignment &cmp
|
|||
// doesn't compare resolved TriggerKey/iControl
|
||||
return KeyCombo == cmp.KeyCombo
|
||||
&& sControlName == cmp.sControlName
|
||||
&& fAlwaysUnhandled == cmp.fAlwaysUnhandled
|
||||
&& eTriggerMode == cmp.eTriggerMode;
|
||||
&& iTriggerMode == cmp.iTriggerMode
|
||||
&& iPriority == cmp.iPriority;
|
||||
}
|
||||
|
||||
|
||||
|
@ -140,16 +215,16 @@ bool C4PlayerControlAssignment::operator ==(const C4PlayerControlAssignment &cmp
|
|||
|
||||
void C4PlayerControlAssignmentSet::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
if (!pComp->Name("ControlAssignmentSet")) pComp->excNotFound("ControlAssignmentSet");
|
||||
if (!pComp->Name("ControlSet")) { pComp->NameEnd(); pComp->excNotFound("ControlSet"); }
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(sName, StdCompiler::RCT_Idtf), "Name", "None"));
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Assignments, StdCompiler::SEP_NONE), "Key", AssignmentsVec()));
|
||||
pComp->Value(mkSTLContainerAdapt(Assignments, StdCompiler::SEP_NONE));
|
||||
pComp->NameEnd();
|
||||
}
|
||||
|
||||
void C4PlayerControlAssignmentSet::MergeFrom(const C4PlayerControlAssignmentSet &Src, bool fLowPrio)
|
||||
{
|
||||
// take over all assignments defined in Src
|
||||
for (AssignmentsVec::const_iterator i = Src.Assignments.begin(); i != Src.Assignments.end(); ++i)
|
||||
for (C4PlayerControlAssignmentVec::const_iterator i = Src.Assignments.begin(); i != Src.Assignments.end(); ++i)
|
||||
{
|
||||
const C4PlayerControlAssignment &SrcAssignment = *i;
|
||||
// overwrite if def of same name existed if it's not low priority anyway
|
||||
|
@ -166,14 +241,345 @@ void C4PlayerControlAssignmentSet::MergeFrom(const C4PlayerControlAssignmentSet
|
|||
}
|
||||
}
|
||||
|
||||
C4PlayerControlAssignment *C4PlayerControlAssignmentSet::GetAssignmentByControlName(const char *szControlName) const
|
||||
bool C4PlayerControlAssignmentSet::ResolveRefs(C4PlayerControlDefs *pDefs)
|
||||
{
|
||||
for (AssignmentsVec::const_iterator i = Assignments.begin(); i != Assignments.end(); ++i)
|
||||
// resolve in order; ignore already resolved because they might have been resolved by cross reference
|
||||
for (C4PlayerControlAssignmentVec::iterator i = Assignments.begin(); i != Assignments.end(); ++i)
|
||||
if (!(*i).IsRefsResolved())
|
||||
if (!(*i).ResolveRefs(this, pDefs))
|
||||
return false;
|
||||
// now sort assignments by priority
|
||||
std::sort(Assignments.begin(), Assignments.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
C4PlayerControlAssignment *C4PlayerControlAssignmentSet::GetAssignmentByControlName(const char *szControlName)
|
||||
{
|
||||
for (C4PlayerControlAssignmentVec::iterator i = Assignments.begin(); i != Assignments.end(); ++i)
|
||||
if (SEqual((*i).GetControlName(), szControlName))
|
||||
return &*i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool C4PlayerControlAssignmentSet::operator ==(const C4PlayerControlAssignmentSet &cmp) const
|
||||
{
|
||||
return Assignments == cmp.Assignments
|
||||
&& sName == cmp.sName;
|
||||
}
|
||||
|
||||
|
||||
/* C4PlayerControlAssignmentSets */
|
||||
|
||||
void C4PlayerControlAssignmentSets::Clear()
|
||||
{
|
||||
Sets.clear();
|
||||
}
|
||||
|
||||
void C4PlayerControlAssignmentSets::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Sets, StdCompiler::SEP_NONE), "ControlSets", AssignmentSetList()));
|
||||
}
|
||||
|
||||
void C4PlayerControlAssignmentSets::MergeFrom(const C4PlayerControlAssignmentSets &Src, bool fLowPrio)
|
||||
{
|
||||
// take over all assignments in known sets and new sets defined in Src
|
||||
for (AssignmentSetList::const_iterator i = Src.Sets.begin(); i != Src.Sets.end(); ++i)
|
||||
{
|
||||
const C4PlayerControlAssignmentSet &SrcSet = *i;
|
||||
// overwrite if def of same name existed if it's not low priority anyway
|
||||
C4PlayerControlAssignmentSet *pPrevSet = GetSetByName(SrcSet.GetName());
|
||||
if (pPrevSet)
|
||||
{
|
||||
pPrevSet->MergeFrom(SrcSet, fLowPrio);
|
||||
}
|
||||
else
|
||||
{
|
||||
// new def: Append a copy
|
||||
Sets.push_back(SrcSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool C4PlayerControlAssignmentSets::ResolveRefs(C4PlayerControlDefs *pDefs)
|
||||
{
|
||||
for (AssignmentSetList::iterator i = Sets.begin(); i != Sets.end(); ++i)
|
||||
if (!(*i).ResolveRefs(pDefs)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
C4PlayerControlAssignmentSet *C4PlayerControlAssignmentSets::GetSetByName(const char *szName)
|
||||
{
|
||||
for (AssignmentSetList::iterator i = Sets.begin(); i != Sets.end(); ++i)
|
||||
if (SEqual((*i).GetName(), szName))
|
||||
return &*i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* C4PlayerControlFile */
|
||||
|
||||
void C4PlayerControlFile::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(ControlDefs);
|
||||
pComp->Value(AssignmentSets);
|
||||
}
|
||||
|
||||
bool C4PlayerControlFile::Load(C4Group &hGroup, const char *szFilename, C4LangStringTable *pLang)
|
||||
{
|
||||
// clear previous
|
||||
Clear();
|
||||
// load and prepare file contents
|
||||
StdStrBuf Buf;
|
||||
if (!hGroup.LoadEntryString(szFilename, Buf)) return false;
|
||||
if (pLang) pLang->ReplaceStrings(Buf);
|
||||
// parse it!
|
||||
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(*this, Buf, szFilename)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4PlayerControlFile::Save(C4Group &hGroup, const char *szFilename)
|
||||
{
|
||||
// decompile to buffer and save buffer to group
|
||||
StdStrBuf Buf;
|
||||
if (!DecompileToBuf_Log<StdCompilerINIWrite>(*this, &Buf, szFilename)) return false;
|
||||
hGroup.Add(szFilename, Buf, false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void C4PlayerControlFile::Clear()
|
||||
{
|
||||
ControlDefs.Clear();
|
||||
AssignmentSets.Clear();
|
||||
}
|
||||
|
||||
|
||||
/* C4PlayerControl */
|
||||
|
||||
void C4PlayerControl::CSync::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(ControlDownStates), "Down", DownStateVec()));
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(ControlDisableStates), "Disabled", DisableStateVec()));
|
||||
}
|
||||
|
||||
bool C4PlayerControl::CSync::operator ==(const CSync &cmp) const
|
||||
{
|
||||
return ControlDownStates == cmp.ControlDownStates
|
||||
&& ControlDisableStates == cmp.ControlDisableStates;
|
||||
}
|
||||
|
||||
void C4PlayerControl::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
// compile sync values only
|
||||
pComp->Value(mkNamingAdapt(Sync, "PlayerControl", CSync()));
|
||||
}
|
||||
|
||||
bool C4PlayerControl::ProcessKeyEvent(const C4KeyCodeEx &key, bool fUp, const C4KeyEventData &rKeyExtraData)
|
||||
{
|
||||
// collect all matching keys
|
||||
C4PlayerControlAssignmentVec Matches;
|
||||
pControlSet->GetAssignmentsByKey(key, fUp, &Matches, DownKeys, RecentKeys);
|
||||
// process async controls
|
||||
C4ControlPlayerControl2 *pControlPacket = NULL;
|
||||
for (C4PlayerControlAssignmentVec::const_iterator i = Matches.begin(); i != Matches.end(); ++i)
|
||||
{
|
||||
const C4PlayerControlAssignment &rAssignment = *i;
|
||||
int32_t iControlIndex = rAssignment.GetControl();
|
||||
C4PlayerControlDef *pControlDef = ControlDefs.GetControlByIndex(iControlIndex);
|
||||
if (pControlDef && pControlDef->IsValid() && (!fUp || pControlDef->IsHoldKey()))
|
||||
{
|
||||
if (pControlDef->IsAsync() && !pControlPacket)
|
||||
{
|
||||
if (ExecuteControl(iControlIndex, fUp, rKeyExtraData, rAssignment.GetTriggerMode(), key.IsRepeated()))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// sync control
|
||||
// ignore key repeats, because we do our own key repeat for sync controls
|
||||
if (key.IsRepeated()) return false;
|
||||
// sync control has higher priority - no more async execution then
|
||||
// build a control packet and add control data instead. even for async controls later in chain, as they may be blocked by a sync handler
|
||||
if (!pControlPacket) pControlPacket = new C4ControlPlayerControl2(iPlr, fUp, rKeyExtraData);
|
||||
pControlPacket->AddControl(iControlIndex, rAssignment.GetTriggerMode());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// push sync control to input
|
||||
if (pControlPacket) Game.Input.Add(CID_PlrControl2, pControlPacket);
|
||||
}
|
||||
|
||||
bool C4PlayerControl::ProcessKeyDown(const C4KeyCodeEx &key)
|
||||
{
|
||||
// add key to local "down" list if it's not already in there
|
||||
if (std::find(DownKeys.begin(), DownKeys.end(), C4PlayerControlRecentKey(key,0)) == DownKeys.end()) DownKeys.push_back(C4PlayerControlRecentKey(key,Game.FrameCounter));
|
||||
// process!
|
||||
bool fResult = ProcessKeyEvent(key, false, Game.KeyboardInput.GetLastKeyExtraData());
|
||||
// add to recent list unless repeated
|
||||
if (!key.IsRepeated()) RecentKeys.push_back(C4PlayerControlRecentKey(key,Game.FrameCounter));
|
||||
return fResult;
|
||||
}
|
||||
|
||||
bool C4PlayerControl::ProcessKeyUp(const C4KeyCodeEx &key)
|
||||
{
|
||||
// remove key from "down" list
|
||||
C4PlayerControlRecentKeyList::iterator i = find(DownKeys.begin(), DownKeys.end(), C4PlayerControlRecentKey(key,0));
|
||||
if (i != DownKeys.end()) DownKeys.erase(i);
|
||||
// process!
|
||||
return ProcessKeyEvent(key, true, Game.KeyboardInput.GetLastKeyExtraData());
|
||||
}
|
||||
|
||||
void C4PlayerControl::ExecuteControlPacket(const class C4ControlPlayerControl2 *pCtrl)
|
||||
{
|
||||
// callback from control queue. Execute controls in packet until one of them gets processed
|
||||
// assume async packets always as not processed to ensure sync safety (usually, sync commands should better not ovberride async commands anyway)
|
||||
for (C4ControlPlayerControl2::ControlItemVec::const_iterator i = pCtrl->GetControlItems().begin(); i != pCtrl->GetControlItems().end(); ++i)
|
||||
{
|
||||
const C4ControlPlayerControl2::ControlItem &rItem = *i;
|
||||
C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(rItem.iControl);
|
||||
if (pCtrlDef)
|
||||
{
|
||||
if (ExecuteControl(rItem.iControl, pCtrl->IsReleaseControl(), pCtrl->GetExtraData(), rItem.iTriggerMode, false))
|
||||
if (pCtrlDef->IsSync())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool C4PlayerControl::ExecuteControl(int32_t iControl, bool fUp, const C4KeyEventData &rKeyExtraData, int32_t iTriggerMode, bool fRepeated)
|
||||
{
|
||||
// execute single control. return if handled
|
||||
C4PlayerControlDef *pControlDef = ControlDefs.GetControlByIndex(iControl);
|
||||
if (!pControlDef || Sync.IsControlDisabled(iControl)) return false;
|
||||
C4PlayerControlDef::Actions eAction = pControlDef->GetAction();
|
||||
C4KeyEventData KeyExtraData(rKeyExtraData);
|
||||
// global controls only in global context
|
||||
if (IsGlobal() != pControlDef->IsGlobal()) return false;
|
||||
// hold-actions only work on script controls with the hold flag
|
||||
if (iTriggerMode & (C4PlayerControlAssignment::CTM_Hold | C4PlayerControlAssignment::CTM_Release))
|
||||
{
|
||||
if (eAction != C4PlayerControlDef::CDA_Script) return false;
|
||||
if (!pControlDef->IsHoldKey()) return false;
|
||||
if (fUp) return false; // hold triggers have no "up"-event
|
||||
// perform hold/release
|
||||
const CSync::ControlDownState *pCtrlDownState = Sync.GetControlDownState(iControl);
|
||||
if (!pCtrlDownState) return false;
|
||||
bool fWasDown = (pCtrlDownState->DownState.iStrength > 0);
|
||||
if (fWasDown)
|
||||
{
|
||||
// control is currently down: release?
|
||||
if (iTriggerMode & C4PlayerControlAssignment::CTM_Release)
|
||||
{
|
||||
KeyExtraData.iStrength = 0;
|
||||
Sync.SetControlDownState(iControl, KeyExtraData, Game.FrameCounter, false);
|
||||
// now process as a regular "Up" event
|
||||
fUp = true;
|
||||
fRepeated = false;
|
||||
}
|
||||
else //if (iTriggerMode & C4PlayerControlAssignment::CTM_Hold) - must be true
|
||||
{
|
||||
// control is down but trigger key is pressed again: Refresh down state
|
||||
Sync.SetControlDownState(iControl, KeyExtraData, Game.FrameCounter, false);
|
||||
// now process as a regular, repeated "down" event
|
||||
fRepeated = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// control is currently up. Put into hold-down-state if this is a hold key
|
||||
if (iTriggerMode & C4PlayerControlAssignment::CTM_Hold)
|
||||
{
|
||||
Sync.SetControlDownState(iControl, KeyExtraData, Game.FrameCounter, false);
|
||||
// now process as a regular "down" event
|
||||
fRepeated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//. Ignore if it's only a release key
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fUp)
|
||||
{
|
||||
// regular ControlUp: Only valid if that control was down
|
||||
const CSync::ControlDownState *pCtrlDownState = Sync.GetControlDownState(iControl);
|
||||
if (!pCtrlDownState) return false;
|
||||
bool fWasDown = (pCtrlDownState->DownState.iStrength > 0);
|
||||
if (!fWasDown) return false;
|
||||
}
|
||||
// perform action for this control
|
||||
bool fHandled = ExecuteControlAction(iControl, eAction, pControlDef->GetExtraData(), fUp, KeyExtraData, fRepeated);
|
||||
// return if handled, unless control is defined as always unhandled
|
||||
return fHandled && !(iTriggerMode & C4PlayerControlAssignment::CTM_AlwaysUnhandled);
|
||||
}
|
||||
|
||||
bool C4PlayerControl::ExecuteControlAction(int32_t iControl, C4PlayerControlDef::Actions eAction, C4ID idControlExtraData, bool fUp, const C4KeyEventData &rKeyExtraData, bool fRepeated)
|
||||
{
|
||||
// get affected player
|
||||
C4Player *pPlr = NULL;
|
||||
if (iPlr > -1)
|
||||
{
|
||||
pPlr = Game.Players.Get(iPlr);
|
||||
if (!pPlr) return false;
|
||||
}
|
||||
// exec action (on player)
|
||||
switch (eAction)
|
||||
{
|
||||
// scripted player control
|
||||
case C4PlayerControlDef::CDA_Script:
|
||||
return ExecuteControlScript(iControl, idControlExtraData, fUp, rKeyExtraData, fRepeated);
|
||||
|
||||
// menu controls
|
||||
case C4PlayerControlDef::CDA_Menu: if (!pPlr || fUp) return false; if (pPlr->Menu.IsActive()) pPlr->Menu.Close(false); else pPlr->ActivateMenuMain(); return true; // toggle
|
||||
case C4PlayerControlDef::CDA_MenuOK: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuEnter,0); return true; // ok on item
|
||||
case C4PlayerControlDef::CDA_MenuCancel: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuClose,0); return true; // close menu
|
||||
case C4PlayerControlDef::CDA_MenuLeft: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuLeft ,0); return true; // navigate
|
||||
case C4PlayerControlDef::CDA_MenuUp: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuUp ,0); return true; // navigate
|
||||
case C4PlayerControlDef::CDA_MenuRight: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuRight,0); return true; // navigate
|
||||
case C4PlayerControlDef::CDA_MenuDown: if (!pPlr || !pPlr->Menu.IsActive() || fUp) return false; pPlr->Menu.Control(COM_MenuDown ,0); return true; // navigate
|
||||
|
||||
//unknown action
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool C4PlayerControl::ExecuteControlScript(int32_t iControl, C4ID idControlExtraData, bool fUp, const C4KeyEventData &rKeyExtraData, bool fRepeated)
|
||||
{
|
||||
if (!fUp)
|
||||
{
|
||||
// control down
|
||||
C4AulFunc *pFunc = Game.ScriptEngine.GetFirstFunc(PSF_PlayerControl);
|
||||
if (!pFunc) return false;
|
||||
C4AulParSet Pars(C4VInt(iControl), C4VID(idControlExtraData), C4VInt(rKeyExtraData.x), C4VInt(rKeyExtraData.y), C4VInt(rKeyExtraData.iStrength), C4VBool(fRepeated));
|
||||
return !!pFunc->Exec(NULL, &Pars);
|
||||
}
|
||||
else
|
||||
{
|
||||
// control up
|
||||
C4AulFunc *pFunc = Game.ScriptEngine.GetFirstFunc(PSF_PlayerControlRelease);
|
||||
if (!pFunc) return false;
|
||||
C4AulParSet Pars(C4VInt(iControl), C4VID(idControlExtraData), C4VInt(rKeyExtraData.x), C4VInt(rKeyExtraData.y));
|
||||
return !!pFunc->Exec(NULL, &Pars);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C4PlayerControl::Execute()
|
||||
{
|
||||
// sync execution: Do keyrepeat, etc.
|
||||
}
|
||||
|
||||
C4PlayerControl::C4PlayerControl() : ControlDefs(Game.PlayerControlDefs), iPlr(-1), pControlSet(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void C4PlayerControl::Clear()
|
||||
{
|
||||
}
|
||||
|
||||
void C4PlayerControl::RegisterKeyset(int32_t iPlr, C4PlayerControlAssignmentSet *pKeyset)
|
||||
{
|
||||
// register all keys into Game.KeyboardInput creating KeyBindings
|
||||
}
|
||||
|
||||
|
|
|
@ -1340,6 +1340,7 @@ bool C4StartupOptionsDlg::OnLangComboSelChange(C4GUI::ComboBox *pForCombo, int32
|
|||
Config.General.Language[2] = '\0';
|
||||
UpdateLanguage();
|
||||
Languages.LoadLanguage(Config.General.LanguageEx);
|
||||
Game.UpdateLanguage();
|
||||
// recreate everything to reflect language changes
|
||||
RecreateDialog(true);
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue