Jump to content

Inconsistent results from a user-defined OnDeath handler with filters


DaWrecka

Recommended Posts

I'm working on updating a FO3 mod I made to Tale of Two Wastelands. In that mod, I had a quest stage call GetDead() on every slaver in Paradise Falls, and give the player some bennies once every one was dead. In the update, I decided to try and update it with NVSE capabilities into something more efficient; I decided to try using an OnDeath event handler to trap the death of characters like so:

SetEventHandler "OnDeath" fnProcessParadiseSlaverDeath, "first"::NPCParadiseFallsSlaverLIST

fnProcessParadiseSlaverDeath is an Object script containing a function which I've included here:

scn fnProcessParadiseSlaverDeath

short iKillFlag ; The kill flag associated with the current victim

ref Victim
ref Attacker ; Not actually needed for our purposes, but the parameter must still be present

begin Function { Victim, Attacker }
    if ParadiseLostQUST.bParadiseIsAlreadyLost
        DebugPrint "fnProcessSlaverDeath: Paradise Falls already destroyed, exiting"
        RemoveEventHandler "OnDeath" fnProcessParadiseSlaverDeath
        return
    endif
    
    let Attacker := NPCParadiseFallsSlaverLIST ; DebugPrint throws a hissy fit if you try to pass it a form list directly. It demands a variable!
    ; No deviations! Or you vill be beaten! Achtung! Allarme! And other noises of stubborn insistence!
    ; We have no actual use for the Attacker variable, so why the f*#@ not?
    
    if Victim.IsInList Attacker
        DebugPrint "Victim %i is found on list %i: continuing", Victim, Attacker
    else
        DebugPrint "Victim %i could not be found on list %i: exiting", Victim, Attacker
        Return
    endif
    
    if Victim.GetType == 42 ; NPC_
        DebugPrint "fnProcessSlaverDeath: Victim is NPC type, continuing"
    else
        DebugPrint "fnProcessSlaverDeath: Victim is not an NPC, aborting"
        Return
    endif
    
    DebugPrint "fnProcessSlaverDeath: Found reference %i", Victim
    let Victim := Victim.GetBaseObject
    DebugPrint "fnProcessSlaverDeath: Found base object %i", Victim
    
    let iKillFlag := ListGetFormIndex Attacker Victim
    if iKillFlag == -1 ; Sanity check
        DebugPrint "fnProcessSlaverDeath ERROR: ListGetFormIndex returned value of -1 for Victim and list %i: unable to continue", Attacker
        Return
    else
        DebugPrint "fnProcessSlaverDeath: Victim found on list %i in position %.0f", Attacker, iKillFlag
    endif
    
    DebugPrint "fnProcessSlaverDeath: Previous set of kill flags is %x", ParadiseLostQUST.iKillFlags
    let ParadiseLostQUST.iKillFlags := ParadiseLostQUST.iKillFlags | (2 ^ iKillFlag)
    DebugPrint "fnProcessSlaverDeath: Kill flags have been set to %x", ParadiseLostQUST.iKillFlags
    if eval (ParadiseLostQUST.iKillFlags == ((2 ^ (ListGetCount Attacker))-1))
        DebugPrint "fnProcessSlaverDeath: All kills flagged, executing ParadiseLostQUST stage 200"
        SetStage ParadiseLostQUST 200
    endif
end



NPCParadiseFallsSlaverLIST is a FLST, mostly-empty in FalloutNV.esm and even unused in Fallout3.esm and TaleOfTwoWastelands.esm, that contains base form IDs for every slaver from Paradise Falls. From the debugging lines printed to the console, and saved to my log, I can tell that while the event handler is called on most of the people on that list, including Eulogy Jones, Forty, and some of the unnamed slavers, it isn't called on Grouse, Richter, or Pronto - even though all three are definitely on the FLST.


So I tried setting the event handler another way:

SetEventHandler "OnDeath" fnProcessParadiseSlaverDeath, "first"::NPCParadiseFallsResidentLIST

ResidentLIST is basically like the SlaverLIST, except it includes the slaves. This one still doesn't work; the event handler still fails to catch the death of Grouse, Richter, or Pronto.


So far the only way I've found to actually have my event handler reliably catch all of the slaver deaths is to declare the event handler with no filter at all - which is obviously not ideal. Especially when it SHOULD be working, but isn't because, I don't know, maybe because this engine is held together with spit and sellotape.


I have no idea what the crap is going on here; can anyone provide pointers?


tl:dr; I'm declaring an OnDeath event handler using a form list as a filter for the victims, but the stupid engine is being an arse and refusing to call that event handler for some NPCs which are definitely on that list. Can anyone tell me WTF is going on and WTF I can do to fix? Edited by DaWrecka
Link to comment
Share on other sites

I wish I had Fallout 3 till I could check for you but I don't, so I would say that my instinct tells me that something is wrong with the form list and that Grouse, Richter, and Pronto are somehow not on it. Obviously, you're saying that's not the case, but is it possible that as it's an unused list in the vanilla game, they perhaps made more than one version of the characters that aren't being caught by the event handler and that the old versions of these characters were put on the form list before they decided not to use it and thus never updated it?

 

This probably isn't the problem but do be aware that event handlers must be set every time the game is launched, meaning a save file that was made after the handler is set will not have the handler active if the game is exited to the desktop and relaunched.

 

I'll look over your post again and see did I miss something.

Link to comment
Share on other sites

I wish I had Fallout 3 till I could check for you but I don't, so I would say that my instinct tells me that something is wrong with the form list and that Grouse, Richter, and Pronto are somehow not on it. Obviously, you're saying that's not the case, but is it possible that as it's an unused list in the vanilla game, they perhaps made more than one version of the characters that aren't being caught by the event handler and that the old versions of these characters were put on the form list before they decided not to use it and thus never updated it?

I've checked with GECK and FNVEdit; the base forms in the world are definitely the same ones as on the form list, and there is nothing in my load order overriding the list.

 

I DID notice that Grouse, Richter and Pronto have the "capital M with an arrow through it" model within GECK that's associated with levelled actors... The logical conclusion would be that it's connected, except there are other slavers like Jotun and Carolina Red who also have the same "arrow-M" model in the GECK, and those have no problem.

 

EDIT: Oh, also, a detail I just remembered: If I register the event handler with no filters at all, meaning it catches ALL kills - it will catch Grouse, Richter and Pronto; And when the event handler processes those kills, it reports that yes, those NPCs ARE on the Slaver list, in that both IsInList returns true, and ListGetFormIndex returns a value that is not equal to -1, and they return a base object that, to my eyeballs, is on the list.

 

This probably isn't the problem but do be aware that event handlers must be set every time the game is launched, meaning a save file that was made after the handler is set will not have the handler active if the game is exited to the desktop and relaunched.

I'm aware of this, and no it's not the problem; I have a savegame I'm using for testing which, immediately after loading, has a console entry that states the event handler has been registered; I kill Richter, nothing in console. Kill Grouse, no console output. Move in and kill Forty, the function's debug logging strings appear to show that Forty's death has been registered.

Edited by DaWrecka
Link to comment
Share on other sites

Defo sounds as if the levelled actor is the trouble. You need to check for differences between the way the functioning levelled actors are done and the way these three are done. I'll do some research in the meantime as I don't have FO3. This is really weird (and I secretly love it and find it mentally engaging because I'm sick).

Link to comment
Share on other sites

 

Defo sounds as if the levelled actor is the trouble. You need to check for differences between the way the functioning levelled actors are done and the way these three are done. I'll do some research in the meantime as I don't have FO3. This is really weird (and I secretly love it and find it mentally engaging because I'm sick).

Hmm. Okay. So, comparing the following slavers:

  • Jotun, whose death is trapped
  • Carolina Red, whose death is trapped
  • Grouse, whose death is NOT trapped
  • Ymir, whose death is NOT trapped
and narrowing it down to things which are common to all four; common to one pair and not the other; (ingoring Voice Type for example, since the two working ones have different voice types, the two non-working ones also have different voice types, and to cap it off Ymir - who doesn't work - has the same voice type as Jotun - who does) or just otherwise seem worthy of mention; we have these similarities and differences; (I'm using FNVEdit for these comparisons, with my full load list, to make sure that it isn't an override from something else making things difficult)

  • All four have the "arrow-M" model in the GECK.
  • All four use the LvlSlaver template.
  • All four have the "Use Stats" template flag and no others.
  • All four have the Slaver class.
  • All four have Height and Weight set to 0.00 in their base form
  • None of them have the Essential, "No low level processing", "Quest item", "Respawn", "Is CharGen Face Preset", "No Knockdowns", "Respawn", or "No VATS Melee" flags set.
  • Grouse and Ymir have unique scripts, both of which have OnDeath blocks. Jotun has no script at all, but Carolina Red has a script, ParadiseFallsSlaverScript, which also has an OnDeath block.
  • All four are set to Aggressive, Foolhardy, 50 Responsibility, Mood Neutral, and Assistance "Helps Friends and Allies".
  • All four have their references set to Persistent
I'm just not seeing any differences to explain this...

This is pretty obvious but the sort of thing that sometimes gets overlooked, so I'll mention it: by any chance are those three involved in quests or marked "essential"?

 

All of them are killable, so they're not Essential. Pronto and Grouse are both involved in quests, Pronto in the unmarked quest Economics of Violence, Grouse in the marked sidequest Strictly Business and the story quest Rescue From Paradise. Richter, however, isn't involved in any quests. In fact, in-game he doesn't even have a name, just "Slaver".
Link to comment
Share on other sites

Neither is marked essential , But Pronto and Grouse do have quests. I don't think Richter does though , but maybe he is involved in the Grouse quest , or possibly something with that first scene with a slave running out and his collar blowing up.

 

Oh ya ... and it should me noted that Grouse , Richter and Pronto are never in the Paradise Falls small world cells.

Link to comment
Share on other sites

Oh right. Addendum; I found that the handler fails to catch Ymir's death. Ymir's editor location is the PF barracks, although he gets moved to the main courtyard by a script some time before you get there. Pronto is always in Lock and Load, though.

 

...further addendum, Carolina Red is NOT caught. I'm going through them one-by-one right now to make absolutely certain which deaths are caught and which aren't, and I'm going to take another look after that.

 

So. I've been through the lot of them now, and the following slavers aren't trapped by the event handler:

Grouse
Richter
Pronto
Carolina Red
Jotun
Ymir

 

so it seems the four I was comparing before were all faulty. Yay for wasting my own time. FNVEdit is currently loading up and this time, I'm certain I'll be checking the right bloody ones...

 

However, one point I feel I should make; if I declare my event handler with no filters at all, it DOES trap those deaths, and it DOES process them correctly - meaning that all of those slavers ARE on the list that's used for filtering, because if they weren't I'd be getting entirely different messages in the console.

Edited by DaWrecka
Link to comment
Share on other sites

I tried to get my friend's copy of Fallout 3 to have a look but ran into some trouble with that.

 

My research only really yielded that you can use levelled actors with an event handler, but we knew that. However, if you want, I was reminded that Docta Sax may know what peculiarities are at play here, so you could message him.

 

Try using the console to get the base form of one of the non-working NPCs and then match that in the GECK just to be certain.

 

Or try doing an OnDeath event handler that specifies one of the non-working slavers instead of a form list that includes them. This could work and then lead to a comparatively tedious workaround, though I'd rather find a real solution.

Link to comment
Share on other sites

Oh right. Addendum; I found that the handler fails to catch Ymir's death. Ymir's editor location is the PF barracks, although he gets moved to the main courtyard by a script some time before you get there. Pronto is always in Lock and Load, though.

 

...further addendum, Carolina Red is NOT caught. I'm going through them one-by-one right now to make absolutely certain which deaths are caught and which aren't, and I'm going to take another look after that.

 

So you are saying so far all NPC's relying on the lvlSlaver for Stats only ,which rely on EncSlaver for everything. Are not working so far ? Where as Eulogy and Forty don't use the template data at all , are working ?

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...