Author Topic: Reacting to FTech events?  (Read 1922 times)

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Reacting to FTech events?
« on: July 24, 2013, 09:10:58 AM »
First and foremost. I am an idiot. To those with 10 years Python and BC API experience on me  :bow:
Apologies for the (no doubt) repost. Search of BC Scripting / Modding came up dry with: Creating a basic autoload script and Becoming A Scripter 101. Neither covered what i'm after.
- - - -
How would one go about defining a trigger for a FoundationTech event such as the Breen Damper?

I have a QBautostart script. I know that you can create triggers and react to those triggers within the same script thusly:
Code: [Select]
App.g_kEventManager.AddBroadcastPythonFuncHandler(App.ET_OBJECT_EXPLODING, pMission, __name__ + ".ObjectDestroyed")

def ObjectDestroyed(pObject, pEvent):
        pObject = App.ObjectClass_Cast(pEvent.GetDestination())
        pShip = App.ShipClass_Cast(pObject)
        print pShip.GetName(), " just blew up!"
        pObject.CallNextHandler(pEvent)

I believe I found the way FTech is defining its triggers ( \scripts\FoundationTech.py )
Code: [Select]
App.g_kEventManager.AddBroadcastPythonFuncHandler(self.eventKey, MissionLib.GetEpisode(), 'FoundationTriggers.' + self.name + str(self.eventKey))
The problem is the first argument ( self.eventkey ) because it is a variable dynamically created by FTech. In order to create a:
App.g_kEventManager.AddBroadcastPythonFuncHandler
I will need the value of self.eventkey for Breen Damper tech.

The purpose here is to have custom code triggered when a Damper Weapon enabled FTech torpedo impacts a target.
Code: [Select]
def ShipHitWithDamper(pObject, pEvent):
        pObject = App.ObjectClass_Cast(pEvent.GetDestination())
        pShip = App.ShipClass_Cast(pObject)
        print pShip.GetName(), " was just hit with a Breen Damper torpedo!"
        pObject.CallNextHandler(pEvent)
Great men are not peacemakers! Great men are conquerors!

Offline Mario

  • Senior Software Developer
  • Administrator
  • Posts: 2186
  • Cookies: 1706
  • Life is life
Re: Reacting to FTech events?
« Reply #1 on: July 24, 2013, 01:47:44 PM »
The thing is that the following doesn't belong under BC API category. This mod was written by MLeo so I'd advise you to study the BreenDamper source code and see if it exposes any events for a start.

Many of us who wrote certain scripts exposed certain API elements for others to attach to. However I can't say that we all used some unified approach though.
Acta, non verba.
aka USS Sovereign

Offline Nighthawk

  • |______[o]_|
  • Posts: 750
  • Cookies: 18
Re: Reacting to FTech events?
« Reply #2 on: July 24, 2013, 03:01:56 PM »
IIRC there's a limited set of listeners predefined by FTech, and they're continuously scanning the game at every event being fired.
so if you fire a breen damper, a transphasic torpedo or hit a regenerative shield, it's the same module tracking all those events, which then gets directed to each particular action (cutting power, ignoring shields, or boosting shields, in these cases)

search the code for OnWeaponHit, OnFire, OnYield,... those are bound to be from FTech

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #3 on: July 24, 2013, 03:45:24 PM »
DamperWeapon.py defines its own OnYield's as member functions of a class of BreenDrainerWeaponDef and _BreenDrainerWeaponDef.

Beyond this DamperWeapon.py does not mention triggers anywhere but it does import App, FoundationTech and MissionLib.

In FoundationTech.py it calls oYield.OnYield functions but oYield is set as:
Code: [Select]
oYield = dYields[sName]where dYields is defined as:
Code: [Select]
dYields = {} # Dictionary of weapon yields, placed here by projectile .py's for lookup
This is where the trail dead-ends for me. The only things FoundationTech import are:
Foundation               # 1000+ lines, no mention of "trigger"
FoundationTriggers     # empty
MissionLib                 # include BC API stuff
Registry                   # ?
string                     # irrelevant .pyc
Great men are not peacemakers! Great men are conquerors!

Offline KrrKs

  • Posts: 461
  • Cookies: 25
Re: Reacting to FTech events?
« Reply #4 on: July 25, 2013, 06:46:08 AM »
I hope i'm not totally wrong, but isn't the "WeaponHit" class in FoundationTech pretty much what you want to do?
Note the
Quote
oWeaponHit = WeaponHit('WeaponHit', App.ET_WEAPON_HIT, dMode)
at the end.

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #5 on: July 25, 2013, 08:38:42 AM »
Perhaps that is what I am looking for ... ?
I do not understand how to use it though and naturally failed by implementing it as:
Code: [Select]
import App
import MissionLib
import Foundation
import string
import Lib.LibEngineering
from QuickBattle import Quickbattle

# handle Breen Damper FTech equipped weapons
def WeaponHit(pObject, pEvent):
pShip = App.ShipClass_Cast(pEvent.GetDestination())
weapType = ""
if pEvent.GetWeaponType() == pEvent.PHASER:
weapType = "Phaser"
elif pEvent.GetWeaponType() == pEvent.TRACTOR_BEAM:
weapType = "Tractor"
else:
pTorp = App.Torpedo_Cast(pEvent.GetSource())
if pTorp:
if pTorp.GetGuidanceLifeTime() > 0.0:
weapType = "Torpedo"
else:
weapType = "Pulse weapon"
print pShip.GetName(), "just got hit by a:", weapType
        pObject.CallNextHandler(pEvent)

def init():
App.g_kEventManager.AddBroadcastPythonFuncHandler(App.ET_WEAPON_HIT, pMission, __name__ + ".WeaponHit")

Quote
Error: was unable to load PrimSecShieldGenerators - SyntaxError: ('invalid token', ('.\\Scripts\\Custom\\QBautostart\\PrimSecShieldGenerators.py', 778, 54, '\011\011elif pEvent.GetWeaponType() == pEvent.TRACTOR_BEAM:\012'))
Traceback (innermost last):
  File ".\Scripts\Custom\Autoload\LoadEngineeringExtension.py", line 157, in ImportQBautostart
  File ".\Scripts\Custom\QBautostart\PrimSecShieldGenerators.py", line 778
     elif pEvent.GetWeaponType() == pEvent.TRACTOR_BEAM:
                                                        ^
 SyntaxError: invalid token

Please remember that I am an idiot. The experience gap between me and you is vast.

In addition to getting a handler for weapon impacts, there remains the larger question of determining if it is a Breen Damper FTech weapon.
Great men are not peacemakers! Great men are conquerors!

Offline Mario

  • Senior Software Developer
  • Administrator
  • Posts: 2186
  • Cookies: 1706
  • Life is life
Re: Reacting to FTech events?
« Reply #6 on: July 25, 2013, 02:33:34 PM »
You could always try to load the script and see if it has damper tech.

Code: [Select]
pTorp = App.Torpedo_Cast(pEvent.GetSource())
if pTorp:
pModule = __import__(pTorp.GetModuleName())
if hasattr(pModule, "sYieldName"):
if pModule.sYieldName == "Damper Weapon":
print 'do my stuff'

Note that the following is not perfect because it assumes that the user who added the following tech used the default instructions.
Code: [Select]
sYieldName = 'Damper Weapon'
sFireName = None

try:
import FoundationTech
try:
oFire = FoundationTech.oTechs[sFireName]
FoundationTech.dOnFires[__name__] = oFire
except:
pass

try:
oYield = FoundationTech.oTechs[sYieldName]
FoundationTech.dYields[__name__] = oYield
except:
pass
except:
pass

If I register my tech in the following manner
Code: [Select]
try:
import FoundationTech
try:
oFire = FoundationTech.oTechs[None]
FoundationTech.dOnFires[__name__] = oFire
except:
pass

try:
oYield = FoundationTech.oTechs['Damper Weapon']
FoundationTech.dYields[__name__] = oYield
except:
pass
except:
pass

This approach won't work because my script is missing the sYieldName var.
Acta, non verba.
aka USS Sovereign

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #7 on: July 25, 2013, 04:12:47 PM »
Thanks Sovereign that worked like a charm, although I had to change the handler name to something other than 'WeaponHit' as it overriden the FTech 'WeaponHit' handler  :nono:

Code: [Select]
# handle Breen Damper FTech equiped weapons
def BreenDamperImpactHandler(pObject, pEvent):
pShip = App.ShipClass_Cast(pEvent.GetDestination())
pTorp = App.Torpedo_Cast(pEvent.GetSource())
if pTorp:
print pShip.GetName(), "just got hit by a torpedo"
pModule = __import__(pTorp.GetModuleName())
if hasattr(pModule, "sYieldName"):
if pModule.sYieldName == "Damper Weapon":
# my code for damper impact
elif hasattr(pModule, "oYield"):
if pModule.oYield == "Damper Weapon":  # < - - - - will not work, class instance
# my code for damper impact
        pObject.CallNextHandler(pEvent)

def init():
App.g_kEventManager.AddBroadcastPythonFuncHandler(App.ET_WEAPON_HIT, pMission, __name__ + ".BreenDamperImpactHandler")

As you can see I am extending the use of hasattr to find "oYield". Even though oYield is in a try block it works.
Only problem is that during runtime oYield is an instance of
ftb.Tech.DamperWeapon.BreenDrainerWeaponDef
and I do not know how to do class type comparisons.

I am also unsure as to the overhead of using __import__ and hasattr in a handler that could be called for every Damper equipped torpedo  :(

Of course it would be ideal for an actual FTech handler for FTech torpedos but I guess it is what it is.  :idk:
Great men are not peacemakers! Great men are conquerors!

Offline KrrKs

  • Posts: 461
  • Cookies: 25
Re: Reacting to FTech events?
« Reply #8 on: July 25, 2013, 07:12:26 PM »
Only problem is that during runtime oYield is an instance of
ftb.Tech.DamperWeapon.BreenDrainerWeaponDef
and I do not know how to do class type comparisons.

I am also unsure as to the overhead of using __import__ and hasattr in a handler that could be called for every Damper equipped torpedo  :(

Of course it would be ideal for an actual FTech handler for FTech torpedos but I guess it is what it is.  :idk:

AFAIK
Quote
type(<yourInstance>)
returns a class identifier (not just the name but something like
Quote
<class 'whatever'>
),
so you should be able to use that.

Concerning the import overhead: I think pretty much every script in BC imports the App and/or MissionLib; plus most custom ones Foundation and/or QBAutostart.
If there were any kind of (noticeable) slowdown due to the import statement, BC would be pretty much unplayable.

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #9 on: July 25, 2013, 09:03:44 PM »
Krrks you were so close to giving me the straight shot answer for my == problem. Python is not my thing so it took over half an hour to find the answer to my type() == classname problem.
http://stackoverflow.com/questions/54867/old-style-and-new-style-classes-in-python/54873#54873
In the older version of Python used by BC type(instancevar) is always <type 'instance'>.
Only way to do comparison in older versions is: instancevar.__class__ == classname
 - - - - -

I got it working to an acceptable level but aren't sure of the quality or robustness of the implementation.
Code: [Select]
# handle Breen Damper FTech equipped weapons
def BreenDamperHandler(pObject, pEvent):
pShip = App.ShipClass_Cast(pEvent.GetDestination())
pTorp = App.Torpedo_Cast(pEvent.GetSource())
if pTorp:
pModule = __import__(pTorp.GetModuleName())
if hasattr(pModule, "sYieldName"):
if pModule.sYieldName == "Damper Weapon":
ReactToBreenDamperHit(pShip)
elif hasattr(pModule, "oYield"):
pDamperModule = __import__("ftb.Tech.DamperWeapon")
if pModule.oYield.__class__ == pDamperModule.BreenDrainerWeaponDef:
ReactToBreenDamperHit(pShip)
        pObject.CallNextHandler(pEvent)

def init():
App.g_kEventManager.AddBroadcastPythonFuncHandler(App.ET_WEAPON_HIT, pMission, __name__ + ".BreenDamperHandler")

Input on how I could improve the function is welcomed. If nobody has any more suggestions i'd like to leave my thanks here and give you all a round of cookies.

Great men are not peacemakers! Great men are conquerors!

Offline Nighthawk

  • |______[o]_|
  • Posts: 750
  • Cookies: 18
Re: Reacting to FTech events?
« Reply #10 on: July 26, 2013, 12:11:45 AM »
AFAIK, you don't have to check which torpedo type is hitting, because the damper torpedo already passes the "it's me" token when it's fired.

like I said, FTech is continuously checking for specific events while it's active, so try tracking the code until you find what you need.

if you look at the torpedo file,

Code: [Select]
##################################################################################
#
## Foundation Technologies, copyright 2004 by Daniel Rollings AKA Dasher42
#
# This string is used to set a yield type using Foundation Technology plugins.
# If you wish extra functionality, subclassing an existing plugin here is acceptable,
# but the easiest way to set a special yield is to set this string to the name of an
# existing technology.

sYieldName = 'Breen Drainer Weapon'

sFireName = None

##################################################
#
# Do not edit below.

import FoundationTech
import ftb.Tech.BreenDrainer

#oFire = FoundationTech.oTechs[sFireName]
oFire = ftb.Tech.BreenDrainer.oDrainerWeapon
FoundationTech.dOnFires[__name__] = oFire
oYield = FoundationTech.oTechs[sYieldName]

FoundationTech.dYields[__name__] = oYield

when the torpedo fires, it's gonna carry with it the info "hey, I'm a FTech weapon, and I'm a drainer torpedo. Activate the draining effect when I hit"

likewise, you can use the technology to give draining effects to any other weapon.
I suggest you check scripts/ftb/BreenDrainer.py to better understand how it works.

Offline hobbs

  • Posts: 1373
  • Cookies: 77
Re: Reacting to FTech events?
« Reply #11 on: July 26, 2013, 05:30:59 AM »
can i ask... what is it you wanted this trigger for? sorry if ive missed something but im even less of a scripter than you... but i cant see for looking what it is you want this script to do.
"We are dreamers, shapers, singers and makers..." Michael Ansara, "Elric" Babylon 5 "The Geometry of Shadows,"


Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #12 on: July 26, 2013, 08:06:14 AM »
Sorry Nighthawk I don't fully understand.

What you are saying makes sense but it's hard to see how it changes the implementation because it already reads the torpedo script by importing it and then parsing it with hasattr. Are you saying I could just check the torpedo script for Damper Weapon values / class instances match ups? ... because that's what it's doing at the moment.

Code: [Select]
if pTorp:
pModule = __import__(pTorp.GetModuleName())
if hasattr(pModule, "sYieldName"):
if pModule.sYieldName == "Damper Weapon":
ReactToBreenDamperHit(pShip)
Is a torpedo. Import torpedo script as object and scan for sYieldName. sYieldName exists? Yep. sYieldName == "Damper Weapon".
Bingo!

Code: [Select]
elif hasattr(pModule, "oYield"):
pDamperModule = __import__("ftb.Tech.DamperWeapon")
if pModule.oYield.__class__ == pDamperModule.BreenDrainerWeaponDef:
ReactToBreenDamperHit(pShip)
oYield exists in script object? Yep. Import DamperWeapon script object. Compare oYield class type to BreenDrainerWeaponDef in DamperWeapon.py.

can i ask... what is it you wanted this trigger for? sorry if ive missed something but im even less of a scripter than you... but i cant see for looking what it is you want this script to do.
Worf: Fifty-two disruptor banks, twenty-seven photon torpedo bays, primary and secondary shields.
Nemesis as it should have been:
Great men are not peacemakers! Great men are conquerors!

Offline Nighthawk

  • |______[o]_|
  • Posts: 750
  • Cookies: 18
Re: Reacting to FTech events?
« Reply #13 on: July 26, 2013, 08:48:38 AM »
why do you need a drainer weapon to add shield effects?... just look at ShieldGenerators.py script from QBAutostart  :lostit:

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #14 on: July 26, 2013, 10:02:50 AM »
why do you need a drainer weapon to add shield effects?... just look at ShieldGenerators.py script from QBAutostart  :lostit:
ShieldGenerators.py is a different implementation. It treats all generators as contributing to one massive strong shield.
My interpretation of having 2 generators is that they are seperate and interchangeable. Ergo: primary and secondary shields.
Graphical shield effects are irrelevant.

Code: [Select]
# handle Breen Damper FTech equipped weapons
def BreenDamperHandler(pObject, pEvent):
pShip = App.ShipClass_Cast(pEvent.GetDestination())
pTorp = App.Torpedo_Cast(pEvent.GetSource())
if pTorp:
pModule = __import__(pTorp.GetModuleName())
if hasattr(pModule, "sYieldName"):
if pModule.sYieldName == "Damper Weapon":
ReactToBreenDamperHit(pShip)
elif hasattr(pModule, "oYield"):
pDamperModule = __import__("ftb.Tech.DamperWeapon")
if pModule.oYield.__class__ == pDamperModule.BreenDrainerWeaponDef:
ReactToBreenDamperHit(pShip)
        pObject.CallNextHandler(pEvent)

def init():
App.g_kEventManager.AddBroadcastPythonFuncHandler(App.ET_WEAPON_HIT, pMission, __name__ + ".BreenDamperHandler")
Input on how I could improve the function is welcomed. If nobody has any more suggestions i'd like to leave my thanks here and give you all a round of cookies.
Great men are not peacemakers! Great men are conquerors!

Offline Mario

  • Senior Software Developer
  • Administrator
  • Posts: 2186
  • Cookies: 1706
  • Life is life
Re: Reacting to FTech events?
« Reply #15 on: July 26, 2013, 03:24:51 PM »
AFAIK, you don't have to check which torpedo type is hitting, because the damper torpedo already passes the "it's me" token when it's fired.

like I said, FTech is continuously checking for specific events while it's active, so try tracking the code until you find what you need.

if you look at the torpedo file,

Code: [Select]
##################################################################################
#
## Foundation Technologies, copyright 2004 by Daniel Rollings AKA Dasher42
#
# This string is used to set a yield type using Foundation Technology plugins.
# If you wish extra functionality, subclassing an existing plugin here is acceptable,
# but the easiest way to set a special yield is to set this string to the name of an
# existing technology.

sYieldName = 'Breen Drainer Weapon'

sFireName = None

##################################################
#
# Do not edit below.

import FoundationTech
import ftb.Tech.BreenDrainer

#oFire = FoundationTech.oTechs[sFireName]
oFire = ftb.Tech.BreenDrainer.oDrainerWeapon
FoundationTech.dOnFires[__name__] = oFire
oYield = FoundationTech.oTechs[sYieldName]

FoundationTech.dYields[__name__] = oYield

when the torpedo fires, it's gonna carry with it the info "hey, I'm a FTech weapon, and I'm a drainer torpedo. Activate the draining effect when I hit"

likewise, you can use the technology to give draining effects to any other weapon.
I suggest you check scripts/ftb/BreenDrainer.py to better understand how it works.

FTech doesn't externally expose an event which he can listen for, so this won't work.
Acta, non verba.
aka USS Sovereign

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #16 on: July 26, 2013, 03:45:52 PM »
Sovereign has spoken  :dontcare:

Thanks for all your help. Would have taken me weeks to solve this  :thumbsup:

Cookies for all :)
Great men are not peacemakers! Great men are conquerors!

Offline Nighthawk

  • |______[o]_|
  • Posts: 750
  • Cookies: 18
Re: Reacting to FTech events?
« Reply #17 on: July 27, 2013, 01:38:09 AM »
FTech doesn't externally expose an event which he can listen for, so this won't work.

but he can write a script similar to the one actually used by FTech .... every script in ftb/tech handles the reaction to a given type of event, so he can just modify one activated by OnTorpDefense, and use the same code as BreenDrainer.py

what I mean was, that he has the framework doing that already... no need to write a check script to see if the thing being fired is a FTech weapon, when the very script is written for FTech.

Offline Bat66wat6

  • Posts: 144
  • Cookies: 34
  • Running custom BC 1.1
Re: Reacting to FTech events?
« Reply #18 on: July 27, 2013, 07:45:52 AM »
but he can write a script similar to the one actually used by FTech .... every script in ftb/tech handles the reaction to a given type of event, so he can just modify one activated by OnTorpDefense, and use the same code as BreenDrainer.py

what I mean was, that he has the framework doing that already... no need to write a check script to see if the thing being fired is a FTech weapon, when the very script is written for FTech.

Will I not have to edit one of the Foundation files (\scripts\FoundationTech.py) ... or is this an addition I can add to my \scripts\custom\QBautostart.py ?

I will listen to what you have to say but I will need help. Code in FoundationTech.py looks like gibberish :\
Great men are not peacemakers! Great men are conquerors!

Offline Nighthawk

  • |______[o]_|
  • Posts: 750
  • Cookies: 18
Re: Reacting to FTech events?
« Reply #19 on: July 27, 2013, 09:17:03 AM »
read BreenDrainer.py

Code: [Select]
class BreenDrainerWeaponDef(MultipleDisableDef):

def IsDrainYield(self):
debug(__name__ + ", IsDrainYield")
return 1

def OnYield(self, pShip, pInstance, pEvent, pTorp):
debug(__name__ + ", OnYield")
if FoundationTech.EffectsLib:
FoundationTech.EffectsLib.CreateSpecialFXSeq(pShip, pEvent, 'Damper')

pShipID = pShip.GetObjID()
pShip = App.ShipClass_Cast(App.TGObject_GetTGObjectPtr(pShipID))

# useless against stations
if not pShip or pShip.GetShipProperty().IsStationary():
return

pPlayer = MissionLib.GetPlayer()
if pPlayer.GetObjID() == pShip.GetObjID():
pVoice = App.g_kSoundManager.GetSound("PowerDisabled")
if pVoice:
        pVoice.Play()

                        pSound = App.g_kSoundManager.GetSound("BreenDraining")
                        if not pSound:
                                pSound = App.TGSound_Create("sfx/BreenDraining.wav", "BreenDraining", 0)
                        if pSound:
                                pSound.Play()

if FoundationTech.BridgeFX:
FoundationTech.BridgeFX.CreateDrainEffect()
                       
                        # disable glow on ship
if not pShip.IsDead(): # possible crash work around
                        pShip.DisableGlowAlphaMaps()

                # clients shouldn't do anything here
                if App.g_kUtopiaModule.IsMultiplayer() and not App.g_kUtopiaModule.IsHost():
                        return

pPower = pShip.GetPowerSubsystem()
if pPower:
                        IonSubSystem(pPower)
                #pProp = pPower.GetProperty()
                #pProp.SetPowerOutput(0.0)
                        #pProp.SetMainConduitCapacity(0.000001)
                        #pProp.SetBackupConduitCapacity(0.000001)

pShields = pShip.GetShields()
if pShields:
                        IonSubSystem(pShields)

pCloak = pShip.GetCloakingSubsystem()
if pCloak:
                        IonSubSystem(pCloak)

                pImpulse = pShip.GetImpulseEngineSubsystem()
                if pImpulse:
                        IonSubSystem(pImpulse)

                pWarp = pShip.GetWarpEngineSubsystem()
                if pWarp:
                        IonSubSystem(pWarp)

        pWeaponSys = pShip.GetTorpedoSystem()
        if pWeaponSys:
        IonSubSystem(pWeaponSys)
        pWeaponSys = pShip.GetPhaserSystem()
        if pWeaponSys:
        IonSubSystem(pWeaponSys)
        pWeaponSys = pShip.GetPulseWeaponSystem()
        if pWeaponSys:
        IonSubSystem(pWeaponSys)

OnYield gets activated when FTech detects a BreenDrainer torpedo has hit something... FTech goes check WHAT actually hit WHAT, and if it's a torpedo, then it fires the OnTorpDefense function, which takes you to the OnYield function here.
... to sum things up: study these kind of scripts and you will learn how to create the reaction you need for a given input.

like I said, FTech is always checking specific events, yours included... you don't need to write another handler for an event that's already being watched by a larger framework... just add your effect to the queue of effects to be fired when the trigger goes off.