Wall Climbing and Jumper Attribute Help

Started by Miraitto, August 25, 2022, 06:50:39 AM

Previous topic - Next topic

Miraitto

I just recently reinstalled the original :ff: and noticed how good the parkour is in this game with the combined "wall climbing" and "jumper" attribute. After playing with it. I haven't experienced any glitch. My character will just climb when there's a wall in front and jump over any close rooftops under him.

While in :ffvstr: the "jumper" attribute is still fine. But the wall climbing is a bit clunky. Sometimes your character will teleport straight at the top of a building.

If we could combine this into 1 attribute and call it "parkour" or something.

Is there a base script for FFX3 for this 2 attributes so I can edit them for :ffvstr:? Even just the wall climber script. I have looked at the FFX3's ffx.py and ffx2.py and found none.


stumpy

My recollection is that both of those attributes are hard-coded into the engine. My guess is that combining them with scripting would be a challenge if it's possible, as most path-planning tasks tend to be pretty involved.
Courage is knowing it might hurt, and doing it anyway. Stupidity is the same. And that's why life is hard. - Jeremy Goldberg

SickAlice

#2
I play with those a lot. I usually avert teleport to the top as you say when I want just climbing by pointing at part of the side of the building. I have found glitches though, you might be seeing that. But they are caused by the building nifs themselves typically. Like there is a building for example in the city level to the right of the starting point that if you try and jump on it your character will fall through and no longer be visible, then they will have to work there way out of wherever it is they are getting stuck. I assume that is somewhere at the base of the same building. So short version see if it's the same building or not. It's Bounding Box or another detail in it just might not be set up correctly, I know the actual game devs. made some mistakes like that, the aforementioned building in the city being an example (second up in the first row to the right of the starting point I think?). I mentioned it because I ran into that teleporting effect as you call it but only on specific things.

Scripting in this game isn't my area otherwise, sorry. I take stumpy and Epimethee at there word and know the options for these games are limited. My learning of game dev. stopped at 2d right around when 3d first took off (Quake, Unreal, so on). My mind says then "relative, proximity, checksum, if and else" commands. In this example check if object X (wall of object) is relative distance from character X, if then wall climb, else leap. Or something to the this effect. But I don't know the script for these games nor what type of options are available. If been told relative height for example is not available and sort of understand how that tracks with how terrain and paths are made. And mind you again none of what I'm thinking will actually work if the game object/terrain space doesn't have the proper set up as well which in a few cases they do not. That gets worse with modified maps made from other maps (game building object is set on the wrong type of terrain space for example, doesn't have proper bounding boxes, so on). It's sort of just a common glitch I run into myself and just deal with.

Epimethee

AFAIK, simulating the built-in jumping and climbing through scripting is impossible... Well, at least, I never had any success.
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

Miraitto

Isn't something like living laser attribute close to jumping attribute?

Would anyone be willing to share their ffx code here? Just so we have something to start from.

Epimethee

Never had any code worth keeping for Climber, IIRC (it has been twenty years or close to!). I think the best idea I had was creating an invisible platform beneath the character when he was again a wall and locking him in a climbing animation. However, we had no way to detect buildings bounding boxes. We now have a workaround, I believe,but I'm not sure it's reliable enough;you may have to fire invisible projectiles, for ex. to detect walls and roofs.

For jumping, the closest I've got is already in FFX, through Limited Jumping, Clumsy Jumper and Jump Travel. Jumping Jack combines the last two with Dr Mike's Super Leaper.

Good luck, would be cool to have someone solve this! :)
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

oktokels

Quote from: Miraitto on August 27, 2022, 05:37:53 AM


Would anyone be willing to share their ffx code here? Just so we have something to start from.
what part of the code? i can post it

Miraitto

I honestly have no idea where to start. There is no code for wall climbing only jumping. Something similar to FFX FlyMelee or Grapple maybe? But instead of locking on characters its only for buildings and structures.

oktokels

I found this:

# TRIGGERFORCE JUMPERS #

Spoiler
Quote###################### TRIGGERFORCE JUMPERS ######################################
# An alternative to the buit-in Jumper attribute and to FFX's super-leaper.
# It looks clumsy, but it works! The HIGH JUMP command is certainly not as easy to use nor as precise
# as the build-in JUMP command. Well, it IS cheaper (and it can be combined with other scripted attributes).
#
# Status: 1.6

# Added 1.4 (FFX 3.0):
# -Updated EP cost to new system
# Added 1.6 FFX 3.2):
# -Changed landing animation method to use dummy power, as Slippery
# -Made compatible with Acrobatic and Acrobatic Amateur.
# -High Jumper, Jump Travel: Reduced initial pos. check frequency.
# -Made removable.
# -Hard-coded Jump Travel EP cost.

# Notes/Bugs
# -What are the actual effects of TF_NO_GRAVITY and TF_NO_COLLISION? TF_NO_DAMPING isn't recognized by the game engine.
# -Very rarely, you may get stuck in an object when landing. Jump again to solve.
# -Your character may be unable to jump again just after landing; just move him a bit to solve.
# -minForce and mass are only partialy compensated, because, hey, there should be some advantage to being lighter! ;)
#  (Well, that was the idea, anyway. However, I haven't found how to account for mass; the values below are just trial
#  and error. Help!)
# -Fixed?: Character sometimes got stuck in the landing animation. The same happened from time to time with Superleaper and Acrobat,
#  if I remember correctly. Found a couple workaround, but - guess what? - Dr. Mike had again found a better one. I can't
#  reproduce this intermitent bug anymore, which doesn't imply it doesn't exist anymore, of course. ;/
#  EDIT: bug still happened sometimes, apparently. Should be OK now. EDIT 2: Changed the method for FFvsTTR.
# -Corrected a bug in Jump Travel resulting in possible stun if energy wasn't full!

def initffqhighjumper(char, update=0, remove=0):
    if remove:
        Mission_RemoveCustomAction('CUSTOM_FFQHIGHJUMP',char,char,)
    else:
        Mission_CustomAction('CUSTOM_FFQHIGHJUMP',char,char,'ffqJumpHigh',1,0)

def initffqlowjumper(char, update=0, remove=0):
    if remove:
        Mission_RemoveCustomAction('CUSTOM_FFQLOWJUMP',char,char,)
    else:
        Mission_CustomAction('CUSTOM_FFQLOWJUMP',char,char,'ffqJumpLow',1,0)

def initffqlongjumper(char, update=0, remove=0):
    if remove:
        Mission_RemoveCustomAction('CUSTOM_FFQFARJUMP',char,char,)
    else:
        Mission_CustomAction('CUSTOM_FFQFARJUMP',char,char,'ffqJumpFar',1,0)

def ffqJumpHigh(char,dummy):
    FFX_ObjectSetAttr(char, 'voluntary_flailing', 1)
    AI_Animate(char,'jump_stand','OnFFQjumpHigh',0,1)

def ffqJumpLow(char,dummy):
    FFX_ObjectSetAttr(char, 'voluntary_flailing', 1)
    AI_Animate(char,'jump_stand','OnFFQjumpLow',0,1)

def ffqJumpFar(char,dummy):
    if chargeEP(char, 33)==0:
        return
    FFX_ObjectSetAttr(char, 'voluntary_flailing', 1)
    AI_Animate(char,'jump_stand','OnFFQjumpFar',0,1)

#mass, minForce and strength matter here!
def OnFFQjumpHigh(event):
    char=event.object
    print "%s is jumping high"%(char)
    myMassFactor=Object_GetAttr(char,'mass')
    myMassFactor=sqrt(myMassFactor)
    magnitude=(Object_GetAttr(char,'strength')*5000 + 15000 + Object_GetAttr(char,'minForce')*0.9) / 9*myMassFactor
    Trigger_Force(char,0,-0.2,1,magnitude,TF_NO_ROTATION)
    Object_SetAttr(char,'prejumpMinHealth',Object_GetAttr(char,'minHealth'))
    Object_SetAttr(char,'minHealth',Object_GetAttr(char,'health'))
    pos=Get_ObjectPos(char)
    Object_SetAttr(char,'ffqz1',pos[2])
    RegTimer('ffqGetMaxHeight',0.3,0,char)

#tries to compensate for mass; ignores minForce and strength
def OnFFQjumpLow(event):
    char=event.object
    print "%s is jumping low"%(char)
    myMassFactor=Object_GetAttr(char,'mass')/100
    magnitude=(15000 + (Object_GetAttr(char,'minForce'))) * myMassFactor
    Trigger_Force(char,0,-0.2,1,magnitude,TF_NO_ROTATION)
    Object_SetAttr(char,'prejumpMinHealth',Object_GetAttr(char,'minHealth'))
    Object_SetAttr(char,'minHealth',Object_GetAttr(char,'health'))
    pos=Get_ObjectPos(char)
    Object_SetAttr(char,'ffqz1',pos[2])
    RegTimer('ffqGetMaxHeight',0.1,0,char)

#mass, minForce and strength matter here!
def OnFFQjumpFar(event):
    char=event.object
    print "%s is jumping far"%(char)
    myMassFactor=Object_GetAttr(char,'mass')
    myMassFactor=sqrt(myMassFactor)
    magnitude=(Object_GetAttr(char,'strength')*5500 + 12000 + Object_GetAttr(char,'minForce')*0.7) / 6 * myMassFactor
    Trigger_Force(char,0,-0.9,0.5,magnitude,TF_NO_ROTATION)
    Object_SetAttr(char,'prejumpMinHealth',Object_GetAttr(char,'minHealth'))
    Object_SetAttr(char,'minHealth',Object_GetAttr(char,'health'))
    pos=Get_ObjectPos(char)
    Object_SetAttr(char,'ffqz1',pos[2])
    RegTimer('ffqGetMaxHeight',0.5,0,char)

def ffqGetMaxHeight(event):
    char=event.object
    pos=Get_ObjectPos(char)
    ffqz2=pos[2]
    if (ffqz2 < Object_GetAttr(char,'ffqz1')) | (ffqz2 > 429):
        RegTimer('landonfeet', 0.1, 0, char)
        Object_SetAttr(char,'minHealth',Object_GetAttr(char,'prejumpMinHealth'))
    else:
        Object_SetAttr(char,'ffqz1',ffqz2)
        RegTimer('ffqGetMaxHeight',0.1,0,char)

oktokels

and the grapple code (had to remove some parts because it surpassed the forum length capacity):

Spoiler
Quote#################### grapple state swap ########################################################
# Wrestling Hold State Swap that locks the target and attacker in place. Every two seconds the
# target gets a chance to break free or gets dealt damage equal to twice the attacker's strength
# -TaskmasterX
################################################################################################

def grappleStartCheck(char,source,intensity):
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==1:
        return
    AI_Animate(source,'lock')
    mlogreader.regDodgeStart(source,'grappleCancel',0,0,0,char)
    ffx.FFX_ObjectSetAttr(source,'grappleIntensity',intensity)
    pos1 = Get_ObjectPos(char)
    pos2 = Get_ObjectPos(source)
    dist = cshelper.distance2D(pos1, pos2)
    subtype = m25ai.FindTacticType(char, 'subtype')
    if dist > 46:#check if the target moved too far away
        if (Object_GetClass(char)&js.OC_VEHICLE)!=1:
            if not ('vehicle' in subtype):
                AI_Animate(source,'unlock')
                AI_Animate(source,'melee_idle')
                return
    if (ffx.FFX_ObjectGetAttr(char,'grappleMental')==0) & (ffx.FFX_ObjectGetAttr(char,'grappleMystic')==0) & (ffx.FFX_ObjectGetAttr(char,'grappleEnergy')==0):
        ffx.FFX_ObjectSetAttr(char,'grapplePhysical',1)
        damage_type = m25ai.ai_damage_type['crushing']
        damage_mode = m25ai.ai_damage_mode['melee']
        if ffx.FFX_ObjectGetAttr(char,'ffactivedefense')==1:
            useStr=ffx.getByTemplate(source,FFX_RANGEGRAPPLE_CUSTOM,2)
            adHP=ffx.FFX_ObjectGetAttr(char,'ffactivedefenseHP')
            grappleDmg=ffx.getByTemplate(source,FFX_RANGEGRAPPLE_CUSTOM,4)
            if grappleDmg=='Yes':
                if useStr=='Yes':
                    grappleDmg=Object_GetAttr(source,'strength')+1
                else:
                    grappleDmg=ffx.getByTemplate(source,FFX_RANGEGRAPPLE_CUSTOM,3)
            else:
                grappleDmg=0
            newHP=adHP-grappleDmg
            ffx.FFX_ObjectSetAttr(char,'ffactivedefenseHP',newHP)
            if ffx.FFX_ObjectGetAttr(char,'ffactivedefenseSelf',0)==0:
                FFX_crushTest1a(char,source)
                return
            power=ffx.getByTemplate(char,FFX_FFACTIVEDEFENSE_CUSTOM,3)
            powdata = datfiles.Campaign_ReadPowers()[power]
            if powdata['PowerType'] == datfiles.PT_ACTIVE_DEFENCE:
                if ( powdata['DamageTypesBlocked'] & damage_type ) and \
                ( powdata['AttackModesBlocked'] & damage_mode ):
                    m25getset.GetObjectVar(char, 'defense ' + `damage_type` + '_' + `damage_mode`, 1,nosave=1)
                    AI_Animate(source,'unlock')
                    AI_Animate(source,'melee_idle')
                    return
        if ffx.FFX_HasPortrait(char):
            if not m25ai.AIInWatch(char):
                FFX_crushTest1a(char,source)
                return
        if m25ai.HasActiveDefenceActive(char,damage_type,damage_mode):
            AI_Animate(source,'unlock')
            AI_Animate(source,'melee_idle')
            return
        if ffx.FFX_ObjectGetAttr(char,'phased_out',0)==1:
            AI_Animate(source,'unlock')
            AI_Animate(source,'melee_idle')
            return
    makegrappled(char, source)

def FFX_crushTest1a(char,source):
    name=ffx.getDummyName()
    Object_SpawnAt('ffx_tiggot',Get_ObjectPos(source),name)
    Trigger_Power(name,char,'ffx_melee_crush_test','',10)
    ffx.FFX_ObjectSetAttr(char,'crushTestA',1)
    ffx.FFX_ObjectSetAttr(source,'crushTestA',1)
    ffx.RegTimer('ffx.destroyTemp',1,0,name)
    ffx.RegCharState(char,PCSTATE_STUNNED,'FFX_crushTest2a',0,0,source)
    ffx.RegTimer('FFX_crushTest3a',2,0,char,source)

def FFX_crushTest2a(event):
    char=event.object
    source=event.string
    if ffx.FFX_ObjectGetAttr(char,'crushTestA',0)==1:
        if ffx.FFX_ObjectGetAttr(source,'crushTestA',0)==1:
            ffx.FFX_ObjectSetAttr(source,'crushTestA',0)
            Object_SetPrimaryState(char,PCSTATE_STUNNED,0,REMOVE_STATE)
            makegrappled(char,source)
    ffx.FFX_ObjectSetAttr(char,'crushTestA',0)

def FFX_crushTest3a(event):
    char=event.object
    source=event.string
    ffx.FFX_ObjectSetAttr(source,'crushTestA',0)
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==0:
        AI_Animate(source,'unlock')
        AI_Animate(source,'melee_idle')
    else:
        AI_Animate(char,'pain')

def makegrappled(char,source):
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==1:
        return
    pos1 = Get_ObjectPos(char)
    pos2 = Get_ObjectPos(source)
    ffx.FFX_ObjectSetAttr(char,'grappled',1)
    ffx.FFX_ObjectSetAttr(source,'grappler',1)
    ffx.FFX_ObjectSetAttr(char,'lastY',pos1[1])
    ffx.FFX_ObjectSetAttr(char,'lastX',pos1[0])
    ffx.FFX_ObjectSetAttr(source,'lastY',pos2[1])
    ffx.FFX_ObjectSetAttr(source,'lastX',pos2[0])
    ffx.FFX_ObjectSetAttr(source,'gLastHealth',Object_GetAttr(source,'health'))
    grappleFX=ffx.getByTemplate(source,FFX_GRAPPLE_CUSTOM,1)
    if grappleFX!='':
        handle = Object_PlayEffect(char, grappleFX,'',FX_LOOP|FX_TRACK_OBJECT_FULL,0,'centre')
        ffx.FFX_ObjectSetAttr(char,'grapple_handle',handle)
    ffx.FFX_ObjectSetAttr(source,'grapple_duration',12)
    AI_Animate(char,'pain')
    hasPortrait=ffx.FFX_HasPortrait(char)
    pcAIEnabled=m25ai.AIInWatch(char)
    if pcAIEnabled or not hasPortrait:
        m25ai.AIDisable(char)
    ffx.RegTimer('grappleStart',0.4,0,char,source)
    ffx.RegTimer('grappleLock',0.1,0,char,source)
    ffx.RegTimer('grappleMoveCheck',0.2,0,source,char)
    ffx.RegTimer('grappleEnergy',1,0,char,source)

def grappleCancel(event):
    source=event.object
    char=event.string
    if ffx.FFX_ObjectGetAttr(source,'grappler',0)==0:
        AI_Animate(source,'unlock')
        AI_Animate(source,'melee_idle')
    ffx.FFX_ObjectSetAttr(char,'grappled',0)
    ffx.FFX_ObjectSetAttr(source,'grappler',0)

def grappleLock(event):
    char=event.object
    source=event.string
    flailing=mlogreader.MLOG_IsFlailing(char)
    flailingS=mlogreader.MLOG_IsFlailing(source)
    if flailing:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        mlogreader.regGetupStop(char,'grappleRecover',0,0,0)
        if flailingS:
            mlogreader.regGetupStop(source,'grappleRecover',0,0,0)
        else:
            ffx.RegTimer('grappleRecover',1,0,source)
        return
    if flailingS:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        mlogreader.regGetupStop(source,'grappleRecover',0,0,0)
        if flailing:
            mlogreader.regGetupStop(char,'grappleRecover',0,0,0)
        else:
            ffx.RegTimer('grappleRecover',1,0,char)
        return
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==0:
        if ffx.FFX_ObjectGetAttr(char,'grappleBreak',0)==0:
            if Object_IsAlive(char)!=0:
                Trigger_Force(char,0,0,1,Object_GetAttr(char,'mass')*100,TF_ABSOLUTE)
            if ffx.FFX_ObjectGetAttr(char,'acrobatic',0)!=1:
                mlogreader.regGetupStop(char,'grappleRecover',0,0,0)
            else:
                ffx.RegTimer('grappleRecover',1,0,char)
        else:
            ffx.RegTimer('grappleRecover',1,0,char)
        ffx.RegTimer('grappleRecover',1,0,source)
        return
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==1:
        AI_Animate(char,'pain')
    ffx.RegTimer('grappleLock',0.3,0,char,source)

def grappleStart(event):
    char=event.object
    source=event.string
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==0:
        return
    if grappleBreakCheck(char,source):
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        ffx.FFX_ObjectSetAttr(char,'grappleBreak',1)
        handle=ffx.FFX_ObjectGetAttr(char,'grapple_handle')
        Object_StopEffect(char,handle)
        return
    if Object_GetPrimaryState(char)==ffx.PCSTATE_EXILE:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    grappledAgl=Object_GetAttr(char,'agility')-3
    ffx.FFX_ObjectSetAttr(char,'baseAgility',Object_GetAttr(char,'agility'))
    ffx.FFX_ObjectSetAttr(source,'baseAgility',Object_GetAttr(source,'agility'))
    Object_SetAttr(char,'energy',0)
    Object_SetAttr(source,'agility',grappledAgl)
    Object_SetAttr(char,'agility',0)
    grappleDmg(source,char)
    ffx.RegTimer('grappleCheck',3,0,char,source)

def grappleMoveCheck(event):#checks grappler's and target's conditions (movement, damage, Primary State, KOed)
    source = event.object
    char = event.string
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==0:
        return
    lasthealth=ffx.FFX_ObjectGetAttr(source,'gLastHealth')
    health=Object_GetAttr(source,'health')
    if health < lasthealth:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    if (Object_GetPrimaryState(source)!=PCSTATE_NORMAL) | (Object_IsAlive(source)==0) | (ffx.FFX_ObjectGetAttr(source,'grappled',0)==1) | (ffx.FFX_ObjectGetAttr(source,'rangedgrappled',0)==1) | (ffx.FFX_ObjectGetAttr(source,'tangled',0)==1) | (ffx.FFX_ObjectGetAttr(source,'eTangled',0)==1) | (ffx.FFX_ObjectGetAttr(source,'thrownCharacter',0)==1):#if the grappler is koed, blanked, enraged, hexed, etc. cancel the grapple
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    if Object_GetPrimaryState(char)==ffx.PCSTATE_EXILE:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    if (Object_IsAlive(char)==0):#if the target is koed, cancel the grapple
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    pos=Get_ObjectPos(source)
    pos2=Get_ObjectPos(char)
    dist=(pos[0]-ffx.FFX_ObjectGetAttr(source,'lastX'),pos[1]-ffx.FFX_ObjectGetAttr(source,'lastY'),0)
    dist2=(pos2[0]-ffx.FFX_ObjectGetAttr(char,'lastX'),pos2[1]-ffx.FFX_ObjectGetAttr(char,'lastY'),0)
    ffx.FFX_ObjectSetAttr(source,'lastY',pos[1])
    ffx.FFX_ObjectSetAttr(source,'lastX',pos[0])
    ffx.FFX_ObjectSetAttr(char,'lastY',pos2[1])
    ffx.FFX_ObjectSetAttr(char,'lastX',pos2[0])
    if (dist[0]*dist[0]+dist[1]*dist[1]) > 10:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    elif (dist2[0]*dist2[0]+dist2[1]*dist2[1]) > 20:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    ffx.FFX_ObjectSetAttr(source,'gLastHealth',health)
    flailing=mlogreader.MLOG_IsFlailing(char)
    myflailing=mlogreader.MLOG_IsFlailing(source)
    if not flailing:
        AI_Animate(char,'lock')
    if not myflailing:
        AI_Animate(source,'lock')
    ffx.RegTimer('grappleMoveCheck',0.7,0,source,char)

def grappleBreakCheck(char,source):
    #calculate the target's resistance based on the kind of grapple(physical, mental, mystical, cold or energy)
    if ffx.FFX_ObjectGetAttr(char,'grappleMental',0)==1:
        targetStr=ffx.getMentalResistanceValue(char, passive=0, active=0, attribs=1, states=1, material=1)
    elif ffx.FFX_ObjectGetAttr(char,'grappleMystic',0)==1:
        targetStr=ffx.getMysticalResistanceValue(char, passive=0, active=0, attribs=1, states=1, material=1)
    elif ffx.FFX_ObjectGetAttr(char,'grappleEnergy',0)==1:
        targetStr=ffx.getEnergyResistanceValue(char, passive=0, active=0, attribs=1, states=1, material=1)
    else:
        targetStr=Object_GetAttr(char,'strength')+1
        if ffx.FFX_ObjectGetAttr(char,'grappleCold',0)!=1:
            if ffx.hasAttribute(char,'wrestler'):
                targetStr=ffx.FFX_ObjectGetAttr(char,'wrestler')
    #calculate the grappler's hold strength (Strength Stat or Custom Value)
    useStr=ffx.getByTemplate(source,FFX_GRAPPLE_CUSTOM,2)
    if useStr=='Yes':
        holdStr=Object_GetAttr(source,'strength')+1
        if ffx.FFX_ObjectGetAttr(char,'grappleCold',0)!=1:
            if ffx.hasAttribute(source,'wrestler'):
                holdStr=ffx.FFX_ObjectGetAttr(source,'wrestler')
    else:
        holdStr=ffx.getByTemplate(source,FFX_GRAPPLE_CUSTOM,3)
    #calculate the difference in the grappler's and target's strength
    if ffx.FFX_ObjectGetAttr(char,'grapplePhysical',0)!=1:
        if targetStr==1:
            if holdStr < 7:
                holdStr=holdStr+2
            else:
                holdStr=holdStr+1
        if targetStr > 1:
            holdStr=(holdStr*0.5)+1.5
        if targetStr == 0.5:
            holdStr=holdStr*1.5
        if targetStr == 0.25:
            holdStr=holdStr*2.5
        chance=holdStr*targetStr
    else:
        if targetStr>holdStr:
            targetStr=targetStr+1
            strDiff=targetStr-holdStr
            chance=5-strDiff
        if targetStr==holdStr:
            chance=6
        if holdStr>targetStr:
            targetStr=targetStr-1
            strDiff=holdStr-targetStr
            chance=5+strDiff
    #calculate the chance to break free
    breakFree=randint(1,10)
    if breakFree > chance:
        return 1
    else:
        return 0

def grappleDmg(source,char):
    #apply damage if hold is successful
    if ffx.FFX_ObjectGetAttr(char,'grappleMental',0)==1:
        targetStr=ffx.getMentalResistanceValue(char, passive=0, active=0, attribs=1, states=1, material=1)
    elif ffx.FFX_ObjectGetAttr(char,'grappleMystic',0)==1:
        targetStr=ffx.getMysticalResistanceValue(char, passive=0, active=0, attribs=1, states=1, material=1)
    elif ffx.FFX_ObjectGetAttr(char,'grappleEnergy',0)==1:
        targetStr=ffx.getEnergyResistanceValue(char, passive=0, active=0, attribs=1, states=1, material=1)
    useStr=ffx.getByTemplate(source,FFX_GRAPPLE_CUSTOM,2)
    grappleDmg=ffx.getByTemplate(source,FFX_GRAPPLE_CUSTOM,4)
    if grappleDmg=='Yes':
        if useStr=='Yes':
            grappleDmg=Object_GetAttr(source,'strength')+1
        else:
            grappleDmg=ffx.getByTemplate(source,FFX_GRAPPLE_CUSTOM,3)
    else:
        grappleDmg=0
    if grappleDmg > 0:
        baseDmg=grappleDmg*2
        if ffx.FFX_ObjectGetAttr(char,'grapplePhysical',0)!=1:
            damage=baseDmg*targetStr
        else:
            if ffx.FFX_ObjectGetAttr(char,'grappleCold',0)==1:
                targetStr=ffx.getColdResistanceValue(char,passive=0,active=0,attribs=1,states=1,material=1)
            else:
                targetStr=ffx.getCrushResistanceValue(char,passive=0,active=0,attribs=1,states=1,material=1)
            damage=baseDmg*targetStr
        if damage < 1:
            damage=1
        if (ffx.FFX_ObjectGetAttr(char,'grappleMental')==1) | (ffx.FFX_ObjectGetAttr(char,'grappleMystic')==1):
            ffx.FFX_ApplyDamage(char,damage,mental=1)
        else:
            if damage > 0:
                ffx.FFX_ApplyDamage(char,damage,mental=0)

def grappleCheck(event):
    char=event.object
    source=event.string
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==0:
        return
    duration=ffx.FFX_ObjectGetAttr(source,'grapple_duration')-3
    if duration<=0:
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        return
    if Object_GetPrimaryState(char)!=PCSTATE_NORMAL:
        ffx.FFX_ObjectSetAttr(source,'grapple_duration',duration)
        ffx.RegTimer('grappleCheck',3,0,char,source)
        return
    if grappleBreakCheck(char,source):
        ffx.FFX_ObjectSetAttr(char,'grappled',0)
        ffx.FFX_ObjectSetAttr(source,'grappler',0)
        ffx.FFX_ObjectSetAttr(char,'grappleBreak',1)
        return
    ffx.FFX_ObjectSetAttr(source,'grapple_duration',duration)
    grappleDmg(source,char)
    ffx.RegTimer('grappleCheck',3,0,char,source)

def grappleRecover(event):
    char=event.object
    if Object_IsAlive(char)==0:
        return
    flailing=mlogreader.MLOG_IsFlailing(char)
    if flailing:
        mlogreader.regGetupStop(char,'grappleRecover',0,0,0)
        return
    agility=ffx.FFX_ObjectGetAttr(char,'baseAgility')
    Object_SetAttr(char,'agility',agility)
    baseEnergy=ffx.FFX_ObjectGetAttr(char,'baseEnergy')
    energy=Object_GetAttr(char,'energy')
    if baseEnergy!=energy:
        Object_SetAttr(char,'energy',baseEnergy)
    AI_Animate(char,'unlock')
    hasPortrait=ffx.FFX_HasPortrait(char)
    pcAIEnabled=m25ai.AIInWatch(char)
    if pcAIEnabled or not hasPortrait:
        m25ai.ClearAIStandardOnly(char)
        m25ai.AIEnable(char)
        m25ai.AIEnableCustom(char)
        m25ai.SetBrawler(char)
        m25event.SetTimer(1.0, 'm25ai.AIRecoverBroken', char, user=m25ai.GetAITimeStamp(char))
    if ffx.FFX_ObjectGetAttr(char,'grappleBreak',0)==1:
        if ffx.FFX_ObjectGetAttr(char,'grappleMystic',0)==1:
            AI_Animate(char,'recover_from_stun')
        elif ffx.FFX_ObjectGetAttr(char,'grappleMental',0)==1:
            AI_Animate(char,'recover_from_stun')
        else:
            AI_Animate(char,'swing_pole')
        ffx.FFX_ObjectSetAttr(char,'grappleBreak',0)
    else:
        AI_Animate(char,'melee_idle')
    handle=ffx.FFX_ObjectGetAttr(char,'grapple_handle')
    Object_StopEffect(char,handle)
    ffx.FFX_ObjectSetAttr(char,'grappleMental',0)
    ffx.FFX_ObjectSetAttr(char,'grappleMystic',0)
    ffx.FFX_ObjectSetAttr(char,'grappleCold',0)
    ffx.FFX_ObjectSetAttr(char,'grappleEnergy',0)
    ffx.FFX_ObjectSetAttr(char,'grapplePhysical',0)
    ffx.RegTimer('grappleRecover2a',1,0,char)

def grappleRecover2a(event):
    char=event.object
    if Object_IsAlive(char)==0:
        return
    pos=Get_ObjectPos(char)
    ffx.FFX_ObjectSetAttr(char,'lastY',pos[1])
    ffx.FFX_ObjectSetAttr(char,'lastX',pos[0])
    ffx.RegTimer('grappleRecover2b',5,0,char)

def grappleRecover2b(event):
    char=event.object
    if Object_IsAlive(char)==0:
        return
    flailing=mlogreader.MLOG_IsFlailing(char)
    getup=mlogreader.MLOG_IsGettingUp(char)
    pos=Get_ObjectPos(char)
    dist=(pos[0]-ffx.FFX_ObjectGetAttr(char,'lastX'),pos[1]-ffx.FFX_ObjectGetAttr(char,'lastY'),0)
    ffx.FFX_ObjectSetAttr(char,'lastY',pos[1])
    ffx.FFX_ObjectSetAttr(char,'lastX',pos[0])
    if ffx.FFX_ObjectGetAttr(char,'grappled',0)==1:
        return
    if ffx.FFX_ObjectGetAttr(char,'grappler',0)==1:
        return
    if flailing:
        mlogreader.regGetupStop(char,'grappleRecover2b',0,0,0)
        return
    if getup:
        mlogreader.regGetupStop(char,'grappleRecover2b',0,0,0)
        return
    if (dist[0]*dist[0]+dist[1]*dist[1]) > 10:
        return
    if not m25ai.IsPerformingTactic(char):
        AI_Animate(char,'unlock')
        hasPortrait=ffx.FFX_HasPortrait(char)
        pcAIEnabled=m25ai.AIInWatch(char)
        if pcAIEnabled or not hasPortrait:
            m25ai.ClearAIStandardOnly(char)
            m25ai.AIEnable(char)
            m25ai.AIEnableCustom(char)
            m25ai.SetBrawler(char)
            m25event.SetTimer(1.0, 'm25ai.AIRecoverBroken', char, user=m25ai.GetAITimeStamp(char))
    ffx.RegTimer('grappleRecover2b',5,0,char)

Miraitto

Oh my goodness. Didn't expect the codes to be that long. I was expecting a code like ClingToWall or something. But thanks nonetheless. I'll tinker with it.

SickAlice

Oh you do use if, else and relative pos. commands then? Side note if I ever want to learn the coding for this game (likely not but you never know) I'll make sure to go to oktokels for that.

Miraitto

Of course, I did edit the old flying melee. But without any success.

oktokels

Quote from: SickAlice on August 28, 2022, 05:54:05 PM
Side note if I ever want to learn the coding for this game (likely not but you never know) I'll make sure to go to oktokels for that.
Can't help you that much there, since I'm a begginer too. The ffx code is still unreadable for me, for the most part. It was relatively easy to find the parts requested by miraitto, though, since everything is structured like chapters in a book.

SickAlice

I'm less of a beginner and you actually have the basics down. Like I said I abandoned coding a long time ago. Much of what I'm looking is still familiar though. Looks like anything I used to do for 2d platformers.