#=============================================================================== #Global states (not halted by pause/superPause, no helper limitations) #=============================================================================== [StateDef -4] if stateNo = 100 && roundState != 2 && aiLevelF { changeState{value: 0; ctrl: 1} } # this ZSS AI file is used to define and implement AI for kung fu man. #it can also be used a guide for you to create your own AI using IKEMEN GO. #------------|dis values|------------------------------------------------------- #This code will calculate a "velocity" even if the opponent uses posadds for movement. ignoreHitPause if gameTime%2 = 0 { mapSet{map: "ppx"; value: p2,pos x} } #=============================================================================== #Global states (commands) #=============================================================================== [StateDef -1] #This is used to prevent undesirable actions after getting up from a knock down for a short amount of time if anim = 5120 || roundState != 2 { #getuprecoverytime mapSet{map: "gurt"; value: 10} } #global AI loop ignoreHitPause if aiLevelF && roundState = 2 && !standby { #prevent default jump behavior assertSpecial{flag: nojump; flag2: noairjump} #prevent default walk behavior assertSpecial{flag: nowalk; flag2: nobrake} #------------|AI variable declarations|----------------------------------------- let inrange = 0; #get all lights let lights = stateNo = 200 || stateNo = 230 || stateNo = 400 || stateNo = 430; #get all heavies that can cancel let heavy = stateNo = 210 || stateNo = 240 || stateNo = 410; #opponent is not in air or lying down let grounded = p2StateType = S || p2StateType = C; #Super cancel flag let SC = stateNo = [1000, 1420] && stateType != A && map(canCombo); #CC - CanCombo, this variable checks and returns the current amount of hitstun the opponent is in. # because KFM has no projectiles, we can easily detect if he has a target to accomplish this. let CC = cond(numTarget, cond(!p2,hitFall, target,getHitVar(hittime), getHitVar(fall.recovertime)), 0); #typically you could check the velocity of the opponent to determine how fast they are moving #however, if they use posadds to move instead, the vel will remain 0. Using some trickery we can determine the position based velocity #using this code below because if the opponent has moved position on the x-axis, we can check 1 frame later to determine how far they moved. #if they have not moved, we can try to track velocity instead. let trvelx = cond((abs(map(ppx)) - abs(p2,pos x)) = 0 || p2,vel x > (abs(map(ppx)) - abs(p2,pos x)), p2,vel x, (abs(map(ppx)) - abs(p2,pos x))); #game specific values let nojug = p2,anim = 5120 || p2StateNo = 5040 && p2,ctrl || p2StateNo = 52 && p2,time < 3 && p2,prevStateNo = 5040; #how many points do we have to juggle with? let jugpt = map(jug); let hitfall = p2,hitFall || $CC > 8; #Allows the AI to possibly link attacks if they have less recovery than the opponent. if ctrl && !p2,ctrl && (p2,getHitVar(hittime) > 0) { let AI_JI = p2,getHitVar(hittime); } #things to do in neutral(not attacking) #Neutral attacks and combo conditions are separated to prevent accidental code preventing either from working #properly. if (ctrl && stateNo != 105 || stateNo = 20 || stateNo = 100 || stateNo = 1310 || stateNo = 1330 || stateNo = 1330 || stateNo = 1350) { if stateType != A { #--|Reversals|----------------------------------------------------------- if (p2MoveType = A) && p2,time > 1 { #------------|SUPERS|--------------------------------------------------- if power >= 1000 && p2,alive { if (p2BodyDist x = [-10, (35+floor($trvelx*.4)*3)] &&(!$grounded && p2BodyDist y = [-80+(floor(p2,vel y*.4)*-5), -15] || $grounded)) { changeState{value: 3050} } #Tripple Kung Fu Palm #This first condition checks for if the opponent is in range of the attack hitting, it adds the opponents current velocity #to determine if they would be hit by them moving closer while attacking. This can be set to any range if you are using this #as an example. if (p2BodyDist x = [30*($hitfall)-36, (90+floor($trvelx*.4)*5)] && (p2BodyDist y = [-50+(floor(p2,vel y*.4)*-5), -15] || $grounded) && (p2StateNo != 5040 && p2MoveType != H || !$grounded && p2BodyDist y = [-50, -15])) && power >= 1000 { changeState{value: 3000} } } #------------------------------------------------------------------------- #Kung Fu Knee if p2StateType = A && p2BodyDist x = [40*($hitfall)-30, (50+floor($trvelx*.4)*10)] && p2BodyDist y = [-80+(floor(p2,vel y*.4)*-5), -60+($hitfall)*40] && (p2StateNo != 5040 && p2MoveType != H || !$grounded && p2BodyDist y = [-60, -15]) && (!map(gurt) || p2BodyDist x > 30) && random <= (350 * (aiLevelF ** 2 / 48.0)) { if power >= 500 && p2,alive && random%3 = 1 && p2BodyDist y < -70 { let version2 = 1070; } else if p2,vel x > 0 && p2BodyDist y < -70 { let version2 = 1060; } else { let version2 = 1050; } changeState{value: $version2} } #----------------------------------------------------------------------- #Kung Fu Blocking #This is a command parry that kung fu man has, from an AI perspective, it can be challenging to indicate when it should be used. #For now, this is the most case handling we will attempt. We start by checking if they are moving or what the attack distance of their #current attack is. We can use that math loosely to determine where their attack is. Because this can make fighting challenging, it is disabled #unless the aiLevelF is 5 or higher if p2BodyDist x = [-15, 30+floor($trvelx*.4)*10+floor(p2,const(size.attack.dist)*.5)] && p2BodyDist y = [-50+(floor(p2,vel y *.6)*-10), 0] && random <= (335 * (aiLevelF ** 2 / 48.0)) && p2MoveType = A && aiLevel > 4 { changeState{value: cond(p2StateType != C,1300,1320)} } } #----------------------------------------------------------------------- #anti air specials are used where it is safe for kfm to try to stop the opponent from jumping in and attacking #because of how they can connect, even on a blocking opponent, it leaves kfm moderately safe and is considered #minimal risk to perform. #Kung Fu Upper #We reduce the chance of this happening to 25% to prevent overusage. if p2StateType = A && p2BodyDist x = [5*($hitfall)-20, (30+floor($trvelx*.4)*20)] && (p2StateNo != 5040 && p2MoveType != H || !$grounded && p2BodyDist y = [-80+(floor(p2,vel y*.6)*-5), -40+($hitfall)*30]) && (!map(gurt) || p2BodyDist x > 30) && random <= (450 * (aiLevelF ** 2 / 48.0)) { #1/3 chance to use ex move when power is at least half of one meter if power >= 500 && p2,alive && random%3 = 1 { let version = 1120; #use this for advancing enemies } else if p2,vel x > 0 { let version = 1110; #default version } else { let version = 1100; } changeState{value: $version} } #----------------------------------------------------------------------- #anti air normals if random <= (420 * (aiLevelF ** 2 / 48.0)) && p2BodyDist x < 45 && p2BodyDist y = [-70+(floor(p2,vel y*.4)*-5), -20] && !$nojug && jugglePoints(p2, ID) = 0 { changeState{value: 410} } #----------------------------------------------------------------------- #throw if random <= (310 * (aiLevelF ** 2 / 48.0)) && stateType = S && stateNo != 100 && (p2MoveType != H || p2StateNo = [120, 131]) && (map(AI_JI) < 2) && p2BodyDist x < 30 && $grounded { changeState{value: 800} } #----------------------------------------------------------------------- #blocking if (p2MoveType = A && prevStateNo != [1300, 1350] && stateNo != [1300, 1350] && inGuardDist && random <= (700 * (aiLevelF ** 2 / 48.0)) || p2,numProj > 0 && random < (440 * (aiLevelF ** 2 / 48.0))) && p2BodyDist x > -20 && p2StateType != L && (ctrl || stateNo = 20 || stateNo = 100) || (p2,numProj >= 1) { assertSpecial{flag: autoguard} changeState{value: 120} } #----------------------------------------------------------------------- #this attack is a special case attack, the angle of attack indicates it can be used #to stop crouching attacking opponents preemptively, so kfm will try to do so when possible. #used to hit crouching attacking opponents from a distance if (p2BodyDist x = [35, 55+(floor($trvelx*.4)*5)]) && p2StateType = C && (p2MoveType = A) && random <= (450 * (aiLevelF ** 2 / 48.0)) { changeState{value: 240} } #----------------------------------------------------------------------- #light attacks (200,230,400,430) if p2BodyDist x < 55 + (floor($trvelx * .4) * 5) && !$AI_JI && !$nojug && (!map(gurt) || p2BodyDist x > 35) && (p2BodyDist x > 25 || random <= (225 * (aiLevelF ** 2 / 48.0)) || p2StateType = A) && (p2StateNo != [1025, 1028] || (p2MoveType != H || $CC > 3 && $hitfall && p2StateNo != [1025, 1028])) { if ($grounded || p2BodyDist y = [-40+(floor(p2,vel y*.4)*-10), -15]) && p2BodyDist x < 45 { let att = cond(p2BodyDist y < -40 || p2StateType = S, 200, 400); if $att = 400 && p2BodyDist x < 35 + (floor($trvelx * .4) * 5) || $att != 400 { changeState{value: $att} } } else if (p2BodyDist x > 25 || random <= (225 * (aiLevelF ** 2 / 48.0))) && $grounded { let att = cond(p2BodyDist y > -10 || p2StateType = S, 430, 230); if $att = 430 && p2BodyDist x < 45 + (floor($trvelx * .4) * 5) || $att != 430 { changeState{value: $att} } } } #----------------------------------------------------------------------- #heavy attacks (210,240) #we do not include 440 or 410 here because they are defined elsewhere in a more #specialized way that focuses on what they are capable of doing in a match. if p2BodyDist x < 60 + (floor($trvelx * .4) * 5) && !$AI_JI && (!$nojug || p2BodyDist y > -10) && (!map(gurt) || p2BodyDist x > 35) && random <= (425 * (aiLevelF ** 2 / 48.0)) && (p2StateNo != [1025, 1028] || p2MoveType != H) { if ($grounded || p2BodyDist y = [-50 + (floor(p2,vel y*.6)*-10), -25]) { let att = cond(p2BodyDist y > -10 || p2StateType = S, 240, 210); if $att = 240 && p2BodyDist x < 45 + (floor($trvelx * .4) * 5) || $att != 240 { changeState{value: $att} } } } #----------------------------------------------------------------------- #jump in landing attacks can be used to start combos from a successful jump attack (600-640) #Using the $AI_JumpIn variable, we can inform the AI about how much time they have to #start a combo by linking a ground attack. if $AI_JI > 9 && p2BodyDist x = [35, 60] && $grounded { changeState{value: cond(p2BodyDist x < 50, 240, 210)} } if $AI_JI > 3 && p2BodyDist x <= 55 && $grounded { changeState{value: cond(p2StateType = S, cond(p2BodyDist x > 40, 230, 200), cond(p2BodyDist x < 30, 400, 430))} } #----------------------------------------------------------------------- #The term "poke" is used to refer to attacks that can usually attack opponents from a safe distance #without high risk. The attacks below meet that criteria but can be changed if more attacks are added later. #pokes if p2BodyDist x = [45, 60] && p2MoveType != H && $grounded && random < (250 * (aiLevelF ** 2 / 48.0)) { if p2BodyDist x = [30, 60+(floor($trvelx*.4)*5)] && random%4 = 0 { let att2 = 210; } else if p2BodyDist x = [30, 50+(floor($trvelx*.4)*5)] && random%4 = 1 { let att2 = 240; } else if p2BodyDist x = [30, 60+(floor($trvelx*.4)*5)] && p2StateType = S { let att2 = 440; } if $att2 > 0 { changeState{value: $att2} } } #----------------------------------------------------------------------- #OTG - attacks that can hit a fallen opponent. if (p2StateType = L || p2StateNo = 52) && jugglePoints(p2, ID) > 2 && p2BodyDist x = [-2, 45] && (!$nojug || p2StateNo = 52) { changeState{value: cond(jugglePoints(p2, ID) > 7 && p2,time < 20, 440, 430)} } #End of file: stateType != A #=========================================================================== #This section of AI handles attacks that are done in the air. } else if stateType = A && p2StateType != L { #kung fu blocking - air if p2BodyDist x = [-15, 35+floor($trvelx*.4)*5+floor(p2,const(size.attack.dist)*.5)] && p2BodyDist y = [-20+(floor(p2,vel y*.4)*-5), 30+(floor(vel y*.4)*5)] && random <= (600 * (aiLevelF ** 2 / 48.0)) && p2MoveType = A { changeState{value: 1340} } #cross up #currently this character has no way to do a cross up(attack that hits behind opponent while you jump) #so this is commented, however you could add that ability right now! If you do you can use this code #to define it. #let cu = p2BodyDist x = [-65, 10]; #if $cu && vel x > 0 && (p2StateNo = 5120 || $grounded && !$nojug) && vel y > 0 { # ChangeState{value: 630} #} #------------|air normal attacks|--------------------------------------- #we do not want kfm to try to hit an attacking opponent using specials because this typically means kfm will lose to it. #However, if it's a lower AI level it's ok to make mistakes, or if kfm is behind the opponent anyway. if (p2,hitDefAttr != SCA,SA || facing != p2,facing || aiLevelF < 6) && random <= (700 * (aiLevelF ** 2 / 48.0)) { #These attacks will have variable y distance detection depending on if the opponent is standing or crouching, it is not perfect #but the illusion of intelligence is all that matters. We do not want kfm to attack characters in a recovering (state 5040) state. #heavy attacks are given priority as they have bigger rewards, but light attacks are faster so both will be taken into account. if (frontEdgeBodyDist < 50 || p2BodyDist x = [-5, (55+(floor($trvelx * .4)*5) + (floor(vel x * .4)*20))]) && (p2BodyDist y > 30 || p2BodyDist y < 0) && p2BodyDist y = [5,40 + ((p2StateType = S || p2StateNo = [5115,5122])*40) + ((p2StateType = C)*25)] && (vel y > 0 || !$grounded && !$nojug) { changeState{value: 640} } if (frontEdgeBodyDist < 50 || p2BodyDist x = [-8, (45+(floor($trvelx * .4)*5) + (floor(vel x * .4)*5))]) && (p2BodyDist y > 30 || p2BodyDist y < 0) && p2BodyDist y = [-20,45 + ((p2StateType = S || p2StateNo = [5115,5122])*40) + ((p2StateType = C)*25)] && (vel y > 0 || !$grounded && !$nojug) { changeState{value: 610} } if (frontEdgeBodyDist < 50 || p2BodyDist x = [-15, (40+(floor($trvelx * .4)*5) + (floor(vel x * .4)*20))]) && p2BodyDist y = [-20,35+((p2StateType = S || p2StateNo = [5115,5122])*40) + ((p2StateType = C)*25)] && (vel y > 0 || !$grounded && !$nojug) { changeState{value: 600} } if (frontEdgeBodyDist < 50 || p2BodyDist x =[-15, (30+(floor($trvelx * .4)*5) + (floor(vel x * .4)*25))]) && p2BodyDist y = [-80,35+((p2StateType = S || p2StateNo = [5115,5122])*40) + ((p2StateType = C)*25)] && (vel y > 0 || (!$grounded) && (!$nojug) || $hitfall) { changeState{value: 630} } } #End of file: stateType = A #=========================================================================== } #End of file: ctrl #=============================================================================== #this section of AI is meant for attacks to be done after an attack defined above connects either as a hit #or blocked by the opponent. } else if moveContact = [1, 3] && hitPauseTime = 0 && stateType != A { #--------------------------------------------------------------------------- #These are freeform random combo fillers. They have very basic conditions and #do not break the human pattern of combos. lights can be used to build distance before #finishing combos as well as giving additional damage. #lights if jugglePoints(p2, ID) > 9 && random < (700 * (aiLevelF ** 2 / 48.0)) { if p2BodyDist x < 20 && moveContact && $lights { if random%2 || p2StateType = A { changeState{value: cond(p2BodyDist y < -18, 200, 400)} } else { changeState{value: cond(p2BodyDist x < 25, 430, 230)} } } #--------------------------------------------------------------------------- #light to other #this block will build the middle piece of combos. Sometimes a super will occur if the condition #is met. if p2BodyDist x < 85 && moveHit && $lights && !$nojug && random < (600 * (aiLevelF ** 2 / 48.0)) { if power > 1000 && p2,alive && $hitfall && jugglePoints(p2, ID) = [5, 7] && p2BodyDist x = [-8, 35] && p2BodyDist y > -75 && p2BodyDist y != 0 { changeState{value: 3050} } #We must ensure kfm's attack will combo by checking how much hittime the opponent has remaining. if (random%5 < 3 || p2StateType = A) && (p2StateType != L || p2BodyDist y != 0) && p2BodyDist x < 60 { if $CC > 8 { changeState{value: cond(p2BodyDist y < -30 || p2BodyDist x > 40, 210, 240)} } else if p2BodyDist x < 35 { changeState{value: 410} } } else { changeState{value: 440} } } } #--------------------------------------------------------------------------- #this block will determine how and if kfm will cancel into his various specials. The criteria is that the hitpause of the current attack #is over and the opponent is either not falling or in the air in a possible juggle state. It also requires at least 11 frames of hittime #to ensure the special will connect and the combo will continue unless they are in the air where fall.recovertime is prioritized instead. if ($heavy || $lights && (!$grounded && p2BodyDist y < -10 & p2BodyDist x > 55 || p2BodyDist x >55)) && (moveHit) && ($hitfall || $grounded || $CC > 11) && random < (800 * (aiLevelF ** 2 / 48.0)) { #using our somewhat accurate juggle point system, we are specifying that we only want moves to be used #if we haven't used more than 8 juggle points. if jugglePoints(p2, ID) >= 7 { #if we have at least 7 frames of hittime from the current attack, we #can cancel into the specials below without fail. For lower levels, #we randomly cancel 50% of the time. if $CC > 7 || aiLevel < 5 && random%2 { #the range of kung fu palm requires at least 120 pixels of space to #connect without missing. The opponent needs to at least be 50 pixels in the air #while falling to ensure the attack juggles. Or they are not in the air at all. if p2BodyDist x = [40, 120] && (p2BodyDist y = [10, -50] || $grounded) { #1/3 chance of using ex version if possible. if power > 450 && p2,alive && $grounded && random%3 = 0 { let spver = 1020; #if we have at least 9 frames of hittime } else if $CC > 9 && p2BodyDist x < 85 { let spver = 1010; } else { #at minimum we use weak kung fu palm let spver = 1000; } changeState{value: $spver} #if the opponent is closer, we can use higher damaging moves that deal more stun. #such as kung fu zankou } else if p2BodyDist x < 40 && (p2BodyDist y = [10, -50] || $grounded) { if power > 450 && p2,alive && $grounded && random%3 = 0 { let spver = 1420; } else if $CC > 9 && p2BodyDist x > 40 { let spver = 1410; } else { let spver = 1400; } changeState{value: $spver} } } #if the opponent is in the air and they are in range, kfm will try to use kung fu knee if !$grounded && p2BodyDist y = [-80+(floor(p2,vel y*.4)*-5), -25] && $CC > 6 && p2BodyDist x < 40 { if power > 450 && p2,alive && $grounded && random%3 = 0 { let spver = 1070; } else if p2BodyDist x > 40 || random%2 { let spver = 1060; } else { let spver = 1050; } changeState{value: $spver} } # if kfm is about to run out of juggle points, he will try to use kung fu blow to deal a # devastating end to a combo. } else if jugglePoints(p2, ID) = [3+(power < 1000), 7] { #finishers if p2BodyDist x = [-8, 80] && p2BodyDist y = [-55+(floor(p2,vel y*.4)*-5), -35] { changeState{value: 1200 + (random%2) * 10} } } } #--------------------------------------------------------------------------- #This is used to determine if kfm should cancel his supers attacks into hyper attacks #as a reminder $SC is used to identify the same check a human player has to meet to perform this #cancel. we then check if a heavy attack or even a light attack can be used if the opponent is #close to losing. This will gurantee kfm's victory usually. if ($SC || ($heavy && (p2,life < 350) || $lights)) && moveHit && jugglePoints(p2, ID) > 1 && random < (700 * (aiLevelF ** 2 / 48.0)) { if power >= 1000 && p2,alive { if p2BodyDist x = [-5, 25] && (p2BodyDist y = [-75, -1] || $grounded) { changeState{value: 3050} } if p2BodyDist x = [-5, 80] && (p2BodyDist y = [-40+(floor(p2,vel y*.6)*-5), -25] || $grounded) { changeState{value: 3000} } } } #End of file: moveContact #=============================================================================== } #------------|Kung Fu Knee follow up|------------------------------------------- #If there was more follow ups to his kung fu knee, this is the place to handle it #The criteria matches the same rule as a non-cpu. Refer to state 1051 to verify. #This is placed outside of the main two blocks above because it is considered a special case outlier. if (stateNo = 1051 || stateNo = 1061 || stateNo = 1071) && (moveHit || moveContact && aiLevel < 6) && vel y < -1 { if stateNo = [1050, 1069] { changeState{value: 1055} } else { changeState{value: 1075} } } #------------|MOVEMENT|--------------------------------------------------------- #------------|walking|---------------------------------------------------------- #These are the conditions that will make kfm walk forward. mapSet{map: "AIw"; value: 0} if (p2MoveType != A || p2BodyDist x > 25) || (p2StateType = L && p2BodyDist x > 70) || $AI_JI > 0 { mapSet{map: "AIw"; value: 1} } #These are the conditions that will make kfm walk backwards if backEdgeBodyDist > 40 && (p2MoveType = A || p2StateType != L && p2BodyDist x < 30) { mapSet{map: "AIw"; value: -1} } #there's a 25% chance at any time that if possible, kfm will walk a given direction with the conditions given if stateType = S && ctrl && stateNo != 100 && random < 249 && (p2MoveType != A || backEdgeBodyDist < 40) && p2BodyDist x = [25, 120] && map(AIw) != 0 { changeState{value: 20} } #If the AI is walking, we don't want them to stutter crouching as it looks very robotic. if map(AIw) != 0 && aiLevel > 3 { assertSpecial{flag: nocrouch} } #if the walk condition zeros out, kfm will stop walking. if map(AIw) = 0 && stateNo = 20 { printToConsole{text: "changeState{value: 0}"} changeState{value: 0; ctrl: 1} } #------------|running|---------------------------------------------------------- #These are the conditions that will make kfm run if stateType != A && (ctrl || stateNo = 20) && stateNo != 100 && random <= (396 * (aiLevelF ** 2 / 48.0)) && (p2MoveType != A || backEdgeBodyDist < 40) && (p2BodyDist x >= cond($hitfall || p2StateNo = 5300, 10, 120)) { changeState{value: 100} } #this will make kfm stop running. If you are making your own character with a stop running animation, #be sure to change this value: 0 to whatever that state is. if stateNo = 100 && (p2BodyDist x < 40 - 20 * (!$grounded) && p2StateNo != 5040 || p2BodyDist x < - 65 || roundState != 2) { changeState{value: 0; ctrl: 1} } #------------|jumping|---------------------------------------------------------- #this will decrement the get-up recovery-time map set above if map(gurt) > 0 { mapAdd{map: "gurt"; value: -1} } #this is to control optimal times to jump and attack on an opponent getting up from #a knock down. let p2l = p2,anim = 5120 || p2StateNo = 5110 && p2,time > 10; #These are the jump conditions for kfm. Starting off, kfm should not jump immediately after getting up as statistically, #it leads to the worst outcome. However, if an opponent tries to throw and kfm detects it, he will still jump. #He will also jump if the opponent is waking up from their knock down to score a hit or maintain advantageous pressure. #Lastly, he will try to jump after hitting an enemy with an attack that did not knock down. This usually puts the opponent #in state 5040 or if they are stunned (state 5300). it is worth mentioning that at lower levels kfm will not be as precise #and will leave himself open forbeginners. if stateType != A && (((!map(gurt)) && (random < (375 * (aiLevelF ** 2 / 48.0)) || p2MoveType = A && aiLevelF > 6) && (p2BodyDist x > 45 + ((p2MoveType != A && $grounded) * 45) || frontEdgeBodyDist < 50 || $p2l || p2StateNo = 5040 && p2BodyDist y > -40)) || p2,hitDefAttr = SC,AT && random < (455 * (aiLevelF ** 2 / 48.0))) && ( p2,hitDefAttr = SC,AT || (p2BodyDist x = [70, 90+(floor(vel x*.4)*5)] || frontEdgeDist < 30) && p2MoveType != H || $p2l && (p2BodyDist x = [50, 75+(floor(vel x*.4)*5)] || frontEdgeDist < 60) || p2StateNo = 5040 && p2BodyDist x = [-20, 60] || p2StateNo = 5300 && p2BodyDist x < 40 ) { let AIJ = 1; } #this will cancel out a jump declaration if the conditions have changed to prevent bad jumping behavior. #This is usually meant as a last ditch effort to ensure a jump should be done because it is considered a #high risk action. if stateType = A || moveType = H && stateNo != [120, 155] || prevStateNo = 5120 && p2StateType = A || p2BodyDist x < 80 && frontEdgeBodyDist > 60 && !$nojug || map(gurt) > 0 && p2,hitDefAttr != SC,AT || p2BodyDist x > 180 { let AIJ = 0; } #If the AIJumping indicator remains valid, kfm will jump if he has control. if $AIJ && (ctrl || stateNo = 20 || stateNo = 100) { changeState{value: 40} } if stateNo = 40 { sysVar(1) := 0; #We override default sysVar setting to influence jumping forward or backward if p2BodyDist x >= 60 || (p2StateNo = 5120 || p2MoveType = H) && p2BodyDist x >= 20 || p2StateType = A && p2BodyDist x >= 60 { sysVar(1) := 1; } if p2BodyDist x < 15 && p2MoveType = A && backEdgeBodyDist > 30 && frontEdgeBodyDist > 60 { sysVar(1) := -1; } } #------------------------------------------------------------------------------- #These are the conditions that will make kfm back dash/jump it has it's own random modifier because #we do not want him to back jump as often if stateType != A && (ctrl || stateNo = 20) && random <= (296 * (aiLevelF ** 2 / 48.0)) && backEdgeBodyDist > 40 && (p2MoveType = A && p2BodyDist x < 55 || p2BodyDist x < 20 && p2,anim = 5120 && p2,backEdgeBodyDist > 60) { changeState{value: 105; ctrl: 0} } #---------|AI recover|---------------------------------------------------------- #This will let kfm recover if possible with a 20% chance at any time. if alive && canRecover && random%5 = 0 && hitFall && stateNo = 5050 { if vel y > 0 && pos y >= const(movement.air.gethit.groundrecover.ground.threshold) { changeState{value: 5200} } if vel y > const(movement.air.gethit.airrecover.threshold) { changeState{value: 5210} } } #displayToClipboard{text: "%v %v %v %v"; params: sysVar(1), jugglePoints(p2, ID), $CC, $AI_JI} } #End of file: AI