• Welcome to Freedom Reborn Archive.
 

Mlog Reader Help

Started by Conduit, March 10, 2007, 07:31:46 AM

Previous topic - Next topic

Conduit

I'm looking to make a script that plays different effects on characters based on what animations they are using.  The Mlog reader is supposed to watch animations, but it only has an isFlying function, which treats flying and hovering as the same thing, and I want separate hovering and flying animations.  I looked in the script to see if I could modify it, but I found myself completely unable to understand it.  The WatchFlying function sets the variable 'ai_flying' to 1 if the character is hovering or flying, but that variable isn't referenced anywhere else.  The actual isFlying function checks for the attribute 'isFlying', but this attribute is only set to 1 in a long section that has been commented out.

How, exactly, does this thing work, and how could I add an isMoving function?

stumpy

The mlogreader module is a tricky one, largely because 1) it has been tweaked to do what it does in a reasonably fast way. (It hunts through the ff.log file ten times per second. That file will typically grow to several megabytes during game play. You do the math...) And 2) it provides the same sort of event sink functionality that the game engine itself does, which is a more complicated scripting task than typical mission or even attribute scripting.

Most of the external functionality of the module is available in the regSomething() functions that set up callback sinks when various things happen, similar to those provided by the game for damage detection, KOs, state changes, etc. At some point, we (I forget if it was Épiméthée or I who did this most recently) had posted documentation for those functions to this forum, but they aren't available now and I don't know if the mlogreader page (ffx3\manual\mlogreader.html) is as up-to-date as what was here. But, it is a good place to start.

If you look at the mlogreader.py file and go down to the "Basic Animation State Determination" section, you will see how have set up the registration for detecting changes of flying, flailing, getting up, landing, idling, and knockback states.

You are right that we treat flying and hovering as the same because the intended use was mostly related to figuring out if a given character was on the ground or not (e.g. should he be a target for a melee attack? should NIMBLE FLIER kick in now?) and so on. You can certainly write functions that differentiate the two types of animations, though it can be a little hairy. You would need to look at how we have done it for flying and go from there. You will also want to look at the documention for the chunkstring module at http://www.stumpyanker.com/ffscripts/ChunkstringDocumentation.html.

BTW, some consideration was given to adding functions to mlogreader that would allow setting sinks and callback handlers for any animation state (for example, maybe you want to know when a character enters a "special" animation state to detect transformation or teleportation, etc.). But there is a performance hit for that and it was back-burnered. (At least by me; maybe someone else has tested it out...)

Conduit

Quote from: stumpy on March 10, 2007, 09:42:33 AM
At some point, we (I forget if it was Épiméthée or I who did this most recently) had posted documentation for those functions to this forum, but they aren't available now and I don't know if the mlogreader page (ffx3\manual\mlogreader.html) is as up-to-date as what was here. But, it is a good place to start.

Where is that Mlogreader page?  I looked on fundamentzero.com, but it wasn't there.

stumpy

Those are the manual pages on your hard drive from when you installed FFX 3.2 (and maybe earlier versions, but I didn't save all my old documentation, so I don't know). In other words ..\Freedom Force vs The 3rd Reich\ffx3\manual\mlogreader.html

Conduit

It isn't in my version.  Where can I get FFX 3.2?

stumpy

The second beta is on catwhowalksbyhimself's site http://libertybay.freedomforceforever.com/ffx.htm. I could also email you just the html file, but FFX 3.2 has a substantially updated mlogreader and a newer version of the chunkstring module. If you are still using FFX 3.1, you will want to upgrade, though back up all your stuff first. There isn't much point in customizing the older mlogreader.py only to have a hard time bringing the customizations to the new version because they are so different.

Epimethee

I'll second the recommendatioon to upgrade to FFX 3.2 for playing with the MLOG Reader. BTW, hovering could mean that your character is either flying, levitating, jumping up or jumping down. The "hovering" animation is used by all of those.

As for the doc, I'm currently revamping the manual a bit, so the MLOG Reader's should be more accessible and up to date when we finally get the official release out the door.

Conduit

Thanks.  I noticed that the new mlogreader has an isIdle function.  This detects hovering as idling.  So, I should be able to combine that with isFlying to differentiate hovering and flying, right?

Unfortunately, I seem to be having trouble getting it to work.  Whenever I use one of the animation detection functions, it just returns the default value, no matter what the character is doing.  Do you have any idea what might be causing this?

stumpy

That's a clever approach, and much easier than writing and testing new functions.  :cool:

I didn't have any trouble getting the state functions to work. What were you trying? Just as a test, I opened the console and printed out the flying and idling states for a hero and baddy in the RR at different times and got
for o in Mission_GetDynamicObjects():print '%s: %d %d'%(o,mlogreader.MLOG_IsFlying(o),mlogreader.MLOG_IsIdle(o))
hero_0: 0 1
_skalien_sergeant01: 1 0
>>> for o in Mission_GetDynamicObjects():print '%s: %d %d'%(o,mlogreader.MLOG_IsFlying(o),mlogreader.MLOG_IsIdle(o))
hero_0: 1 0
_skalien_sergeant01: 1 0
>>> for o in Mission_GetDynamicObjects():print '%s: %d %d'%(o,mlogreader.MLOG_IsFlying(o),mlogreader.MLOG_IsIdle(o))
hero_0: 1 0
_skalien_sergeant01: 1 1
>>> for o in Mission_GetDynamicObjects():print '%s: %d %d'%(o,mlogreader.MLOG_IsFlying(o),mlogreader.MLOG_IsIdle(o))
hero_0: 1 0
_skalien_sergeant01: 1 0
>>> for o in Mission_GetDynamicObjects():print '%s: %d %d'%(o,mlogreader.MLOG_IsFlying(o),mlogreader.MLOG_IsIdle(o))
hero_0: 1 0
_skalien_sergeant01: 1 0
>>> for o in Mission_GetDynamicObjects():print '%s: %d %d'%(o,mlogreader.MLOG_IsFlying(o),mlogreader.MLOG_IsIdle(o))
hero_0: 1 1
_skalien_sergeant01: 1 1
>>> for o in Mission_GetDynamicObjects():print '%s: %d %d'%(o,mlogreader.MLOG_IsFlying(o),mlogreader.MLOG_IsIdle(o))
hero_0: 1 1
_skalien_sergeant01: 1 1


(I deleted the other stuff and the entries for ffxgun and ffxtarget.)

There are entries for both the hero and baddy, flying and idling.

Conduit

Well, here's the onPostInit function of the mission I'm testing it on:

def OnPostInit():
    ff.RANGED_MIN=1
    MLOG_Init()
    MLOG_IsFlying('sentinel1')
    MLOG_IsFlailing('sentinel1')
    MLOG_IsIdle('sentinel1')


I've tested it out by opening up the console and entering print + one of the last 3 functions.  Regardless of what animation the character is using, it always returns 0.0 for isFlying and isFlailing, and 1.0 for isIdle.

Edit: I did some testing, and it appears as if it isn't reading the log at all.  Do I have to do anything special to enable the log?

stumpy

You can enable the module separately, but it should be enabled when FFX starts up. Of course, FFX should be imported and you should have FFX_InitSkirmish() (for RR sessions, InitMission() for campaign missions) in your OnPostInit() before the mlogreader calls. And, depending on how you imported mlogreader, you might need to call the functions as mlogreader.MLOG_IsFlying('sentinel1'), etc.

Of course, the three MLOG_* lines you have in OnPostInit() won't do anything that you can see, since they just return a value and you are not doing anything with the value. I assume you are using them elsewhere to do your testing... You should post that code.

BTW, just to check, 'sentinel1' is the name of the in-game object you are testing, not the object's template name, right?

You might want to post your script.log with your code and describe what you want that code to do.



Here is an outline of some code you might try in your script. I haven't tested it and I don't really know what you want to do, but it should point you in the right direction
import mlogreader
from ffx import *

def OnPostInit():
    FFX_InitSkirmish()  # if this is a RR script, OR
    FFX_InitMission()   # if this is a campaign mission
    # ...
    # 'sentinel1' is the name of a character object
    mlogreader.regFlightStart('sentinel1','CheckFlyAndHover',persistent=1)
    mlogreader.regIdleStart('sentinel1','CheckFlyAndHover',persistent=1)
    # ...

def CheckFlyAndHover(event):
    char = event.object
    if mlogreader.MLOG_IsFlying(char):
        if mlogreader.MLOG_IsIdle(char):    # we're hovering
            Mission_StatusText('%s is hovering'%char)
            regIdleStop(char,'OnHoverStop')
            # Whatever else you want to do when hovering starts
            # NB: the character might still be flying...
        else:   # we're fliying
            Mission_StatusText('%s is flying'%char)
            regFlightStop(char,'OnFlightStop')
            # Whatever else you want to do when flying starts
            # NB: the character will have just left the ground

def OnFlightStop(event):
    char = event.object
    Mission_StatusText('%s stopped flying'%char)
    # Whatever else you want to do when character lands
    # NB: this isn't triggered when the character switches from fly to hover

def OnHoverStop(event):
    char = event.object
    Mission_StatusText('%s stopped hovering'%char)
    # Whatever else you want to do when character stops hovering
    # NB: character might still be flying, or might have been knocked back, etc.


I tried to note some possible areas to be careful, since it will be easy to think of flying and hovering as completely separate states, when the code is thinking about hovering (in this case) as just a subset of flying. In other words, a hovering character is both flying and idle, so you have to keep that straight.

Anyway, I hope that helps, at least as an example of using the mlogreader functions.

Conduit

I've figured out the problem.  It turns out that in order for the game to generate a log, you have to run it in a command line with -log at the end, ie with a shortcut.  I was running it through FFEdit, which by default points directly at the game exe, so there was no log for the Mlog reader to look through.  I added -log to the end of the game exe path, and it worked.  Thanks a lot for your help.