[script] add shader help

Post » Fri Nov 16, 2012 6:28 pm

Im looking to make a mod that shows the player as snowy when in snow for awhile.

I've got a shader which is played by the script in a Quest but for some reason the shader seems to blink off then on?
Also: All of this was written by tox2ik on nexus who has been a big help:

Scriptname getSnowyQuestScript extends Quest  EffectShader Property getSnowyShader AutoEvent OnInit()registerforupdate(4)EndEventEvent OnUpdate()EffectShader shader = getSnowyShaderWeather currentWeather = Weather.GetCurrentWeather()if currentWeather != noneint wClass = currentWeather.GetClassification() if wClass == 3;trace("weather class: snow ")shader.play(game.getPlayer(), -1 )elseif wClass == 2;trace("weather class: rain")shader.stop(game.getPlayer())elseif wClass == 1;trace("weather class: cloudy")shader.stop(game.getPlayer())elseif wClass == 0;trace("weather class: pleasant")shader.stop(game.getPlayer())else shader.stop(game.getPlayer())endIfelse ;trace("no current weather")endIfEndEvent
User avatar
Megan Stabler
 
Posts: 3420
Joined: Mon Sep 18, 2006 2:03 pm

Post » Fri Nov 16, 2012 10:30 am

Post reserved so I can post a bunch of info. Stay tuned.

Edit: Creation Kit wiki is throwing an SQL error when trying to view pages. That's not very helpful.

Edit 2: I would do something like this.

Scriptname getSnowyQuestScript extends QuestSpell property _Treb_PlayerSnowSpell autoGlobalVariable property _Treb_Debug autoimport debugEvent OnInit()	RegisterForSingleUpdateGameTime(0.25)endEventEvent OnUpdateGameTime()	Actor pPlayer = Game.GetPlayer()	float myDebug = _Treb_Debug.GetValue()	Weather currentWeather = Weather.GetCurrentWeather()	if currentWeather != none		int wClass = currentWeather.GetClassification()		if wClass == 3	;Snow			pPlayer.AddSpell(_Treb_PlayerSnowSpell, false)			if myDebug == 1.0				notification("Added snow shader spell to player")			endif		else			pPlayer.RemoveSpell(_Treb_PlayerSnowSpell)			if myDebug == 1.0				notification("Removed snow shader spell from player")			endif		endif	endif	RegisterForSingleUpdateGameTime(0.25)endEvent

I simplified the weather logic; we only care about it either being snowy, or not. If it is; add the spell. If it's not, remove it.

I use RegisterForSingleUpdateGameTime() to avoid any possibility of stacking scripts on top of one another. I use GameTIme updates to run the script less frequently (once every 10 in-game minutes). On the default 20:1 timescale this translates to every 30 seconds. It would be fine to run this as an OnUpdate, but still use RegisterForSingleUpdate() and chain it at the bottom of the OnUpdate() event. 4 seconds on the update time is a bit quick; I'd think you'd need time for that snow to build up. Every 15-30 seconds I think would be fine (and perhaps more immersive / realistic). Not to mention, this is an aesthetic behavior script that should be given relatively lower priority than some others, so should probably be given fewer updates over time so that other scripts that need to run on a faster loop, have more of a CPU time slice to do it in without this trying to get in the way. Always strive to update as infrequently as possible without compromising the functionality of your mod.

I implement a new global variable that can be set at runtime using the developer console for debugging.

I use a spell instead of playing the shader effect directly. I don't know if this is the better way to do it, I've always just done it this way.

Make sure that the magic effect tied to the spell (if you go that route) has "FX Persist" checked. Also be sure to clear out any keywords the spell may have (if you duplicate another one to use as a template). Use the Ability type so that once it's applied it never goes away (duration is meaningless).

How to make this better:
  • Replace the OnInit() event with a Papyrus fragment that kicks off this script when a new quest stage is set. This is good for being able to start up / shut down this mod on the fly. While this script is fairly simple, if something ever goes "off the rails" for a user it's handy to have a way to be able to restart it.
  • Provide a configuration option to shut the mod down. A global variable would be sufficient.
  • Hook up new logic at the bottom of the OnUpdate event to facilitate shutting down the mod by bypassing registering for the next update.
You can look at my magic effect in Frostfall to see what parameters I use, they should be fine for your purposes. The visual effect is a slightly modified frost damage shader, with a less intense (almost non-existent) edge glow and slightly increased alpha. You are free to copy the parameters of this shader and tweak it to your own use.

I hope this was helpful. Good luck!
User avatar
Wanda Maximoff
 
Posts: 3493
Joined: Mon Jun 12, 2006 7:05 am

Post » Fri Nov 16, 2012 9:55 pm

I use RegisterForSingleUpdateGameTime() to avoid any possibility of stacking scripts on top of one another. I use GameTIme updates to run the script less frequently (once every 10 in-game minutes). On the default 20:1 timescale this translates to every 30 seconds. It would be fine to run this as an OnUpdate, but still use RegisterForSingleUpdate() and chain it at the bottom of the OnUpdate() event.
i just wanted to reinforce this point. IMO mods should be forbidden from using registerforupdate or registerforgametimeupdate entirely. as chesko mentioned just use 'single' instead, and recall the single in the update if necessary like chesko suggests.

it may seem trivial, but the reason for this is that even if you have a proper method of uninstalling your mod that you offer to your users, the majority of them will not use your uninstallm and will simply remove the mod and its files if they plan to not use it anymore.

since threaded scripts are saved in the save game, the update loop will continuously run and throw an infinite amount of errors for every interval the update was originally registered with (just look at all of the vanilla script errors for an example of this). if you register single, the save game will run only update once, and since it can no longer find the OnUpdate event in the script (which has been deleted by the user) it stops the error looping after trying only once.
User avatar
Cameron Garrod
 
Posts: 3427
Joined: Sat Jun 30, 2007 7:46 am

Post » Fri Nov 16, 2012 12:43 pm

@Chesko, you are amazing! It seems to work flawlessly. I'll be singing your praise to anyone who'll listen.

@Amethyst, thanks, will definitely never look at using registerforupdate again! And will show people the above workaround when ever i see it in use.

Now Im just looking for help with understanding shaders, there doesn't seem to be much documentation/tutes around about how they work.
User avatar
Project
 
Posts: 3490
Joined: Fri May 04, 2007 7:58 am

Post » Fri Nov 16, 2012 6:02 pm

  • Why not define Player with a property...
    Actor Property PlayerREF Auto
    ...rather than defining...
    Actor pPlayer = Game.GetPlayer()
    ...every iteration?
  • Also...
    if currentWeather
    ...will work just like...
    if currentWeather != none
    ...but is 'cheaper'.
  • Lastly, the weather clasification only needs to be checked once per iteration, so things could be sped up by not caching it.
    Bool bGetSnowyActor Property PlayerREF AutoEffectShader Property GetSnowyShader Auto	EndEvent	RegisterForSingleUpdateGameTime(5.00) ; Snow would take a moment to accumulate/thawEndEventEvent OnUpdateGameTime()	If bGetSnowy != (Weather.GetCurrentWeather().GetClassification() == 3)		bGetSnowy = !bGetSnowy		If bGetSnowy			GetSnowyShader.Play(PlayerREF)		Else			GetSnowyShader.Stop(PlayerREF)		EndIf	EndIf	RegisterForSingleUpdateGameTime(5.00)EndEvent
User avatar
Jimmie Allen
 
Posts: 3358
Joined: Sun Oct 14, 2007 6:39 am

Post » Fri Nov 16, 2012 6:33 pm

I agree with everything except putting the entire block inside the "if bDebug" :)
User avatar
Melly Angelic
 
Posts: 3461
Joined: Wed Aug 15, 2007 7:58 am

Post » Fri Nov 16, 2012 6:05 pm

I agree with everything except putting the entire block inside the "if bDebug" :)
Oh! It's only the notifications that are contingent upon that. *edits above
User avatar
Neko Jenny
 
Posts: 3409
Joined: Thu Jun 22, 2006 4:29 am


Return to V - Skyrim