Getting the activated target ref from an activation Perk

Post » Fri May 13, 2011 10:25 am

I just discovered this little trick yesterday and thought I'd share, since it could have a lot of useful applications.

Say you use a Perk with an activation entry point, to give the player additional options when activating certain objects. When that option is chosen, you can then run additional script, but until now I had never found a way to get a reference to the object that was activated, which could then be used in subsequent script.

What I found is that when used in the Perk Entry result script, the FOSE function http://fose.silverlock.org/fose_command_doc.html#GetCrosshairRef will return a reference to the object that was just activated by the Player. Since you can't define variables in result scripts, it needs to be assigned to a Global or a Quest variable, but that's no problem.


I'll illustrate with a specific example: After seeing http://www.fallout3nexus.com/downloads/file.php?id=13267, I started fiddling with a little mod that would let you harvest the brains from corpses (muahahaha!). I wanted to use an activation perk so it would be similar to the way the Cannibal Perk works, that is, when activating a corpse (with an intact head of course) you get an option to harvest the brain, and when chosen the head is dismembered and a brain is added to Player inventory. Adding the brain to inventory is simple (and even getting the Player to run a custom 3rd-person idle animation wasn't that hard - but that's another story), but in order to dismember that corpse's head I needed a reference to that actor. Here's a http://www.youtube.com/watch?v=Y8TFRJjrKcI to show what I wanted to do.

So here's the "trick". In the perk result script, I did this:

set BrainHarvest.rTarget to GetCrosshairRefStartQuest BrainHarvest

...and here's a simplified version of the BrainHarvest quest script:

ScriptName BrainHarvestScriptref rTargetBegin GameMode	PrintToConsole "ActionRef: %n" rTarget	rTarget.Kill Player 1	rTarget.AddItem BrainHarvestToken 1	Player.AddItem BrainHuman 1	ResetQuest BrainHarvest	End


Of course, the http://fose.silverlock.org/fose_command_doc.html#PrintToConsole line is unnecessary, but it's a quick and simple way to demonstrate that the activated target ref was assigned correctly. Also, it's not strictly necessary to encapsulate the bulk of the code in a quest script - you could just as easily continue to use the quest variable (or a global) in the result script, depending on what you need to do. The point is that you're now able to use that specific reference in script in any way you'd like.


So why do it this way instead of using an OnActivate block in an object script attached to the specific objects you want to affect? At least three reasons I can think of at the moment:

Mod compatibility -
By adding or modifying an object script on existing vanilla objects, the object's or script's record is completely overridden, creating potential mod conflicts. This is why http://www.fallout3nexus.com/downloads/file.php?id=4447 and http://www.fallout3nexus.com/downloads/file.php?id=3388 use activation perk to add options to the workbench. Many previous and beginner modders modified workbenches by directly altering the vanilla workbench script, meaning none of them can work together unless someone manually combined (re-wrote) their scripts to integrate them (if even possible), something that cannot be automated.

Conditions -
By using a Perk Entry, you have access to the editor's built-in http://geck.gamesas.com/index.php/Category:Conditions forms, a simple, powerful, and more efficient way to narrow down the specific conditions under which your script will run. For example, in my example above, at the moment the "Harvest Brain" option is only presented if the Player is sneaking, the activated actor is not a creature, is dead, has a head, and does not contain the BrainHarvestToken flagging it as already harvested (hmm... I guess that one's unnecessary now). All that would otherwise create at least several lines of code to clutter up script.

Convenience -
This doesn't really apply if you're only interested in doing something on activation on one particular base object, but an activation perk allows you to add an activation option to EVERY object that can be activated in the game at once. Of course, you almost certainly want to narrow this down with Conditions, but again take my example. To do the same thing via OnActivate blocks, I'd need to add/modify the script on every NPC, and that would still not cover any NPCs added by other mods.


Hmm... this turned into a bit of an article. Well, if you understood the first few sentences, that's all you really need ^_^

EDIT: forgot to add the video!
User avatar
maddison
 
Posts: 3498
Joined: Sat Mar 10, 2007 9:22 pm

Post » Fri May 13, 2011 5:39 am

set BrainHarvest.rTarget to GetCrosshairRefStartQuest BrainHarvest
Nice. My solution was just use CIOS to cast an effect on the actor, which can define as many variables as much as it wants.

Instead of a quest, you can also use a persistent scripted activator off in a remote cell somewhere and use 'Set ActivatorRef.X to Y, ActivatorRef.activate Player 1'. This has the advantage that it happens instantaneously, and the activator script will conclude before anything else happens, even before a FOSE loop finishes, and you can nest it.
User avatar
Lalla Vu
 
Posts: 3411
Joined: Wed Jul 19, 2006 9:40 am

Post » Fri May 13, 2011 12:34 pm

Yup, those are other nice ways to compartmentalize and organize scripts - I've just kinda acquired the habit of using quest scripts in most cases. But to return to the real topic of my post, it's the first line that was my point:

set SomeQuest.SomeQuestVariable to GetCrosshairRef
or
set SomeGlobalVariable to GetCrosshairRef
...used in the result script of a perk activation Entry Point allows you to get a reference to the specific activated item.
User avatar
Jason White
 
Posts: 3531
Joined: Fri Jul 27, 2007 12:54 pm

Post » Fri May 13, 2011 9:48 am

Yup, those are other nice ways to compartmentalize and organize scripts - I've just kinda acquired the habit of using quest scripts in most cases. But to return to the real topic of my post, it's the first line that was my point:

set SomeQuest.SomeQuestVariable to GetCrosshairRef
or
set SomeGlobalVariable to GetCrosshairRef

...used in the result script of a perk activation Entry Point allows you to get a reference to the specific activated item.

I'm thinking how I'm going to use this instead of refwalks and/or hotkeys in a script that I am currently puzzling over.
This is awesome. Thanks for sharing it!
User avatar
Nicole M
 
Posts: 3501
Joined: Thu Jun 15, 2006 6:31 am

Post » Fri May 13, 2011 5:42 pm

Hey, I just found a better way. You can use http://geck.gamesas.com/index.php/GetSelf rather than GetCrosshairRef. I say this is better because it eliminates the need to use a FOSE function, and thus an extra dependency if you otherwise weren't relying upon FOSE (not because there's any other inherent reason not to use FOSE).

Apparently in the activation Entry Point result script, the activated object is the calling (implicit) reference. This makes sense, but I don't recall finding that information anywhere before. Of course this seems obvious now, and I feel like I made a big deal about nothing :blush:

So to revise:

set SomeQuest.SomeQuestVariable to GetSelf
or
set SomeGlobalVariable to GetSelf

...used in the result script of a perk activation Entry Point allows you to get a reference to the specific activated item.

Everything else said above still applies.
User avatar
Lil Miss
 
Posts: 3373
Joined: Thu Nov 23, 2006 12:57 pm

Post » Fri May 13, 2011 2:53 pm

In some cases, http://fose.silverlock.org/fose_command_doc.html#GetCrosshairRef would still be more useful, as http://geck.gamesas.com/index.php/GetSelf will return 0 if called on a reference that is stored in the save, i.e one that's refID starts with "FF", like references created via http://geck.gamesas.com/index.php/PlaceAtMe.

If you need to get the refID of an actor with such a refID, you could force it to activate a remote persistent activator's http://geck.gamesas.com/index.php/OnActivate (odd... the forum is making that all lower case for some reason) block via http://geck.gamesas.com/index.php/Activate, then use http://geck.gamesas.com/index.php/GetActionRef in that script in order to get its refID.

Also, if I remember correctly, global variables cannot be used to store references, so you'd need to use a variable declared in a remotely accessible script.

Cipscis
User avatar
Khamaji Taylor
 
Posts: 3437
Joined: Sun Jul 29, 2007 6:15 am

Post » Fri May 13, 2011 5:00 am

In some cases, http://fose.silverlock.org/fose_command_doc.html#GetCrosshairRef would still be more useful, as http://geck.gamesas.com/index.php/GetSelf will return 0 if called on a reference that is stored in the save, i.e one that's refID starts with "FF", like references created via http://geck.gamesas.com/index.php/PlaceAtMe.

Good point. You'd think I would've mentioned that myself, huh? ;)


Also, if I remember correctly, global variables cannot be used to store references, so you'd need to use a variable declared in a remotely accessible script.

Ooops, you're completely right there of course. I'll strike out my mentions of globals above.


... http://geck.gamesas.com/index.php/OnActivate (odd... the forum is making that all lower case for some reason) ...

Yes, it's http://thenexusforums.com/index.php?showtopic=210837. I suppose it wouldn't hurt to report that here as well.
User avatar
luke trodden
 
Posts: 3445
Joined: Sun Jun 24, 2007 12:48 am

Post » Fri May 13, 2011 4:42 pm

If you need to get the refID of an actor with such a refID, you could force it to activate a remote persistent activator's http://geck.gamesas.com/index.php/OnActivate (odd... the forum is making that all lower case for some reason) block

The really annoying "feature" is that it screws with the link as well. As the urls of the geck wiki are case sensitive, the link does not work.

Edit: It seems someone managed to fix it before I finished :)
User avatar
Tasha Clifford
 
Posts: 3295
Joined: Fri Jul 21, 2006 7:08 am

Post » Fri May 13, 2011 8:18 pm

I've turned the page it links to into a redirect into the real http://geck.gamesas.com/index.php/OnActivate page, so it should work now.

Cipscis
User avatar
marina
 
Posts: 3401
Joined: Tue Mar 13, 2007 10:02 pm

Post » Fri May 13, 2011 11:06 am

In some cases, http://fose.silverlock.org/fose_command_doc.html#GetCrosshairRef would still be more useful, as http://geck.gamesas.com/index.php/GetSelf will return 0 if called on a reference that is stored in the save, i.e one that's refID starts with "FF", like references created via http://geck.gamesas.com/index.php/PlaceAtMe.
Aaaaargh so /that's/ the problem. Suddenly a huge bunch of inexplicable errors fall into place.
User avatar
Trent Theriot
 
Posts: 3395
Joined: Sat Oct 13, 2007 3:37 am


Return to Fallout 3