Multiple Scripts for Multiple Conditions on One Weapon?

Post » Sun Aug 30, 2015 4:31 am

I have a weapon that I would like to modify some faction standing value (one unused in the game of course) based on what conditions are met when a weapon (the one using the scripts) is used.

Faction standing is used because it is a value that does not get reset on save, load or cell change. Is there a better way to preserve a value that is invisible to the player in-game.

Anyways, the three conditions are:

1. When the wielder kills an actor.

2. When the wielders health goes below 50%.

3. When the wielder un-equips the weapon. Un-equips, NOT sheaths.

Is there a way to have one script for each of these conditions on the same weapon? If it is possible, is that the best way to do it or should there just be one script?

Is there a way to have some checks (locks and monitors etc. for those of you familiar with concurrency) to avoid corruption of the value being modified when two conditions are met at the same time?

Thanks for the help.

User avatar
michael flanigan
 
Posts: 3449
Joined: Thu Jun 14, 2007 2:33 pm

Post » Sun Aug 30, 2015 1:44 am

Killing an actor is tricky to catch. There are OnDeath and OnDying events, but you need a script to be already running on the victim, and that's tricky to arrange. Also those events are a bit finnicky in my experience and don't always fire when you'd expect. Better is probably the story manager Kill Actor event. That needs to launch a quest, bit it can be a small repeatable one the just starts up, bumps the killer's faction rank and stops again. There can be a bit of a lag for SM events though, so it might take a few seconds before the effects propagate.

The wielder's health is another awkward one. I could have sworn there were events that fired when actor values changed, but I can't find them now. So my best advice is an OnUpdate loop that polls the wielder's health periodically

The unequip event you can catch from either the weapon or the actor.

I'd be tempted to set up a quest to manage the weapon. You could put the health and unequip events on the weapon directly, but you need a reference to it somewhere so the SM event can find it. So I'd have one quest, probably start game enabled that had an alias for the weapon and an empty one for the wielder. Give the quest script methods that can be called to tell it when an actor dies because of the weapon, and when the weapon is equipped (so it can set the weilder alias) or unequipped. The weapon can message the quest script for unquip events. You'll need a second quest for the story manager, but all that does is call the manager quest script's opponent_killed method.

At least, that's how I'd approach it. Might be someone here has an easier way you could do it :)

And yeah, factions are about your best bet for this sort of thing. The alternatives are script properties or one of the SKSE plugins like JContainers. But factions are lightweight and easy to use in conditions

User avatar
Kelvin
 
Posts: 3405
Joined: Sat Nov 17, 2007 10:22 am

Post » Sun Aug 30, 2015 11:16 am

The weapon I'm hoping to write the script(s) for already has an old script I -with the help of some other friendly forum members- wrote awhile back. It seems to detect the "killed actor" part reliably as much as I've been able to determine so I just need to add the faction rank modifier to the end of it. It's the other conditions I'm not sure how to optimally handle.

I don't know how exactly Skyrim handles scripts, but I suspect it fires one off on a thread which runs it to completion. The issue then with having all conditions in one file is that the results of these conditions need to take several seconds of in-game time to complete for how I want the weapon to behave.

To explain in more detail I'll just outline what I'd like to do:

On Actor Kill: Faction rank (which should have started out at some default initial state, I'll call it absolute zero) is increased by a static amount.

With this new faction rank, a trait (eg Max Stamina, Carry Weight, scale etc...) is increased in steps to some new max determined by the new faction rank. This new maximum should be reached in steps and not all in one go.

On Wielder Take Damage: If wielder health is below 50%, decrease the faction rank by a static amount unless this carries it below absolute zero. If it would otherwise carry it below absolute zero, set the faction rank to absolute zero.

Decrease the wielders trait to the new maximum dictated by the faction rank. This new maximum should be attained in steps again, not all in one go. The wielder should also be healed by a value according to faction rank lost. Let me explain this better. When the wielder takes damage and is below 50% health from that damage, if it has faction standing, it should start healing slowly until its health reaches 50%, say 3% health for every 4 standing points and the trait should slowly decrease.

On Weapon Unequip: Set the faction rank to absolute zero. Decrease the wielders trait to the new maximum as dictated by the new faction rank. This new maximum should correspond to it's value before the wielder ever equipped the weapon in the first place. It should be reached in steps and not all at once.

Basically the faction standing is used as the background initial value holder for the trait which is the in-game manifestation of this rank. It would also be nice to have different spell effects for the various conditions.

Now where I can see problems arising is each condition will take a long time (1-2 seconds maybe or more depending on how much the faction rank is increased or decreased in a time. to complete and many conditions can be fired off and be true while one is still terminating. The wielder could kill something as its taking damage and of course, it would be still in the middle of the taking damage condition as it takes more damage.

Since the faction rank is the base line used for the incremental parts that should make things a bit simpler. As the loops performing the incrementing iterate, they should be able to check the value of the faction rank and act accordingly. Since the loops themselves don't modify the faction rank there shouldn't be any problems with race conditions (concurrency). Because of this I'm thinking there might need to be a script for each condition so that multiple conditions can occur "simultaneously". Yes it's fine if this trait is being both incremented and decremented at the same time. That just means its value shouldn't be changing.

There's probably a smart way of writing the script(s) so that overlapping trait modification is smart and doesn't cause a jittering of the value. Probably something like if the rank falls above/below the point where the corresponding trait value is above/below the required value, stop incrementing/decrementing.

Eg. If current faction rank value is 10 and the trait value the wielder currently has requires rank 12 then stop incrementing.

Also thanks for helping me on this.

User avatar
hannaH
 
Posts: 3513
Joined: Tue Aug 15, 2006 4:50 am

Post » Sun Aug 30, 2015 6:10 am

There's a fair bit on the threading model the game uses on the CK wiki. Basically when an event fires or a function is called, the script gets attached to a thread and stays there until it either ends, calls a method on another script, or runs a "latent" method from the Papyrus API. As a rule of thumb, assume that as long as you're calling your own methods you keep control, but if you call an outside function the thread drops and everyone else gets a chance to execute before it gets back to you.

You've got the kill target event sorted out then, so that much is done. You can give the script a property, point it at your faction and change it that way. That's easy enough.

Thinking about it, there is a perk entry point that modifies incoming damage. You could use that to compare incoming damage against current health and see what the result is going to be. Still not 100% reliable since there might be a healing spell running at the same time, but it might be easier than an update loop. You could assign the perk when the weapon is equipped and remove it when unequipped. There is also an entry point for recovered health as well. Are you going to track when the health goes back above 50%? You might still be better off with an onUpdate loop and maybe a pair of states.

Seems like you could do it all with the perk and a weapon script in which case. You have three events handled by the weapon - equip, unequip and whatever detects the actor deaths. None of them are going to happen at the same time, and the perk handles actor damage.

User avatar
Lilit Ager
 
Posts: 3444
Joined: Thu Nov 23, 2006 9:06 pm

Post » Sun Aug 30, 2015 10:31 am

So basically the perk handles the health monitoring and the effects of the wielder taking damage and the script manages the weapon killing an actor and being unequipped? And both would be able to access and modify the faction rank of the wielder.

User avatar
Maria Garcia
 
Posts: 3358
Joined: Sat Jul 01, 2006 6:59 am

Post » Sun Aug 30, 2015 2:21 am

Basically. The perk knows who it is attached to, and you can give the perk script a property pointing to the faction.

Similarly, you'd need to give the weapon script a faction property. Other than that ... the only thing I can see that might cause problems is the way that object reference data gets recycled when an item is added to your inventory. You may lose state when the weapon is unequipped - in which case you'll need a manager script after all.

But try it the easy way first :smile:
User avatar
Kevin Jay
 
Posts: 3431
Joined: Sun Apr 29, 2007 4:29 am


Return to V - Skyrim