diff --git a/Cheat Engine/HotKeys.lfm b/Cheat Engine/HotKeys.lfm index 49785f9da7..d117cbe39e 100755 --- a/Cheat Engine/HotKeys.lfm +++ b/Cheat Engine/HotKeys.lfm @@ -15,7 +15,7 @@ object HotKeyForm: THotKeyForm LCLVersion = '2.0.6.0' object ListView1: TListView Left = 0 - Height = 173 + Height = 154 Top = 0 Width = 582 Align = alClient @@ -51,17 +51,17 @@ object HotKeyForm: THotKeyForm end object Panel1: TPanel Left = 0 - Height = 208 - Top = 173 + Height = 227 + Top = 154 Width = 582 Align = alBottom AutoSize = True - ClientHeight = 208 + ClientHeight = 227 ClientWidth = 582 TabOrder = 1 object PageControl1: TPageControl Left = 1 - Height = 173 + Height = 192 Top = 1 Width = 580 ActivePage = TabSheet2 @@ -105,7 +105,7 @@ object HotKeyForm: THotKeyForm end object TabSheet2: TTabSheet Caption = 'TabSheet2' - ClientHeight = 165 + ClientHeight = 184 ClientWidth = 572 object btnApply: TButton AnchorSideLeft.Control = Panel3 @@ -113,7 +113,7 @@ object HotKeyForm: THotKeyForm AnchorSideTop.Side = asrBottom Left = 0 Height = 25 - Top = 138 + Top = 157 Width = 75 AutoSize = True BorderSpacing.Top = 4 @@ -129,7 +129,7 @@ object HotKeyForm: THotKeyForm AnchorSideTop.Control = btnApply Left = 77 Height = 25 - Top = 138 + Top = 157 Width = 75 AutoSize = True BorderSpacing.Left = 2 @@ -143,12 +143,12 @@ object HotKeyForm: THotKeyForm AnchorSideLeft.Control = TabSheet2 AnchorSideTop.Control = TabSheet2 Left = 0 - Height = 134 + Height = 153 Top = 0 Width = 292 AutoSize = True BevelOuter = bvNone - ClientHeight = 134 + ClientHeight = 153 ClientWidth = 292 TabOrder = 2 object Label1: TLabel @@ -219,13 +219,13 @@ object HotKeyForm: THotKeyForm end object edtFreezeValue: TEdit AnchorSideLeft.Control = Label1 - AnchorSideTop.Control = cbFreezedirection + AnchorSideTop.Control = cbOnlyWhileDown AnchorSideTop.Side = asrBottom AnchorSideRight.Control = edtHotkey AnchorSideRight.Side = asrBottom Left = 4 Height = 23 - Top = 69 + Top = 88 Width = 235 Anchors = [akTop, akLeft, akRight] BorderSpacing.Top = 2 @@ -238,7 +238,7 @@ object HotKeyForm: THotKeyForm AnchorSideTop.Side = asrBottom Left = 4 Height = 15 - Top = 94 + Top = 113 Width = 117 BorderSpacing.Top = 2 Caption = 'Description (Optional)' @@ -253,7 +253,7 @@ object HotKeyForm: THotKeyForm Left = 4 Height = 23 Hint = 'When autogenerating a trainer this field will be used as description' - Top = 111 + Top = 130 Width = 235 Anchors = [akTop, akLeft, akRight] BorderSpacing.Top = 2 @@ -261,6 +261,17 @@ object HotKeyForm: THotKeyForm ShowHint = True TabOrder = 4 end + object cbOnlyWhileDown: TCheckBox + AnchorSideLeft.Control = cbFreezedirection + AnchorSideTop.Control = cbFreezedirection + AnchorSideTop.Side = asrBottom + Left = 4 + Height = 19 + Top = 67 + Width = 281 + Caption = 'Only while hotkey is down/Restore when released' + TabOrder = 5 + end end object lblActivateSound: TLabel AnchorSideLeft.Control = Panel3 @@ -271,7 +282,7 @@ object HotKeyForm: THotKeyForm AnchorSideBottom.Control = cbActivateSound Left = 300 Height = 15 - Top = 3 + Top = 7 Width = 79 Anchors = [akLeft, akBottom] BorderSpacing.Left = 8 @@ -285,7 +296,7 @@ object HotKeyForm: THotKeyForm AnchorSideTop.Side = asrBottom Left = 300 Height = 23 - Top = 20 + Top = 24 Width = 149 Anchors = [akLeft] BorderSpacing.Top = 2 @@ -308,7 +319,7 @@ object HotKeyForm: THotKeyForm AnchorSideTop.Side = asrCenter Left = 451 Height = 22 - Top = 20 + Top = 24 Width = 23 BorderSpacing.Left = 2 Enabled = False @@ -356,7 +367,7 @@ object HotKeyForm: THotKeyForm AnchorSideTop.Side = asrBottom Left = 300 Height = 15 - Top = 68 + Top = 72 Width = 91 BorderSpacing.Top = 2 Caption = 'Deactivate sound' @@ -371,7 +382,7 @@ object HotKeyForm: THotKeyForm AnchorSideRight.Side = asrBottom Left = 300 Height = 23 - Top = 85 + Top = 89 Width = 149 Anchors = [akTop, akLeft, akRight] BorderSpacing.Top = 2 @@ -394,7 +405,7 @@ object HotKeyForm: THotKeyForm AnchorSideTop.Side = asrCenter Left = 451 Height = 22 - Top = 85 + Top = 89 Width = 23 BorderSpacing.Left = 2 Enabled = False @@ -444,7 +455,7 @@ object HotKeyForm: THotKeyForm AnchorSideRight.Side = asrBottom Left = 300 Height = 23 - Top = 43 + Top = 47 Width = 149 Anchors = [akTop, akLeft, akRight] ParentShowHint = False @@ -459,7 +470,7 @@ object HotKeyForm: THotKeyForm Left = 451 Height = 19 Hint = 'Tries to set the language of the windows speech synthesizer to English when speaking this. Won''t speak if there is no English voice installed' - Top = 45 + Top = 49 Width = 90 BorderSpacing.Left = 2 Caption = 'Force English' @@ -478,7 +489,7 @@ object HotKeyForm: THotKeyForm AnchorSideRight.Side = asrBottom Left = 300 Height = 23 - Top = 108 + Top = 112 Width = 149 Anchors = [akTop, akLeft, akRight] ParentShowHint = False @@ -493,7 +504,7 @@ object HotKeyForm: THotKeyForm Left = 451 Height = 19 Hint = 'Tries to set the language of the windows speech synthesizer to English when speaking this. Won''t speak if there is no English voice installed' - Top = 110 + Top = 114 Width = 90 BorderSpacing.Left = 2 Caption = 'Force English' @@ -508,7 +519,7 @@ object HotKeyForm: THotKeyForm object Panel2: TPanel Left = 1 Height = 33 - Top = 174 + Top = 193 Width = 580 Align = alBottom AutoSize = True diff --git a/Cheat Engine/HotKeys.pas b/Cheat Engine/HotKeys.pas index 72b7d8e6e9..3c850c1234 100755 --- a/Cheat Engine/HotKeys.pas +++ b/Cheat Engine/HotKeys.pas @@ -31,6 +31,7 @@ THotKeyForm = class(TForm) cbFreezedirection: TComboBox; cbForceEnglishActivate: TCheckBox; cbForceEnglishDeactivate: TCheckBox; + cbOnlyWhileDown: TCheckBox; edtActivateText: TEdit; edtDeactivateText: TEdit; edtDescription: TEdit; @@ -123,6 +124,8 @@ implementation rsTextToSpeechHint = 'The text to speak'#13#10'{Description} = The description of the hotkey'#13#10'{MRDescription} = The description field of the memory record'#13#10'{MRValue} = The value of the memory record'; rsDefaultActivated = '%s Activated'; rsDefaultDeactivated = '%s Deactivated'; + rsDeactivateOnRelease = 'Deactivate on release'; + rsRestoreToOriginalOnRelease = 'Restore to original on release'; function THotkeyform.getBtnOKCustomButton: TCustomButton; @@ -343,10 +346,11 @@ procedure THotKeyForm.btnApplyClick(Sender: TObject); hk.action:=getHotkeyAction; hk.value:=edtFreezeValue.text; hk.fdescription:=edtDescription.text; + hk.fOnlyWhileDown:=cbOnlyWhileDown.checked; hk.registerkeys; end else - hk:=memrec.Addhotkey(keys, getHotkeyAction, edtFreezeValue.text, edtDescription.text ); + hk:=memrec.Addhotkey(keys, getHotkeyAction, edtFreezeValue.text, edtDescription.text, cbOnlyWhileDown.checked ); @@ -447,11 +451,30 @@ procedure THotKeyForm.cbFreezedirectionSelect(Sender: TObject); begin onpossible:=cbFreezeDirection.itemindex in [0,1]; offpossible:=cbFreezeDirection.itemindex in [0,2]; + + if onpossible then + begin + cbOnlyWhileDown.Caption:=rsDeactivateOnRelease; + cbOnlyWhileDown.visible:=true; + end + else + cbOnlyWhileDown.visible:=false; end else begin onpossible:=cbFreezeDirection.itemindex in [0,1,2,3,5,6,7]; offpossible:=cbFreezeDirection.itemindex in [0,1,2,4]; + + if cbFreezeDirection.itemindex in [0,1,2,3,5] then + begin + case cbFreezeDirection.itemindex of + 0, 1, 2, 3: cbOnlyWhileDown.Caption:=rsDeactivateOnRelease; + 5: cbOnlyWhileDown.Caption:=rsRestoreToOriginalOnRelease; + end; + cbOnlyWhileDown.visible:=true; + end + else + cbOnlyWhileDown.visible:=false; end; lblActivateSound.enabled:=onpossible; @@ -462,6 +485,8 @@ procedure THotKeyForm.cbFreezedirectionSelect(Sender: TObject); cbDeactivateSound.enabled:=offpossible; sbPlayDeactivate.enabled:=offpossible; + + end; procedure THotKeyForm.cbPlaySoundChange(Sender: TObject); diff --git a/Cheat Engine/MemoryRecordUnit.pas b/Cheat Engine/MemoryRecordUnit.pas index 97eae42ce1..3f481108f7 100755 --- a/Cheat Engine/MemoryRecordUnit.pas +++ b/Cheat Engine/MemoryRecordUnit.pas @@ -290,10 +290,11 @@ TMemoryRecord=class function hasHotkeys: boolean; - function Addhotkey(keys: tkeycombo; action: TMemrecHotkeyAction; value, description: string): TMemoryRecordHotkey; + function Addhotkey(keys: tkeycombo; action: TMemrecHotkeyAction; value, description: string; onlyWhileDown: boolean=false): TMemoryRecordHotkey; function removeHotkey(hk: TMemoryRecordHotkey): boolean; procedure DoHotkey(hk :TMemoryRecordHotkey); //execute the specific hotkey action + procedure DoHotkeyDisable(hk :TMemoryRecordHotkey); //disable the specific hotkey procedure disablewithoutexecute; @@ -389,20 +390,27 @@ TMemoryRecordHotkey=class fdeactivateSound: string; fActivateSoundFlag: THKSoundFlag; fDeactivateSoundFlag: THKSoundFlag; + fValueAtActivation: string; public fID: integer; fDescription: string; + fOnlyWhileDown: boolean; fOwner: TMemoryRecord; keys: Tkeycombo; fAction: TMemrecHotkeyAction; fValue: string; + Down: boolean; + + + procedure playActivateSound; procedure playDeactivateSound; procedure doHotkey; + procedure doHotkeyDisable; procedure registerKeys; constructor create(AnOwner: TMemoryRecord); destructor destroy; override; @@ -415,6 +423,7 @@ TMemoryRecordHotkey=class property Description: string read fDescription write fDescription; property Action: TMemrecHotkeyAction read fAction write fAction; property Value: string read fValue write fValue; + property OnlyWhileDown: boolean read fOnlyWhileDown write fOnlyWhileDown; property Owner: TMemoryRecord read fOwner; property ID: integer read fID; property OnHotkey: TNotifyEvent read fOnHotkey write fOnHotkey; @@ -572,8 +581,6 @@ function TMemrecOffset.getOffset(currentBase: ptruint): integer; if luaref=-1 then begin - //todo: add previous offset results that can be referenced - foffset:=symhandler.getAddressFromName(text, false, finvalid); if finvalid then setoffsetText(text); @@ -720,6 +727,15 @@ procedure TMemoryRecordHotkey.registerKeys; RegisterHotKey2(mainform.handle, -1, keys, self); end; +procedure TMemoryRecordHotkey.doHotkeyDisable; +begin + if Down then + begin + owner.DoHotkeyDisable(self); + down:=false; + end; +end; + procedure TMemoryRecordHotkey.doHotkey; begin if assigned(fonhotkey) then @@ -728,8 +744,12 @@ procedure TMemoryRecordHotkey.doHotkey; if owner<>nil then //just be safe (e.g other app sending message) owner.DoHotkey(self); + down:=true; + if assigned(fonPostHotkey) then fOnPostHotkey(self); + + end; procedure TMemoryRecordHotkey.playActivateSound; @@ -1549,6 +1569,10 @@ procedure TMemoryRecord.setXMLnode(CheatEntry: TDOMNode); if tempnode.ChildNodes[i].NodeName='Hotkey' then begin + a:=tempnode2.Attributes.GetNamedItem('OnlyWhileDown'); + if (a<>nil) then + hk.OnlyWhileDown:=a.TextContent='1'; + hk.value:=''; ZeroMemory(@hk.keys,sizeof(TKeyCombo)); @@ -1969,6 +1993,13 @@ procedure TMemoryRecord.getXMLNode(node: TDOMNode; selectedOnly: boolean); begin hk:=hks.AppendChild(doc.CreateElement('Hotkey')); hk.AppendChild(doc.CreateElement('Action')).TextContent:=MemRecHotkeyActionToText(hotkey[i].action); + if hotkey[i].OnlyWhileDown then + begin + a:=doc.CreateAttribute('OnlyWhileDown'); + a.TextContent:='1'; + hk.Attributes.SetNamedItem(a); + end; + hkkc:=hk.AppendChild(doc.createElement('Keys')); j:=0; while (j<5) and (hotkey[i].keys[j]<>0) do @@ -2181,7 +2212,7 @@ function TMemoryRecord.getuniquehotkeyid: integer; end; end; -function TMemoryRecord.Addhotkey(keys: tkeycombo; action: TMemrecHotkeyAction; value, description: string): TMemoryRecordHotkey; +function TMemoryRecord.Addhotkey(keys: tkeycombo; action: TMemrecHotkeyAction; value, description: string; onlyWhileDown: boolean=false): TMemoryRecordHotkey; { adds and registers a hotkey and returns the hotkey index for this hotkey return -1 if failure @@ -2196,6 +2227,7 @@ function TMemoryRecord.Addhotkey(keys: tkeycombo; action: TMemrecHotkeyAction; v hk.action:=action; hk.value:=value; hk.fdescription:=description; + hk.fOnlyWhileDown:=onlyWhileDown; hk.RegisterKeys; result:=hk; @@ -2286,10 +2318,25 @@ procedure TMemoryRecord.disablewithoutexecute; {$ENDIF} end; +procedure TMemoryRecord.DoHotkeyDisable(hk :TMemoryRecordHotkey); //disable the specific hotkey +begin + if (hk<>nil) and (hk.owner=self) and (hk.OnlyWhileDown) then + begin + try + case hk.Action of + mrhActivate, mrhToggleActivation, mrhToggleActivationAllowIncrease, mrhToggleActivationAllowDecrease: active:=false; + mrhSetValue: setvalue(hk.fValueAtActivation); + end; + + except + end; + end; +end; + procedure TMemoryRecord.DoHotkey(hk: TMemoryRecordhotkey); var oldstate: boolean; begin - if (hk<>nil) and (hk.owner=self) then + if (hk<>nil) and (hk.owner=self) and (hk.down=false) then begin try case hk.action of @@ -2311,6 +2358,9 @@ procedure TMemoryRecord.DoHotkey(hk: TMemoryRecordhotkey); mrhSetValue: begin + if hk.down=false then + hk.fValueAtActivation:=GetValue; + SetValue(hk.value); hk.playActivateSound; @@ -2598,7 +2648,7 @@ procedure TMemoryRecord.setActive(state: boolean); else begin autoassemblerdata.lastExecutionFailed:=true; - autoassemblerdata.lastExecutionFailedReason:='Unknown'; + autoassemblerdata.lastExecutionFailedReason:=rsUnknown; end; except //running the script failed, state unchanged diff --git a/Cheat Engine/hotkeyhandler.pas b/Cheat Engine/hotkeyhandler.pas index 7093b0abc5..6230b92b9d 100755 --- a/Cheat Engine/hotkeyhandler.pas +++ b/Cheat Engine/hotkeyhandler.pas @@ -48,6 +48,7 @@ Thotkeythread=class(tthread) mainformhotkey2command: integer; procedure memrechotkey; + procedure memrechotkeydisable; procedure handleGenericHotkey; procedure mainformhotkey2; public @@ -617,6 +618,15 @@ procedure Thotkeythread.memrechotkey; TMemoryRecordHotkey(memrechk).DoHotkey; end; +procedure Thotkeythread.memrechotkeydisable; +begin +// sendmessage(mainform.handle,integer(cefuncproc.WM_HOTKEY2),0,ptrUint(memrechk)); + + //not 100% sure why sendmessage works here but not from within the thread... + //but since we're here anyhow: + TMemoryRecordHotkey(memrechk).DoHotkeyDisable; +end; + procedure Thotkeythread.handleGenericHotkey; begin if assigned(generichk.onNotify) then @@ -695,7 +705,14 @@ TActiveHotkeyData=record //structure to hold hotkey and keycount end else + begin hotkeylist[i].lastactivate:=0; //not currently down. The user released the key so repeat can be skipped + if (hotkeylist[i].memrechotkey<>nil) and TMemoryrecordHotkey(hotkeylist[i].memrechotkey).down and TMemoryrecordHotkey(hotkeylist[i].memrechotkey).OnlyWhileDown then + begin + memrechk:=hotkeylist[i].memrechotkey; + synchronize(memrechotkeydisable); + end; + end; end;