thomasd1979 Posted July 26, 2009 Share Posted July 26, 2009 Let me start off with an apology if this has been asked elsewhere. I've had no luck with the forum search engine, but that may just be me. I'm trying to create a enhanced night vision mod that not only increases the ambient light, but also highlights anything moving (Though to start with, I'll settle for anything not flagged as dead). I've created a test item with the effect applied and the light amplification works as intended. The problem I'm having is applying the effect shader to everything. I have the shader made, and it looks great when I manually apply it via the console. The issue is, I've been unable in the last 12 or so hours of trying to actually apply it to every living thing via a script. I've even gone to the extent of downloading similar mods to see how they did it, but of the 2 I've found, one is extremely unstable and the other is extremely involved and the visual modes are a very small part of it. Both have handled the problem differently. I tried to emulate how the stable but huge one did the job, but it was written in Italian and that makes it a bit hard to follow for this dumb American. Also since it was a small part of a very large mod, it was written to do a lot more than I'm going for. My most recent (failed) attempt is below. I tried to create an effect and apply it to everyone. Unfortunately while I created the effect just fine, I had no idea how to apply it to everything in sight based on a script. Below that is a before and after screenshot of the effect when it is manually applied. scn TomVisionThermalScript ref callingActor begin GameMode set callingActor to GetSelf if ( callingActor != player ) if ( TomVisionStatus ) == 1 if ( IsActor ) if ( GetDead ) PMS TomTargetDead 120 else PMS TomTargetTherm endif endif endif endif end http://i163.photobucket.com/albums/t304/dariusdarksaber/ScreenShot37.jpghttp://i163.photobucket.com/albums/t304/dariusdarksaber/ScreenShot40.jpg Link to comment Share on other sites More sharing options...
eldiabs Posted July 26, 2009 Share Posted July 26, 2009 My suggestion is not really code related, but you can do some very cool stuff with image space modifiers. They are fairly easy to create. For my Otis Axe weapon on one of my mods, I used the following: ScriptName CallImageSpaceOnEquip Begin OnEquip player imod <Your ISFX> End Begin OnUnequip player rimod <Your ISFX> End It calls the image space modifier on equip, then releases it when you take it off. Nothing special, and I'm sure Cipscis or one of the other script geniuses can make something much prettier and optimized, but it works. ;] Link to comment Share on other sites More sharing options...
thomasd1979 Posted July 26, 2009 Author Share Posted July 26, 2009 Something very similar to that is how I turn on the actual night-vision :) What's bothering me is how to add this effect shader that gets that nice glow on a potential target to appear. I'm not looking for anything really fancy like IFF or anything. just a simple living or dead distinction. But right now i cant even get it to work period. This all sprang out of a desire to make a night-vision rifle scope. I haven't so much given up on that as I've set it aside until I can at least do this. Baby steps :) Maybe if I can get this working, I'll start on the Thermal vision, predator style. Link to comment Share on other sites More sharing options...
Cipscis Posted July 26, 2009 Share Posted July 26, 2009 The best way to cycle through all actors within a cell is to use FOSE's looping and reference walking functions. Here is an example of the structure of a reference walking loop specific to actors:ref rCurrentRef set rCurrentRef to GetFirstRef 200 0 0; Actors Label 1 if rCurrentRef ; Do stuff to rCurrentRef set rCurrentRef to GetNextRef Goto 1 endifWhile you could call GetLineOfSight in order to check if the player can see each actor, I would not recommend it as it is a very slow function. You'll probably want to use a token (an unplayable, therefore invisible piece of armour) in order to control whether or not the shader is applied. The hardest part of this system would be the removal of the appropriate shaders, as opposed to the application of them. You'll want to include a GameMode block in the token's script that handles this, which checks things like whether or not the appropriate ImageSpace Modifier is active. When the shader is removed, the token should be removed as well via RemoveMe. Unfortunately, because GetLineOfSight and GetDistance are both very slow functions, they shouldn't be called every frame in order to check if the shader should be removed, especially not if they are being called by multiple tokens. However, they could be called every 100 frames and have a similar effect when it comes to removing the shader. Something like this should guarantee that they're not being called many times in the same frame if the token is added to many actors in the same frame:ref rContainer int iCountLimit int iCount Begin OnAdd set rContainer to GetContainer set iCountLimit to GetRandomPercent End Begin GameMode set iCount to iCount + 1 if iCount > iCountLimit ; Call GetLineOfSight and/or GetDistance now endif EndCipscis Link to comment Share on other sites More sharing options...
BigKevSexyMan Posted July 26, 2009 Share Posted July 26, 2009 Things are so archaic that we must resort to label and goto to create a simple loop. *sigh* Link to comment Share on other sites More sharing options...
thomasd1979 Posted July 26, 2009 Author Share Posted July 26, 2009 Ok, here is where I'm at right now. Ive been unable to make this work the direct way I've wanted to, and am now about to try via a "enchantment" which is to say a effect that gets applied to them and later dispelled when no longer needed. Here is the not-so-working script I've been trying. If anyone knows how to make it work without having to add tokens or effects I'd REALLY prefer that, since the less involved the better and the less that can go wrong.scn TomVisionScript ref rCurrentRef begin GameMode set rCurrentRef to GetFirstRef 200 0 0; Actors Label 1 if rCurrentRef if (GetDead != 1) ;If they are dead, do nothing. If (TomVisionStatus == 1) if (getiscreature == 1) if (GetIsCreatureType 6 == 1) PMS TomTargetThermRob else PMS TomTargetTherm endif else if (getisrace ghoul == 1) PMS TomTargetThermGho else PMS TomTargetThermHum endif endif Else if (getiscreature == 1) if (GetIsCreatureType 6 == 1) SMS TomTargetThermRob else SMS TomTargetTherm endif else if (getisrace ghoul == 1) SMS TomTargetThermGho else SMS TomTargetThermHum endif endif Endif;End "If TomVisionStatus=1" endif;End "If not dead" set rCurrentRef to GetNextRef Goto 1 endif;End "If rCurrentRef" end Link to comment Share on other sites More sharing options...
Cipscis Posted July 27, 2009 Share Posted July 27, 2009 Things are so archaic that we must resort to label and goto to create a simple loop. *sigh*We should be happy that we have anything at all! In "vanilla" (i.e. non-FOSE) Fallout 3 scripting the closest we have to flow-control structures are conditional statements, and there is no way to form loops. While Label and Goto may sound slightly archaic, they are certainly an awful lot better than nothing at all. @thomasd1979:The problem there is that you're trying to call all of your reference functions with implicit reference syntax, whereas you should be calling them explicitly on "rCurrentRef". For more information on reference functions, have a look at the appropriate section of my Scripting for Beginners tutorial - Reference Functions Try using something like this instead:ScriptName TomVisionScript ref rCurrentRef Begin GameMode set rCurrentRef to GetFirstRef 200 0 0 ; Actors Label 1 if rCurrentRef if rCurrentRef.GetDead ; If they are dead, do nothing else if (TomVisionStatus == 1) if rCurrentRef.GetIsCreature if rCurrentRef.GetIsCreatureType 6 rCurrentRef.PlayMagicShaderVisuals TomTargetThermRob else rCurrentRef.PlayMagicShaderVisuals TomTargetTherm endif elseif rCurrentRef.GetIsRace Ghoul rCurrentRef.PlayMagicShaderVisuals TomTargetThermGho else rCurrentRef.PlayMagicShaderVisuals TomTargetThermHum endif else if rCurrentRef.GetIsCreature if rCurrentRef.GetIsCreatureType 6 rCurrentRef.StopMagicShaderVisuals TomTargetThermRob else rCurrentRef.StopMagicShaderVisuals TomTargetTherm endif elseif rCurrentRef.GetIsRace Ghoul rCurrentRef.StopMagicShaderVisuals TomTargetThermGho else rCurrentRef.StopMagicShaderVisuals TomTargetThermHum endif endif ; if TomVisionStatus == 1 endif ; if not dead set rCurrentRef to GetNextRef Goto 1 endif ; if rCurrentRef End Cipscis Link to comment Share on other sites More sharing options...
thomasd1979 Posted July 29, 2009 Author Share Posted July 29, 2009 So..... It works. Now my only real problem is extending the range. It seems to not pick up an actor until they are about 50 feet away. Any way to extend that? The only other thing is far more minor a tweak. It seems to sometimes take about 3-5 seconds to remove the effect from a few models. I can live with that, but if theres a reasonable fix, that would be great.scn TomVisionThermalScript int iCount int iCountLimit ref rCurrentRef Begin OnEquip Player set iCountLimit to 50; did this to stop some inconsistencies with how fast things would get effected. set TomVisionStatus to 1 imod TomVisionThermalSFX End Begin GameMode set rCurrentRef to GetFirstRef 200 0 0; Actors set iCount to 1 Label 1 if TomVisionStatus == 1 if (iCount) < (iCountLimit) if rCurrentRef if rCurrentRef.GetDead; If they are dead, remove the visual if rCurrentRef.GetIsCreature if rCurrentRef.GetIsCreatureType 6 rCurrentRef.StopMagicShaderVisuals TomTargetThermRob else rCurrentRef.StopMagicShaderVisuals TomTargetTherm endif elseif rCurrentRef.GetIsRace Ghoul rCurrentRef.StopMagicShaderVisuals TomTargetThermGho else rCurrentRef.StopMagicShaderVisuals TomTargetThermHum endif else if rCurrentRef.GetIsCreature if rCurrentRef.GetIsCreatureType 6 rCurrentRef.PlayMagicShaderVisuals TomTargetThermRob else rCurrentRef.PlayMagicShaderVisuals TomTargetTherm endif elseif rCurrentRef.GetIsRace Ghoul rCurrentRef.PlayMagicShaderVisuals TomTargetThermGho else rCurrentRef.PlayMagicShaderVisuals TomTargetThermHum endif endif set rCurrentRef to GetNextRef endif set iCount to (iCount + 1) Goto 1 endif else if (iCount) < (iCountLimit) if rCurrentRef if rCurrentRef.GetIsCreature if rCurrentRef.GetIsCreatureType 6 rCurrentRef.StopMagicShaderVisuals TomTargetThermRob else rCurrentRef.StopMagicShaderVisuals TomTargetTherm endif elseif rCurrentRef.GetIsRace Ghoul rCurrentRef.StopMagicShaderVisuals TomTargetThermGho else rCurrentRef.StopMagicShaderVisuals TomTargetThermHum endif set rCurrentRef to GetNextRef endif set iCount to (iCount + 1) Goto 1 endif endif End Begin OnUnequip Player set TomVisionStatus to 0 rimod TomVisionThermalSFX End Link to comment Share on other sites More sharing options...
Cipscis Posted July 29, 2009 Share Posted July 29, 2009 Increasing the value of GetFirstRef's "cell depth" parameter could probably increase the range of the effect. Like this:ScriptName TomVisionThermalScript int iCount int iCountLimit ref rCurrentRef Begin OnEquip Player set iCountLimit to 50 ; did this to stop some inconsistencies with how fast things would get effected. set TomVisionStatus to 1 ApplyImageSpaceModifier TomVisionThermalSFX End Begin GameMode set rCurrentRef to GetFirstRef 200 0 0 ; Actors set iCount to 1 Label 1 if TomVisionStatus if (iCount) < (iCountLimit) if rCurrentRef if rCurrentRef.IsActor if rCurrentRef.GetDead elseif rCurrentRef.GetItemCount <TomVisionFXToken> else rCurrentRef.AddItem <TomVisionFXToken> 1 1 endif endif set rCurrentRef to GetNextRef endif set iCount to (iCount + 1) Goto 1 endif endif End Begin OnUnequip Player set TomVisionStatus to 0 RemoveImageSpaceModifier TomVisionThermalSFX End I've left in your "iCount"/"iCountMax" code because I'm not sure what it's doing, so I don't want to get rid of it in case it's something that you need. The script on the token would handle the application and removal of the effect. You could use something like this:ref rContainer ref rShader; This is just to shorten the removal code Begin OnAdd set rContainer to GetContainer if rContainer.GetIsCreature if rContainer.GetIsCreatureType 6 set rShader to TomTargetThermRob else set rShader to TomTargetTherm endif elseif rContainer.GetIsRace Ghoul set rShader to TomTargetThermGho else set rShader to TomTargetThermHum endif rContainer.PlayMagicShaderVisuals rShader End Begin GameMode if rContainer.GetDead rContainer.StopMagicShaderVisuals rShader elseif TomVisionStatus else; if TomVisionStatus == 0 rContainer.StopMagicShaderVisuals rShader endif EndCipscis Link to comment Share on other sites More sharing options...
gsmanners Posted July 29, 2009 Share Posted July 29, 2009 Is that really a good idea? I mean using "GetFirstRef 200"? Works every time on regular NPCs, but when I had some creatures that were all parent-enabled from one master object, I only ever got the first one in the loop. Eventually, I just abandoned the idea as impossible to implement in the current FOSE. A good example would be the super mutants on the walkway in front of Jefferson Memorial, or the super mutants in the ruins just across from the Irradiated Metro. Maybe my script just sucked, but then again there could be a problem there. For reference, here is that quest script (a kill-all mod I was messing with, just to see if FOSE could do it): ref target begin GameMode set target to player.GetFirstRef 200 0 0 Label 10 if target if target.GetDisabled == 0 if target.GetDead == 0 if (target.GetFactionRelation player == 1 || target.GetAV Aggression == 3) target.kill endif if (target.GetAV Aggression == 2 && target.GetFactionRelation player == 0) target.kill endif endif endif set target to target.GetNextRef Goto 10 endif end Link to comment Share on other sites More sharing options...
Recommended Posts