[Solved] Help with a python script

I’m trying to create a combo hit script that I can reuse.

I’m sure you’ve seen this before. “God Of War” / “Jak and Daxter” etc. Where you fight an enemy and. . .

You have to press the correct key, in the correct time frame to get a hit. If you get all three, you get a super hit that greatly decreases the enemy health, and gives you more points. If you hit the wrong key, or not in time, you lose health, and the enemy gains back it’s full health, or whatever.

In this script I set up a combination of Ckey, Bkey, vkey. (see Blend file)

I’m wondering if the script is written correctly, or is there a better way to do this.

and, see where I used “def” to make functions (commented out). is there a way to call on these functions if the conditions are right. And reuse these functions in a different order.
So instead of using a property “obj[‘totals’]”. call the funtion directly?

Does this make any sense? Hope so.

Any help is appreciated, even if it’s “out of the box” so to speak.

In the Blend, when you press “P” be patient, I have the timer set really slow, so it takes a few sec before the “C” spawns.

import bge

def add(cont):
    

    obj = cont.owner
    sce = bge.logic.getCurrentScene()
    E1 = sce.objects['Empty_1']
    E2 = sce.objects['Empty_2']
    E3 = sce.objects['Empty_3']
    
    cee = bge.logic.keyboard.events[bge.events.CKEY]
    vee = bge.logic.keyboard.events[bge.events.VKEY]
    bee = bge.logic.keyboard.events[bge.events.BKEY]
    ay = bge.logic.keyboard.events[bge.events.AKEY]
        
    
#def cee(cont):    

    if not 'init' in obj: # create properties
         obj['init'] = 1
         obj['timer'] = 0.0
         obj['totals'] = 0
         

    obj['timer'] += 1.0 / bge.logic.getLogicTicRate()  # starts the timer 
    
    if obj['totals'] == 0:
        if obj['timer'] > 5.0 and obj['timer'] < 10.0:
             sce.addObject("C", E2, 2) # spawns first key
             
        if cee and obj['timer'] > 5.0 and obj['timer'] < 10.0:
             print ("on time")
             obj['totals'] = 1
             sce.addObject("hit", obj, 10)
             obj['timer'] = 0.0
             #go to the next function (bee)
             
        elif cee and obj['timer'] > 0.0 and obj['timer'] < 4.0:
            print ("too early")
            # bring up "failed" overlay scene
            # remove this scene
            
        elif obj['timer'] > 10.1 and cee:
            print ("too late")
            # bring up "failed" overlay scene
            # remove this scene    
            
        elif bee or vee:
            print ("wrong key")
            # bring up "failed" overlay scene
            # remove this scene
            
    
         
        
#def bee(cont):
    
    if obj['totals'] == 1: 
        if not 'init' in obj: # create properties
             obj['init'] = 1
             obj['timer'] = 0.0

        obj['timer'] += 1.0 / bge.logic.getLogicTicRate()  # starts the timer 
        
        if obj['timer'] > 5.0 and obj['timer'] < 10.0:
             sce.addObject("B", E3, 2) # spawns 2nd key
             
        if bee and obj['timer'] > 5.0 and obj['timer'] < 10.0:
             print ("on time")
             obj['totals'] = 2
             obj['timer'] = 0.0
             sce.addObject("hit",obj,10)
             #go to the next function (vee)
             
        elif bee and obj['timer'] > 0.0 and obj['timer'] < 4.0:
            print ("too early")
            # bring up "failed" overlay scene
            # remove this scene
            
        elif obj['timer'] > 10.1 and bee:
            print ("too late")
            # bring up "failed" overlay scene
            # remove this scene    
            
        elif cee or vee:
            print ("wrong key")
            # bring up "failed" overlay scene
            # remove this scene 
        
##def vee(cont):    
    if obj['totals'] == 2:
        if not 'init' in obj: # create properties
             obj['init'] = 1
             obj['timer'] = 0.0

        obj['timer'] += 1.0 / bge.logic.getLogicTicRate()  # starts the timer 
        
        if obj['timer'] > 5.0 and obj['timer'] < 10.0:
             sce.addObject("V", E1, 2) # spawns 3rd key
             
        if vee and obj['timer'] > 5.0 and obj['timer'] < 10.0:
             print ("on time")
             obj['totals'] = 3
             sce.addObject("hit",obj,10)
             #combo completed
             
        elif vee and obj['timer'] > 0.0 and obj['timer'] < 4.0:
            print ("too early")
            # bring up "failed" overlay scene
            # remove this scene
            
        elif obj['timer'] > 10.1 and vee:
            print ("too late")
            # bring up "failed" overlay scene
            # remove this scene    
            
        elif cee or bee:
            print ("wrong key")
            # bring up "failed" overlay scene
            # remove this scene 

                  
        if obj['totals'] == 3:   
            obj.sendMessage("superduperpowerhit")#changes player to a state that plays the superduperpowerhit animation
            # remove this scene

http://pasteall.org/blend/index.php?id=50126
BF 2.78

This script and stuff will be on an overlay scene that will be called when the enemys health decreases a few hp’s.

I have each move pop into a cooldown state that holds possible key presses and timing ranges,

if the key is in the list it then calls that state (in python) I use functions as states with a system I call an ‘actStrip’

I am quite drunk. Hope this helps tho.

#----------------------------------------------------------------------
def getRandomKeyFromList(keyList):
    from random import randint
    random_num = randint(0,len(keyList)-1)
    rightKey = keyList.pop(random_num)
    return rightKey,keyList
#----------------------------------------------------------------------
def getIfAnyKey(keyList):
    for key in keyList:
        if key:
            return True
    return False
#----------------------------------------------------------------------
def quickTimeEvent(rightKey,wrongKeys,timer,min,max):
    rightTime = timer_min < timer < timer_max
    wrongButton = getIfAnyKey(wrongKeys)
    condition = (rightTime) and (rightKey)
#------------------
    if condition:
        functionName(first_argument,secnd_argument(...),nth_argument)
#------------------
    elif not rightTime:
        if wrongButton:
            print("Wrong key!")
        elif rightKey:
            print("Your timing was off!")
#----------------------------------------------------------------------
def main(cont):
    own = cont.owner
    own["timer"] += 1.0 / bge.logic.getLogicTicRate()
    cee = bge.logic.keyboard.events[bge.events.CKEY]
    vee = bge.logic.keyboard.events[bge.events.VKEY]
    bee = bge.logic.keyboard.events[bge.events.BKEY]
    ay = bge.logic.keyboard.events[bge.events.AKEY]
#------------------
    keyList = [cee,vee,bee,ay]
    rightKey,wrongKeys = getRandomKeyFromList(keyList)
    quickTimeEvent(rightKey,wrongKeys,timer,5.0,10.0)
#----------------------------------------------------------------------

NINJAEDIT: Just clarifying the fact, that rum is good.

@BPR
That’s kind of what I want. I don’t want to use any logic bicks except one on an empty to call the script. I have nothing against logic bricks, it’s just for learning purposes.

Oh yeah, I agree. I love Captain Morgan spiced rum. Also the cannonball rum.
I drink for medicinal purposes. wink, wink,

So many questions, but let me experiment with this first. Maybe i won’t have to bug you guys so much.

Return True, return False? If a key is pressed, = True, if it isn’t it’s false? is how that works.

so if do;

def rightcondition():

	Armature.playAction("powerhit", 1, 40, blah, blah,) #players animation (of course Armature,and enemy would be defined.
	enemy['enhp'] = - 10 # enemy health minus 10
	etc.

I would call this like this;???

if condition:
        rightcondition(first_argument,secnd_argument(...),nth_argument)

If so, what’s the first_argument, so on??

this is a interesting problem, here is my attempt to make something that supports multiple combos.

## Pure Python

combos = {}
combos["vdc"] = {"reward":""}

def checkcombo(current,keypress):
    tmp = current + keypress
    for combo in combos:
        if tmp in combo:
             return tmp

        
current = ""
for _ in range(3):
    keypress = input(">")
    
    if len(keypress) == 1:
        out = checkcombo(current,keypress)
        
        if out:
            current = out
            if current in combos:
                print(current,combos[current])
        else:
            print("Fail")
            break
    else:
        print("Fail")
        break


@Edderkop
Thanks for helping. What is vdc and reward, I don’t see it defined.

Wow, this is complex. I have a lot of home work to do. :slight_smile:

the keys in that dict is your key combos so the vdc stands for the vkey,dkey and ckey and the reward is whatever you want it to be

OK. let me see if can something working with all this info.

Say f(x) equals x*2. x is the argument of the function; input. you hand over a value, and the function does things with it.

return is output. it exits the function and returns a value.

I can’t really explain much with words so I’m just going to type code.

def playAnim(Armature,animName,frameStart,frameEnd):
    Armature.playAction(animName,frameStart,frameEnd)
    if True:
        return "Dope"
    print("This statement will not ever be seen on your console.")

eval = True
if eval:
    arma = scene.objects["Armature"]
    ans, x, y = "powerhit", 1, 40
    some_string = playAnim(arma,ans,x,y)
    print(some_string)

>>>"Dope"

Got it. :slight_smile: Thank you very much for helping.
And thanks to every one that helped. I’ll mark it solved.

I use python functions as states and store a list of them

actor[‘actStrip’]= [ [‘stateName’, dataForState] , [‘state2Name’, dataForState2] ]

like

badGuy[‘actStrip’] = [ [‘navigate’, target], [‘dialog’, string], [‘ThrowNade’, target]]

would make a actor walk to a mark - say a line and throw a grenade.

but it can also call things like

[‘punch’, strength]

that automatically insert [‘CoolDown’, [duration,possibleMoves] ]

like

possibleMoves =[ [ ‘SuperPunch’, [Time, button] ], [‘SweepKick’, [Time,button] ]

and if triggered it just pops then new state into the act strip -

I call them like this


def stateFunction(args):
    doStuff()
    proceessInputOrNot()
    exitConditions()

stateDict = {  'StateFunction' , StateFunciton }
    
def main():
    if 'ActStrip' not in actor:
        proccessInput()
        playAnimations() 
        #etc 
    elif len(actor['ActStrip'])>=1:
        stateData = actor['ActStrip'][0]
        functionString = stateData[0]
        function = stateDictionary[functionString] 
        function(stateData[1])
    else:
        del actor['ActStrip']

Thanks for this BPR. I’m gaining. :slight_smile: now, how to implement all this power for good. LOL