forked from Mirrors/openclonk
Moving controls to script...
parent
ce6d73b92a
commit
2d5ad9fca1
|
@ -163,22 +163,11 @@ public:
|
|||
class C4ControlPlayerControl : public C4ControlPacket // sync
|
||||
{
|
||||
public:
|
||||
C4ControlPlayerControl()
|
||||
: iPlr(-1), iCom(-1), iData(-1) { }
|
||||
C4ControlPlayerControl(int32_t iPlr, int32_t iCom, int32_t iData)
|
||||
: iPlr(iPlr), iCom(iCom), iData(iData) { }
|
||||
protected:
|
||||
int32_t iPlr, iCom, iData;
|
||||
public:
|
||||
DECLARE_C4CONTROL_VIRTUALS
|
||||
};
|
||||
|
||||
class C4ControlPlayerControl2 : public C4ControlPacket // sync
|
||||
{
|
||||
public:
|
||||
C4ControlPlayerControl2() : iPlr(-1), fRelease(false) {}
|
||||
C4ControlPlayerControl2(int32_t iPlr, bool fRelease, const C4KeyEventData &rExtraData)
|
||||
C4ControlPlayerControl() : iPlr(-1), fRelease(false) {}
|
||||
C4ControlPlayerControl(int32_t iPlr, bool fRelease, const C4KeyEventData &rExtraData)
|
||||
: iPlr(iPlr), fRelease(fRelease), ExtraData(rExtraData) { }
|
||||
C4ControlPlayerControl(int32_t iPlr, int32_t iControl, int32_t iExtraData) // old-style menu com emulation
|
||||
: iPlr(iPlr), fRelease(false), ExtraData(iExtraData,0,0) { AddControl(iControl,0); }
|
||||
|
||||
struct ControlItem
|
||||
{
|
||||
|
|
|
@ -204,9 +204,6 @@ class C4Game
|
|||
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);
|
||||
bool Init();
|
||||
bool PreInit();
|
||||
|
|
|
@ -1163,7 +1163,7 @@ namespace C4GUI {
|
|||
private:
|
||||
enum CursorOperation { COP_BACK, COP_DELETE, COP_LEFT, COP_RIGHT, COP_HOME, COP_END, };
|
||||
|
||||
bool KeyCursorOp(C4KeyCodeEx key, CursorOperation op);
|
||||
bool KeyCursorOp(const C4KeyCodeEx &key, CursorOperation op);
|
||||
bool KeyEnter();
|
||||
bool KeyCopy() { Copy(); return true; }
|
||||
bool KeyPaste() { Paste(); return true; }
|
||||
|
@ -1671,7 +1671,7 @@ namespace C4GUI {
|
|||
bool KeyBack();
|
||||
bool KeyAbort();
|
||||
bool KeyConfirm();
|
||||
bool KeyHotkey(C4KeyCodeEx key);
|
||||
bool KeyHotkey(const C4KeyCodeEx &key);
|
||||
|
||||
private:
|
||||
static int32_t iGlobalMenuIndex;
|
||||
|
@ -2005,7 +2005,7 @@ namespace C4GUI {
|
|||
virtual void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam); // input: mouse. forwards to child controls
|
||||
|
||||
private:
|
||||
bool KeyHotkey(C4KeyCodeEx key);
|
||||
bool KeyHotkey(const C4KeyCodeEx &key);
|
||||
bool KeyFocusDefault();
|
||||
|
||||
public:
|
||||
|
@ -2329,7 +2329,7 @@ namespace C4GUI {
|
|||
{
|
||||
private:
|
||||
typedef C4KeyCBPassKey<TargetClass> Base;
|
||||
typedef bool(TargetClass::*CallbackFunc)(C4KeyCodeEx key);
|
||||
typedef bool(TargetClass::*CallbackFunc)(const C4KeyCodeEx &key);
|
||||
public:
|
||||
DlgKeyCBPassKey(TargetClass &rTarget, CallbackFunc pFuncDown, CallbackFunc pFuncUp=NULL, CallbackFunc pFuncPressed=NULL)
|
||||
: Base(rTarget, pFuncDown, pFuncUp, pFuncPressed) {}
|
||||
|
@ -2366,7 +2366,7 @@ namespace C4GUI {
|
|||
{
|
||||
private:
|
||||
typedef C4KeyCBExPassKey<TargetClass, ParameterType> Base;
|
||||
typedef bool(TargetClass::*CallbackFunc)(C4KeyCodeEx key, ParameterType par);
|
||||
typedef bool(TargetClass::*CallbackFunc)(const C4KeyCodeEx &key, ParameterType par);
|
||||
public:
|
||||
ControlKeyCBExPassKey(TargetClass &rTarget, const ParameterType &rPar, CallbackFunc pFuncDown, CallbackFunc pFuncUp=NULL, CallbackFunc pFuncPressed=NULL)
|
||||
: Base(rTarget, rPar, pFuncDown, pFuncUp, pFuncPressed) {}
|
||||
|
|
|
@ -176,6 +176,7 @@ 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) {}
|
||||
C4KeyEventData(int32_t iStrength, int32_t x, int32_t y) : iStrength(iStrength), x(x), y(y) {}
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool operator ==(const struct C4KeyEventData &cmp) const;
|
||||
};
|
||||
|
@ -189,7 +190,7 @@ class C4KeyboardCallbackInterface
|
|||
class C4CustomKey *pOriginalKey;
|
||||
|
||||
public:
|
||||
virtual bool OnKeyEvent(C4KeyCodeEx key, C4KeyEventType eEv) = 0; // return true if processed
|
||||
virtual bool OnKeyEvent(const C4KeyCodeEx &key, C4KeyEventType eEv) = 0; // return true if processed
|
||||
|
||||
friend class C4KeyboardMapping;
|
||||
|
||||
|
@ -214,7 +215,7 @@ template <class TargetClass> class C4KeyCB : public C4KeyboardCallbackInterface
|
|||
CallbackFunc pFuncDown, pFuncUp, pFuncPressed;
|
||||
|
||||
protected:
|
||||
virtual bool OnKeyEvent(C4KeyCodeEx key, C4KeyEventType eEv)
|
||||
virtual bool OnKeyEvent(const C4KeyCodeEx &key, C4KeyEventType eEv)
|
||||
{
|
||||
if (!CheckCondition()) return false;
|
||||
switch (eEv)
|
||||
|
@ -237,14 +238,14 @@ template <class TargetClass> class C4KeyCB : public C4KeyboardCallbackInterface
|
|||
template <class TargetClass> class C4KeyCBPassKey : public C4KeyboardCallbackInterface
|
||||
{
|
||||
public:
|
||||
typedef bool(TargetClass::*CallbackFunc)(C4KeyCodeEx key);
|
||||
typedef bool(TargetClass::*CallbackFunc)(const C4KeyCodeEx &key);
|
||||
|
||||
protected:
|
||||
TargetClass &rTarget;
|
||||
CallbackFunc pFuncDown, pFuncUp, pFuncPressed;
|
||||
|
||||
protected:
|
||||
virtual bool OnKeyEvent(C4KeyCodeEx key, C4KeyEventType eEv)
|
||||
virtual bool OnKeyEvent(const C4KeyCodeEx &key, C4KeyEventType eEv)
|
||||
{
|
||||
if (!CheckCondition()) return false;
|
||||
switch (eEv)
|
||||
|
@ -275,7 +276,7 @@ template <class TargetClass, class ParameterType> class C4KeyCBEx : public C4Key
|
|||
ParameterType par;
|
||||
|
||||
protected:
|
||||
virtual bool OnKeyEvent(C4KeyCodeEx key, C4KeyEventType eEv)
|
||||
virtual bool OnKeyEvent(const C4KeyCodeEx &key, C4KeyEventType eEv)
|
||||
{
|
||||
if (!CheckCondition()) return false;
|
||||
switch (eEv)
|
||||
|
@ -297,7 +298,7 @@ template <class TargetClass, class ParameterType> class C4KeyCBEx : public C4Key
|
|||
template <class TargetClass, class ParameterType> class C4KeyCBExPassKey : public C4KeyboardCallbackInterface
|
||||
{
|
||||
public:
|
||||
typedef bool(TargetClass::*CallbackFunc)(C4KeyCodeEx key, ParameterType par);
|
||||
typedef bool(TargetClass::*CallbackFunc)(const C4KeyCodeEx &key, ParameterType par);
|
||||
|
||||
protected:
|
||||
TargetClass &rTarget;
|
||||
|
@ -305,7 +306,7 @@ template <class TargetClass, class ParameterType> class C4KeyCBExPassKey : publi
|
|||
ParameterType par;
|
||||
|
||||
protected:
|
||||
virtual bool OnKeyEvent(C4KeyCodeEx key, C4KeyEventType eEv)
|
||||
virtual bool OnKeyEvent(const C4KeyCodeEx &key, C4KeyEventType eEv)
|
||||
{
|
||||
if (!CheckCondition()) return false;
|
||||
switch (eEv)
|
||||
|
@ -356,9 +357,9 @@ class C4CustomKey
|
|||
int iRef;
|
||||
|
||||
public:
|
||||
C4CustomKey(C4KeyCodeEx DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority = PRIO_Base); // ctor for default key
|
||||
C4CustomKey(const C4KeyCodeEx &DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority = PRIO_Base); // ctor for default key
|
||||
C4CustomKey(const CodeList &rDefCodes, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority = PRIO_Base); // ctor for default key with multiple possible keys assigned
|
||||
C4CustomKey(C4KeyCodeEx Code, const StdStrBuf &rName); // ctor for single custom key override
|
||||
C4CustomKey(const C4KeyCodeEx &Code, const StdStrBuf &rName); // ctor for single custom key override
|
||||
C4CustomKey(const C4CustomKey &rCpy, bool fCopyCallbacks);
|
||||
virtual ~C4CustomKey(); // dtor
|
||||
|
||||
|
@ -382,7 +383,7 @@ class C4CustomKey
|
|||
class C4KeyBinding : protected C4CustomKey
|
||||
{
|
||||
public:
|
||||
C4KeyBinding(C4KeyCodeEx DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority = PRIO_Base); // ctor for default key
|
||||
C4KeyBinding(const C4KeyCodeEx &DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority = PRIO_Base); // ctor for default key
|
||||
C4KeyBinding(const CodeList &rDefCodes, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority = PRIO_Base); // ctor for default key
|
||||
~C4KeyBinding();
|
||||
};
|
||||
|
|
|
@ -46,10 +46,10 @@ class C4ChatInputDialog : public C4GUI::InputDialog
|
|||
private:
|
||||
bool KeyHistoryUpDown(bool fUp);
|
||||
bool KeyCompleteNick(); // complete nick at cursor pos of edit
|
||||
bool KeyPlrControl(C4KeyCodeEx key);
|
||||
bool KeyGamepadControlDown(C4KeyCodeEx key);
|
||||
bool KeyGamepadControlUp(C4KeyCodeEx key);
|
||||
bool KeyGamepadControlPressed(C4KeyCodeEx key);
|
||||
bool KeyPlrControl(const C4KeyCodeEx &key);
|
||||
bool KeyGamepadControlDown(const C4KeyCodeEx &key);
|
||||
bool KeyGamepadControlUp(const C4KeyCodeEx &key);
|
||||
bool KeyGamepadControlPressed(const C4KeyCodeEx &key);
|
||||
bool KeyBackspaceClose(); // close if chat text box is empty (on backspace)
|
||||
|
||||
protected:
|
||||
|
|
|
@ -220,7 +220,6 @@ class C4Object
|
|||
C4Object *ComposeContents(C4ID id);
|
||||
BOOL MenuCommand(const char *szCommand);
|
||||
|
||||
BOOL CallControl(C4Player *pPlr, BYTE byCom, C4AulParSet *pPars = 0);
|
||||
C4Value Call(const char *szFunctionCall, C4AulParSet *pPars = 0, bool fPassError = false);
|
||||
|
||||
|
||||
|
@ -338,9 +337,6 @@ class C4Object
|
|||
const char *GetName();
|
||||
void SetName (const char *NewName = 0);
|
||||
int32_t GetValue(C4Object *pInBase, int32_t iForPlayer);
|
||||
void DirectCom(BYTE byCom, int32_t iData);
|
||||
void AutoStopDirectCom(BYTE byCom, int32_t iData);
|
||||
void AutoStopUpdateComDir();
|
||||
BOOL BuyEnergy();
|
||||
void AutoSellContents();
|
||||
BOOL SetOwner(int32_t iOwner);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <C4ObjectInfoList.h>
|
||||
#include <C4InfoCore.h>
|
||||
#include <C4ObjectList.h>
|
||||
#include <C4PlayerControl.h>
|
||||
|
||||
const int32_t C4PVM_Cursor = 0,
|
||||
C4PVM_Target = 1,
|
||||
|
@ -70,7 +71,7 @@ class C4Player: public C4PlayerInfoCore
|
|||
int32_t Team; // team ID - may be 0 for no teams
|
||||
int32_t Color; // OldGfx color index
|
||||
uint32_t ColorDw; // color as DWord for newgfx
|
||||
int32_t Control;
|
||||
int32_t ControlSet;
|
||||
int32_t MouseControl;
|
||||
int32_t Position;
|
||||
int32_t PlrStartIndex;
|
||||
|
@ -112,13 +113,10 @@ class C4Player: public C4PlayerInfoCore
|
|||
C4IDList Knowledge;
|
||||
C4IDList Magic;
|
||||
// Control
|
||||
C4PlayerControl Control;
|
||||
C4Object *Cursor, *ViewCursor;
|
||||
int32_t SelectCount;
|
||||
int32_t SelectFlash,CursorFlash;
|
||||
int32_t LastCom;
|
||||
int32_t LastComDelay;
|
||||
int32_t LastComDownDouble;
|
||||
int32_t PressedComs;
|
||||
int32_t CursorSelection,CursorToggled;
|
||||
class C4GamePadOpener *pGamepad;
|
||||
// Message
|
||||
|
@ -169,9 +167,6 @@ class C4Player: public C4PlayerInfoCore
|
|||
void CursorToggle();
|
||||
void SelectAllCrew();
|
||||
void UpdateSelectionToggleStatus();
|
||||
void DirectCom(BYTE byCom, int32_t iData);
|
||||
void InCom(BYTE byCom, int32_t iData);
|
||||
BOOL ObjectCom(BYTE byCom, int32_t iData);
|
||||
BOOL ObjectCommand(int32_t iCommand, C4Object *pTarget, int32_t iTx, int32_t iTy, C4Object *pTarget2=NULL, int32_t iData=0, int32_t iAddMode=C4P_Command_Set);
|
||||
void ObjectCommand2Obj(C4Object *cObj, int32_t iCommand, C4Object *pTarget, int32_t iX, int32_t iY, C4Object *pTarget2, int32_t iData, int32_t iMode);
|
||||
BOOL DoPoints(int32_t iChange);
|
||||
|
|
|
@ -60,6 +60,8 @@ class C4PlayerControlDef
|
|||
bool IsHoldKey() const { return fIsHoldKey; }
|
||||
C4ID GetExtraData() const { return idControlExtraData; }
|
||||
bool IsGlobal() const { return fGlobal; }
|
||||
int32_t GetRepeatDelay() const { return iRepeatDelay; }
|
||||
int32_t GetInitialRepeatDelay() const { return iInitialRepeatDelay; }
|
||||
|
||||
//C4PlayerControlDef &operator =(const C4PlayerControlDef &src);
|
||||
bool operator ==(const C4PlayerControlDef &cmp) const;
|
||||
|
@ -80,6 +82,15 @@ class C4PlayerControlDefs
|
|||
typedef std::vector<C4PlayerControlDef> DefVecImpl;
|
||||
DefVecImpl Defs;
|
||||
|
||||
public:
|
||||
struct CInternalCons
|
||||
{
|
||||
int32_t CON_MenuSelect, CON_MenuEnterAll, CON_MenuEnter, CON_MenuClose;
|
||||
CInternalCons() : CON_MenuSelect(CON_None), CON_MenuEnterAll(CON_None), CON_MenuEnter(CON_None), CON_MenuClose(CON_None) {}
|
||||
} InternalCons;
|
||||
|
||||
void UpdateInternalCons();
|
||||
|
||||
public:
|
||||
C4PlayerControlDefs() {}
|
||||
~C4PlayerControlDefs() {}
|
||||
|
@ -88,12 +99,25 @@ class C4PlayerControlDefs
|
|||
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);
|
||||
const C4PlayerControlDef *GetControlByIndex(int32_t idx) const;
|
||||
int32_t GetControlIndexByIdentifier(const char *szIdentifier) const; // return CON_None for not found
|
||||
int32_t GetCount() const { return Defs.size(); }
|
||||
|
||||
bool operator ==(const C4PlayerControlDefs &cmp) const { return Defs == cmp.Defs; }
|
||||
};
|
||||
|
||||
struct C4PlayerControlRecentKey
|
||||
{
|
||||
C4KeyCodeEx Key;
|
||||
DWORD tTime;
|
||||
C4PlayerControlRecentKey(const C4KeyCodeEx &Key, DWORD tTime) : Key(Key), tTime(tTime) {}
|
||||
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;
|
||||
|
||||
typedef std::vector<C4KeyCodeEx> C4KeyCodeExVec;
|
||||
|
||||
// a key/mouse/gamepad assignment to a PlayerControlDef
|
||||
class C4PlayerControlAssignment
|
||||
{
|
||||
|
@ -140,6 +164,7 @@ class C4PlayerControlAssignment
|
|||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool ResolveRefs(class C4PlayerControlAssignmentSet *pParentSet, C4PlayerControlDefs *pControlDefs); // resolve references between assignments
|
||||
bool IsComboMatched(const C4PlayerControlRecentKeyList &DownKeys, const C4PlayerControlRecentKeyList &RecentKeys) const; // check if combo is currently fulfilled (assuming TriggerKey is already matched)
|
||||
|
||||
bool operator ==(const C4PlayerControlAssignment &cmp) const; // doesn't compare resolved TriggerKey/iControl
|
||||
bool operator <(const C4PlayerControlAssignment &cmp) const { return iPriority < cmp.iPriority; }
|
||||
|
@ -148,19 +173,13 @@ class C4PlayerControlAssignment
|
|||
bool IsRefsResolved() const { return fRefsResolved; }
|
||||
bool IsAlwaysUnhandled() const { return iTriggerMode & CTM_AlwaysUnhandled; }
|
||||
int32_t GetTriggerMode() const { return iTriggerMode; }
|
||||
const C4KeyCodeEx &GetTriggerKey() const { return TriggerKey; }
|
||||
bool HasCombo() const { return KeyCombo.size()>1; }
|
||||
};
|
||||
|
||||
typedef std::vector<C4PlayerControlAssignment> C4PlayerControlAssignmentVec;
|
||||
typedef std::vector<const C4PlayerControlAssignment *> C4PlayerControlAssignmentPVec;
|
||||
|
||||
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
|
||||
|
@ -181,7 +200,8 @@ class C4PlayerControlAssignmentSet
|
|||
const char *GetName() const { return sName.getData(); }
|
||||
|
||||
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
|
||||
void GetAssignmentsByKey(const C4PlayerControlDefs &rDefs, const C4KeyCodeEx &key, bool fHoldKeysOnly, C4PlayerControlAssignmentPVec *pOutVec, const C4PlayerControlRecentKeyList &DownKeys, const C4PlayerControlRecentKeyList &RecentKeys) const; // match only by TriggerKey (last key of Combo) if fHoldKeysOnly
|
||||
void GetTriggerKeys(const C4PlayerControlDefs &rDefs, C4KeyCodeExVec *pRegularKeys, C4KeyCodeExVec *pHoldKeys) const; // put all trigger keys of keyset into output vectors
|
||||
|
||||
bool operator ==(const C4PlayerControlAssignmentSet &cmp) const;
|
||||
};
|
||||
|
@ -225,6 +245,9 @@ class C4PlayerControlFile
|
|||
// runtime information about a player's control
|
||||
class C4PlayerControl
|
||||
{
|
||||
public:
|
||||
enum { MaxRecentKeyLookback = 3000, MaxSequenceKeyDelay = 800 }; // milliseconds: Time to press key combos
|
||||
|
||||
private:
|
||||
C4PlayerControlDefs &ControlDefs; // shortcut
|
||||
|
||||
|
@ -232,8 +255,9 @@ class C4PlayerControl
|
|||
int32_t iPlr;
|
||||
|
||||
// async values
|
||||
C4PlayerControlAssignmentSet *pControlSet; // the control set used by this player
|
||||
std::list<C4KeyBinding *> KeyBindings; // keys registered into Game.KeyboardInput
|
||||
C4PlayerControlAssignmentSet *pControlSet; // the control set used by this player - may be NULL if the player cannot be controlled!
|
||||
typedef std::list<C4CustomKey *> KeyBindingList;
|
||||
KeyBindingList KeyBindings; // keys registered into Game.KeyboardInput
|
||||
C4PlayerControlRecentKeyList RecentKeys; // keys pressed recently; for combinations
|
||||
C4PlayerControlRecentKeyList DownKeys; // keys currently held down
|
||||
|
||||
|
@ -247,8 +271,13 @@ class C4PlayerControl
|
|||
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) {}
|
||||
bool IsDown() const { return DownState.iStrength>0; }
|
||||
|
||||
ControlDownState() : DownState(), iDownFrame(0), fDownByUser(false) {}
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool operator ==(const ControlDownState &cmp) const;
|
||||
};
|
||||
typedef std::vector<int32_t> DownStateVec;
|
||||
typedef std::vector<ControlDownState> 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.
|
||||
|
@ -259,6 +288,7 @@ class C4PlayerControl
|
|||
void SetControlDownState(int32_t iControl, const C4KeyEventData &rDownState, int32_t iDownFrame, bool fDownByUser);
|
||||
void SetControlDisabled(int32_t iControl, int32_t iVal);
|
||||
|
||||
void Clear();
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
bool operator ==(const CSync &cmp) const;
|
||||
} Sync;
|
||||
|
@ -273,8 +303,8 @@ class C4PlayerControl
|
|||
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();
|
||||
// init
|
||||
void AddKeyBinding(const C4KeyCodeEx &key, bool fHoldKey, int32_t idx);
|
||||
|
||||
public:
|
||||
C4PlayerControl();
|
||||
|
@ -288,7 +318,10 @@ class C4PlayerControl
|
|||
bool IsGlobal() const { return iPlr==-1; }
|
||||
|
||||
// callback from control queue
|
||||
void ExecuteControlPacket(const class C4ControlPlayerControl2 *pCtrl);
|
||||
void ExecuteControlPacket(const class C4ControlPlayerControl *pCtrl);
|
||||
|
||||
// sync execution: Do keyrepeat, etc.
|
||||
void Execute();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ class C4StartupOptionsDlg : public C4StartupDlg
|
|||
int32_t iCtrlSet;
|
||||
|
||||
protected:
|
||||
bool KeyDown(C4KeyCodeEx key);
|
||||
bool KeyDown(const C4KeyCodeEx &key);
|
||||
public:
|
||||
KeySelDialog(int32_t iKeyID, int32_t iCtrlSet, bool fGamepad);
|
||||
virtual ~KeySelDialog();
|
||||
|
|
|
@ -355,31 +355,10 @@ void C4ControlPlayerSelect::CompileFunc(StdCompiler *pComp)
|
|||
C4ControlPacket::CompileFunc(pComp);
|
||||
}
|
||||
|
||||
|
||||
// *** C4ControlPlayerControl
|
||||
|
||||
void C4ControlPlayerControl::Execute() const
|
||||
{
|
||||
C4Player *pPlr=Game.Players.Get(iPlr);
|
||||
if(pPlr)
|
||||
{
|
||||
if (!Inside<int>(iCom, COM_ReleaseFirst, COM_ReleaseLast))
|
||||
pPlr->CountControl(C4Player::PCID_DirectCom, iCom*10000+iData);
|
||||
pPlr->InCom(iCom, iData);
|
||||
}
|
||||
}
|
||||
|
||||
void C4ControlPlayerControl::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkIntPackAdapt(iPlr), "Player", -1));
|
||||
pComp->Value(mkNamingAdapt(mkIntPackAdapt(iCom), "Com", 0));
|
||||
pComp->Value(mkNamingAdapt(mkIntPackAdapt(iData), "Data", 0));
|
||||
C4ControlPacket::CompileFunc(pComp);
|
||||
}
|
||||
|
||||
|
||||
// *** C4ControlPlayerControl2
|
||||
|
||||
void C4ControlPlayerControl2::Execute() const
|
||||
{
|
||||
C4PlayerControl *pTargetCtrl = NULL;
|
||||
if (iPlr == -1)
|
||||
|
@ -392,20 +371,20 @@ void C4ControlPlayerControl2::Execute() const
|
|||
C4Player *pPlr=Game.Players.Get(iPlr);
|
||||
if (pPlr)
|
||||
{
|
||||
//pPlr->CountControl(C4Player::PCID_DirectCom, iCom*10000+iData);
|
||||
pTargetCtrl = &(pPlr->Control);
|
||||
}
|
||||
}
|
||||
if (pTargetCtrl) pTargetCtrl->ExecuteControlPacket(this);
|
||||
}
|
||||
|
||||
void C4ControlPlayerControl2::ControlItem::CompileFunc(StdCompiler *pComp)
|
||||
void C4ControlPlayerControl::ControlItem::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(iControl);
|
||||
pComp->Seperator();
|
||||
pComp->Value(iTriggerMode);
|
||||
}
|
||||
|
||||
void C4ControlPlayerControl2::CompileFunc(StdCompiler *pComp)
|
||||
void C4ControlPlayerControl::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkIntPackAdapt(iPlr), "Player", -1));
|
||||
pComp->Value(mkNamingAdapt(fRelease, "Release", false));
|
||||
|
|
|
@ -3161,37 +3161,6 @@ bool C4Game::InitKeyboard()
|
|||
KeyboardInput.RegisterKey(new C4CustomKey(C4KeyCodeEx(KEY_Default ), "NetAllowJoinToggle", KEYSCOPE_Generic, new C4KeyCB <C4Network2> (Network, &C4Network2::ToggleAllowJoin)));
|
||||
KeyboardInput.RegisterKey(new C4CustomKey(C4KeyCodeEx(KEY_Default ), "NetStatsToggle", KEYSCOPE_Generic, new C4KeyCB <C4GraphicsSystem>(GraphicsSystem, &C4GraphicsSystem::ToggleShowNetStatus)));
|
||||
|
||||
// Map player keyboard controls
|
||||
int32_t iKdbSet,iCtrl;
|
||||
StdStrBuf sPlrCtrlName;
|
||||
for (iKdbSet=C4P_Control_Keyboard1; iKdbSet<=C4P_Control_Keyboard4; iKdbSet++)
|
||||
for (iCtrl=0; iCtrl<C4MaxKey; iCtrl++)
|
||||
{
|
||||
sPlrCtrlName.Format("Kbd%dKey%d", iKdbSet-C4P_Control_Keyboard1+1, iCtrl+1);
|
||||
KeyboardInput.RegisterKey(new C4CustomKey(
|
||||
C4KeyCodeEx(Config.Controls.Keyboard[iKdbSet][iCtrl]),
|
||||
sPlrCtrlName.getData(), KEYSCOPE_Control,
|
||||
new C4KeyCBExPassKey<C4Game, C4KeySetCtrl>(*this, C4KeySetCtrl(iKdbSet, iCtrl), &C4Game::LocalControlKey, &C4Game::LocalControlKeyUp),
|
||||
C4CustomKey::PRIO_PlrControl));
|
||||
}
|
||||
|
||||
// Map player gamepad controls
|
||||
int32_t iGamepad;
|
||||
for (iGamepad=C4P_Control_GamePad1; iGamepad<=C4P_Control_GamePad1+C4ConfigMaxGamepads; iGamepad++)
|
||||
{
|
||||
C4ConfigGamepad &cfg = Config.Gamepads[iGamepad-C4P_Control_GamePad1];
|
||||
for (iCtrl=0; iCtrl<C4MaxKey; iCtrl++)
|
||||
{
|
||||
if (cfg.Button[iCtrl] == -1) continue;
|
||||
sPlrCtrlName.Format("Joy%dBtn%d", iGamepad-C4P_Control_GamePad1+1, iCtrl+1);
|
||||
KeyboardInput.RegisterKey(new C4CustomKey(
|
||||
C4KeyCodeEx(cfg.Button[iCtrl]),
|
||||
sPlrCtrlName.getData(), KEYSCOPE_Control,
|
||||
new C4KeyCBExPassKey<C4Game, C4KeySetCtrl>(*this, C4KeySetCtrl(iGamepad, iCtrl), &C4Game::LocalControlKey, &C4Game::LocalControlKeyUp),
|
||||
C4CustomKey::PRIO_PlrControl));
|
||||
}
|
||||
}
|
||||
|
||||
// load any custom keysboard overloads
|
||||
KeyboardInput.LoadCustomConfig();
|
||||
|
||||
|
@ -3297,71 +3266,6 @@ void C4Game::FixRandom(int32_t iSeed)
|
|||
Randomize3();
|
||||
}
|
||||
|
||||
bool C4Game::LocalControlKey(C4KeyCodeEx key, C4KeySetCtrl Ctrl)
|
||||
{
|
||||
// keyboard callback: Perform local player control
|
||||
C4Player *pPlr;
|
||||
if (pPlr = Players.GetLocalByKbdSet(Ctrl.iKeySet))
|
||||
{
|
||||
// Swallow a event generated from Keyrepeat for AutoStopControl
|
||||
if (pPlr->PrefControlStyle)
|
||||
{
|
||||
if (key.IsRepeated())
|
||||
return true;
|
||||
}
|
||||
LocalPlayerControl(pPlr->Number,Control2Com(Ctrl.iCtrl, false));
|
||||
return true;
|
||||
}
|
||||
// not processed - must return false here, so unused keyboard control sets do not block used ones
|
||||
return false;
|
||||
}
|
||||
|
||||
bool C4Game::LocalControlKeyUp(C4KeyCodeEx key, C4KeySetCtrl Ctrl)
|
||||
{
|
||||
// Direct callback for released key in AutoStopControl-mode (ignore repeated)
|
||||
if (key.IsRepeated())
|
||||
return true;
|
||||
C4Player *pPlr;
|
||||
if ((pPlr = Players.GetLocalByKbdSet(Ctrl.iKeySet)) && pPlr->PrefControlStyle)
|
||||
{
|
||||
int iCom = Control2Com(Ctrl.iCtrl, true);
|
||||
if (iCom != COM_None) LocalPlayerControl(pPlr->Number, iCom);
|
||||
return true;
|
||||
}
|
||||
// not processed - must return false here, so unused keyboard control sets do not block used ones
|
||||
return false;
|
||||
}
|
||||
|
||||
void C4Game::LocalPlayerControl(int32_t iPlayer, int32_t iCom)
|
||||
{
|
||||
C4Player *pPlr = Players.Get(iPlayer); if (!pPlr) return;
|
||||
int32_t iData=0;
|
||||
// Menu button com
|
||||
if (iCom==COM_PlayerMenu)
|
||||
{
|
||||
// Player menu open: close
|
||||
if (pPlr->Menu.IsActive())
|
||||
pPlr->Menu.Close(false);
|
||||
// Menu closed: open main menu
|
||||
else
|
||||
pPlr->ActivateMenuMain();
|
||||
return;
|
||||
}
|
||||
// Local player menu active: convert menu com and control local
|
||||
if (pPlr->Menu.ConvertCom(iCom,iData,true))
|
||||
{
|
||||
pPlr->Menu.Control(iCom,iData);
|
||||
return;
|
||||
}
|
||||
// Pre-queue asynchronous menu conversions
|
||||
if (pPlr->Cursor && pPlr->Cursor->Menu)
|
||||
pPlr->Cursor->Menu->ConvertCom(iCom,iData,true);
|
||||
// Not for eliminated (checked again in DirectCom, but make sure no control is generated for eliminated players!)
|
||||
if (pPlr->Eliminated) return;
|
||||
// Player control: add to control queue
|
||||
Input.Add(CID_PlrControl, new C4ControlPlayerControl(iPlayer,iCom,iData));
|
||||
}
|
||||
|
||||
BOOL C4Game::DefinitionFilenamesFromSaveGame()
|
||||
{
|
||||
const char *pSource;
|
||||
|
|
|
@ -515,7 +515,7 @@ void C4GraphicsSystem::SortViewportsByPlayerControl()
|
|||
pPlr1 = Game.Players.Get(pView->Player);
|
||||
pPlr2 = Game.Players.Get(pNext->Player);
|
||||
// Swap order
|
||||
if (pPlr1 && pPlr2 && ( LayoutOrder(pPlr1->Control) > LayoutOrder(pPlr2->Control) ))
|
||||
if (pPlr1 && pPlr2 && ( LayoutOrder(pPlr1->ControlSet) > LayoutOrder(pPlr2->ControlSet) ))
|
||||
{
|
||||
if (pPrev) pPrev->Next = pNext; else FirstViewport = pNext;
|
||||
pView->Next = pNext->Next;
|
||||
|
|
|
@ -593,7 +593,7 @@ BOOL Dialog::CharIn(const char * c)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool Dialog::KeyHotkey(C4KeyCodeEx key)
|
||||
bool Dialog::KeyHotkey(const C4KeyCodeEx &key)
|
||||
{
|
||||
WORD wKey = WORD(key.Key);
|
||||
// do hotkey procs for standard alphanumerics only
|
||||
|
|
|
@ -396,7 +396,7 @@ bool Edit::KeyEnter()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Edit::KeyCursorOp(C4KeyCodeEx key, CursorOperation op)
|
||||
bool Edit::KeyCursorOp(const C4KeyCodeEx &key, CursorOperation op)
|
||||
{
|
||||
bool fShift = !!(key.dwShift & KEYS_Shift);
|
||||
bool fCtrl = !!(key.dwShift & KEYS_Control);
|
||||
|
|
|
@ -296,7 +296,8 @@ bool ContextMenu::KeyConfirm()
|
|||
DoOK();
|
||||
return true;
|
||||
}
|
||||
bool ContextMenu::KeyHotkey(C4KeyCodeEx key)
|
||||
|
||||
bool ContextMenu::KeyHotkey(const C4KeyCodeEx &key)
|
||||
{
|
||||
// not if focus is in submenu
|
||||
if (pSubmenu) return false;
|
||||
|
|
|
@ -511,7 +511,7 @@ bool C4KeyEventData::operator ==(const struct C4KeyEventData &cmp) const
|
|||
|
||||
/* ----------------- C4CustomKey------------------ */
|
||||
|
||||
C4CustomKey::C4CustomKey(C4KeyCodeEx DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority)
|
||||
C4CustomKey::C4CustomKey(const C4KeyCodeEx &DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority)
|
||||
: Scope(Scope), Name(), uiPriority(uiPriority), iRef(0)
|
||||
{
|
||||
// generate code
|
||||
|
@ -539,7 +539,7 @@ C4CustomKey::C4CustomKey(const CodeList &rDefCodes, const char *szName, C4KeySco
|
|||
}
|
||||
}
|
||||
|
||||
C4CustomKey::C4CustomKey(C4KeyCodeEx Code, const StdStrBuf &rName)
|
||||
C4CustomKey::C4CustomKey(const C4KeyCodeEx &Code, const StdStrBuf &rName)
|
||||
: Codes(), DefaultCodes(), Scope(KEYSCOPE_None), Name(), uiPriority(PRIO_None), iRef(0)
|
||||
{
|
||||
// ctor for custom key override
|
||||
|
@ -620,7 +620,7 @@ bool C4CustomKey::Execute(C4KeyEventType eEv, C4KeyCodeEx key)
|
|||
|
||||
/* ----------------- C4KeyBinding ------------------ */
|
||||
|
||||
C4KeyBinding::C4KeyBinding(C4KeyCodeEx DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority)
|
||||
C4KeyBinding::C4KeyBinding(const C4KeyCodeEx &DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority)
|
||||
: C4CustomKey(DefCode, szName, Scope, pCallback, uiPriority)
|
||||
{
|
||||
// self holds a ref
|
||||
|
@ -764,6 +764,9 @@ void C4KeyboardInput::UnregisterKeyBinding(C4CustomKey *pUnregKey)
|
|||
|
||||
bool C4KeyboardInput::DoInput(const C4KeyCodeEx &InKey, C4KeyEventType InEvent, DWORD InScope)
|
||||
{
|
||||
// store last-key-info
|
||||
LastKeyExtraData.iStrength = (InEvent != KEYEV_Up) * 100;
|
||||
LastKeyExtraData.x = LastKeyExtraData.y = 0;
|
||||
// check all key events generated by this key: First the keycode itself, then any more generic key events like KEY_Any
|
||||
const int32_t iKeyRangeMax = 5;
|
||||
int32_t iKeyRangeCnt=0, j;
|
||||
|
|
|
@ -177,7 +177,7 @@ bool C4ChatInputDialog::KeyHistoryUpDown(bool fUp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4ChatInputDialog::KeyPlrControl(C4KeyCodeEx key)
|
||||
bool C4ChatInputDialog::KeyPlrControl(const C4KeyCodeEx &key)
|
||||
{
|
||||
// Control pressed while doing this key: Reroute this key as a player-control
|
||||
Game.DoKeyboardInput(WORD(key.Key), KEYEV_Down, !!(key.dwShift & KEYS_Alt), false, !!(key.dwShift & KEYS_Shift), key.IsRepeated(), NULL, true);
|
||||
|
@ -185,7 +185,7 @@ bool C4ChatInputDialog::KeyPlrControl(C4KeyCodeEx key)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4ChatInputDialog::KeyGamepadControlDown(C4KeyCodeEx key)
|
||||
bool C4ChatInputDialog::KeyGamepadControlDown(const C4KeyCodeEx &key)
|
||||
{
|
||||
// filter gamepad control
|
||||
if (!Key_IsGamepad(key.Key)) return false;
|
||||
|
@ -194,7 +194,7 @@ bool C4ChatInputDialog::KeyGamepadControlDown(C4KeyCodeEx key)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4ChatInputDialog::KeyGamepadControlUp(C4KeyCodeEx key)
|
||||
bool C4ChatInputDialog::KeyGamepadControlUp(const C4KeyCodeEx &key)
|
||||
{
|
||||
// filter gamepad control
|
||||
if (!Key_IsGamepad(key.Key)) return false;
|
||||
|
@ -203,7 +203,7 @@ bool C4ChatInputDialog::KeyGamepadControlUp(C4KeyCodeEx key)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4ChatInputDialog::KeyGamepadControlPressed(C4KeyCodeEx key)
|
||||
bool C4ChatInputDialog::KeyGamepadControlPressed(const C4KeyCodeEx &key)
|
||||
{
|
||||
// filter gamepad control
|
||||
if (!Key_IsGamepad(key.Key)) return false;
|
||||
|
|
|
@ -1064,8 +1064,9 @@ void C4MouseControl::Wheel(DWORD dwFlags)
|
|||
// Ctrl + Wheel: pass to player control (might be used for inventory or such)
|
||||
else
|
||||
{
|
||||
if(iDelta > 0) Game.LocalPlayerControl(Player, COM_WheelUp);
|
||||
if(iDelta < 0) Game.LocalPlayerControl(Player, COM_WheelDown);
|
||||
// 2do
|
||||
//if(iDelta > 0) Game.LocalPlayerControl(Player, COM_WheelUp);
|
||||
//if(iDelta < 0) Game.LocalPlayerControl(Player, COM_WheelDown);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3181,499 +3181,6 @@ void C4Object::Clear()
|
|||
while (FirstRef) FirstRef->Set(0);
|
||||
}
|
||||
|
||||
BOOL C4Object::ContainedControl(BYTE byCom)
|
||||
{
|
||||
// Check
|
||||
if (!Contained) return FALSE;
|
||||
// Check if object is about to exit; if so, return
|
||||
// dunno, maybe I should check all the commands, not just the first one?
|
||||
if ((byCom == COM_Left || byCom == COM_Right) && Command)
|
||||
if (Command->Command == C4CMD_Exit)
|
||||
// hack: in structures only; not in vehicles
|
||||
// they might have a pending Exit-command due to a down-control
|
||||
if (Contained->Category & C4D_Structure)
|
||||
return FALSE; // or TRUE? Currently it doesn't matter.
|
||||
// get script function if defined
|
||||
C4AulFunc* sf = Contained->Def->Script.GetSFunc(FormatString(PSF_ContainedControl,ComName(byCom)).getData());
|
||||
// in old versions, do hardcoded actions first (until gwe3)
|
||||
// new objects may overload them
|
||||
C4Def *pCDef = Contained->Def;
|
||||
bool fCallSfEarly = CompareVersion(pCDef->rC4XVer[0],pCDef->rC4XVer[1],pCDef->rC4XVer[2],pCDef->rC4XVer[3],4,9,1,3) >= 0;
|
||||
bool result = false;
|
||||
C4Player * pPlr = Game.Players.Get(Controller);
|
||||
if(fCallSfEarly)
|
||||
{
|
||||
if (sf && !!sf->Exec(Contained, &C4AulParSet(C4VObj(this)))) result = true;
|
||||
// AutoStopControl: Also notify container about controlupdate
|
||||
// Note Contained may be nulled now due to ContainedControl call
|
||||
if(Contained && !(byCom & (COM_Single | COM_Double)) && pPlr->PrefControlStyle)
|
||||
{
|
||||
int32_t PressedComs = pPlr->PressedComs;
|
||||
C4AulParSet set(C4VObj(this),
|
||||
C4VInt(Coms2ComDir(PressedComs)),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Dig))),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Throw))));
|
||||
Contained->Call(PSF_ContainedControlUpdate, &set);
|
||||
}
|
||||
}
|
||||
if(result) return true;
|
||||
|
||||
// hardcoded actions
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Down:
|
||||
PlayerObjectCommand(Owner,C4CMD_Exit);
|
||||
break;
|
||||
case COM_Throw:
|
||||
PlayerObjectCommand(Owner,C4CMD_Throw);
|
||||
break;
|
||||
case COM_Up:
|
||||
if (ValidPlr(Contained->Base))
|
||||
if (!Hostile(Owner,Contained->Base))
|
||||
if (Game.C4S.Game.Realism.BaseFunctionality & BASEFUNC_Buy)
|
||||
ActivateMenu(C4MN_Buy);
|
||||
break;
|
||||
case COM_Dig:
|
||||
if (ValidPlr(Contained->Base))
|
||||
if (!Hostile(Owner,Contained->Base))
|
||||
if (Game.C4S.Game.Realism.BaseFunctionality & BASEFUNC_Sell)
|
||||
ActivateMenu(C4MN_Sell);
|
||||
break;
|
||||
}
|
||||
// Call container script if defined for old versions
|
||||
if (!fCallSfEarly)
|
||||
{
|
||||
if(sf) sf->Exec(Contained, &C4AulParSet(C4VObj(this)));
|
||||
if(Contained && !(byCom & (COM_Single | COM_Double)) && pPlr->PrefControlStyle)
|
||||
{
|
||||
int32_t PressedComs = pPlr->PressedComs;
|
||||
C4AulParSet set(C4VObj(this),
|
||||
C4VInt(Coms2ComDir(PressedComs)),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Dig))),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Throw))));
|
||||
Contained->Call(PSF_ContainedControlUpdate, &set);
|
||||
}
|
||||
}
|
||||
// Take/Take2
|
||||
if(!sf || fCallSfEarly) switch (byCom)
|
||||
{
|
||||
case COM_Left:
|
||||
PlayerObjectCommand(Owner,C4CMD_Take);
|
||||
break;
|
||||
case COM_Right:
|
||||
PlayerObjectCommand(Owner,C4CMD_Take2);
|
||||
break;
|
||||
}
|
||||
// Success
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL C4Object::CallControl(C4Player *pPlr, BYTE byCom, C4AulParSet *pPars)
|
||||
{
|
||||
assert(pPlr);
|
||||
|
||||
bool result = !!Call(FormatString(PSF_Control,ComName(byCom)).getData(),pPars);
|
||||
|
||||
// Call ControlUpdate when using Jump'n'Run control
|
||||
if(pPlr->PrefControlStyle)
|
||||
{
|
||||
int32_t PressedComs = pPlr->PressedComs;
|
||||
C4AulParSet set(pPars ? pPars->Par[0] : C4VObj(this),
|
||||
C4VInt(Coms2ComDir(PressedComs)),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Dig))),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Throw))),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Special))),
|
||||
C4VBool(!!(PressedComs & (1 << COM_Special2))));
|
||||
Call(PSF_ControlUpdate, &set);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void C4Object::DirectCom(BYTE byCom, int32_t iData) // By player ObjectCom
|
||||
{
|
||||
#ifdef DEBUGREC_OBJCOM
|
||||
C4RCObjectCom rc = { byCom, iData, Number };
|
||||
AddDbgRec(RCT_ObjCom, &rc, sizeof(C4RCObjectCom));
|
||||
#endif
|
||||
|
||||
// COM_Special and COM_Contents specifically bypass the menu and always go to the object
|
||||
bool fBypassMenu = ((byCom == COM_Special) || (byCom == COM_Contents));
|
||||
|
||||
// Menu control
|
||||
if (!fBypassMenu)
|
||||
if (Menu && Menu->Control(byCom,iData)) return;
|
||||
|
||||
// Ignore any menu com leftover in control queue from closed menu
|
||||
if (Inside(byCom,COM_MenuNavigation1,COM_MenuNavigation2)) return;
|
||||
|
||||
// Wether this is a KeyRelease-event
|
||||
bool IsRelease = Inside(byCom, COM_ReleaseFirst, COM_ReleaseLast);
|
||||
|
||||
// Decrease NoCollectDelay
|
||||
if (!(byCom & COM_Single) && !(byCom & COM_Double) && !IsRelease)
|
||||
if (NoCollectDelay>0)
|
||||
NoCollectDelay--;
|
||||
|
||||
// COM_Contents contents shift (data is target number (not ID!))
|
||||
// contents shift must always be done to container object, which is not necessarily this
|
||||
if (byCom==COM_Contents)
|
||||
{
|
||||
C4Object *pTarget = Game.Objects.SafeObjectPointer(iData);
|
||||
if (pTarget && pTarget->Contained)
|
||||
pTarget->Contained->DirectComContents(pTarget, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Contained control (except specials - hey, doesn't catch singles or doubles)
|
||||
if (Contained)
|
||||
if (byCom!=COM_Special && byCom!=COM_Special2 && byCom!=COM_WheelUp && byCom!=COM_WheelDown)
|
||||
{ ContainedControl(byCom); return; }
|
||||
|
||||
// Regular DirectCom clears commands
|
||||
if (!(byCom & COM_Single) && !(byCom & COM_Double) && !IsRelease)
|
||||
ClearCommands();
|
||||
|
||||
// Object script override
|
||||
C4Player *pController;
|
||||
if (pController = Game.Players.Get(Controller))
|
||||
if (CallControl(pController, byCom))
|
||||
return;
|
||||
|
||||
// direct wheel control
|
||||
if (byCom==COM_WheelUp || byCom==COM_WheelDown)
|
||||
// scroll contents
|
||||
{ ShiftContents(byCom==COM_WheelUp, TRUE); return; }
|
||||
|
||||
// The Player updates Controller before calling this, so trust Players.Get will return it
|
||||
if (pController && pController->PrefControlStyle)
|
||||
{
|
||||
AutoStopDirectCom(byCom, iData);
|
||||
return;
|
||||
}
|
||||
|
||||
// Control by procedure
|
||||
switch (GetProcedure())
|
||||
{
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_WALK:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left: ObjectComMovement(this,COMD_Left); break;
|
||||
case COM_Right: ObjectComMovement(this,COMD_Right); break;
|
||||
case COM_Down: ObjectComMovement(this,COMD_Stop); break;
|
||||
case COM_Up: ObjectComUp(this); break;
|
||||
case COM_Down_D: ObjectComDownDouble(this); break;
|
||||
case COM_Dig_S:
|
||||
if (ObjectComDig(this))
|
||||
{
|
||||
Action.ComDir = (Action.Dir==DIR_Right) ? COMD_DownRight : COMD_DownLeft;
|
||||
}
|
||||
break;
|
||||
case COM_Dig_D: ObjectComDigDouble(this); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Throw); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_FLIGHT: case DFA_KNEEL: case DFA_THROW:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left: ObjectComMovement(this,COMD_Left); break;
|
||||
case COM_Right: ObjectComMovement(this,COMD_Right); break;
|
||||
case COM_Down: ObjectComMovement(this,COMD_Stop); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Throw); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_SCALE:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left:
|
||||
if (Action.Dir==DIR_Left) ObjectComMovement(this,COMD_Stop);
|
||||
else { ObjectComMovement(this,COMD_Left); ObjectComLetGo(this,-1); }
|
||||
break;
|
||||
case COM_Right:
|
||||
if (Action.Dir==DIR_Right) ObjectComMovement(this,COMD_Stop);
|
||||
else { ObjectComMovement(this,COMD_Right); ObjectComLetGo(this,+1); }
|
||||
break;
|
||||
case COM_Up: ObjectComMovement(this,COMD_Up); break;
|
||||
case COM_Down: ObjectComMovement(this,COMD_Down); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Drop); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_HANGLE:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left: ObjectComMovement(this,COMD_Left); break;
|
||||
case COM_Right: ObjectComMovement(this,COMD_Right); break;
|
||||
case COM_Up: ObjectComMovement(this,COMD_Stop); break;
|
||||
case COM_Down: ObjectComLetGo(this,0); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Drop); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_DIG:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left: if (Inside<int32_t>(Action.ComDir,COMD_UpRight,COMD_Left)) Action.ComDir++; break;
|
||||
case COM_Right: if (Inside<int32_t>(Action.ComDir,COMD_Right,COMD_UpLeft)) Action.ComDir--; break;
|
||||
case COM_Down: ObjectComStop(this); break;
|
||||
case COM_Dig_D: ObjectComDigDouble(this); break;
|
||||
case COM_Dig_S: Action.Data = (!Action.Data); break; // Dig mat 2 object request
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_SWIM:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left: ObjectComMovement(this,COMD_Left); break;
|
||||
case COM_Right: ObjectComMovement(this,COMD_Right); break;
|
||||
case COM_Up:
|
||||
ObjectComMovement(this,COMD_Up);
|
||||
ObjectComUp(this); break;
|
||||
case COM_Down: ObjectComMovement(this,COMD_Down); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Drop); break;
|
||||
case COM_Dig_D: ObjectComDigDouble(this); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_BRIDGE: case DFA_BUILD: case DFA_CHOP:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Down: ObjectComStop(this); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_FIGHT:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left: ObjectComMovement(this,COMD_Left); break;
|
||||
case COM_Right: ObjectComMovement(this,COMD_Right); break;
|
||||
case COM_Down: ObjectComStop(this); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_PUSH:
|
||||
{
|
||||
bool fGrabControlOverload = false;
|
||||
if(Action.Target)
|
||||
{
|
||||
// New grab-control model: objects version 4.95 or higher (CE)
|
||||
// may overload control of grabbing clonks
|
||||
C4Def *pTDef = Action.Target->Def;
|
||||
if(CompareVersion(pTDef->rC4XVer[0],pTDef->rC4XVer[1],pTDef->rC4XVer[2],pTDef->rC4XVer[3],4,9,5,0) >= 0)
|
||||
fGrabControlOverload = true;
|
||||
}
|
||||
// Call object control first in case it overloads
|
||||
if (fGrabControlOverload)
|
||||
if (Action.Target)
|
||||
if (Action.Target->CallControl(pController, byCom, &C4AulParSet(C4VObj(this))))
|
||||
return;
|
||||
// Clonk direct control
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left: ObjectComMovement(this,COMD_Left); break;
|
||||
case COM_Right: ObjectComMovement(this,COMD_Right); break;
|
||||
case COM_Up:
|
||||
// Target -> enter
|
||||
if (ObjectComEnter(Action.Target))
|
||||
ObjectComMovement(this,COMD_Stop);
|
||||
// Else, comdir up for target straightening
|
||||
else
|
||||
ObjectComMovement(this,COMD_Up);
|
||||
break;
|
||||
case COM_Down: ObjectComMovement(this,COMD_Stop); break;
|
||||
case COM_Down_D: ObjectComUnGrab(this); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Throw); break;
|
||||
}
|
||||
// Action target call control late for old objects
|
||||
if (!fGrabControlOverload)
|
||||
if (Action.Target)
|
||||
Action.Target->CallControl(pController, byCom, &C4AulParSet(C4VObj(this)));
|
||||
break;
|
||||
}
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
}
|
||||
}
|
||||
|
||||
void C4Object::AutoStopDirectCom(BYTE byCom, int32_t iData) // By DirecCom
|
||||
{
|
||||
C4Player * pPlayer = Game.Players.Get(Controller);
|
||||
// Control by procedure
|
||||
switch (GetProcedure())
|
||||
{
|
||||
case DFA_WALK:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Up: ObjectComUp(this); break;
|
||||
case COM_Down:
|
||||
// inhibit controldownsingle on freshly grabbed objects
|
||||
if (ObjectComDownDouble(this))
|
||||
pPlayer->LastCom = COM_None;
|
||||
break;
|
||||
case COM_Dig_S: ObjectComDig(this); break;
|
||||
case COM_Dig_D: ObjectComDigDouble(this); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Throw); break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_FLIGHT:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Throw:
|
||||
// Drop when pressing left, right or down
|
||||
if (pPlayer->PressedComs & ((1<<COM_Left)|(1<<COM_Right)|(1<<COM_Down)))
|
||||
PlayerObjectCommand(Owner,C4CMD_Drop);
|
||||
else
|
||||
// This will fail, but whatever.
|
||||
PlayerObjectCommand(Owner,C4CMD_Throw);
|
||||
break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_KNEEL: case DFA_THROW:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Throw); break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_SCALE:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Left:
|
||||
if (Action.Dir == DIR_Right) ObjectComLetGo(this,-1);
|
||||
else AutoStopUpdateComDir();
|
||||
break;
|
||||
case COM_Right:
|
||||
if (Action.Dir == DIR_Left) ObjectComLetGo(this,+1);
|
||||
else AutoStopUpdateComDir();
|
||||
break;
|
||||
case COM_Dig: ObjectComLetGo(this,(Action.Dir == DIR_Left) ? +1 : -1);
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Drop); break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_HANGLE:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Down: ObjectComLetGo(this,0); break;
|
||||
case COM_Dig: ObjectComLetGo(this,0); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Drop); break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_DIG:
|
||||
switch (byCom)
|
||||
{
|
||||
// Dig mat 2 object request
|
||||
case COM_Throw: case COM_Dig: Action.Data = (!Action.Data); break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_SWIM:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Up:
|
||||
AutoStopUpdateComDir();
|
||||
ObjectComUp(this);
|
||||
break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Drop); break;
|
||||
case COM_Dig_D: ObjectComDigDouble(this); break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_BRIDGE: case DFA_BUILD: case DFA_CHOP:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Down: ObjectComStop(this); break;
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_FIGHT:
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Down: ObjectComStop(this); break;
|
||||
default: AutoStopUpdateComDir();
|
||||
}
|
||||
break;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
case DFA_PUSH:
|
||||
{
|
||||
bool fGrabControlOverload = false;
|
||||
if(Action.Target)
|
||||
{
|
||||
// New grab-control model: objects version 4.95 or higher (CE)
|
||||
// may overload control of grabbing clonks
|
||||
C4Def *pTDef = Action.Target->Def;
|
||||
if(CompareVersion(pTDef->rC4XVer[0],pTDef->rC4XVer[1],pTDef->rC4XVer[2],pTDef->rC4XVer[3],4,9,5,0) >= 0)
|
||||
fGrabControlOverload = true;
|
||||
// Call object control first in case it overloads
|
||||
if (fGrabControlOverload)
|
||||
{
|
||||
if (Action.Target->CallControl(pPlayer, byCom, &C4AulParSet(C4VObj(this))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clonk direct control
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_Up:
|
||||
// Target -> enter
|
||||
if (ObjectComEnter(Action.Target))
|
||||
ObjectComMovement(this,COMD_Stop);
|
||||
// Else, comdir up for target straightening
|
||||
else
|
||||
AutoStopUpdateComDir();
|
||||
break;
|
||||
case COM_Down:
|
||||
// FIXME: replace constants
|
||||
// ComOrder(3) is COM_Down, ComOrder(11) is COM_Down_S and ComOrder(19) is COM_Down_D
|
||||
if(Action.Target
|
||||
&& !DrawCommandQuery(Controller, Action.Target->Def->Script, Action.Target->Def->Script.ControlMethod, 3)
|
||||
&& !DrawCommandQuery(Controller, Action.Target->Def->Script, Action.Target->Def->Script.ControlMethod, 11)
|
||||
&& !DrawCommandQuery(Controller, Action.Target->Def->Script, Action.Target->Def->Script.ControlMethod, 19))
|
||||
{
|
||||
ObjectComUnGrab(this);
|
||||
}
|
||||
break;
|
||||
case COM_Down_D: ObjectComUnGrab(this); break;
|
||||
case COM_Throw: PlayerObjectCommand(Owner,C4CMD_Drop); break;
|
||||
default:
|
||||
AutoStopUpdateComDir();
|
||||
}
|
||||
// Action target call control late for old objects
|
||||
if (!fGrabControlOverload && Action.Target)
|
||||
Action.Target->CallControl(pPlayer, byCom, &C4AulParSet(C4VObj(this)));
|
||||
break;
|
||||
}
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
}
|
||||
}
|
||||
|
||||
void C4Object::AutoStopUpdateComDir()
|
||||
{
|
||||
C4Player * pPlr = Game.Players.Get(Controller);
|
||||
if (!pPlr || pPlr->Cursor != this) return;
|
||||
int32_t NewComDir = Coms2ComDir(pPlr->PressedComs);
|
||||
if (Action.ComDir == NewComDir) return;
|
||||
if (NewComDir == COMD_Stop && GetProcedure() == DFA_DIG)
|
||||
{
|
||||
ObjectComStop(this);
|
||||
return;
|
||||
}
|
||||
ObjectComMovement(this, NewComDir);
|
||||
}
|
||||
|
||||
BOOL C4Object::MenuCommand(const char *szCommand)
|
||||
{
|
||||
// Native script execution
|
||||
|
|
|
@ -607,10 +607,10 @@ BOOL ObjectComPut(C4Object *cObj, C4Object *pTarget, C4Object *pThing)
|
|||
if (pTarget!=cObj->Contained)
|
||||
if (!(pTarget->Def->GrabPutGet & C4D_Grab_Put))
|
||||
{
|
||||
// Was meant to be a drop anyway
|
||||
if (ValidPlr(cObj->Owner))
|
||||
if (Game.Players.Get(cObj->Owner)->LastComDownDouble)
|
||||
return ObjectComDrop(cObj, pThing);
|
||||
// Was meant to be a drop anyway - probably obsolete as controls are being revised
|
||||
//if (ValidPlr(cObj->Owner))
|
||||
// if (Game.Players.Get(cObj->Owner)->LastComDownDouble)
|
||||
// return ObjectComDrop(cObj, pThing);
|
||||
// No grab put: fail
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1009,8 +1009,8 @@ BOOL PlayerObjectCommand(int32_t plr, int32_t cmdf, C4Object *pTarget, int32_t t
|
|||
if (cmdf==C4CMD_Throw)
|
||||
{
|
||||
bool fConvertToDrop = false;
|
||||
// Drop on down-down-throw (classic)
|
||||
if (pPlr->LastComDownDouble)
|
||||
// Drop on down-down-throw (classic) - obsolete?
|
||||
/*if (pPlr->LastComDownDouble)
|
||||
{
|
||||
fConvertToDrop = true;
|
||||
// Dropping one object automatically reenables LastComDownDouble to
|
||||
|
@ -1021,7 +1021,7 @@ BOOL PlayerObjectCommand(int32_t plr, int32_t cmdf, C4Object *pTarget, int32_t t
|
|||
pPlr->LastComDownDouble = C4DoubleClick;
|
||||
}
|
||||
// Jump'n'Run: Drop on combined Down/Left/Right+Throw
|
||||
if (pPlr->PrefControlStyle && (pPlr->PressedComs & (1 << COM_Down))) fConvertToDrop = true;
|
||||
if (pPlr->PrefControlStyle && (pPlr->PressedComs & (1 << COM_Down))) fConvertToDrop = true;*/
|
||||
if (fConvertToDrop) return pPlr->ObjectCommand(C4CMD_Drop,pTarget,tx,ty,NULL,0,iAddMode);
|
||||
}
|
||||
// Route to player
|
||||
|
|
|
@ -434,20 +434,20 @@ void C4ObjectMenu::Execute()
|
|||
|
||||
void C4ObjectMenu::OnUserSelectItem(int32_t Player, int32_t iIndex)
|
||||
{
|
||||
// queue....
|
||||
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Player,COM_MenuSelect,iIndex | C4MN_AdjustPosition));
|
||||
// queue.... 2do
|
||||
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Player,Game.PlayerControlDefs.InternalCons.CON_MenuSelect,iIndex | C4MN_AdjustPosition));
|
||||
}
|
||||
|
||||
void C4ObjectMenu::OnUserEnter(int32_t Player, int32_t iIndex, bool fRight)
|
||||
{
|
||||
// object menu: Through queue
|
||||
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Player,fRight ? COM_MenuEnterAll : COM_MenuEnter,iIndex));
|
||||
// object menu: Through queue 2do
|
||||
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Player,fRight ? Game.PlayerControlDefs.InternalCons.CON_MenuEnterAll : Game.PlayerControlDefs.InternalCons.CON_MenuEnter,iIndex));
|
||||
}
|
||||
|
||||
void C4ObjectMenu::OnUserClose()
|
||||
{
|
||||
// Queue
|
||||
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Game.MouseControl.GetPlayer(),COM_MenuClose,0));
|
||||
// Queue 2do
|
||||
Game.Input.Add(CID_PlrControl, new C4ControlPlayerControl(Game.MouseControl.GetPlayer(),Game.PlayerControlDefs.InternalCons.CON_MenuClose,0));
|
||||
}
|
||||
|
||||
bool C4ObjectMenu::IsReadOnly()
|
||||
|
|
|
@ -113,7 +113,7 @@ const C4PktHandlingData PktHandlingData[] =
|
|||
{ CID_JoinPlr, PC_Control, "Join Player", false, true, 0, PKT_UNPACK(C4ControlJoinPlayer) },
|
||||
{ CID_RemovePlr, PC_Control, "Remove Player", false, true, 0, PKT_UNPACK(C4ControlRemovePlr) },
|
||||
{ CID_PlrSelect, PC_Control, "Player Select", false, true, 0, PKT_UNPACK(C4ControlPlayerSelect)},
|
||||
{ CID_PlrControl, PC_Control, "Player Control", false, true, 0, PKT_UNPACK(C4ControlPlayerControl)},
|
||||
{ CID_PlrControl, PC_Control, "Player Control", false, true, 0, PKT_UNPACK(C4ControlPlayerControl)},
|
||||
{ CID_PlrCommand, PC_Control, "Player Command", false, true, 0, PKT_UNPACK(C4ControlPlayerCommand)},
|
||||
{ CID_Message, PC_Control, "Message", false, true, 0, PKT_UNPACK(C4ControlMessage) },
|
||||
{ CID_EMMoveObj, PC_Control, "EM Move Obj", false, true, 0, PKT_UNPACK(C4ControlEMMoveObject)},
|
||||
|
|
|
@ -1081,7 +1081,6 @@ void C4Player::Default()
|
|||
ControlCount = ActionCount = 0;
|
||||
LastControlType = PCID_None;
|
||||
LastControlID = 0;
|
||||
PressedComs = 0;
|
||||
pMsgBoardQuery = NULL;
|
||||
pGamepad = NULL;
|
||||
NoEliminationCheck = false;
|
||||
|
@ -1209,26 +1208,7 @@ BOOL C4Player::MakeCrewMember(C4Object *pObj, bool fForceInfo, bool fDoCalls)
|
|||
|
||||
void C4Player::ExecuteControl()
|
||||
{
|
||||
|
||||
// LastCom
|
||||
if (LastCom != COM_None)
|
||||
{
|
||||
// Advance delay counter
|
||||
LastComDelay++;
|
||||
// Check for COM_Single com (after delay)
|
||||
if (LastComDelay > C4DoubleClick)
|
||||
{
|
||||
// Pass additional COM_Single com (unless it already was a single com in the first place)
|
||||
if (!(LastCom & COM_Single))
|
||||
DirectCom(LastCom | COM_Single, 0); // Currently, com data is not stored for single coms...
|
||||
LastCom = COM_None;
|
||||
LastComDelay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// LastComDownDouble
|
||||
if (LastComDownDouble>0) LastComDownDouble--;
|
||||
|
||||
Control.Execute();
|
||||
}
|
||||
|
||||
void C4Player::AdjustCursorCommand()
|
||||
|
@ -1375,30 +1355,6 @@ void C4Player::UpdateSelectionToggleStatus()
|
|||
CursorToggled=0;
|
||||
}
|
||||
|
||||
BOOL C4Player::ObjectCom(BYTE byCom, int32_t iData) // By DirectCom
|
||||
{
|
||||
if (Eliminated) return FALSE;
|
||||
#ifdef DEBUGREC_OBJCOM
|
||||
C4RCObjectCom rc = { byCom, iData, Number };
|
||||
AddDbgRec(RCT_PlrCom, &rc, sizeof(C4RCObjectCom));
|
||||
#endif
|
||||
// Hide startup
|
||||
ShowStartup=FALSE;
|
||||
// If regular com, update cursor & selection status
|
||||
if (!(byCom & COM_Single) && !(byCom & COM_Double) && (byCom < COM_ReleaseFirst || byCom > COM_ReleaseLast))
|
||||
UpdateSelectionToggleStatus();
|
||||
// Apply direct com to cursor object
|
||||
if (Cursor)
|
||||
{
|
||||
// update controller
|
||||
Cursor->Controller = Number;
|
||||
// send com
|
||||
Cursor->DirectCom(byCom,iData);
|
||||
}
|
||||
// Done
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL C4Player::ObjectCommand(int32_t iCommand, C4Object *pTarget, int32_t iX, int32_t iY, C4Object *pTarget2, int32_t iData, int32_t iMode)
|
||||
{
|
||||
// Eliminated
|
||||
|
@ -1455,71 +1411,6 @@ void C4Player::ObjectCommand2Obj(C4Object *cObj, int32_t iCommand, C4Object *pTa
|
|||
else if (iMode & C4P_Command_Set) cObj->SetCommand(iCommand,pTarget,iX,iY,pTarget2,TRUE,iData);
|
||||
}
|
||||
|
||||
void C4Player::DirectCom(BYTE byCom, int32_t iData) // By InCom or ExecuteControl
|
||||
{
|
||||
switch (byCom)
|
||||
{
|
||||
case COM_CursorLeft: CursorLeft(); break;
|
||||
case COM_CursorRight: CursorRight(); break;
|
||||
case COM_CursorToggle: CursorToggle(); break;
|
||||
case COM_CursorToggle_D: SelectAllCrew(); break;
|
||||
|
||||
default: ObjectCom(byCom,iData); break;
|
||||
}
|
||||
}
|
||||
|
||||
void C4Player::InCom(BYTE byCom, int32_t iData)
|
||||
{
|
||||
#ifdef DEBUGREC_OBJCOM
|
||||
C4RCObjectCom rc = { byCom, iData, Number };
|
||||
AddDbgRec(RCT_PlrInCom, &rc, sizeof(C4RCObjectCom));
|
||||
#endif
|
||||
// Cursor object menu active: convert regular com to menu com
|
||||
if (Cursor) if (Cursor->Menu)
|
||||
{
|
||||
int32_t iCom = byCom;
|
||||
Cursor->Menu->ConvertCom(iCom,iData, false);
|
||||
byCom = iCom;
|
||||
}
|
||||
// Menu control: no single/double processing
|
||||
if (Inside(byCom,COM_MenuFirst,COM_MenuLast))
|
||||
{ DirectCom(byCom,iData); return; }
|
||||
// Ignore KeyRelease for Single/Double
|
||||
if (!Inside(byCom, COM_ReleaseFirst, COM_ReleaseLast))
|
||||
{
|
||||
// Reset view
|
||||
ResetCursorView();
|
||||
// Update state
|
||||
if (Inside<int>(byCom, COM_ReleaseFirst - 16, COM_ReleaseLast - 16))
|
||||
PressedComs |= 1 << byCom;
|
||||
// Check LastCom buffer for prior COM_Single
|
||||
if (LastCom!=COM_None)
|
||||
if (LastCom!=byCom)
|
||||
{
|
||||
DirectCom(LastCom | COM_Single,iData);
|
||||
// AutoStopControl uses a single COM_Down instead of DOM_Down_D for drop
|
||||
// So a COM_Down_S does what a COM_Down_D normally does, if generated by another key
|
||||
// instead of a timeout
|
||||
if (PrefControlStyle && LastCom == COM_Down) LastComDownDouble = C4DoubleClick;
|
||||
}
|
||||
// Check LastCom buffer for COM_Double
|
||||
if (LastCom==byCom) byCom|=COM_Double;
|
||||
// LastCom/Del process
|
||||
// this is set before issuing the DirectCom, so DirectCom-scripts may delete it
|
||||
LastCom=byCom; LastComDelay=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update state
|
||||
if (Inside(byCom, COM_ReleaseFirst, COM_ReleaseLast))
|
||||
PressedComs &= ~(1 << (byCom - 16));
|
||||
}
|
||||
// Pass regular/COM_Double byCom to player
|
||||
DirectCom(byCom,iData);
|
||||
// LastComDownDouble process
|
||||
if (byCom == COM_Down_D) LastComDownDouble = C4DoubleClick;
|
||||
}
|
||||
|
||||
void C4Player::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
assert(ID);
|
||||
|
@ -1534,7 +1425,7 @@ void C4Player::CompileFunc(StdCompiler *pComp)
|
|||
pComp->Value(mkNamingAdapt(Evaluated, "Evaluated", false));
|
||||
pComp->Value(mkNamingAdapt(Color, "Color", -1));
|
||||
pComp->Value(mkNamingAdapt(ColorDw, "ColorDw", 0u));
|
||||
pComp->Value(mkNamingAdapt(Control, "Control", 0));
|
||||
pComp->Value(mkNamingAdapt(ControlSet, "Control", 0));
|
||||
pComp->Value(mkNamingAdapt(MouseControl, "MouseControl", 0));
|
||||
pComp->Value(mkNamingAdapt(Position, "Position", 0));
|
||||
pComp->Value(mkNamingAdapt(ViewMode, "ViewMode", C4PVM_Cursor));
|
||||
|
@ -1563,10 +1454,6 @@ void C4Player::CompileFunc(StdCompiler *pComp)
|
|||
pComp->Value(mkNamingAdapt((int32_t&)Cursor, "Cursor", 0));
|
||||
pComp->Value(mkNamingAdapt((int32_t&)ViewCursor,"ViewCursor", 0));
|
||||
pComp->Value(mkNamingAdapt((int32_t&)Captain, "Captain", 0));
|
||||
pComp->Value(mkNamingAdapt(LastCom, "LastCom", 0));
|
||||
pComp->Value(mkNamingAdapt(LastComDelay, "LastComDel", 0));
|
||||
pComp->Value(mkNamingAdapt(PressedComs, "PressedComs", 0));
|
||||
pComp->Value(mkNamingAdapt(LastComDownDouble, "LastComDownDouble", 0));
|
||||
pComp->Value(mkNamingAdapt(CursorSelection, "CursorSelection", 0));
|
||||
pComp->Value(mkNamingAdapt(CursorToggled, "CursorToggled", 0));
|
||||
pComp->Value(mkNamingAdapt(MessageStatus, "MessageStatus", 0));
|
||||
|
@ -1672,7 +1559,7 @@ void C4Player::DefaultRuntimeData()
|
|||
AtClient=C4ClientIDUnknown;
|
||||
SCopy("Local",AtClientName);
|
||||
Color=-1;
|
||||
Control=C4P_Control_None;
|
||||
ControlSet=C4P_Control_None;
|
||||
MouseControl=FALSE;
|
||||
Position=-1;
|
||||
PlrStartIndex=0;
|
||||
|
@ -1694,9 +1581,6 @@ void C4Player::DefaultRuntimeData()
|
|||
Cursor=ViewCursor=NULL;
|
||||
SelectCount=0;
|
||||
SelectFlash=CursorFlash=30;
|
||||
LastCom=0;
|
||||
LastComDelay=0;
|
||||
LastComDownDouble=0;
|
||||
CursorSelection=CursorToggled=0;
|
||||
MessageStatus=0;
|
||||
MessageBuf[0]=0;
|
||||
|
@ -1836,7 +1720,7 @@ void C4Player::InitControl()
|
|||
if (!GetInfo() || GetInfo()->GetType() == C4PT_User)
|
||||
LocalControl=TRUE;
|
||||
// Set control
|
||||
Control=C4P_Control_None;
|
||||
ControlSet=C4P_Control_None;
|
||||
// Preferred control
|
||||
int32_t iControl = PrefControl;
|
||||
// gamepad control safety
|
||||
|
@ -1848,32 +1732,35 @@ void C4Player::InitControl()
|
|||
if (Game.Players.ControlTaken(iControl))
|
||||
{
|
||||
// Preferred control taken, search for available keyboard control
|
||||
for (iControl=C4P_Control_Keyboard1; iControl<=C4P_Control_Keyboard4; iControl++)
|
||||
for (iControl=C4P_Control_Keyboard1; iControl<=C4P_Control_Keyboard2; iControl++)
|
||||
if (!Game.Players.ControlTaken(iControl)) // Available control found
|
||||
break;
|
||||
// No available control found
|
||||
if (iControl>C4P_Control_Keyboard4)
|
||||
if (iControl>C4P_Control_Keyboard2)
|
||||
iControl=C4P_Control_None;
|
||||
}
|
||||
// Set control
|
||||
Control=iControl;
|
||||
ControlSet=iControl;
|
||||
// init gamepad
|
||||
if (pGamepad) { delete pGamepad; pGamepad=NULL; }
|
||||
if (Inside<int32_t>(Control, C4P_Control_GamePad1, C4P_Control_GamePadMax))
|
||||
if (Inside<int32_t>(ControlSet, C4P_Control_GamePad1, C4P_Control_GamePadMax))
|
||||
{
|
||||
pGamepad = new C4GamePadOpener(Control - C4P_Control_GamePad1);
|
||||
pGamepad = new C4GamePadOpener(ControlSet - C4P_Control_GamePad1);
|
||||
}
|
||||
// Mouse
|
||||
if (PrefMouse && !Game.Control.isReplay())
|
||||
if (!Game.C4S.Head.DisableMouse)
|
||||
if (Inside<int32_t>(Control, C4P_Control_Keyboard1, C4P_Control_GamePadMax))
|
||||
if (Inside<int32_t>(ControlSet, C4P_Control_Keyboard1, C4P_Control_GamePadMax))
|
||||
if (!Game.Players.MouseControlTaken())
|
||||
MouseControl=TRUE;
|
||||
// no controls issued yet
|
||||
ControlCount = ActionCount = 0;
|
||||
LastControlType = PCID_None;
|
||||
LastControlID = 0;
|
||||
PressedComs = 0;
|
||||
// init control callbacks
|
||||
StdStrBuf sKeysetName;
|
||||
sKeysetName.Format("Keyboard%d%s", ControlSet, PrefControlStyle ? "" : "Classic");
|
||||
Control.RegisterKeyset(Number, Game.PlayerControlAssignmentSets.GetSetByName(sKeysetName.getData()));
|
||||
}
|
||||
|
||||
int igOffX, igOffY;
|
||||
|
|
|
@ -66,14 +66,24 @@ bool C4PlayerControlDef::operator ==(const C4PlayerControlDef &cmp) const
|
|||
|
||||
/* C4PlayerControlDefs */
|
||||
|
||||
void C4PlayerControlDefs::UpdateInternalCons()
|
||||
{
|
||||
InternalCons.CON_MenuSelect = GetControlIndexByIdentifier("MenuSelect");
|
||||
InternalCons.CON_MenuEnter = GetControlIndexByIdentifier("MenuEnter");
|
||||
InternalCons.CON_MenuEnterAll = GetControlIndexByIdentifier("MenuEnterAll");
|
||||
InternalCons.CON_MenuClose = GetControlIndexByIdentifier("MenuClose");
|
||||
}
|
||||
|
||||
void C4PlayerControlDefs::Clear()
|
||||
{
|
||||
Defs.clear();
|
||||
UpdateInternalCons();
|
||||
}
|
||||
|
||||
void C4PlayerControlDefs::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Defs, StdCompiler::SEP_NONE), "ControlDefs", DefVecImpl()));
|
||||
if (pComp->isCompiler()) UpdateInternalCons();
|
||||
}
|
||||
|
||||
void C4PlayerControlDefs::MergeFrom(const C4PlayerControlDefs &Src)
|
||||
|
@ -94,9 +104,10 @@ void C4PlayerControlDefs::MergeFrom(const C4PlayerControlDefs &Src)
|
|||
Defs.push_back(SrcDef);
|
||||
}
|
||||
}
|
||||
UpdateInternalCons();
|
||||
}
|
||||
|
||||
C4PlayerControlDef *C4PlayerControlDefs::GetControlByIndex(int32_t idx)
|
||||
const C4PlayerControlDef *C4PlayerControlDefs::GetControlByIndex(int32_t idx) const
|
||||
{
|
||||
// safe index
|
||||
if (idx<0 || idx>=Defs.size()) return NULL;
|
||||
|
@ -201,6 +212,49 @@ bool C4PlayerControlAssignment::ResolveRefs(C4PlayerControlAssignmentSet *pParen
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4PlayerControlAssignment::IsComboMatched(const C4PlayerControlRecentKeyList &DownKeys, const C4PlayerControlRecentKeyList &RecentKeys) const
|
||||
{
|
||||
assert(HasCombo());
|
||||
// check if combo is currently fulfilled (assuming TriggerKey is already matched)
|
||||
if (fComboIsSequence)
|
||||
{
|
||||
DWORD tKeyLast = timeGetTime();
|
||||
// combo is a sequence: The last keys of RecentKeys must match the sequence
|
||||
// the last ComboKey is the TriggerKey, which is omitted because it has already been matched and is not to be found in RecentKeys yet
|
||||
C4PlayerControlRecentKeyList::const_reverse_iterator ri = RecentKeys.rbegin();
|
||||
for (KeyComboVec::const_reverse_iterator i = KeyCombo.rbegin()+1; i!=KeyCombo.rend(); ++i,++ri)
|
||||
{
|
||||
// no more keys pressed but combo didn't end? -> no combo match
|
||||
if (ri == RecentKeys.rend()) return false;
|
||||
const C4PlayerControlRecentKey &rk = *ri;
|
||||
// user waited for too long?
|
||||
DWORD tKeyRecent = rk.tTime;
|
||||
if (tKeyLast - tKeyRecent > C4PlayerControl::MaxSequenceKeyDelay) return false;
|
||||
// key doesn't match?
|
||||
const KeyComboItem &k = *i;
|
||||
if (!(rk.Key == k.Key)) return false;
|
||||
// key OK
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// combo requires keys to be down simultanuously: check that all keys of the combo are in the down-list
|
||||
for (KeyComboVec::const_iterator i = KeyCombo.begin(); i!=KeyCombo.end(); ++i)
|
||||
{
|
||||
const KeyComboItem &k = *i;
|
||||
bool fFound = false;
|
||||
for (C4PlayerControlRecentKeyList::const_iterator di = DownKeys.begin(); di!=DownKeys.end(); ++di)
|
||||
{
|
||||
const C4PlayerControlRecentKey &dk = *di;
|
||||
if (dk.Key == k.Key) { fFound = true; break; }
|
||||
}
|
||||
if (!fFound) return false;
|
||||
}
|
||||
}
|
||||
// combo OK!
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4PlayerControlAssignment::operator ==(const C4PlayerControlAssignment &cmp) const
|
||||
{
|
||||
// doesn't compare resolved TriggerKey/iControl
|
||||
|
@ -267,6 +321,63 @@ bool C4PlayerControlAssignmentSet::operator ==(const C4PlayerControlAssignmentSe
|
|||
&& sName == cmp.sName;
|
||||
}
|
||||
|
||||
void C4PlayerControlAssignmentSet::GetAssignmentsByKey(const C4PlayerControlDefs &rDefs, const C4KeyCodeEx &key, bool fHoldKeysOnly, C4PlayerControlAssignmentPVec *pOutVec, const C4PlayerControlRecentKeyList &DownKeys, const C4PlayerControlRecentKeyList &RecentKeys) const
|
||||
{
|
||||
assert(pOutVec);
|
||||
// primary match by TriggerKey
|
||||
for (C4PlayerControlAssignmentVec::const_iterator i = Assignments.begin(); i != Assignments.end(); ++i)
|
||||
{
|
||||
const C4PlayerControlAssignment &rAssignment = *i;
|
||||
if (!(rAssignment.GetTriggerKey() == key)) continue;
|
||||
// check linked control def
|
||||
const C4PlayerControlDef *pCtrl = rDefs.GetControlByIndex(rAssignment.GetControl());
|
||||
if (!pCtrl) continue;
|
||||
// only want hold keys?
|
||||
if (fHoldKeysOnly)
|
||||
{
|
||||
// a hold/release-trigger key is not a real hold key, even if the underlying control is
|
||||
if (!pCtrl->IsHoldKey() || (rAssignment.GetTriggerMode() & (C4PlayerControlAssignment::CTM_Hold | C4PlayerControlAssignment::CTM_Release))) continue;
|
||||
}
|
||||
else if (rAssignment.HasCombo())
|
||||
{
|
||||
// hold-only events match the trigger key only (i.e., Release-events are generated as soon as the trigger key goes up)
|
||||
// other events must match either the sequence or the down-key-combination
|
||||
if (!rAssignment.IsComboMatched(DownKeys, RecentKeys)) continue;
|
||||
}
|
||||
// we got match! Store it
|
||||
pOutVec->push_back(&rAssignment);
|
||||
}
|
||||
}
|
||||
|
||||
void C4PlayerControlAssignmentSet::GetTriggerKeys(const C4PlayerControlDefs &rDefs, C4KeyCodeExVec *pRegularKeys, C4KeyCodeExVec *pHoldKeys) const
|
||||
{
|
||||
// put all trigger keys of keyset into output vectors
|
||||
// first all hold keys
|
||||
for (C4PlayerControlAssignmentVec::const_iterator i = Assignments.begin(); i != Assignments.end(); ++i)
|
||||
{
|
||||
const C4PlayerControlAssignment &rAssignment = *i;
|
||||
const C4PlayerControlDef *pDef = rDefs.GetControlByIndex(rAssignment.GetControl());
|
||||
if (pDef && pDef->IsHoldKey())
|
||||
{
|
||||
const C4KeyCodeEx &rKey = rAssignment.GetTriggerKey();
|
||||
if (std::find(pHoldKeys->begin(), pHoldKeys->end(), rKey) == pHoldKeys->end()) pHoldKeys->push_back(rKey);
|
||||
}
|
||||
}
|
||||
// then all regular keys that aren't in the hold keys list yet
|
||||
for (C4PlayerControlAssignmentVec::const_iterator i = Assignments.begin(); i != Assignments.end(); ++i)
|
||||
{
|
||||
const C4PlayerControlAssignment &rAssignment = *i;
|
||||
const C4PlayerControlDef *pDef = rDefs.GetControlByIndex(rAssignment.GetControl());
|
||||
if (pDef && !pDef->IsHoldKey())
|
||||
{
|
||||
const C4KeyCodeEx &rKey = rAssignment.GetTriggerKey();
|
||||
if (std::find(pHoldKeys->begin(), pHoldKeys->end(), rKey) == pHoldKeys->end())
|
||||
if (std::find(pRegularKeys->begin(), pRegularKeys->end(), rKey) == pRegularKeys->end())
|
||||
pRegularKeys->push_back(rKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* C4PlayerControlAssignmentSets */
|
||||
|
||||
|
@ -355,6 +466,67 @@ void C4PlayerControlFile::Clear()
|
|||
|
||||
/* C4PlayerControl */
|
||||
|
||||
void C4PlayerControl::CSync::ControlDownState::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(DownState);
|
||||
pComp->Seperator();
|
||||
pComp->Value(iDownFrame);
|
||||
pComp->Seperator();
|
||||
pComp->Value(fDownByUser);
|
||||
}
|
||||
|
||||
bool C4PlayerControl::CSync::ControlDownState::operator ==(const ControlDownState &cmp) const
|
||||
{
|
||||
return DownState == cmp.DownState && iDownFrame == cmp.iDownFrame && fDownByUser == cmp.fDownByUser;
|
||||
}
|
||||
|
||||
const C4PlayerControl::CSync::ControlDownState *C4PlayerControl::CSync::GetControlDownState(int32_t iControl) const
|
||||
{
|
||||
// safe access
|
||||
if (iControl < 0 || iControl >= ControlDownStates.size()) return NULL;
|
||||
return &ControlDownStates[iControl];
|
||||
}
|
||||
|
||||
int32_t C4PlayerControl::CSync::GetControlDisabled(int32_t iControl) const
|
||||
{
|
||||
// safe access
|
||||
if (iControl < 0 || iControl >= ControlDisableStates.size()) return 0;
|
||||
return ControlDisableStates[iControl];
|
||||
}
|
||||
|
||||
void C4PlayerControl::CSync::SetControlDownState(int32_t iControl, const C4KeyEventData &rDownState, int32_t iDownFrame, bool fDownByUser)
|
||||
{
|
||||
// update state
|
||||
if (iControl < 0) return;
|
||||
if (iControl >= ControlDownStates.size()) ControlDownStates.resize(iControl+1);
|
||||
ControlDownState &rState = ControlDownStates[iControl];
|
||||
rState.DownState = rDownState;
|
||||
rState.iDownFrame = iDownFrame;
|
||||
rState.fDownByUser = fDownByUser;
|
||||
}
|
||||
|
||||
void C4PlayerControl::CSync::SetControlDisabled(int32_t iControl, int32_t iVal)
|
||||
{
|
||||
// disable control
|
||||
if (iControl < 0) return;
|
||||
if (iControl >= ControlDisableStates.size()) ControlDisableStates.resize(iControl+1);
|
||||
ControlDisableStates[iControl] = iVal;
|
||||
// if a control is disabled, its down-state is reset silently
|
||||
const ControlDownState *pDownState = GetControlDownState(iControl);
|
||||
if (pDownState && pDownState->IsDown())
|
||||
{
|
||||
C4KeyEventData KeyDownState = pDownState->DownState;
|
||||
KeyDownState.iStrength = 0;
|
||||
SetControlDownState(iControl, KeyDownState, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
void C4PlayerControl::CSync::Clear()
|
||||
{
|
||||
ControlDownStates.clear();
|
||||
ControlDisableStates.clear();
|
||||
}
|
||||
|
||||
void C4PlayerControl::CSync::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(ControlDownStates), "Down", DownStateVec()));
|
||||
|
@ -376,20 +548,22 @@ void C4PlayerControl::CompileFunc(StdCompiler *pComp)
|
|||
bool C4PlayerControl::ProcessKeyEvent(const C4KeyCodeEx &key, bool fUp, const C4KeyEventData &rKeyExtraData)
|
||||
{
|
||||
// collect all matching keys
|
||||
C4PlayerControlAssignmentVec Matches;
|
||||
pControlSet->GetAssignmentsByKey(key, fUp, &Matches, DownKeys, RecentKeys);
|
||||
C4PlayerControlAssignmentPVec Matches;
|
||||
assert(pControlSet); // shouldn't get this callback for players without control set
|
||||
pControlSet->GetAssignmentsByKey(ControlDefs, key, fUp, &Matches, DownKeys, RecentKeys);
|
||||
// process async controls
|
||||
C4ControlPlayerControl2 *pControlPacket = NULL;
|
||||
for (C4PlayerControlAssignmentVec::const_iterator i = Matches.begin(); i != Matches.end(); ++i)
|
||||
C4ControlPlayerControl *pControlPacket = NULL;
|
||||
for (C4PlayerControlAssignmentPVec::const_iterator i = Matches.begin(); i != Matches.end(); ++i)
|
||||
{
|
||||
const C4PlayerControlAssignment &rAssignment = *i;
|
||||
int32_t iControlIndex = rAssignment.GetControl();
|
||||
C4PlayerControlDef *pControlDef = ControlDefs.GetControlByIndex(iControlIndex);
|
||||
const C4PlayerControlAssignment *pAssignment = *i;
|
||||
assert(pAssignment);
|
||||
int32_t iControlIndex = pAssignment->GetControl();
|
||||
const 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()))
|
||||
if (ExecuteControl(iControlIndex, fUp, rKeyExtraData, pAssignment->GetTriggerMode(), key.IsRepeated()))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -399,24 +573,31 @@ bool C4PlayerControl::ProcessKeyEvent(const C4KeyCodeEx &key, bool fUp, const C4
|
|||
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());
|
||||
if (!pControlPacket) pControlPacket = new C4ControlPlayerControl(iPlr, fUp, rKeyExtraData);
|
||||
pControlPacket->AddControl(iControlIndex, pAssignment->GetTriggerMode());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// push sync control to input
|
||||
if (pControlPacket) Game.Input.Add(CID_PlrControl2, pControlPacket);
|
||||
if (pControlPacket)
|
||||
{
|
||||
Game.Input.Add(CID_PlrControl2, pControlPacket);
|
||||
// assume processed (although we can't really know that yet)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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));
|
||||
C4PlayerControlRecentKey RKey(key,timeGetTime());
|
||||
if (std::find(DownKeys.begin(), DownKeys.end(), C4PlayerControlRecentKey(key,0)) == DownKeys.end()) DownKeys.push_back(RKey);
|
||||
// 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));
|
||||
if (!key.IsRepeated()) RecentKeys.push_back(RKey);
|
||||
return fResult;
|
||||
}
|
||||
|
||||
|
@ -429,14 +610,14 @@ bool C4PlayerControl::ProcessKeyUp(const C4KeyCodeEx &key)
|
|||
return ProcessKeyEvent(key, true, Game.KeyboardInput.GetLastKeyExtraData());
|
||||
}
|
||||
|
||||
void C4PlayerControl::ExecuteControlPacket(const class C4ControlPlayerControl2 *pCtrl)
|
||||
void C4PlayerControl::ExecuteControlPacket(const class C4ControlPlayerControl *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)
|
||||
for (C4ControlPlayerControl::ControlItemVec::const_iterator i = pCtrl->GetControlItems().begin(); i != pCtrl->GetControlItems().end(); ++i)
|
||||
{
|
||||
const C4ControlPlayerControl2::ControlItem &rItem = *i;
|
||||
C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(rItem.iControl);
|
||||
const C4ControlPlayerControl::ControlItem &rItem = *i;
|
||||
const C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(rItem.iControl);
|
||||
if (pCtrlDef)
|
||||
{
|
||||
if (ExecuteControl(rItem.iControl, pCtrl->IsReleaseControl(), pCtrl->GetExtraData(), rItem.iTriggerMode, false))
|
||||
|
@ -449,10 +630,12 @@ void C4PlayerControl::ExecuteControlPacket(const class C4ControlPlayerControl2 *
|
|||
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);
|
||||
const C4PlayerControlDef *pControlDef = ControlDefs.GetControlByIndex(iControl);
|
||||
if (!pControlDef || Sync.IsControlDisabled(iControl)) return false;
|
||||
C4PlayerControlDef::Actions eAction = pControlDef->GetAction();
|
||||
C4KeyEventData KeyExtraData(rKeyExtraData);
|
||||
const CSync::ControlDownState *pCtrlDownState = Sync.GetControlDownState(iControl);
|
||||
bool fWasDown = pCtrlDownState ? pCtrlDownState->IsDown() : false;
|
||||
// global controls only in global context
|
||||
if (IsGlobal() != pControlDef->IsGlobal()) return false;
|
||||
// hold-actions only work on script controls with the hold flag
|
||||
|
@ -462,9 +645,6 @@ bool C4PlayerControl::ExecuteControl(int32_t iControl, bool fUp, const C4KeyEven
|
|||
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?
|
||||
|
@ -479,6 +659,7 @@ bool C4PlayerControl::ExecuteControl(int32_t iControl, bool fUp, const C4KeyEven
|
|||
else //if (iTriggerMode & C4PlayerControlAssignment::CTM_Hold) - must be true
|
||||
{
|
||||
// control is down but trigger key is pressed again: Refresh down state
|
||||
// (this will restart the KeyRepeat time)
|
||||
Sync.SetControlDownState(iControl, KeyExtraData, Game.FrameCounter, false);
|
||||
// now process as a regular, repeated "down" event
|
||||
fRepeated = true;
|
||||
|
@ -503,10 +684,14 @@ bool C4PlayerControl::ExecuteControl(int32_t iControl, bool fUp, const C4KeyEven
|
|||
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;
|
||||
Sync.SetControlDownState(iControl, KeyExtraData, Game.FrameCounter, true);
|
||||
}
|
||||
else if (pControlDef->IsHoldKey())
|
||||
{
|
||||
// regular ControlDown on Hold Key: Set in down list
|
||||
Sync.SetControlDownState(iControl, KeyExtraData, Game.FrameCounter, true);
|
||||
fRepeated = fWasDown;
|
||||
}
|
||||
// perform action for this control
|
||||
bool fHandled = ExecuteControlAction(iControl, eAction, pControlDef->GetExtraData(), fUp, KeyExtraData, fRepeated);
|
||||
|
@ -546,6 +731,19 @@ bool C4PlayerControl::ExecuteControlAction(int32_t iControl, C4PlayerControlDef:
|
|||
|
||||
bool C4PlayerControl::ExecuteControlScript(int32_t iControl, C4ID idControlExtraData, bool fUp, const C4KeyEventData &rKeyExtraData, bool fRepeated)
|
||||
{
|
||||
C4Player *pPlr = Game.Players.Get(iPlr);
|
||||
if (pPlr)
|
||||
{
|
||||
// Not for eliminated (checked again in DirectCom, but make sure no control is generated for eliminated players!)
|
||||
if (pPlr->Eliminated) return false;
|
||||
// control count for statistics
|
||||
pPlr->CountControl(C4Player::PCID_DirectCom, iControl*2+fUp);
|
||||
}
|
||||
else if (iPlr > -1)
|
||||
{
|
||||
// player lost?
|
||||
return false;
|
||||
}
|
||||
if (!fUp)
|
||||
{
|
||||
// control down
|
||||
|
@ -567,7 +765,39 @@ bool C4PlayerControl::ExecuteControlScript(int32_t iControl, C4ID idControlExtra
|
|||
|
||||
void C4PlayerControl::Execute()
|
||||
{
|
||||
// sync execution: Do keyrepeat, etc.
|
||||
// sync execution: Do keyrepeat
|
||||
for (int32_t i=0; i<ControlDefs.GetCount(); ++i)
|
||||
{
|
||||
const CSync::ControlDownState *pControlDownState = Sync.GetControlDownState(i);
|
||||
if (pControlDownState && pControlDownState->IsDown())
|
||||
{
|
||||
const C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(i);
|
||||
assert(pCtrlDef);
|
||||
int32_t iCtrlRepeatDelay = pCtrlDef->GetRepeatDelay();
|
||||
if (iCtrlRepeatDelay)
|
||||
{
|
||||
int32_t iFrameDiff = Game.FrameCounter - pControlDownState->iDownFrame;
|
||||
int32_t iCtrlInitialRepeatDelay = pCtrlDef->GetInitialRepeatDelay();
|
||||
if (iFrameDiff && iFrameDiff >= iCtrlInitialRepeatDelay)
|
||||
{
|
||||
if (!((iFrameDiff-iCtrlInitialRepeatDelay) % iCtrlRepeatDelay))
|
||||
{
|
||||
// it's RepeatTime for this key!
|
||||
ExecuteControlAction(i, pCtrlDef->GetAction(), pCtrlDef->GetExtraData(), false, pControlDownState->DownState, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup old recent keys
|
||||
C4PlayerControlRecentKeyList::iterator irk;
|
||||
DWORD tNow = timeGetTime();
|
||||
for (irk = RecentKeys.begin(); irk != RecentKeys.end(); ++irk)
|
||||
{
|
||||
C4PlayerControlRecentKey &rk = *irk;
|
||||
if (rk.tTime + MaxRecentKeyLookback > tNow) break;
|
||||
}
|
||||
if (irk != RecentKeys.begin()) RecentKeys.erase(RecentKeys.begin(), irk);
|
||||
}
|
||||
|
||||
C4PlayerControl::C4PlayerControl() : ControlDefs(Game.PlayerControlDefs), iPlr(-1), pControlSet(NULL)
|
||||
|
@ -576,10 +806,37 @@ C4PlayerControl::C4PlayerControl() : ControlDefs(Game.PlayerControlDefs), iPlr(-
|
|||
|
||||
void C4PlayerControl::Clear()
|
||||
{
|
||||
iPlr = NO_OWNER;
|
||||
pControlSet = NULL;
|
||||
for (KeyBindingList::iterator i = KeyBindings.begin(); i != KeyBindings.end(); ++i) delete *i;
|
||||
KeyBindings.clear();
|
||||
RecentKeys.clear();
|
||||
DownKeys.clear();
|
||||
Sync.Clear();
|
||||
}
|
||||
|
||||
void C4PlayerControl::RegisterKeyset(int32_t iPlr, C4PlayerControlAssignmentSet *pKeyset)
|
||||
{
|
||||
// clear any previous settings
|
||||
Clear();
|
||||
// setup
|
||||
pControlSet = pKeyset;
|
||||
this->iPlr = iPlr;
|
||||
// register all keys into Game.KeyboardInput creating KeyBindings
|
||||
if (pControlSet)
|
||||
{
|
||||
C4KeyCodeExVec RegularKeys, HoldKeys;
|
||||
pControlSet->GetTriggerKeys(ControlDefs, &RegularKeys, &HoldKeys);
|
||||
int32_t idx=0;
|
||||
for (C4KeyCodeExVec::const_iterator i = RegularKeys.begin(); i != RegularKeys.end(); ++i) AddKeyBinding(*i, false, idx++);
|
||||
for (C4KeyCodeExVec::const_iterator i = HoldKeys.begin(); i != HoldKeys.end(); ++i) AddKeyBinding(*i, true, idx++);
|
||||
}
|
||||
}
|
||||
|
||||
void C4PlayerControl::AddKeyBinding(const C4KeyCodeEx &key, bool fHoldKey, int32_t idx)
|
||||
{
|
||||
KeyBindings.push_back(new C4CustomKey(
|
||||
key, FormatString("PlrKey%02d", idx).getData(), KEYSCOPE_Control,
|
||||
new C4KeyCBPassKey<C4PlayerControl>(*this, &C4PlayerControl::ProcessKeyDown, fHoldKey ? &C4PlayerControl::ProcessKeyUp : NULL),
|
||||
C4CustomKey::PRIO_PlrControl));
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ int C4PlayerList::CheckColorDw(DWORD dwColor, C4Player *pExclude)
|
|||
BOOL C4PlayerList::ControlTaken(int iControl) const
|
||||
{
|
||||
for (C4Player *pPlr=First; pPlr; pPlr=pPlr->Next)
|
||||
if (pPlr->Control==iControl)
|
||||
if (pPlr->ControlSet==iControl)
|
||||
if (pPlr->LocalControl)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
@ -185,7 +185,7 @@ C4Player* C4PlayerList::GetLocalByKbdSet(int iKbdSet) const
|
|||
{
|
||||
for (C4Player *pPlr=First; pPlr; pPlr=pPlr->Next)
|
||||
if (pPlr->LocalControl)
|
||||
if (pPlr->Control==iKbdSet)
|
||||
if (pPlr->ControlSet==iKbdSet)
|
||||
return pPlr;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -645,7 +645,7 @@ void C4PlayerList::DenumeratePointers()
|
|||
int C4PlayerList::ControlTakenBy(int iControl) const
|
||||
{
|
||||
for (C4Player *pPlr=First; pPlr; pPlr=pPlr->Next)
|
||||
if (pPlr->Control==iControl)
|
||||
if (pPlr->ControlSet==iControl)
|
||||
if (pPlr->LocalControl)
|
||||
return pPlr->Number;
|
||||
return NO_OWNER;
|
||||
|
|
|
@ -2692,24 +2692,6 @@ static bool FnDoHomebaseProduction(C4AulContext *cthr, long iPlr, C4ID id, long
|
|||
return Game.Players.Get(iPlr)->HomeBaseProduction.SetIDCount(id,iLastcount+iChange,TRUE);
|
||||
}
|
||||
|
||||
static long FnGetPlrDownDouble(C4AulContext *cthr, long iPlr)
|
||||
{
|
||||
if (!ValidPlr(iPlr)) return FALSE;
|
||||
return Game.Players.Get(iPlr)->LastComDownDouble;
|
||||
}
|
||||
|
||||
static bool FnClearLastPlrCom(C4AulContext *cthr, long iPlr)
|
||||
{
|
||||
// get player
|
||||
C4Player *pPlr = Game.Players.Get(iPlr);
|
||||
if (!pPlr) return FALSE;
|
||||
// reset last coms
|
||||
pPlr->LastCom = COM_None;
|
||||
pPlr->LastComDownDouble = 0;
|
||||
// done, success
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool FnSetPlrKnowledge(C4AulContext *cthr, long iPlr, C4ID id, bool fRemove)
|
||||
{
|
||||
C4Player *pPlr=Game.Players.Get(iPlr);
|
||||
|
@ -6586,8 +6568,6 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
|
|||
AddFunc(pEngine, "SetPlrView", FnSetPlrView);
|
||||
AddFunc(pEngine, "SetPlrKnowledge", FnSetPlrKnowledge);
|
||||
AddFunc(pEngine, "SetPlrMagic", FnSetPlrMagic);
|
||||
AddFunc(pEngine, "GetPlrDownDouble", FnGetPlrDownDouble);
|
||||
AddFunc(pEngine, "ClearLastPlrCom", FnClearLastPlrCom);
|
||||
AddFunc(pEngine, "GetPlrViewMode", FnGetPlrViewMode);
|
||||
AddFunc(pEngine, "GetPlrView", FnGetPlrView);
|
||||
AddFunc(pEngine, "GetWealth", FnGetWealth);
|
||||
|
|
|
@ -170,7 +170,7 @@ C4StartupOptionsDlg::KeySelDialog::~KeySelDialog()
|
|||
delete pKeyListener;
|
||||
}
|
||||
|
||||
bool C4StartupOptionsDlg::KeySelDialog::KeyDown(C4KeyCodeEx key)
|
||||
bool C4StartupOptionsDlg::KeySelDialog::KeyDown(const C4KeyCodeEx &key)
|
||||
{
|
||||
// check if key is valid for this set
|
||||
// do not mix gamepad and keyboard keys
|
||||
|
|
|
@ -1407,10 +1407,10 @@ StdStrBuf PlrControlKeyName(int32_t iPlayer, int32_t iControl, bool fShort)
|
|||
// player control
|
||||
if (pPlr)
|
||||
{
|
||||
if (Inside<int32_t>(pPlr->Control,C4P_Control_Keyboard1,C4P_Control_Keyboard4))
|
||||
return C4KeyCodeEx::KeyCode2String(Config.Controls.Keyboard[pPlr->Control][iControl], true, fShort);
|
||||
if (Inside<int32_t>(pPlr->Control,C4P_Control_GamePad1,C4P_Control_GamePadMax))
|
||||
return C4KeyCodeEx::KeyCode2String(Config.Gamepads[pPlr->Control-C4P_Control_GamePad1].Button[iControl], true, fShort);
|
||||
if (Inside<int32_t>(pPlr->ControlSet,C4P_Control_Keyboard1,C4P_Control_Keyboard4))
|
||||
return C4KeyCodeEx::KeyCode2String(Config.Controls.Keyboard[pPlr->ControlSet][iControl], true, fShort);
|
||||
if (Inside<int32_t>(pPlr->ControlSet,C4P_Control_GamePad1,C4P_Control_GamePadMax))
|
||||
return C4KeyCodeEx::KeyCode2String(Config.Gamepads[pPlr->ControlSet-C4P_Control_GamePad1].Button[iControl], true, fShort);
|
||||
}
|
||||
// global control
|
||||
else
|
||||
|
@ -1461,24 +1461,8 @@ void C4Viewport::DrawPlayerControls(C4TargetFacet &cgo)
|
|||
ty = cgo.Y+15;
|
||||
break;
|
||||
}
|
||||
int32_t iShowCtrl = Game.Players.Get(Player)->ShowControl;
|
||||
int32_t iLastCtrl = Com2Control(Game.Players.Get(Player)->LastCom);
|
||||
int32_t scwdt=size/3,schgt=size/4;
|
||||
BOOL showtext;
|
||||
|
||||
const int32_t C4MaxShowControl = 10;
|
||||
|
||||
for (int32_t iCtrl=0; iCtrl<C4MaxShowControl; iCtrl++)
|
||||
if (iShowCtrl & (1<<iCtrl))
|
||||
{
|
||||
showtext= iShowCtrl & (1<<(iCtrl+C4MaxShowControl)) ;
|
||||
if (iShowCtrl & (1<<(iCtrl+2*C4MaxShowControl)))
|
||||
if (Tick35>18) showtext=FALSE;
|
||||
C4Facet ccgo;
|
||||
ccgo.Set(cgo.Surface,tx+scwdt*(iCtrl%3),ty+schgt*(iCtrl/3),scwdt,schgt);
|
||||
DrawControlKey(ccgo,iCtrl,(iLastCtrl==iCtrl) ? 1 : 0,
|
||||
showtext ? PlrControlKeyName(Player,iCtrl,true).getData() : NULL);
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
||||
extern int32_t DrawMessageOffset;
|
||||
|
@ -1496,20 +1480,20 @@ void C4Viewport::DrawPlayerStartup(C4TargetFacet &cgo)
|
|||
cgo.X+(cgo.Wdt-GfxR->fctKeyboard.Wdt)/2+55,
|
||||
cgo.Y+cgo.Hgt * 2/3 - 10 + DrawMessageOffset,
|
||||
0,0);
|
||||
if (Inside<int32_t>(pPlr->Control,C4P_Control_Keyboard1,C4P_Control_Keyboard4))
|
||||
if (Inside<int32_t>(pPlr->ControlSet,C4P_Control_Keyboard1,C4P_Control_Keyboard4))
|
||||
{
|
||||
GfxR->fctKeyboard.Draw(cgo.Surface,
|
||||
cgo.X+(cgo.Wdt-GfxR->fctKeyboard.Wdt)/2,
|
||||
cgo.Y+cgo.Hgt * 2/3 + DrawMessageOffset,
|
||||
pPlr->Control-C4P_Control_Keyboard1,0);
|
||||
pPlr->ControlSet-C4P_Control_Keyboard1,0);
|
||||
iNameHgtOff=GfxR->fctKeyboard.Hgt;
|
||||
}
|
||||
else if (Inside<int32_t>(pPlr->Control,C4P_Control_GamePad1,C4P_Control_GamePad4))
|
||||
else if (Inside<int32_t>(pPlr->ControlSet,C4P_Control_GamePad1,C4P_Control_GamePad4))
|
||||
{
|
||||
GfxR->fctGamepad.Draw(cgo.Surface,
|
||||
cgo.X+(cgo.Wdt-GfxR->fctKeyboard.Wdt)/2,
|
||||
cgo.Y+cgo.Hgt * 2/3 + DrawMessageOffset,
|
||||
pPlr->Control-C4P_Control_GamePad1,0);
|
||||
pPlr->ControlSet-C4P_Control_GamePad1,0);
|
||||
iNameHgtOff=GfxR->fctGamepad.Hgt;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue