steamcanuck Posted May 25, 2015 Share Posted May 25, 2015 People may remember the Subjugation mod, it's still here on the Nexus. I've decided to revisit it and update things, make it cleaner, squish a few bugs, etc. Anyway, I'll share a code snippet first. It's a UDF that gets called when the player first subjugates a victim. My plan is to, instead of controlling the original target with my scripts & so on, create a copy. I figured, get the base form, and then use PlaceAtMe to create a copy, then destroy it when the subjugate gets released. scn SubSubjugateVictim ; reciprocal: SubReleaseVictim ref theVictim ref theBaseForm ref theSubjugate short listCount array_var fact_list Begin function {theVictim} printtoconsole "[SubC - SubSubjugateVictim] Received victim: %n %i" theVictim theVictim theVictim.RemoveItem SubjugateInitToken 1 ; check to see if he's in the forbidden list (companions) ; if so, scold the player and abort if eval (theVictim.IsInList SubjugateForbiddenList) MessageEx "%n is a companion and cannot be subjugated." theVictim return endif ; get the base form let theBaseForm := theVictim.GetBaseForm if eval (theBaseForm == 0) printtoconsole "[SubC] theBaseForm is empty." return endif ; add the victim to the form list AddFormToFormList SubjugateVictimList theVictim ; error checking let listCount := ListGetCount SubjugateVictimList printtoconsole "[SubC] SubjugateVictimList contains %.0f" listCount printc "[SubC]REF: %n (%i)%r[SubC]GBF: %n (%i)" theVictim theVictim theBaseForm theBaseForm ; create the subjugate ; NOTE: GetSelf will not work on the created form let theSubjugate := theVictim.PlaceAtMe theBaseForm 1 . . . PlaceAtMe results in a crash--I won't bother posting the remaining code (but will if people want). Can anyone shed light on why? Am I missing something important here? I should be clear, I'm aware of GetBaseObject, but GetBaseObject doesn't work well on levelled actors (as far as I understand from reading the GECK documentation). Link to comment Share on other sites More sharing options...
rickerhk Posted May 25, 2015 Share Posted May 25, 2015 Have you tried using the vanilla scripting syntax: set theSubjugate to theVictim.PlaceAtMe theBaseForm 1 Link to comment Share on other sites More sharing options...
steamcanuck Posted May 25, 2015 Author Share Posted May 25, 2015 Have you tried using the vanilla scripting syntax: set theSubjugate to theVictim.PlaceAtMe theBaseForm 1 Doesn't matter, still results in a CTD. Link to comment Share on other sites More sharing options...
steamcanuck Posted May 26, 2015 Author Share Posted May 26, 2015 Right. So I removed the code above from the UDF back to a token (I was using a token initially, anyway), and poof, it works. So for some reason, PlaceAtMe won't work in a UDF. Bug or feature, I wonder? Link to comment Share on other sites More sharing options...
hlp Posted May 26, 2015 Share Posted May 26, 2015 Definitively not a feature. One more thing to look at. :smile: Link to comment Share on other sites More sharing options...
Fallout2AM Posted May 26, 2015 Share Posted May 26, 2015 couldn't be simply because placeatme requires more than a frame to generate a ref while theBaseForm disappears after the UDF execution?... Link to comment Share on other sites More sharing options...
rickerhk Posted May 27, 2015 Share Posted May 27, 2015 couldn't be simply because placeatme requires more than a frame to generate a ref while theBaseForm disappears after the UDF execution?...You would assume theBaseForm gets handed off to the PlaceAtMe function code. But yeah - I always loop till it's 3D is loaded before performing any further functions on the PlaceAtMe spawn. Link to comment Share on other sites More sharing options...
jazzisparis Posted May 27, 2015 Share Posted May 27, 2015 GetBaseObject doesn't work well on levelled actorsNeither does GetBaseForm, which in many cases will only return a dummy form - the leveled list container - not the actual base form. Consider using GetLeveledActorBase, which should always return the correct base form (despite its name, the function will work on any actor, including non-leveled). PlaceAtMe won't work in a UDF.Using NVSE 4.6b1 and PlaceAtMe appears to work fine when called from a UDF. couldn't be simply because placeatme requires more than a frame to generate a ref while theBaseForm disappears after the UDF execution?...You would assume theBaseForm gets handed off to the PlaceAtMe function code. But yeah - I always loop till it's 3D is loaded before performing any further functions on the PlaceAtMe spawn. PlaceAtMe returns the spawned objectRef, which must therefore be a valid, initialised reference on the same frame the function is called. All functions meant to work on that type of object should (at least in theory) work properly, already on the same frame.I've done something very similar to the OP in CC&C, without ever encountering any issues. RHK - Do you remember which functions you found that may fail unless the object is fully-rendered? Link to comment Share on other sites More sharing options...
Fallout2AM Posted May 27, 2015 Share Posted May 27, 2015 PlaceAtMe returns the spawned objectRef, which must therefore be a valid, initialised reference on the same frame the function is calledI do remember calling this: If rMyRef else Let rMyRef := PlaceAtMe MyBaseID Return endifInside a spell it was spawning more than a ref, I had to move it on a quest with a slower delay. But due to the lenght of the script, at this point I can't really say if it was crashing for some other reason. Strange it wasn't crashing on a quest, however. RHK - Do you remember which functions you found that may fail unless the object is fully-rendered?Not sure if it's inherent with what you ask, but Update3D and MoveTo weren't work properly OnLoad, I had to delay on a GameMode.Since the model was still rendering, they both had as result the model remaining invisible. Link to comment Share on other sites More sharing options...
rickerhk Posted May 27, 2015 Share Posted May 27, 2015 GetBaseObject doesn't work well on levelled actorsNeither does GetBaseForm, which in many cases will only return a dummy form - the leveled list container - not the actual base form. Consider using GetLeveledActorBase, which should always return the correct base form (despite its name, the function will work on any actor, including non-leveled). PlaceAtMe won't work in a UDF.Using NVSE 4.6b1 and PlaceAtMe appears to work fine when called from a UDF. couldn't be simply because placeatme requires more than a frame to generate a ref while theBaseForm disappears after the UDF execution?...You would assume theBaseForm gets handed off to the PlaceAtMe function code. But yeah - I always loop till it's 3D is loaded before performing any further functions on the PlaceAtMe spawn. PlaceAtMe returns the spawned objectRef, which must therefore be a valid, initialised reference on the same frame the function is called. All functions meant to work on that type of object should (at least in theory) work properly, already on the same frame.I've done something very similar to the OP in CC&C, without ever encountering any issues. RHK - Do you remember which functions you found that may fail unless the object is fully-rendered? It was 'MoveTo' and 'SetPos'. From that point on, though, I never used PlaceAtme without waiting for 3D to load. Probably anything where the object needs to be translated/rotated in game. Link to comment Share on other sites More sharing options...
Recommended Posts