Jump to content

Script help request


thomasd1979

Recommended Posts

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.jpg

http://i163.photobucket.com/albums/t304/dariusdarksaber/ScreenShot40.jpg

Link to comment
Share on other sites

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

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

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
endif

While 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

End

Cipscis

Link to comment
Share on other sites

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

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

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

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

End

Cipscis

Link to comment
Share on other sites

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...