Nessa Posted June 23, 2014 Posted June 23, 2014 OK, I've got a question about resurrection and respawning. Here's the setup: Â The player is captured and can: Kill the captor via dialog Make captor unconscious via dialog I need the captor reset so it can be used again. (Repeating quest here.) Â If unconscious this is simple. Move captor back to holding cell, make conscious, disable. It can be reused for when the player is captured again. Â Now, the question is, what is the best practice if the captor is killed? Would calling RessurectActor on it, moving it to the holding cell, then disabling be the way to go? Would forcing it to respawn be better? Â And perhaps another question: am I making this too complicated or is there a better way to go about this?
Odessa Posted June 23, 2014 Posted June 23, 2014 I've done a little investigation with UDFs, perhaps someone will find this interesting.  So, you should never do 'sv_destruct' on a function argument, or on a local UDF string_var if you set it to another string_var (that makes a pointer to it, not a copy of it, unlike 'let').  (From gribbleshnibbit documentation):    A note about local variables within functions: when the function terminates, all local variables are reset to zero. Local array variables are automatically cleaned up so there is no need to use ar_Null to reset them. String variables used to hold function arguments are also automatically destroyed. Local string variables, however, are not automatically cleaned up because they may refer to strings in use by other scripts. It is the scripter's responsibility to use sv_Destruct to destroy any local variables when appropriate. The following example code illustrates this idea: scn SomeFunction string_var arg string_var local0 string_var local1 string_var local2    Begin Function { arg }     let local0 := "some string"     set local1 to someQuest.someStringVar     let local2 := someQuest.someStringVar     sv_Destruct local0 local2 End In the above script, the string variable arg will be automatically cleaned up by OBSE when the function terminates. local1 will not be, and should not be destroyed explicitly because doing so would invalidate the someStringVar variable in an external script. local0, however, must be explicitly destroyed as it is not referenced by any other script. local2 must also be destroyed as let, unlike set, creates a copy of the string with a new string ID.    Does that mean that function arguments are not 'real' variables, they are pointers to real variables? I tested this with:    scn myUDF string_var arg1 int arg2 Begin Function { arg1, arg2 }   printc "myudf: %z and %g", arg1, arg2    sv_destruct arg1    set arg2 to 99 ; * identical result with let or set   printc "myudf: %z and %g", arg1, arg2 End scn mytestquestscript string_var mystring int myint ref rRef int itype Begin GameMode    let mystring := "my important string"    let myint := 5    printc "First: %z %g ", mystring, myint    call myudf mystring, myint    printc "Post UDF: %z %g ", mystring, myint   let rRef := myudf   let itype := GetType rRef   PrintC "the type of a udf is %g" itype End    Which gave my the scof output:   SetConsoleOutputFilename >> 'udf2.txt' First: my important string 5  ( the two vars in my quest ) myudf: my important string and 5 ( the two vars as arguments in the function )myudf: NULL and 99 ( the two var as arguments, after I sv_destruct and reset )Post UDF: my important string 5 ( the two vars in my quest post UDF are still unchanged )the type of a udf is 17   ----  Conclusion: Apparently not. A shame, I would love to be able to pass a pointer to a quest var like this.  Whilst needless, doing "sv_destruct" on an argument is not dangerous.  Presumably then, the only reason NVSE does not automatically destroy local string_vars is just in case you did 'set .. to ..' with them, which does create a pointer (I checked myself).Â
ArgusSCCT Posted June 23, 2014 Posted June 23, 2014 Anybody know where I can find an explanation of what SetUIFloat, SetUIString and what UI functions in general do? I checked the NVSE command list but it doesn't really say what they do. I'd assume SetUIFloat has to do with x,y positions and SetUIString has to do with placing messages on the HUD. Regardless, I can't figure out how it is that they work, I mean, say I use those functions, what is it that is supposed to happen on the HUD/game?
Guest Posted June 23, 2014 Posted June 23, 2014 There's no documentation on huds and it's better if you know some xml to work with them. You can set variables or (behaviours?features?) using these functions, you see them starting with underscore usually. You must cross-check the hud file to understand what they are doing, it is inside Data\menus\prefabs\name of the mod
jaam Posted June 23, 2014 Posted June 23, 2014 You could try looking at Perlinor's scripts in MCM also. Â
Guest tomm434 Posted June 23, 2014 Posted June 23, 2014 OK, I've got a question about resurrection and respawning. Here's the setup:  The player is captured and can: Kill the captor via dialog Make captor unconscious via dialog I need the captor reset so it can be used again. (Repeating quest here.)  If unconscious this is simple. Move captor back to holding cell, make conscious, disable. It can be reused for when the player is captured again.  Now, the question is, what is the best practice if the captor is killed? Would calling RessurectActor on it, moving it to the holding cell, then disabling be the way to go? Would forcing it to respawn be better?  And perhaps another question: am I making this too complicated or is there a better way to go about this?  Do you do use fade to black on scene when captor is killed? ;Somewhere in the quest you have a reference. ref CaptorDeadRef ------------------------------------------------------------------ Effect script (yeah, a spell) Scriptname CaptorScene int scene int stage float timer ref CaptorDeadRef float ftimer begin ScriptEffectUpdate let timer +=GetSecondsPassed if eval ((ftimer += ScriptEffectElapsedSeconds) < 0.3) return else let fTimer := 0 endif if stage ==0 if timer >=0 DisablePlayerControls 1 1 1 1 1 1 1 Captor.setrestrained 1 imod FadeToBlack9sISFX set timer to 0 set stage to 1 endif endif if stage ==1 if timer >=6 CaptorRef.disable set YourQuest.CaptorDeadRef to Captor.placeatme aaMS15CaptoryDeadBody 1 set CaptorDeadRef to YourQuest.CaptorDeadRef CaptorDeadRef.killactor CG01DadREF 3 ; Instead of CG01Dad ref you insert any reference imod FadeInFromBlack4sISFX set timer to 0 set stage to 2 endif endif if stage ==2 if timer >=4 set scene to 1 set stage to 3 endif endif if scene ==1 EnablePlayerControls set scene to 2 dispel CaptorScene endif end So after some time you need to clean up created dead body, you can do it from any script you want, just type ref MyRef set Myref to myquest.CaptorDeadBody MyRef.disable Myref.markfordelete And the captor who was in dialogue will always be A-L-I-V-E! I know that means lying to player but it's easier for you.
ArgusSCCT Posted June 23, 2014 Posted June 23, 2014 Yeah I know about XMLs, and that's all done, the old mod has it. I just need to know what it is that those functions in particular do, I'll check MCM, checked oHUD, but I didn't see much with it, I'll see if I can find out what's going on with it through the hardcore needs part, guessing that will use the string function.Â
Guest Posted June 23, 2014 Posted June 23, 2014 they mainly set variables which are contained inside the xml, there's not much more, it's the xml that says how the hud behaves, you must look at that
Guest Posted June 23, 2014 Posted June 23, 2014 An example pasted from a hud of mine: Â XML: ... <systemcolor> <copy> &hudmain; </copy> <onlyif> Â Â Â <copy src="io()" trait="_HealthLow" /> Â Â Â <eq> 0 </eq> </onlyif> Script: ... (If the health is not low) SETUIFloat "HUDMainMenu\_HealthLow" 0 ... The hud color is inherited if that var HealthLow is 0. Inside the script I check the PC health value and I decide it's not low, so I set that value to 0 with SETUIFloat
Nessa Posted June 23, 2014 Posted June 23, 2014  Do you do use fade to black on scene when captor is killed?  Ah! Now there's an idea! Much simpler I think. Thanks for the suggestion!  I think that about wraps up my problem then. Once I get that working I think I can add a few more encounters to this project before release.
Nessa Posted June 23, 2014 Posted June 23, 2014 Nessa, is this for TTW? New quest mod? Â Yes, actually. It's a TTW extension for Odessa's glorious Another Kick in the Head. Â It's actually fully functional, I'm just adding more "Bad End" mini quests and dream sequences at the moment. Oddly that's taking more time than the rest of the mod took setting up. Odessa did a beyond splendid job making it simple to add to!
prideslayer Posted June 24, 2014 Posted June 24, 2014 Ok peeps, I present you with this: let arTmp := rSrc.NX_GetEVFoAr "Sexout:Start::" foreach element <- arTmp ar_dump element let nxKey := element["key"] sv_Replace "Sexout:Start::|Sexout:Started::" nxKey let foVal := element["value"] DebugPrint "fnSCSv fo: %z %n (%i)" nxKey foVal foVal rTgt.NX_SetEVFo $nxKey foVal sv_destruct nxKey loop Which outputs this to the debug log: ** Dumping Array #6 ** Refs: 1 Owner 0C: Sexout.esm [ key ] : sexout:start::actora [ value ] : 1104096.000000 fnSCSv fo: Sexout:Started::actora <no name> (00000000) The question I pose... what gives? Â I use the same code (except for the sv_replace) in a different UDF and it works fine. This one is having some kind of problem with foVal -- that or I did some stupid "is it plugged in" move and can't see it. Â Identical code in the same UDF for copying floats rather than forms works fine.
DoctaSax Posted June 24, 2014 Posted June 24, 2014 Ah, yeah, it gives you the decimal of the formid. For some reason, this is what happens with an ar_dump on GetEvfloAr, because iirc nx stores forms decimally. But if you pass element["value"] to a ref var, you should be able to still get a form from that. For readouts, you can output to a hex formID string with let sv_hex := NumToHex iNum 8
prideslayer Posted June 24, 2014 Posted June 24, 2014 It's actually 0 as presented. foVal is a form and you can see in the debugprint, it's coming up all 0's. Â let foVal := element["value"] DebugPrint "fnSCSv fo: %z %n (%i)" nxKey foVal foVal (output) fnSCSv fo: Sexout:Started::actora <no name> (00000000) When I get the EVFo out later, it's 0 as well. This is basically identical to what I do in fnSexoutActRun, which works perfectly well. I'm missing something stupid and basic this go around; it's my first time using the NX_Get....Ar's and sv_replace.
DoctaSax Posted June 24, 2014 Posted June 24, 2014 I could be wrong about reconverting them back to forms, and NX_GETEVFOAr may need fixing. I've only ever needed the NX_Ar functions for readouts through ar_dump etc, so when I got numbers there I probably converted to hex, got a readout from that & moved on.
prideslayer Posted June 24, 2014 Posted June 24, 2014 I kinda figured it was an NX issue. I'll fire it off to jaam to take a look at since he wrote those functions. In the script I've switched to just doing an NX_GetEV.. with the key and that seems to be working fine, just finishing up testing.
jaam Posted June 24, 2014 Posted June 24, 2014 You tried DebugPrint "fnSCSv fo: %z %n (%i) %g" nxKey foVal foVal foVal ? Â
prideslayer Posted June 24, 2014 Posted June 24, 2014 I didn't, but the print isn't actually the issue.  This code: let arTmp := rSrc.NX_GetEVFoAr "Sexout:Start::" foreach element <- arTmp let nxKey := element["key"] let foVal := element["value"] sv_Replace "Sexout:Start::|Sexout:Started::" nxKey rTgt.NX_SetEVFo $nxKey foVal sv_destruct nxKey loop Is just doing the NX_GetEVFoAr in order to copy all the elements to a new namespace. When it runs (there is a similar one right before it for floats), the NX destination vars all come up null/0 and sexout of course aborts when it sees that. The floats work fine.  I changed it to this and it works fine: let arTmp := rSrc.NX_GetEVFoAr "Sexout:Start::" foreach element <- arTmp let nxKey := element["key"] let rVal := rSrc.NX_GetEVFo $nxKey sv_Replace "Sexout:Start::|Sexout:Started::" nxKey rTgt.NX_SetEVFo $nxKey rVal sv_destruct nxKey loop The only difference there is I'm not using the element value and am instead doing a normal NX_GetEVFo with the element key.
jaam Posted June 24, 2014 Posted June 24, 2014 Don't bite but.. foVal was defined as a ref ? Â I'll try to debug that, after the other three things I piled up today. Â
prideslayer Posted June 24, 2014 Posted June 24, 2014 Yeah, it was. Here's the full original UDF. Â scn fnSexoutCopyStartvars ; Copies Sexout:Start NX vars from rSrc to rTgt and renames them ; into the Sexout:Started namespace. ; args ref rSrc ref rTgt ; internal array_var element array_var arTmp string_var nxKey float fVal ref rVal Begin Function{rSrc rTgt} let arTmp := rSrc.NX_GetEVFoAr "Sexout:Start::" foreach element <- arTmp let nxKey := element["key"] let rVal := element["value"] sv_Replace "Sexout:Start::|Sexout:Started::" nxKey DebugPrint "fnSCSv fo: %z %n (%i)" nxKey rVal rVal rTgt.NX_SetEVFo $nxKey rVal sv_destruct nxKey loop let arTmp := rSrc.NX_GetEVFlAr "Sexout:Start::" foreach element <- arTmp let nxKey := element["key"] let fVal := element["value"] sv_Replace "Sexout:Start::|Sexout:Started::" nxKey DebugPrint "fnSCSv fl: %z %f" nxKey fVal rTgt.NX_SetEVFl $nxKey fVal sv_destruct nxKey loop End That is the checked in version right now in svn, except for the change to NX_GetEV.. from element["value"]Â I never checked in the nonworking version, before the variable rename.
DoctaSax Posted June 24, 2014 Posted June 24, 2014 Question for the more mathematically inclined:  I literally only just found out that if you let an int to a float, you'll get the floor of the float. What I want instead is the float rounded up or down according to regular rounding methods (eg the ceil if the float is >= .5 , the floor if < .5). How do I go about doing that in as few lines as possible?
DoctaSax Posted June 24, 2014 Posted June 24, 2014 Heh, and to think I was looking at using fmod etc.
prideslayer Posted June 24, 2014 Posted June 24, 2014 Regular rounding (bank rounding) is a bit more complex than that (you round x.5 towards the even number -- so 1.5 rounds to 2, as does 2.5), but that should get you by.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now