Assimilator into Matter Eating and Other Sundries

Started by BentonGrey, June 06, 2019, 03:54:52 AM

Previous topic - Next topic

BentonGrey

Howdy guys, I am trying to figure out how to properly portray Matter Eater Lad, and I cam across the FFX attribute Assimilator, which lets you consume parts of objects to get new powers and weapons.  I'm wondering if there's anyone with the know-how to take that attribute and tweak it into something that just gives you health or energy for 'eating' objects.
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

Since Assimilator is built to affect a different target, it might be easier to customize Transmutator instead. For example (caveat emptor: not tested, I don't have access to a PC and I haven't played with these in a looong time), in ffx.py (back up first!) you could add a OnTransmuteToHealth function to add 10 hp, say, right between the lines for def OnHarmlessGas2(event): and def OnFlashGas(target,char):

def OnTransmuteToHealth(target,char):
    Trigger_Damage(char,-10)
    OnTransmute(target,char,'OnHarmlessGas2')


(If you want a different FX instead of the effect_ffx_pheremones, you'd have to replace OnHarmlessGas2 by a new call to a copy of the function with a different name and a different FX.)

In ffxtransmutes.py, under the transmutables=( list, you would have to add a line before the final closing parenthesis:
('CUSTOM_EAT','solid','OnTransmuteToHealth'),

('solid' could be replace by any of the other available types, of course.)

Finally, you'll need to add the CUSTOM_EAT entry to strings.txt and compile the file.

This could be made more sophisticated, to check for the object's HP and give corresponding health or for eating objects bite by bite. However, as I'm unable to use trial and error, I can't be of much help.
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

Epimethee

To also increase both health and energy, you could probably use this:
def OnTransmuteToHealth(target,char):
    Trigger_Damage(char,-10)
    currentEnergy = Object_GetAttr(char, 'energyPoints')
    FFX_SetEnergy(char,currentEnergy+10)
    OnTransmute(target,char,'OnHarmlessGas2')


FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Epi, you are awesome!  I will have to test these out soon, but (so far as I can tell in my great ignorance) they seem pretty perfect!  Thanks man!
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

BentonGrey

Alright, here's a new one.  Would/could anyone tweak the Mimic attribute to copy powers/stats and not appearance? 
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

Copying stats should be  easy. Copying powers without using the mesh, on the other hand... basically impossible IIRC, plus animations are not standardized, so it wouldn't be reliable anyway. The only way it could be made to work would be for a specific campaign with a set Mimic and specific targets. You'd basically create a copy of every character and powers to use with the mimic's mesh and keyframes. I think Dr.Mike did this in The Strangers with Devil Doll.
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Yeah, I should have realized that.  Thanks Epi!

So, what do I need to do to create a version of Transmutator that ONLY allows you to munch down on solid matter as a melee attack?
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

Good point! Since the distance is hard-coded into the Transmutator attribute's custom actions, you currently can't. You could change the Transutator script to add a new category similar to "solid", but for melee range – let's call it "food".

def inittransmutator(char,update=0):
    if isMP():
        return
    if update==0:
        for set in transmutables:
            if type(set[1]) == TupleType:
                for entry in set[1]:
                    Mission_CustomAction(set[0],char,entry,set[2],30,0)
            else:
                if set[1]=='all':
                    for temp in templates:
                        if isObject(temp[0]):
                           Mission_CustomAction(set[0],char,temp[0],set[2],30,0)
                if set[1]=='solid':
                    for temp in templates:
                        if isObject(temp[0]) and isSolid(temp[2]):
                           Mission_CustomAction(set[0],char,temp[0],set[2],30,0)
                if set[1]=='food':
                    for temp in templates:
                        if isObject(temp[0]) and isSolid(temp[2]):
                           Mission_CustomAction(set[0],char,temp[0],set[2],5,0) #tweak that penultimate number to the correct melee distance based on in-game tests
                elif set[1]=='metal':
                    for temp in templates:
                        if isObject(temp[0]) and temp[2]==1:
                           Mission_CustomAction(set[0],char,temp[0],set[2],30,0)
                elif set[1]=='throwable':
                    for temp in templates:
                        if isObject(temp[0]) and temp[1]!=FFX_TOO_HEAVY:
                           Mission_CustomAction(set[0],char,temp[0],set[2],30,0)
                elif set[1]=='stone':
                    for temp in templates:
                        if isObject(temp[0]) and temp[2]==2:
                           Mission_CustomAction(set[0],char,temp[0],set[2],30,0)
                else:
                    Mission_CustomAction(set[0],char,set[1],set[2],30,0)


However, what I completely missed (oops, weird how much one forgets after stopping working on something for twelve years): Transmute will still give you the other transmute built-in commands, which don't fit your MEL character. Possible solutions:

1. Create a new copy of the Transmute attribute (Matter Eater) to get only the matter eating part.
2. Use the existing Metal Eater attribute instead, even if it doesn't quite follow the way MEL power work in the comics, it could be considered close enough as game mechanics go.
3. Create a carrier power swap to melee attack objects directly. However, FFX uses the effect status to swap these effects, and this depends on EVENT_CHARACTER_STATE_CHANGED and EVENT_CHARACTER_SEC_STATE_CHANGED, which, IIRC, don't trigger for non-characters. Of course, as objects don't dodge or block much (and depending on the state effect, either resist 100% or not at all), we could just bypass this and use some mlog animate check, but it would still mean implementing a whole new carrier attack system...

FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Thanks Epi!  Okay, so I'm getting better at this stuff, but I'm still pretty dense.  What, exactly, will I need to copy/change to get the new copy of Transmutator as Matter Eater?  I haven't done that kind of thing before.
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

I'd guess it would be something like this:

In ffx.py, you'd add the following before the def initassimilator(char,update=0): line:

def initmattereater(char,update=0):
    if isMP():
        return
    if update==0:
        for temp in templates:
            if isObject(temp[0]) and isSolid(temp[2]):
                Mission_CustomAction('CUSTOM_EAT',char,temp[0],OnTransmuteToHealth,5,0) #tweak that penultimate number to the correct melee distance based on in-game tests

def OnTransmuteToHealth(target,char):
    Trigger_Damage(char,-10)
    currentEnergy = Object_GetAttr(char, 'energyPoints')
    FFX_SetEnergy(char,currentEnergy+10)
    OnTransmute(target,char,'OnEating')

def OnEating(event):
    target=event.object
    Object_PlayEffect(target,'effect_ffx_pheremones') #replace with a different effect
    damage=randint(3,7)
    Trigger_Damage(target,damage)
    if Object_IsAlive(target):
        if event.user<4:
            RegTimer('OnEating',2,event.user+1,target)


In FFEdit, add an attribute named "mattereater".

Edit strings.txt Add the CUSTOM_EAT_01, CUSTOM_EAT_DESC_01, ATTRIB_MATTEREATER_01 and ATTRIB_MATTEREATER_DESC_01 entries and compile the file with FFEdit.
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Awesome, thanks so much, Epi, and thanks for your patience, man!
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

#11
No trouble, Benton! I hope it does work; if not, let me know—we'll find a way.
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Okay, I had some unrelated problems to solve, but now that they're out of the way, back to Matter Eating!  I've created the attribute as advised, but I get an error message when using it in game.  Here is the attribute code as I have added it, with the previous and next entries in ffx.py for context:

Quotedef OnShortOut2(event):
    target=event.object
    if Object_GetAttr(target,'health')<=0:
        return
    obj='cu%s'%(target)
    if Object_Exists(obj):
        Trigger_Explosion(obj,'generic electrical explosion')
    else:
        cshelper.spawn(obj,'portal_start_proxy',target)
    RegTimer('OnShortOut2',2,0,target)

def initmattereater(char,update=0):
    if isMP():
        return
    if update==0:
        for temp in templates:
            if isObject(temp[0]) and isSolid(temp[2]):
                Mission_CustomAction('CUSTOM_EAT',char,temp[0],OnTransmuteToHealth,5,0) #tweak that penultimate number to the correct melee distance based on in-game tests

def OnTransmuteToHealth(target,char):
    Trigger_Damage(char,-10)
    currentEnergy = Object_GetAttr(char, 'energyPoints')
    FFX_SetEnergy(char,currentEnergy+10)
    OnTransmute(target,char,'OnEating')

def OnEating(event):
    target=event.object
    Object_PlayEffect(target,'effect_ffx_pheremones') #replace with a different effect
    damage=randint(3,7)
    Trigger_Damage(target,damage)
    if Object_IsAlive(target):
        if event.user<4:
            RegTimer('OnEating',2,event.user+1,target)

def initassimilator(char,update=0):
    if isMP():
        return
    if update==0:
        for set in assimilations:
            if type(set[1]) == TupleType:
                for entry in set[1]:
                    Mission_CustomAction('CUSTOM_ASSIM',char,entry,set[2],4,0)
            else:
                Mission_CustomAction('CUSTOM_ASSIM',char,set[1],set[2],4,0)
    RegTimer('AssimUpdate',1,0,char)

And here is the traceback from scriptlog.  I'm guessing this will mean something to you, Epi.

QuoteexecInitAttrib: init mattereater attribute
    on hero_0 of template custom_template_53 (matter_eater)
execInitAttrib: ERROR in initialising attribute mattereater
Traceback (innermost last):
  File "C:\Program Files (x86)\Steam\steamapps\common\Freedom Force vs. the 3rd Reich\.\DCUG\missions\scripts\ffx.py", line 930, in initAttribsEvent
    initAttribsForChar(event.object,event.user)
  File "C:\Program Files (x86)\Steam\steamapps\common\Freedom Force vs. the 3rd Reich\.\DCUG\missions\scripts\ffx.py", line 893, in initAttribsForChar
    execInitAttrib(char, attribute, update)
  File "C:\Program Files (x86)\Steam\steamapps\common\Freedom Force vs. the 3rd Reich\.\DCUG\missions\scripts\ffx.py", line 914, in execInitAttrib
    execInitAttrib2(char, attribute, init)
  File "C:\Program Files (x86)\Steam\steamapps\common\Freedom Force vs. the 3rd Reich\.\DCUG\missions\scripts\ffx.py", line 922, in execInitAttrib2
    exec init
  File "<string>", line 1, in ?
  File "C:\Program Files (x86)\Steam\steamapps\common\Freedom Force vs. the 3rd Reich\.\DCUG\missions\scripts\ffx.py", line 11355, in initmattereater
    Mission_CustomAction('CUSTOM_EAT',char,temp[0],OnTransmuteToHealth,5,0) #tweak that penultimate number to the correct melee distance based on in-game tests
RuntimeError: Mission_CustomAction(): expects args {ssss|f}
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

Looks like I forgot some quotes...

Mission_CustomAction('CUSTOM_EAT',char,temp[0],OnTransmuteToHealth,5,0)
should be
Mission_CustomAction('CUSTOM_EAT',char,temp[0],'OnTransmuteToHealth',5,0)

I hope it helps.
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Awesome!  It's working!  You're the man, Epi!

So, now ME can eat objects and regain health, which is just awesome.  I'm constantly amazed at how flexible this game is!  We've only got one glitch, it seems that doing so stops his energy from recharging.  Can we fix that?

Also, where can I change the triggered animation?
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

I can't figure out the bug. Do you still get relevant error messages in script.log? Otherwise, I'd suggest adding some basic debug code to OnTransmuteToHealth():


def OnTransmuteToHealth(target,char):
    Trigger_Damage(char,-10)
    currentEnergy = Object_GetAttr(char, 'energyPoints')
    print "Energy Points before = %i" %currentEnergy
    FFX_SetEnergy(char,currentEnergy+10)
    print "Energy Points after =  %i" %Object_GetAttr(char, 'energyPoints')
    OnTransmute(target,char,'OnEating')


Hopefully,* script.log should now give us additional clues.

As for changing the animation... Since we're calling the OnTransmute() function, I think* you might be able to use the following in ffxcustom.py:

FFX_TRANSMUTATOR_CUSTOM=[
["default","ffx_transmute"],
["types","dDummy Power"],
["name of your character","dummy melee power name using a biting animation"],
]



*If it works, the maxim "I think, therefore I am" applies. Otherwise, "I think, therefore I err" wins. To err is human, therefore I'm probably going to be human. However, if, instead of erring, I am, "to am is human" is an error, therefore I'd be erring, which is human.
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Epi, man, I really appreciate all the help you're giving me with this!

So, I added that code and I added the customization.  The customization worked like a charm, and Matter Eatter Lad is now using the appropriate animation!  I'm getting no error messages in the script.log, but here is what little there was following the attributes initiation. 
Spoiler
initAttribsForChar (matter_eater): looking at attribute mattereater
execInitAttrib: init mattereater attribute
    on hero_0 of template custom_template_53 (matter_eater)
lThrowable:no such template exists!
initAttribsForChar: working on _skthug_with_bat01 (thug_with_bat)
initAttribsForChar (thug_with_bat): looking at attribute timid
initAttribsForChar (thug_with_bat): looking at attribute weak minded
Plugin 'firehydrant' OnPostInit() called
Plugin 'zombie' has no OnPostInit()
Plugin 'freeroam_keepbuildingdamage' OnPostInit() called
Plugin 'm25ai_lowjumper' has no OnPostInit()
Plugin 'm25ai_realitymanipulation' has no OnPostInit()
Plugin 'cutscene_power' has no OnPostInit()
Plugin 'm25encexit' has no OnPostInit()
Plugin 'm25enc_opendoor' has no OnPostInit()
Plugin 'm25enc_reqchar' has no OnPostInit()
Plugin 'm25enc_simplechoice' has no OnPostInit()
Plugin 'm25encstory' has no OnPostInit()
2
1
Energy Points before = 105
Energy Points after =  105
Energy Points before = 80
Energy Points after =  80
Energy Points before = 55
Energy Points after =  55

That involves several 'meals' of different objects.
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/

Epimethee

Hmm... FFX_SetEnergy() seems to work differently from how I thought it would. I thought it was a general utility, but it seems to be specific to Battery-powered characters. How I wish this function had been documented.

Could you try this?
def OnTransmuteToHealth(target,char):
    Trigger_Damage(char,-10)
    currentEnergy = Object_GetAttr(char, 'energyPoints')
    print "Energy Points before = %i" %currentEnergy
    Object_SetAttr(char, 'energyPoints', currentEnergy+10)
    print "Energy Points after =  %i" %Object_GetAttr(char, 'energyPoints')
    OnTransmute(target,char,'OnEating')


I've replaced the FFX_SetEnergy() function with the built-in Object_SetAttr() function. IIRC, energyPoints shouldn't go above max. If they do, please replace that line with the following:
    Object_SetAttr(char, 'energyPoints', min(Object_GetAttr(char, 'maxEnergyPoints'), currentEnergy+10))
FFX add-on for FFvsTTR at ffx.freedomforceforever.com

BentonGrey

Thanks Epi!  It seems to be working properly now. 

Spoiler
Plugin 'm25encstory' has no OnPostInit()
2
1
Energy Points before = 105
Energy Points after =  115
Energy Points before = 23
Energy Points after =  33
Energy Points before = 27
Energy Points after =  37
addArrow _sk_arrow _skthug_with_gun04 0 0

I think we've (you've!) got it licked!
God Bless
"If God came down upon me and gave me a wish again, I'd wish to be like Aquaman, 'cause Aquaman can take the pain..." -Ballad of Aquaman
Check out mymods and blog!
https://bentongrey.wordpress.com/