release: InputSequence Module (cheat codes!!)

BlitzMax Forums/BlitzMax Programming/release: InputSequence Module (cheat codes!!)

jondecker76(Posted 2010) [#1]
I have depreciated my proof-of-concept cheat module, and replaced it with this more generalized module.

This module allows you to build "Input Sequences" and act on them. It allows you to add cheat-codes to your games simply, and easily. It is also great for adding "special moves" to games like fighting games.

Currently, keyboard input, joystick input and mouse input are all supported. Macros are also fully supported (this means that you can assign several keys/buttons to one step of the overall sequence, requiring the user to hit the keys/buttons at the same time)! Furthermore, all input types (keyboard,mouse and joystick) can be "inter-mingled" allowing you to create complex input sequences that could require all 3 input devices to enter successfully! This is the only module of its kind that I know of, and it allows you to add these types of input sequences easily in your own games!

You can download jmd.inputsequence here http://code.google.com/p/jmd-blitzmax-modules/downloads/list

Here is a sample of its usage from the documentation:
SuperStrict

Import jmd.inputsequence



'Create a familiar "up,up,down,down,left,right,left,right,B,A,Enter" cheat code
Global livesCheat:TInputSequence = CreateInputSequence()
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_UP)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_UP)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_DOWN)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_DOWN)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_LEFT)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_RIGHT)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_LEFT)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_RIGHT)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_B)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_A)
InSeqAddStroke(livesCheat,KEY_STROKE,KEY_ENTER)


'Create a  "God-Mode" cheat using InSeqAddKeyStrokesFromString()
'activated by typing "heaven" on the keyboard
Global godCheat:TInputSequence = CreateInputSequence()
InSeqAddKeyStrokesFromString(godCheat,"heaven")


'create an "add ammo" cheat that has some macro strokes!
'Activated by: KEY_UP+KEY_LEFT,KEY_SPACE,KEY_X (note that the first stroke is a macro of pressing 2 keys at once!)
Global ammoCheat:TInputSequence = CreateInputSequence(2000) 'Give a little extra time per stroke!
InSeqAddStroke(ammoCheat,KEY_STROKE,KEY_UP,1) 		'Notice that we are now specifying stroke numbers!
InSeqAddStroke(ammoCheat,KEY_STROKE,KEY_LEFT,1)		'KEY_UP and KEY_LEFT are now a "macro-stroke" for the first stroke!
InSeqAddStroke(ammoCheat,KEY_STROKE,KEY_SPACE,2)
InSeqAddStroke(ammoCheat,KEY_STROKE,KEY_X)			'Didn't specify the stroke on this one, which puts it in Auto mode...
													'This means that is will automatically be assigned the next stroke number (which would be 3 in this case)
													
'Create a "super-punch" special move
'activated by LMB,LMB,RMB,LMB,KEY_SPACE
'(LMB is Left Mouse Button, RMB is Right Mouse Button)
Global superPunch:TInputSequence = CreateInputSequence()
InSeqAddStroke(superPunch,MOUSE_STROKE,1)
InSeqAddStroke(superPunch,MOUSE_STROKE,1)
InSeqAddStroke(superPunch,MOUSE_STROKE,2)
InSeqAddStroke(superPunch,MOUSE_STROKE,1)
InSeqAddStroke(superPunch,KEY_STROKE,KEY_SPACE)




'We are starting with 3 lives
Local lives:Int = 3
'We are starting with 100 rounds of ammo
Local ammo:Int= 100

Local godModeString:String = "God Mode Active!!"

'Lets use a fun sound effect for when we perform the Livescheat code properly!
Local sndCredit:TSound=LoadSound("credit.wav")

Local kerplowTimestamp:Int





'Main loop
Graphics 640,480
While Not KeyDown(KEY_ESCAPE)
	Cls
	DrawText "Lives: " + lives, 10,10
	DrawText "Ammo: " + ammo, 500,10
	
	
	
	InSeqUpdateAll() 'must call this every iteration!!!
	
	'god mode cheat
	InSeqSuccessful(godCheat)
	If InSeqEntered(godCheat)>0 
		SetColor 255,0,0
		DrawText godModeString,GraphicsWidth()/2-TextWidth(godModeString)/2,10
		SetColor 255,255,255
	EndIf
	
	
	'ammo cheat
	If InSeqSuccessful(ammoCheat)
		If InSeqEntered(ammoCheat)>1
			Print "Oops! You can only do the ammo cheat once!"
		Else
			PlaySound sndCredit
			ammo=9999
		EndIf
	EndIf
	
	
	
	'lives cheat
	If InSeqSuccessful(livesCheat)
		PlaySound(sndCredit)
		lives:+ 30
	EndIf
	
	
	
	'Super punch sequence!
	If InSeqSuccessful(superPunch) Then kerplowTimestamp=MilliSecs()
	If InSeqEntered(superPunch)
		SetColor 255,0,0
		Local scale:Float=Sin((MilliSecs()/50)*10)
		SetScale Abs(scale)+1,Abs(scale)+1
		DrawText "KERPLOW!!!",GraphicsWidth()/2-TextWidth("KERPLOW!!")/2,GraphicsHeight()/2
		SetScale 1,1
		SetColor 255,255,255
		If MilliSecs() - kerPlowTimestamp > 3000 Then InSeqResetEntered(superPunch)
	EndIf
	
	
	ShowDebugInfo()
	Flip
Wend

End

Function ShowDebugInfo()
	DrawText "livesCheat: " + livesCheat.strokeCounter + " out of " + livesCheat.numStrokes + " strokes.",10,400
	DrawText "godCheat: " + godCheat.strokeCounter + " out of " + godCheat.NumStrokes + " strokes.",10,420
	DrawText "ammoCheat: " + ammoCheat.strokeCounter + " out of " + ammoCheat.numStrokes + " strokes.",10,440
	DrawText "superPunch: " + superPunch.StrokeCounter + " out of " + superPunch.numStrokes + " strokes.",10,460
End Function



Nate the Great(Posted 2010) [#2]
what if i have two players on joysticks and I want to determine wich one did the cheat?


jondecker76(Posted 2010) [#3]
hmm.. Good point, looks like I should add that ability!


jondecker76(Posted 2010) [#4]
I'll have a new release tomorrow that includes multiple joystick support. I just finished the implementation but I'm going to take some time to test it.

Changes in the usage will be very very minimal! The only difference in usage is that you will mask the joystick port with the JOY_STROKE constant! (They will be Or'd together).. So for joystick port 0, the example in the first post will run with no changes. To add a joystick stroke for port #1, it will be as simple as:
InSeqAddStroke(superPunch,JOY_STROKE | 1,1)


With that being said, in a multiple joystick situation, a new TInputSequence will need to be created for each joystick. This initially sounds bad, until you realize that you can make it very easy:
'Create a "extra lives" cheat for each joystick!
Local livesCheat:TInputSequence[JoyCount()]
For Local thisJoy:Int = 0 Until JoyCount()
     livesCheat[thisJoy] = CreateInputSequence()
	InSeqAddStroke(livesCheat,JOY_STROKE | thisJoy,0)
	InSeqAddStroke(livesCheat,JOY_STROKE | thisJoy,2)
	InSeqAddStroke(livesCheat,JOY_STROKE | thisJoy,1)
	InSeqAddStroke(livesCheat,JOY_STROKE | thisJoy,1)
Next
...
...
...
InSeqUpdateAll()
For Local thisJoy:Int=0 Until JoyCount()
	If InSeqSuccessful(livesCheat[thisJoy])
		Print "Lives Cheat entered successfully for joystick #" + thisJoy
	EndIf
Next


I will make another example to the documentation which shows how to do this...



On a happy note, due to the internal changes to the module, multiple mice and multiple keyboards would also be easy to add support for in the future :)