Jump to content

[LE] Quick Questions, Quick Answers


Recommended Posts

Okay then, I suppose I'll start over (with the plugins)

Ah I see what you mean. You have a bunch of plugins each containing separate changes that you were wanting all in one plugin; to merge them all together. You can do this easily with TES5Edit, which is a free tool, but that would require you to learn how to use it. However, eventually if you want to produce mods you'll want to learn it because it's very useful both for mod consumers and mod producers. Basically, it's a tool that presents plugin information in a way that is different to the editor. Instead of showing you the final state of the game after all changes are made (the way the editor does), it separates out each change or addition a plugin makes as a list of entries, or "records"; kind of like the difference between an encyclopedia (editor) and a series of news articles (TES5Edit). In this way, you can load all your plugins and basically copy the records in each of them into one file.

 

I see, thank you for clarifying that, you and IsharaMeradin

 

Though now I have another question. Is there a place where I can upload my follower so someone could test it and see if it works?

 

Can you not test it? If it's a simple vanilla follower then it shouldn't be too complicated, and so if it works for you it probably works for everyone. Still, if you want someone to test it I can do so. Upload it to a file hosting site (like mediafire or dropbox or something like that) and pm me the link. I'll give you feedback there.

Edited by dalsio
Link to comment
Share on other sites

 

Does anyone know of a way to iterate through all child locations within a parent location, e.g. identify all houses/shops in a town at runtime?

The only way I can think of would be to create a quest and set up a fairly large collection of location aliases. Quests have the ability to pick locations that match their conditions and if you have a collection of optional aliases set up as many of them as possible will fill when the quest starts. Make the first alias somehow fill with the parent location then set the others to find children of that one. But keep in mind that locations aren't cells, so you still may not get the effect you want. Using keywords you can find all of the houses, all of the shops, all of the inns, etc. so you might be better off being more specific with certain groups of aliases each looking for certain types of things.

 

Once the quest starts you check which of the aliases are filled. And when you need to search again you just stop and restart the quest.

 

Interesting idea and might work for what I am trying to do. I will give it a shot.

 

Thank you, @cdcooley

Link to comment
Share on other sites

Trying to get a list of all Actors in a cell and repurposing code that I used to find furniture. The only Form Type that reflect Actor is kActorValueInfo (95). I cannot find what that really means. Does that point to Actors or some aspect of Actors? Has anyone used this or is there a better method to get all Actors in the cell?

Link to comment
Share on other sites

I want to replicate dragon absorbing with a non dragon actor and I have no idea what I'm doing. I followed the code which is quite advanced for me and ended up with

            MQkillDragonS.deathSequence(self)

that I assume triggers everything. Is there a simpler way?

Help please!

 

Full Code:

 

 

scriptname dragonActorSCRIPT extends actor
{Base Actor Script for all Dragons}
; _____________
;|			    |
;|    SETUP    |
;|_____________|
ImageSpaceModifier property dragonFOVfx auto
{FX played for various impacts in dragon combat}
float property deathFXrange = 1024.0 auto
{max range to play death FX on player}
quest property MQkillDragon auto
{used to invoke deathSequence() function in MQKillDragonScript.psc}
actor property player auto hidden
{For quick reference and clean-looking script}
float property FOVfalloff auto hidden
{choosing not to expose this and clutter the prop list in CS, since it won't be touched often}
sound property NPCDragonFlyby auto
{Sound played when dragon passes by a target}
explosion property knockBackExplosion auto
{explosion used to knock back enemies}
; NOTE - the dragon breed/skin settings are deprecated and have no effect.
armor property SnowDragonSkin auto
{deprecated - do not use}
armor property TundraDragonSkin auto
{deprecated - do not use}
armor property forestDragonSkin auto
{deprecated - do not use}
int property dragonBreed = 0 auto
{deprecated - do not use}

WIFunctionsScript Property WI Auto		;added by jduvall
{Pointer to WIFunctionsScript on WI quest. Used to create script event to get nearby NPCs to react to the death of the dragon}

ImpactDataSet Property FXDragonTakeoffImpactSet Auto
{Impact data set to use for the dragon takeoff}
ImpactDataSet Property FXDragonLandingImpactSet Auto
{Impact data set to use for the dragon landing}
ImpactDataSet Property FXDragonTailstompImpactSet Auto
{Impact data set to use for the tailstomp}


;*****ADDED FOR DLC2--------------
bool MiraakIntroductionHappened
bool MiraakAppeared
Location Property DLC2ApocryphaLocation Auto
WorldSpace Property DLC2ApocryphaWorld auto
;*****----------------------------

; _____________
;|			   |
;|    EVENTS   |
;|_____________|
	EVENT onInit()
		; just initialize any variables, etc.
		player = game.getPlayer()				; store player reference
		FOVfalloff = 1600				; range at which impact doesn't play FOV
		
		if deathFXrange == 0
			deathFXrange = 1000
		endif
		
		if !isDead() && isGhost()
			; redundancy check to prevent invincible, "ghosted" dragons from respawning.
			setGhost(FALSE)
		endif
		
		gotoState("alive")
	endEVENT
	
	EVENT onReset()
		; if we're resetting a previously-killed dragon, make sure it's not a ghost.
		setGhost(FALSE)
	endEVENT
	
	EVENT onLoad()
		; change markings based on breed of this dragon
		; first, support random selection
		; if dragonBreed == 4
			; dragonBreed = utility.randomInt(0,3)
		; endif
		; then assign the markings, either way.
		; if dragonBreed == 1
			; equipItem(snowDragonSkin)
		; elseif dragonBreed == 2
			; equipItem(tundraDragonSkin)
		; elseif dragonBreed == 3
			; equipItem(forestDragonSkin)
		; endif
		
		if !isDead()
			if isGhost()
				; redundancy check to prevent invincible, "ghosted" dragons from respawning.
				setGhost(FALSE)
			endif
		gotoState("alive")
		endif
		
		registerForAnimationEvent(self, "DragonLandEffect")
		registerForAnimationEvent(self, "DragonForcefulLandEffect")
		registerForAnimationEvent(self, "DragonTakeoffEffect")
		registerForAnimationEvent(self, "DragonBiteEffect")
		registerForAnimationEvent(self, "DragonTailAttackEffect")
		registerForAnimationEvent(self, "DragonLeftWingAttackEffect")
		registerForAnimationEvent(self, "DragonRightWingAttackEffect")
		registerForAnimationEvent(self, "DragonPassByEffect")
		registerForAnimationEvent(self, "flightCrashLandStart")			; Considered temp for showing injury FX test
		registerForAnimationEVENT(self, "DragonKnockbackEvent")
	endEVENT


Event OnLocationChange(Location akOldLoc, Location akNewLoc)
	;USED TO GET DIALOGUE CONDITIONED ON DRAGON HAVING ATTACKED A TOWN	-- only happens if he lands on the ground in a location - ie death, or to land to fight (not on a perch)
	;see also DragonPerchScript

; 	debug.trace(self + "OnLocationChange() calling WI.RegisterDragonAttack(" +akNewLoc + ")")
	WI.RegisterDragonAttack(akNewLoc, self)
	
	if !isDead() && isGhost()
			; redundancy check to prevent invincible, "ghosted" dragons from respawning.
			setGhost(FALSE)
	endif

EndEvent
	
STATE alive
	Event OnCombatStateChanged(Actor akTarget, int aeCombatState)		
	
		if !isDead() && isGhost()
			; redundancy check to prevent invincible, "ghosted" dragons from respawning.
			setGhost(FALSE)
		endif
	
		if akTarget == Game.GetPlayer()
			WI.updateWIDragonTimer()		;used to prevent dragons from appearing too frequently
		endif
	endEvent
	
	EVENT onAnimationEvent(objectReference deliverator, string eventName)
; 		debug.trace("AnimEvent: " + eventName + " delivered by Dragon ("+self+") ")
		if (eventName == "DragonLandEffect")
; 			;debug.trace("Dragon AnimPayLoad: DragonLandEffect")
			game.shakeCamera(self, 1)
			game.shakeController(95, 95, 2)
			KnockAreaEffect(1, getLength())
			animateFOV()								; call the FOV function
			PlayImpactEffect(FXDragonTakeoffImpactSet, "NPC Pelvis", 0, 0, -1, 512)
		elseIf (eventName == "DragonForcefulLandEffect")
; 			;debug.trace("Dragon AnimPayLoad: DragonForcefulLandEffect")
			PlayImpactEffect(FXDragonLandingImpactSet, "NPC Pelvis", 0, 0, -1, 512)
			KnockAreaEffect(1, 2*getLength())
			;notification ("Dragon Forceful Land Effect")
		elseIf (eventName == "DragonTakeoffEffect")
; 			debug.trace("Dragon AnimPayLoad: DragonTakeoffEffect")
			PlayImpactEffect(FXDragonTakeoffImpactSet, "NPC Tail8", 0, 0, -1, 2048)
		elseIf (eventName == "DragonBiteEffect")
			;Removed spit effect on 6/1/10. Leaving logic in case we need to sub in other fx or sounds.
; 			;debug.trace("Dragon ("+self+") AnimPayLoad: DragonBiteEffect")
			;DragonBiteFX.Play(Self, 2)
			;notification ("Dragon Bite Effect")
		elseIf (eventName == "DragonTailAttackEffect")
; 			;debug.trace(" Dragon AnimPayoload: DragonTailAttackEffect")
			PlayImpactEffect(FXDragonTailstompImpactSet, "NPC Tail8", 0, 0, -1, 512)
			;notification("Dragon Tail Attack Effect")
		elseIf (eventName == "DragonLeftWingAttackEffect")
; 			;debug.trace("Dragon AnimPayLoad: DragonLeftWingAttackEffect")
			PlayImpactEffect(FXDragonTailstompImpactSet, "NPC LHand", 0, 0, -1, 512)
			;notification ("Dragon Left Wing Attack Effect")
		elseIf (eventName == "DragonRightWingAttackEffect")
; 			;debug.trace("Dragon AnimPayLoad: DragonRightWingAttackEffect")
			PlayImpactEffect(FXDragonTailstompImpactSet, "NPC RHand", 0, 0, -1, 512)
			;notification ("Dragon Right Wing Attack Effect")
		elseIf (eventName == "DragonPassByEffect")
			NPCDragonFlyby.Play(self)
			game.shakeCamera(self, 0.85)
			game.shakeController(0.65, 0.65, 0.5)
		;elseIf (eventName == "flightCrashLandStart")
			;Removed by mark since leaking magic is a bust. May replace with leaking blood at some point as a second test.
			; apply injury FX art when I crash land.
			;FXinjuryLeaks.play(self, -1)
		elseIf (eventName == "DragonKnockbackEvent")
			; dragon needs to stagger everyone in radius a bit larger than my length
; 			;debug.trace(self + " is knocking back actors within " + 1.5*getLength() + " of self @ " + self.x + ", " + self.y)
			;self.placeAtMe(knockBackExplosion)
			KnockAreaEffect(1, 1.5*getLength())
			animateFOV(1.5*getLength())
		endif
	endEVENT

	EVENT onDeath(actor killer)
; 		debug.trace("Remove mouth/injury FX art, begin death FX sequence for " + self)
		gotoState("deadAndWaiting")
		
		WI.startWIDragonKillQuest(self)		;used to create a scene if any NPCs are nearby when the dragon dies. See WIFunctionsScript attached to WI quest which creates a story manager script event, and WIDragonKilled quest which handles the scene.
		
		; removing update registration in favor of a while() in the STATE below
		;registerForUpdate(1)
	endEVENT
endSTATE

STATE deadAndWaiting

	;-------------------CHANGED FOR DLC2---------------------------
	EVENT onBeginState()

		MQKillDragonScript MQKillDragonS = MQkillDragon as MQKillDragonScript

		;If in Apocrypha, this is the boss fight so do not wait for distance
		if DLC2ApocryphaLocation && DLC2ApocryphaWorld && (game.getPlayer().isInLocation(DLC2ApocryphaLocation) || game.getPlayer().getWorldSpace() == DLC2ApocryphaWorld)
			gotoState("deadDisintegrated")
			MQkillDragonS.deathSequence(self)
		elseif MQKillDragonS.ShouldMiraakAppear(self) && MiraakAppeared == false
			gotoState("deadDisintegrated")
; 			Debug.Trace(self + "MiraakAppears")
			MiraakAppeared = true
			MQkillDragonS.deathSequence(self, MiraakAppears = true)
		else
			;NORMAL BASE GAME BEHAVIOR
			while getDistance(player) > deathFXrange
				utility.wait(1.0)
			endWhile
; 			debug.trace("player close enough to absorb" + self)
			gotoState("deadDisintegrated")
			MQkillDragonS.deathSequence(self)

		endif

	endEVENT
	;--------------------------------------------------------------------------------------------

	; EVENT onUpdate()
		; if getDistance(player) < deathFXrange
; 			; debug.trace("player close enough to absorb" + self)
			; gotoState("deadDisintegrated")
			; unRegisterforUpdate()
			; (MQkillDragon as MQKillDragonScript).deathSequence(self)
		; endif
	;endEVENT
endSTATE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	;; DRAGON STALKING FIX v1.2 by sevencardz

	;; Returns true if this dragon is Durnehviir.
	bool Function IsDurnehviir()
		return GetActorBase() == Game.GetFormFromFile(0x0030D8, "Dawnguard.esm")
	EndFunction

	;; Deletes the dragon to prevent the dragon's corpse from stalking the player.
	Function NoStalking()
		if IsDurnehviir() ; Durnehviir is not deleted because he never dies.
			;;Debug.Trace("DSF IGNORE: " + self + " " + GetBaseObject().GetName() + " is " + GetState())
		else
			DispelAllSpells() ; Remove any lingering magic effect scripts from the dragon.
			Delete() ; Delete the dragon.
			;;Debug.Trace("DSF DELETE: " + self + " " + GetBaseObject().GetName() + " is " + GetState())
		endIf
	EndFunction

	STATE deadDisintegrated

		;; Cleans up any dragon corpses which are already stalking the player in the current save game.
		Event OnLoad()
			NoStalking()
		EndEvent

		;; Cleans up any dragon corpses in the current area after the player leaves the area.
		Event OnUnload()
			NoStalking()
		EndEvent
		
	endSTATE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; _____________
;|			   |
;|  FUNCTIONS  |
;|_____________|
function AnimateFOV(float fFOVfalloff = 1600.0)
	; Function that animates FOV with an ismod.  Declaring here in case needed frequently
	float playerDist = player.getDistance(self)	; get and store the player's current distance from me	
	if playerDist < fFOVfalloff
		float FOVpower = (1- (1/(fFOVfalloff/(playerDist))))		; consider offset to compensate for collision size
		if FOVpower > 1.0
			FOVpower = 1.0		; clamp to prevent wacky values
		endif
; 		;debug.trace("player is " + playerDist + " from landing dragon")
; 		;debug.trace("dragon FOV fx power is" + FOVpower)
		dragonFOVfx.apply(FOVpower) ;animated FOV effect.  Strength based on distance from player
	endif
endFunction


 

 

Link to comment
Share on other sites

I am not sure I follow. Having looked at it as well, I agree, that is what executes the absorption. What is complicated about that call?

 

(MQkillDragon as MQKillDragonScript).deathSequence(self)
Now, looking at the code, I think it may be more hard coded for the Dragon model than you would desire. Which part of the effect are you wanting? Do you just want the waves coming into the player with sound effects or are you also wanting the full disintegration effect of the "dragon" body?
If you just want to have the special effect around the player (same as when the Greybeards at High Hrothgar teach a power word),

;display dragon absorb effect art. One part on dragon one part on player.
DragonAbsorbEffect.Play(dragonRef, 8, GetPlayer())
;; dragonRef.placeAtME(MAGDragonPowerAbsorbExplosion)
DragonAbsorbManEffect.Play(GetPlayer(), 8, dragonRef)

; Sounds for when the wispy particles being to fly at the player.
NPCDragonDeathSequenceWind.play(dragonRef)
NPCDragonDeathSequenceExplosion.play(dragonRef)

wait(0.1)

; On man power absorb effect shader.
DragonPowerAbsorbFXS.Play(GetPlayer())

wait(1)
; turn off remaining effect bits and magic leak fxshaders


wait(1)
; ghost the dragon so you can't hit him
dragonRef.SetGhost(true)

;clear any arrows that may have been stuck in dragon
dragonRef.clearExtraArrows()


;;

wait(4)

;Stop fx shader on player showing power absorb.
DragonPowerAbsorbFXS.Stop(GetPlayer())


VisualEffect Property DragonAbsorbEffect Auto
VisualEffect Property DragonAbsorbManEffect Auto
VisualEffect Property FXDragonDeathLHandBits Auto
VisualEffect Property FXDragonDeathLHandFire Auto
VisualEffect Property FXDragonDeathRHandBits Auto
VisualEffect Property FXDragonDeathRHandFire Auto
;VisualEffect Property DragonDeadswapHide Auto
;VisualEffect Property DragonDeadswap Auto

EffectShader Property DragonHolesFXS Auto
EffectShader Property DragonHolesBitsFXS Auto
EffectShader Property DragonHolesBitsLiteFXS Auto
EffectShader Property DragonPowerAbsorbFXS Auto
EffectShader Property DragonHolesSmokeFXS Auto
EffectShader Property DragonHolesMagicFXS Auto
EffectShader Property DragonHolesLightFXS Auto

ImageSpaceModifier Property DragonPowerAbsorbISM Auto

I recommend that you study that particular function and how it is working. You can also dig around for the Greybeard code.
The Dragon code is MQKillDragonScript.psc and Greybeard is in MQGreybeardAbsorbScript.psc
Link to comment
Share on other sites

  • Recently Browsing   0 members

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