jamochawoke Posted April 5, 2011 Share Posted April 5, 2011 Ok I have a scripted event in mind where I want a corpse of an NPC after you kill it and upon activation of the corpse that the corpse will float in the air for a second or two, play a magic shader effect and a sound, and then drop back down to its corpse state. Now I have the onactivation and playing the sound and shader effect down. It looks really good. Yet I can't for the life of me figure out how to get the NPC to float above the ground. Do I use an animation and force an animation on the actor reference? Is there somehow a console command to change an actor's z axis? I've seen it done in a few mods (Midas Magic and Mannimarco Revisited) but after a few hours searching I can't figure out how they did it. Any help would be appreciated and I'll definitely list you as helping me in my mod! Link to comment Share on other sites More sharing options...
jamochawoke Posted April 7, 2011 Author Share Posted April 7, 2011 Ok then... Let's start here. Is there a way via scripting to force an animation on a dead NPC? I know it is possible using specialidles and token items on a live NPC. I have a floating animation I could easily use to get this effect down. Link to comment Share on other sites More sharing options...
jamochawoke Posted April 7, 2011 Author Share Posted April 7, 2011 Ok since apparently nobody knows the answer to that one I went ahead and tried messing with the Z position. There's only one problem... for some reason on death it stretches the model and sends them FLYING! VERY FAR, VERY FAST. Here's what I've got. It's supposed to, on the NPC's death make their corpse rise above the ground steadily for 5 seconds then drop down again. I wish I could YouTube what actually happens... because it's kind of funny. But whatever. What I'd like to know is why this doesn't work :/. NPCRef is the reference to the test NPC. ScriptName CorpseScriptz short Dead float timer float zmove float endzmove Begin GameMode set endzmove to NPCRef.GetPos z if (Dead == 1) set timer to getSecondsPassed if (timer < 5) set zmove to NPCRef.GetPos z set zmove to zmove + timer NPCRef.SetPos z zmove endif if (timer > 5) NPCRef.SetPos z endzmove endif endif End Begin OnDeath if (Dead == 0) set Dead to 1 endif End Link to comment Share on other sites More sharing options...
fg109 Posted April 7, 2011 Share Posted April 7, 2011 (edited) set endzmove to NPCRef.GetPos z This part should be in the OnDeath block. Otherwise you're setting this to the corpse's current height every time the GameMode block runs. if (timer < 5) set zmove to NPCRef.GetPos z set zmove to zmove + timer NPCRef.SetPos z zmove endif This could explain why your corpse flies off so fast. GameMode runs every frame the game is not in a menu. So let's assume the corpse starts out at 0 on the z axis and you get 10 frames per second (just to make the math a bit easier). After the first frame, zmove is 0.1. After the second frame, it's 0.3 (0.1 + 0.2). After the third frame, it's 0.6 (0.3 + 0.3). Then it goes to 1, 1.5, 2.1, 2.8, 3.6, 4.5, and 5.5 in the first second. In the next second, it's 6.1, 7.3, 8.6, 10, 11.5, 13.1, 14.8, 16.6, 18.5, 20.5. As you can see, it keeps going up faster and faster. And this is only assuming you get 10 frames per second, which I'm sure is not the case. This script would probably work for your original request: scriptname CorpseScriptZ short control_var float startz float endz float currentz float timer Begin OnActivate if (control_var > 0) Return endif if (GetDead) set startz to GetPos Z set timer to 0 set control_var to 1 else Activate endif End Begin GameMode if (control_var == 1) set timer to (timer + GetSecondsPassed) set currentz to (startz + timer) SetPos Z currentz if (timer >= 5) set timer to 0 set control_var to 2 endif Return elseif (control_var == 2) set timer to (timer + GetSecondsPassed) if (timer > = 5) set endz to GetPos Z set timer to 0 set control_var to 3 endif Return elseif (control_var == 3) set timer to (timer + GetSecondsPassed) set currentz to (endz - timer) SetPos Z currentz if (timer >= 5) || (startz >= currentz) SetPos Z startz set timer to 0 set control_var to 0 endif Return endif End I didn't really want to post anything because I'm sure it would look ugly. Much better if it's possible to play an animation. If you find the corpse rising too slowly or not high enough, you can always change it to "set currentz to startz + 2 * timer". Edited April 7, 2011 by fg109 Link to comment Share on other sites More sharing options...
jamochawoke Posted April 7, 2011 Author Share Posted April 7, 2011 Ok, I used your script. Still sent the NPC FLYING! I decided to look into seeing how Miltiades did it in his Mannimarco mod and he used a pretty convoluted system. You have to loot robes which will give the player an ability with a script which will move Mannimarco's corpse up and dissapear while playing sounds. It's a neat effect but a strange way of doing it. His equations to move the z axis were also similar to my first attempt a few posts up and he even multiplied it by 5 every time he set the z axis... which to me seems crazy from the effects I was getting... But I also noticed he disabled the actor and actor AI and reenabled it on script effect finish. Maybe that has something to do with moving the z axis beings when an NPC actor goes into the death state they are governed by Havok?? So I thought I'd try it his way and when my NPC goes into OnDeath state I'd cast a spell with a script containing your script... just to test it out. Nothing happened. Maybe I should resurrect the NPC (it shows a getting up animation when used from script), disable their AI, then try to force the animation to float, then kill them again? I'm just very confused at this point. Link to comment Share on other sites More sharing options...
whalecakes Posted April 7, 2011 Share Posted April 7, 2011 Set a variable to the corpse's z position, then spam 'setpos z' on the corpse, adding a bit to the variable every frame as needed to make it rise; that's how I did it for my corpse carry script. This will have to be in a quest or object script as magic effects get removed from corpses, which means you'll need to set a ref variable to the corpse in question.Some bodies, for whatever reason, will just flip out and stretch into infinity. There does not seem to be any pattern as to which bodies or the conditions. Link to comment Share on other sites More sharing options...
fg109 Posted April 7, 2011 Share Posted April 7, 2011 (edited) That's weird, I just tried out my script and it worked... after some tweaking. It definitely didn't send the corpse flying off. When I first tried it, nothing happened except for the corpse twitching a couple of times. So I went back to the script and modified the lines to "currentz + 10 * timer", and when I went back, the corpse rose to around head level. I also found out that unlike objects, corpses do fall down if you don't use SetPos every frame. So after 5 seconds, it just dropped onto the floor. So I decided to add in some "RunScriptLine "ToggleActorsAI"" after reading your post, and now it sort of worked. But it wasn't reliable, and sometimes the corpse just fell back onto the ground again. This seemed to happen more when I was indoors or when I kept hitting the corpse while it was floating. So I went back and changed the script again. This time everything seemed to work perfectly. scriptname CorpseScriptZ short control_var float startz float endz float currentz float timer Begin OnActivate if (control_var > 0) Return endif if (GetDead) set startz to GetPos Z set timer to 0 set control_var to 1 else Activate endif End Begin GameMode if (control_var == 1) set timer to (timer + GetSecondsPassed) set currentz to (startz + 10 * timer) SetPos Z currentz if (timer >= 5) || (currentz >= 300) set timer to 0 set control_var to 2 endif Return elseif (control_var == 2) set timer to (timer + GetSecondsPassed) SetPos Z currentz if (timer >= 5) set endz to GetPos Z set timer to 0 set control_var to 3 endif Return elseif (control_var == 3) set timer to (timer + GetSecondsPassed) set currentz to (endz - 10 * timer) SetPos Z currentz if (timer >= 5) || (startz >= currentz) SetPos Z startz set timer to 0 set control_var to 0 endif Return endif End There's barely any difference from what I posted before. Not sure why it didn't work for you. Did you try making a clean save? EDIT: whalecakes beat me to saying that spamming SetPos every frame is the key. Edited April 7, 2011 by fg109 Link to comment Share on other sites More sharing options...
jamochawoke Posted April 8, 2011 Author Share Posted April 8, 2011 Ok I just couldn't get your script to work when I embedded it within my NPC's main script. So what I did was OnActivate using (GetDead) I added an ability spell named NPCFloatz with a magic effect script attached named NPCFloat to the player's inventory. The spell has a duration of 20 seconds (giving plenty of time to make it work), is set as ability, and this is the script: scn NPCFloat short control_var float startz float endz float currentz float timer Begin ScriptEffectStart set startz to NPCRef.GetPos Z set timer to 0 set control_var to 1 End Begin ScriptEffectUpdate NPCRef.SetPos Z currentz if (control_var == 1) set timer to (timer + GetSecondsPassed) set currentz to (startz + (10 * timer)) NPCRef.SetPos Z currentz if (timer >= 5) || (currentz >= 300) set timer to 0 set control_var to 2 endif elseif (control_var == 2) set timer to (timer + GetSecondsPassed) NPCRef.SetPos Z currentz if (timer >= 5) set endz to NPCRef.GetPos Z set timer to 0 set control_var to 3 endif elseif (control_var == 3) set timer to (timer + GetSecondsPassed) set currentz to (endz - (10 * timer)) NPCRef.SetPos Z currentz if (timer >= 5) || (startz >= currentz) NPCRef.SetPos Z startz set timer to 0 set control_var to 0 endif endif End Begin ScriptEffectFinish NPCRef.resurrect 1 Player.RemoveSpell NPCFloatz End I took out the returns because I heard if a magic effect script has a return in the Update section it will never use the Finish section. However... what actually happens is strange. The NPC starts doing cartwheels at me, going faster and faster and faster until it's spinning at a million miles an hour then stretches off to infinity. Also the Ability Spell never wears off, even though it has a duration of 20 seconds (I don't think ability spells ever run down though...) and the EffectFinish is supposed to remove the Ability. SO I've learned from this: Using references you can get a magic effect cast on the player to affect an NPC. This still doesn't work for some reason at making them do what I need it to do :/. Link to comment Share on other sites More sharing options...
fg109 Posted April 8, 2011 Share Posted April 8, 2011 That script was not meant to be used as an ability... I'm not even sure that ScriptEffectUpdate works for an ability (I know ScriptEffectFinish only runs when you remove the ability). As for why you can't use the script I posted on your NPC, I don't know. It could be there's some conflict with the rest of your NPC's script, or it might just be something fundamentally different in our games (some mods maybe). Link to comment Share on other sites More sharing options...
jamochawoke Posted April 8, 2011 Author Share Posted April 8, 2011 (edited) Ok I noticed I did something really wrong beings it's an ability script so I fixed it. Now the NPC only does cartwheels but they do resurrect and they FINALLY STOP spinning into infinity lol. Just the cartwheels into the face is so odd (that and sometimes a little dance caused by havok). Is there any way to toggle Havok on/off via script? Here's the "working" script: scn NPCFloat short control_var float startz float endz float currentz float timer Begin ScriptEffectStart set startz to NPCRef.GetPos Z set timer to 0 set control_var to 1 End Begin ScriptEffectUpdate if (control_var == 1) set timer to (timer + GetSecondsPassed) set currentz to (startz + 5 * timer) NPCRef.SetPos Z currentz if (timer >= 5) || (currentz >= 300) set timer to 0 set control_var to 2 endif Return elseif (control_var == 2) set timer to (timer + GetSecondsPassed) NPCRef.SetPos Z currentz if (timer >= 5) set endz to NPCRef.GetPos Z set timer to 0 set control_var to 3 endif Return elseif (control_var == 3) set timer to (timer + GetSecondsPassed) set currentz to (endz - 5 * timer) NPCRef.SetPos Z currentz if (timer >= 5) || (startz >= currentz) NPCRef.SetPos Z startz set timer to 0 set control_var to 4 endif Return elseif (control_var == 4) Player.RemoveSpell NPCFloatz NPCRef.resurrect 1 endif End Edited April 8, 2011 by jamochawoke Link to comment Share on other sites More sharing options...
Recommended Posts