Problem with attribute escapologist and speed phaser

Started by oktokels, September 28, 2024, 12:02:57 AM

Previous topic - Next topic

oktokels

I'm facing an issue in the FFX Mod. Characters with the Escapologist attribute (coded as slippery) or speed phaser are supposed to automatically escape the Stasis state when they have enough energy. While some characters successfully exit Stasis, their AI becomes unresponsive afterward. The attribute should allow them to resume normal behavior after escaping, but instead, they remain stuck.

Here's the code of escapologist from ffx.py:

Quote####################### SLIPPERY ################################################

def initslippery(char,update=0):
    RegCharState(char,PCSTATE_STATIC,'clearStasis')

def clearStasis(event):
    char=event.object
    if hasAttribute(char,'slippery'):
        Object_SetPrimaryState(char,PCSTATE_STATIC,0,REMOVE_STATE)
        RegTimer('landonfeet',0.1,0,char)
        RegCharState(char,PCSTATE_STATIC,'clearStasis')

def landonfeet(event):
    char=event.object
    Trigger_Power(char,char,'land_from_jump','')
    FFX_ObjectSetAttr(char, 'voluntary_flailing', 0) #Ep. 2006-08-30: clear flailing triggered by Jump Travel, Fastball, etc.

How can I modify the code or the AI behavior to ensure that characters resume their actions after escaping from Stasis? Is there a way to reinitialize the AI or reset the character's state completely to prevent them from getting stuck?

Does anyone know if this could work???
QuotePossible Solutions:

Restart the AI State: After the character breaks free from the Stasis state, it might be necessary to explicitly call a function to reactivate the AI. You can try invoking a command like RegAINormalState or Object_SetPrimaryState to ensure that the character returns to its normal active state.

Remove and Re-register the Attribute: Another solution could be to temporarily deactivate the slippery attribute and then reactivate it once the character is free from Stasis. This can be done using FFX_ObjectSetAttr(char, 'slippery', 0) and then re-enabling it with FFX_ObjectSetAttr(char, 'slippery', 1).

Introduce a Temporary Delay: Add a short timer using RegTimer before reactivating the character's actions. This allows time for the game engine to process the removal of Stasis before the character attempts any other actions.

DoctorRuina

I think I've had this problem as well. I even find it happens without using the escapologist attribute. When the characters break free from stasis, their AI becomes unresponsive.

mac402

#2
The problem is with the landonfeet event. If you # that out you won't be getting characters stuck. The landonfeet event prevents them from tripping when stasis is cancelled but causes them to be stuck until you hit them with a knockback attack.

EDIT: Looks like this can be quickly fixed by adding mlogreader.MLOG_ResetKnockBack(char)

def landonfeet(event):
    char=event.object
    Trigger_Power(char,char,'land_from_jump','')
    FFX_ObjectSetAttr(char, 'voluntary_flailing', 0) #Ep. 2006-08-30: clear flailing triggered by Jump Travel, Fastball, etc.
    mlogreader.MLOG_ResetKnockBack(char)  #m25

DoctorRuina


oktokels

I tried to add the line to the speed phaser attribute, but it is coded differently from slippery.

######################################## SPEEDPHASER ##########################################

def initspeedphaser(char,update=0,remove=0):
    if remove:
        FFX_ObjectSetAttr(char,'speedphaser',0)
        return
    FFX_ObjectSetAttr(char,'speedphaser',1)
    RegCharState(char,PCSTATE_STATIC,'speedphaserupdate')
    RegCharState(char,PCSTATE_FROZEN,'speedphaserupdate')


def speedphaserupdate(event):
    char=event.object
    if not ( Object_Exists(char) and FFX_ObjectGetAttr(char,'speedphaser') ):
        return
    state = Object_GetPrimaryState(char)
    percentage=Object_GetAttr(char,'energyPoints') / max( 1.0, Object_GetAttr(char,'maxEnergyPoints') ) #Ep. 2006-08-30: prevented division by zero
    if (percentage>=0.5) and Object_IsAlive(char):
        effect = getByTemplate(char,FFX_SPEEDPHASER_CUSTOM,1)
        if effect:
            RegTimer('speedphaser_escape1',1,0,char)
        else:   # there was no effect to play
            RegTimer('speedphaser_escape2',2,0,char)
    else:
        RegCharState(char,state,'speedphaserupdate')

def speedphaser_escape1(event): # play escape animation
    char=event.object
    effect = getByTemplate(char,FFX_SPEEDPHASER_CUSTOM,1)
    try:
        handle = Object_PlayEffect(char,effect,'speedphaser_escape2')
        Object_StopEffect(char, handle-2)
        Object_StopEffect(char, handle-1)
    except:
        print 'speedphaserupdate(%s): unable to play effect %s' % (repr(char),repr(effect))

def speedphaser_escape2(event):
    char=event.object
    if not ( Object_Exists(char) and FFX_ObjectGetAttr(char,'speedphaser') ):
        return
    state = Object_GetPrimaryState(char)
    if state != PCSTATE_NORMAL: # check that we still need this
        Object_SetPrimaryState(char,state,0,REMOVE_STATE)
        RegTimer('landonfeet',0.1,0,char)
    RegCharState(char,state,'speedphaserupdate')

Do you know how to add the line to this attribute?

oktokels

Quote from: oktokels on October 12, 2024, 08:39:12 PMDo you know how to add the line to this attribute?

It seems that it works like this:

def speedphaser_escape2(event):
    char = event.object
    if not (Object_Exists(char) and FFX_ObjectGetAttr(char, 'speedphaser')):
        return
    state = Object_GetPrimaryState(char)
    if state != PCSTATE_NORMAL:  # Check that we still need this
        Object_SetPrimaryState(char, state, 0, REMOVE_STATE)
        RegTimer('landonfeet', 0.1, 0, char)
        mlogreader.MLOG_ResetKnockBack(char)  # Reset knockback to avoid the unresponsive state
    RegCharState(char, state, 'speedphaserupdate')

mac402

That's redundant. Speedphaser calls the landonfeet event from slippery.