Dynamic Walk Speed Script

Post » Mon Jun 18, 2012 6:03 am

So I've been trying to develop a script that dynamically changes the walk speed depending on your location. I determine this location by the SkyMode, which can distinguish if the sky = interior, world, or "skydome" (which assume are town worldspaces). The speed is changed by adjusting the global speed multiplier only while you are walking. I'm totally new to any level of scripting outside your basic game script and the Wiki isn't much help so I'm basically doing this blind.

Would anyone who knows anything about coding or Papyrus be able to check the following script and see if the game can actually use it to do what I want to do? I'm not sure if I understand everything fully.

Scriptname DynamicWalkSpeed extends ObjectReference;every time cell loads, script activatesEvent OnCellLoad();default stateauto state Default  Game.GetPlayer().ModActorValue("SpeedMult", 1)   if Game.GetPlayer().IsRunning()	GotoState("Run")   elseif Game.GetPlayer().IsSprinting()	GotoState("Sprint")   else	GotoState("Walk")   endifendState;special state that activates when player IsRunning from the Default statestate Run  Game.GetPlayer().ModActorValue("SpeedMult", 1)  GotoState("Default")endState;special state that activates when player IsSprinting from the Default statestate Sprint  Game.GetPlayer().ModActorValue("SpeedMult", 1)  GotoState("Default")endState;special state that activates when player is walking. Then, it checks what the skymode is, and changes SpeedMult depending on that mode. If player runs or sprints while in the walk state, it reverts back to the default state.state Walk  if Weather.GetSkyMode() == 1   Game.GetPlayer().ModActorValue("SpeedMult", 1.75)  elseif Weather.GetSkyMode() == 2   Game.GetPlayer().ModActorValue("SpeedMult", 2)  elseif Weather.GetSkyMode() == 3   Game.GetPlayer().ModActorValue("SpeedMult", 2.5)  endif  if Game.GetPlayer().IsRunning()   GotoState("Default")  elseif Game.GetPlayer().IsSprinting()   GotoState("Default")  endifendStateGotoState("Default")endEvent

There's also an issue of how I get the game to actually use this script. So far, the Wiki appears to only cover how to attatch scripts to objects. What if I want a script to happen all the time? What do I do to get the script to "start" once I'm in game?
User avatar
FoReVeR_Me_N
 
Posts: 3556
Joined: Wed Sep 05, 2007 8:25 pm

Post » Sun Jun 17, 2012 11:11 pm

Allright so I tried attaching the script to the "Player" actor in in the Actor List, and when I saved the script it obviously didn't work. Here's the errors:

Starting 1 compile threads for 1 files...Compiling "DynamicWalkSpeed1"...f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(6,1): no viable alternative at input 'auto'f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(7,2): no viable alternative at input 'Game'f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(7,6): mismatched input '.' expecting LPARENf:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(0,0): error while attempting to read script DynamicWalkSpeed1: Object reference not set to an instance of an object.No output generated for DynamicWalkSpeed1, compilation failed.Batch compile of 1 files finished. 0 succeeded, 1 failed.Failed on DynamicWalkSpeed1

Any insights? I kind of knew it wouldn't work but I want to know why.
User avatar
Prohibited
 
Posts: 3293
Joined: Tue Jun 12, 2007 6:13 am

Post » Mon Jun 18, 2012 12:32 am

Try attaching it to a quest or something? Or just some random reference. That obviously doesn't work because you attached it to the player base object, not a reference. Or you could make an invisible activator that follows the player...
User avatar
Skivs
 
Posts: 3550
Joined: Sat Dec 01, 2007 10:06 pm

Post » Mon Jun 18, 2012 4:32 am

Where a script is attached has nothing to do with errors seen at compilation - the compiler doesn't look inside any data files.

For the first error, "auto" should go at the end of the line. See what shows up if you fix that.

Cipscis
User avatar
james tait
 
Posts: 3385
Joined: Fri Jun 22, 2007 6:26 pm

Post » Sun Jun 17, 2012 10:59 pm

Actually according to http://www.creationkit.com/States_(Papyrus) for states, auto is declared first. I'll try that still though.

EDIT: Here's what it spits out if I do that anyways though:

Starting 1 compile threads for 1 files...Compiling "DynamicWalkSpeed1"...f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(6,1): no viable alternative at input 'state'f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(6,15): required (...)+ loop did not match anything at input 'auto'f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(19,2): no viable alternative at input 'Game'f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(19,6): mismatched input '.' expecting LPARENf:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(0,0): error while attempting to read script DynamicWalkSpeed1: Object reference not set to an instance of an object.No output generated for DynamicWalkSpeed1, compilation failed.Batch compile of 1 files finished. 0 succeeded, 1 failed.Failed on DynamicWalkSpeed1
User avatar
Everardo Montano
 
Posts: 3373
Joined: Mon Dec 03, 2007 4:23 am

Post » Mon Jun 18, 2012 6:03 am

Actually according to http://www.creationkit.com/States_(Papyrus) for states, auto is declared first. I'll try that still though.
Oops, I guess my memory misfired. Thanks for correcting me on that one.

Cipscis

EDIT:

Ah, your states have to surround your events, not the other way around.

Cipscis
User avatar
Chica Cheve
 
Posts: 3411
Joined: Sun Aug 27, 2006 10:42 pm

Post » Mon Jun 18, 2012 3:12 am

Oh I see!

Is it possible to just run without events entirely? I.E. I assume the auto-state means that as soon as the script is loaded, it runs whatever is under that default state.
User avatar
Kaley X
 
Posts: 3372
Joined: Wed Jul 05, 2006 5:46 pm

Post » Sun Jun 17, 2012 8:23 pm

Round 2:

Starting 1 compile threads for 1 files...Compiling "DynamicWalkSpeed1"...f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(5,2): no viable alternative at input 'Game'f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(5,6): mismatched input '.' expecting LPARENf:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(0,0): error while attempting to read script DynamicWalkSpeed1: Object reference not set to an instance of an object.No output generated for DynamicWalkSpeed1, compilation failed.Batch compile of 1 files finished. 0 succeeded, 1 failed.Failed on DynamicWalkSpeed1

That's with the Event's removed. I figured I didn't really need them, though if it's needed to start the script I could always just add

Event OnCellLoad()    GotoState("Default")endEvent

To the beginning. I think...
User avatar
Elina
 
Posts: 3411
Joined: Wed Jun 21, 2006 10:09 pm

Post » Mon Jun 18, 2012 4:13 am

You'll still need events - only declarative code is allowed outside events.

Events are basically the same as functions, except native events are called by the game in response to certain... well, events. Because of this, they're your entry points for your code.

Cipscis
User avatar
jessica sonny
 
Posts: 3531
Joined: Thu Nov 02, 2006 6:27 pm

Post » Sun Jun 17, 2012 11:12 pm

Allright I've revised it with some new events I just learned about:

Scriptname DynamicWalkSpeed1 extends ObjectReferenceEvent onInit()	Game.GetPlayer().ModActorValue("SpeedMult", 1)	registerForUpdate(0.1)	gotoState("Default")endEvent;default statestate Default  Event OnUpdate()   if Game.GetPlayer().IsRunning()	Game.GetPlayer().ModActorValue("SpeedMult", 1)   elseif Game.GetPlayer().IsSprinting()	Game.GetPlayer().ModActorValue("SpeedMult", 1)   else	GotoState("Walk")   endif   RegisterForSingleUpdate(0.1)  endEventendState;special state that activates when player is walking. Then, it checks what the skymode is, and changes SpeedMult depending on that mode. If player runs or sprints while in the walk state, it reverts back to the default state.state Walk  RegisterForSingleUpdate(0.1)  if Weather.GetSkyMode() == 1   Game.GetPlayer().ModActorValue("SpeedMult", 1.75)  elseif Weather.GetSkyMode() == 2   Game.GetPlayer().ModActorValue("SpeedMult", 2)  elseif Weather.GetSkyMode() == 3   Game.GetPlayer().ModActorValue("SpeedMult", 2.5)  endif  if Game.GetPlayer().IsRunning()   GotoState("Default")  elseif Game.GetPlayer().IsSprinting()   GotoState("Default")  endifendState

Current error list when compiling:

Starting 1 compile threads for 1 files...Compiling "DynamicWalkSpeed1"...f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(25,2): no viable alternative at input 'RegisterForSingleUpdate'f:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(25,26): extraneous input '0.1' expecting RPARENf:\program files (x86)\steam\steamapps\common\skyrim\Data\Scripts\Source\temp\DynamicWalkSpeed1.psc(38,1): mismatched input 'endState' expecting ENDFUNCTIONNo output generated for DynamicWalkSpeed1, compilation failed.Batch compile of 1 files finished. 0 succeeded, 1 failed.Failed on DynamicWalkSpeed1

It feels like I'm getting closer :D
User avatar
Pat RiMsey
 
Posts: 3306
Joined: Fri Oct 19, 2007 1:22 am

Post » Mon Jun 18, 2012 5:21 am

You need to wrap the code in your "Walk" state in an event as well. Maybe http://www.creationkit.com/OnBeginState?

Cipscis
User avatar
glot
 
Posts: 3297
Joined: Mon Jul 17, 2006 1:41 pm

Post » Mon Jun 18, 2012 12:05 am

Wow, had no idea that even existed. Thanks, I'll try that out.

If I'm currently operating in the "walk" state, does everything going on in the "Default" state pause? For example, do my update intervals stop firing or are they going to go on all the time, reguardless if I'm in the Walk state of the script or not?

I'm just trying to make it so this doesn't end up flooding the system with an endless stream of commands, causing Papyrus to run slow or crash in-game.

EDIT: Welp it compiled successfully, yay :biggrin: Time to see if it works. I'm expecting it not to but I'll figure out why later :tongue:


Aaaaand didn't work :P I probably need to actually attach it to an invisible quest or something, instead of just attaching it to the player actor in the actor list.
User avatar
JR Cash
 
Posts: 3441
Joined: Tue Oct 02, 2007 12:59 pm

Post » Sun Jun 17, 2012 10:58 pm

Yes! Got it to (mostly) work. Here's what the final code looks like:

Scriptname DynamicWalkSpeed1 extends Quest;Booting the script with onInitEvent onInit()Game.GetPlayer().ForceActorValue("SpeedMult", 1)registerForUpdate(1)endEventEvent OnUpdate()if Game.GetPlayer().IsRunning()  Game.GetPlayer().ForceActorValue("SpeedMult", 100)elseif Game.GetPlayer().IsSprinting()  Game.GetPlayer().ForceActorValue("SpeedMult", 100)elseif Weather.GetSkyMode() == 1  Game.GetPlayer().ForceActorValue("SpeedMult", 175)elseif Weather.GetSkyMode() == 2  Game.GetPlayer().ForceActorValue("SpeedMult", 175)elseif Weather.GetSkyMode() == 3  Game.GetPlayer().ForceActorValue("SpeedMult", 175)endifendEvent

Ended up cutting out a lot of the [censored] when I realized I could just endlessly stack elseif's to get the same effect I was trying to achieve with states. Also had the side effect of working right from the get-go instead of confusing the update timer.

I attached the script to the player via a quest, which was just set to "Start with game" - all you need to get it to work really.

Now there is one major problem that I don't know how to solve - first of all, SpeedMult is a value ONLY checked by the game when you switch from one "movement state" to another. AKA when you switch from run to sprint, or from run to sneak, etc. Which means, my speedmultipliers are succesfully changing at the right moments, but you will never notice anything changed until you start sprinting or sneaking. So it'll do the walking speed multiplier of 200 (100 default). But, if you decide to run, it'll correctly set it back to 100, but you will still be "moving" at 200 until you start sprinting or sneaking.

Is there a way to FORCE the game to "check" what the multiplier is so it changes your speed the moment it gets changed? I thought ForceAV would do this, but it apparently doesn't. As far as I know it's impossible to force an actor to sneak too (which would force the game to check the multipliers), though maybe not.
User avatar
John Moore
 
Posts: 3294
Joined: Sun Jun 10, 2007 8:18 am

Post » Sun Jun 17, 2012 5:59 pm

Okay so I redid my whole method above, to use spells instead of tyring to do it via the commands. It seems to work much better in implementation

Scriptname DynamicWalkSpeed1 extends QuestSPELL Property Speed175  AutoSPELL Property Speed230  Auto;Booting the script with onInitEvent onInit()Game.GetPlayer().RemoveSpell(Speed230)Game.GetPlayer().RemoveSpell(Speed175)registerForUpdate(0.5)endEventEvent OnUpdate()if Game.GetPlayer().IsRunning()  Game.GetPlayer().RemoveSpell(Speed230)  Game.GetPlayer().RemoveSpell(Speed175)  elseif Game.GetPlayer().IsSprinting()  Game.GetPlayer().RemoveSpell(Speed230)  Game.GetPlayer().RemoveSpell(Speed175)  elseif Weather.GetSkyMode() == 1  Game.GetPlayer().RemoveSpell(Speed230)  Game.GetPlayer().AddSpell(Speed175, true)	elseif Weather.GetSkyMode() == 2  Game.GetPlayer().RemoveSpell(Speed175)  Game.GetPlayer().AddSpell(Speed230, true)  elseif Weather.GetSkyMode() == 3  Game.GetPlayer().RemoveSpell(Speed175)  Game.GetPlayer().AddSpell(Speed230, true)  endifendEvent

HOWEVER I do have one big issue - for some reason, my spell effects show up properly, but they don't work. The speed adjustment simply doesn't happen, even though it registers on my magic effects list that the correct speed-adjustment spell is in effect. I've got it set up using the Frostbite spell as a template, except switched it to Constant Effect and Self vs. being hit and having the effect last for X number of seconds.

I've even copied the Wisp's speed increase ability BY THE LETTER when it's magic is above a certain point EXACTLY, and it still doesn't work. I'm starting to wonder if the SpeedMult spell effect was made to only work against non-player actors, and is hard coded to not work with players. Because everything is set up exactly as it should be, and it simply doesn't work (the spell's effect). I'm a complete roadblock here. If I can somehow get the spell to actually work, then this mod is done and releaseable. But it just doesn't!!!
User avatar
casey macmillan
 
Posts: 3474
Joined: Fri Feb 09, 2007 7:37 pm

Post » Sun Jun 17, 2012 4:55 pm

Any help??

EDIT: Finally got it! I never did get around my above issue, but I learned the game checks what your speedmult is whenever something is added to your inventory. So, when I just have it so my script adds then immediately removes a random misc item to the inventory silently (so there is no noise or message), the game will check my speed and then immediatly apply the correct speed.
User avatar
Dina Boudreau
 
Posts: 3410
Joined: Thu Jan 04, 2007 10:59 pm

Post » Sun Jun 17, 2012 8:32 pm

You can add another effect to your spell that changes inventory weight AV by 0.01. That's what I did for slow effects in the hypothermia mod and it worked really well.
User avatar
IM NOT EASY
 
Posts: 3419
Joined: Mon Aug 13, 2007 10:48 pm


Return to V - Skyrim