Jump to content

Some Scripting Help


Myst42

Recommended Posts

Posted
17 hours ago, Myst42 said:

Minor Bugs:

-The eyes sometimes still may disappear, either on morp or de-morph stage. Switching back and forth 1 or 2 times seems to fix them though. Not sure if this is even fixable, since even the Succubus mod had some anomalies like that when I tested it. (Saw character switch to potato face model a few times when that option was enabled, switching back and forth also fixed it)

-Jumping variables (game settings) are still stubborn and refuse to be reversed or changed between saves. I have an idea for that, but not much faith in it though.

EDIT1: HELL YEAH!! Jumping variables storage works now. Added the original "failsafe" code lines for it, and now the changes seem to be working, and be preserved through loading. These, Btw

  Reveal hidden contents


Event OnPlayerLoadGame()
      If Game.GetPlayer().HasSpell(BuffSpells)
            MorphStage.SetValue (1)
            Game.SetGameSettingFloat("fJumpHeightMin", 250.0)
            Game.SetGameSettingFloat("fJumpFallHeightMin", 2000.0)
      Else
            MorphStage.SetValue (0)
            Game.SetGameSettingFloat("fJumpHeightMin", MorphJumpHeight.GetValue() )
            Game.SetGameSettingFloat("fJumpFallMin", MorphJumpFall.GetValue() )
      EndIf
EndEvent

 

 

Minor bug always can appear, and is hard to remove, because the head is made with components and when you change a component the function QueueNiNodeUpdate must re-compose it and not always work 100% perfect, i presume by rounds errors in the mathematics formula.

 

Yes, the GameSetting are not stored in savegame as say the wiki and must be manually regenerated in the function OnPlayerLoadGame.

And that work NOW because you put the lines in a script of the CORRECT type, ReferenceAlias.

 

For the head texture, can give some problems... 

Teorically, the functions GetFaceTextureSet() and SetFaceTextureSet(TextureSet textures) must be called from PlayerBase like the function SetSkin, but for use it correctly you must declare a Property of the correct type for store it as:

Spoiler

;Data definition for store original head parts and armors
HeadPart Property OriginalEyes Auto
HeadPart Property OriginalHair Auto
Int OriginalEyes_Pos
Int OriginalHair_Pos

 

TexTureSet  Property OriginalTextHead Auto ; NEW PROPERTY FOR STORE HEAD TEXTURE

 

Armor Property OriginalSkin Auto
Armor Property OriginalBoots Auto
Armor Property OriginalArmor Auto
Armor Property OriginalGloves Auto

Bool MorphRunning = False

Spoiler

        ;STORING ORIGINALS
        Int NumHeadParts = Player.GetLeveledActorBase().GetNumHeadParts()
        Int i = 0
        While i < NumHeadParts
            If Player.GetLeveledActorBase().GetNthHeadPart(i).GetType() == 2
                OriginalEyes = Player.GetLeveledActorBase().GetNthHeadPart(i)
                OriginalEyes_Pos = i
            EndIf
            If Player.GetLeveledActorBase().GetNthHeadPart(i).GetType() == 3
                OriginalHair = Player.GetLeveledActorBase().GetNthHeadPart(i)
                OriginalHair_Pos = i
            EndIf
            i += 1
        EndWhile
        
        OriginalTextHead = PlayerBase.GetFaceTextureSet(); NEW FUNCTION CALL FOR STORE IT
        
        OriginalSkin = PlayerBase.GetSkin()
        OriginalBoots = Player.GetWornForm(0x00000080) as Armor
        OriginalArmor = Player.GetWornForm(0x00000004) as Armor
        OriginalGloves = Player.GetWornForm(0x00000008) as Armor

This compile for me, but not tested in game. Try it.

 

But this functions come from SKSE and can have some problems, like the first functions used for

restore eyes and when changed to the original functions of the game work perfect

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;PlayerBase.SetNthHeadPart(OriginalEyes, OriginalEyes_Pos)
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;PlayerBase.SetNthHeadPart(OriginalHair, OriginalHair_Pos)
        Player.ChangeHeadPart(OriginalEyes)
        Player.ChangeHeadPart(OriginalHair)

Posted
6 hours ago, GenioMaestro said:

(...)

About the remaining disappearing minor bug... I checked the Dynamic Vampire Appearance mod's script to see if I could learn something from it. There are long paragraps of code dedicated to the conditions for the changes, relating to MCM stuff checks, seeing if player is a vampire, or in combat, what stage of vampirism, has recently fed etc...

But when I got to the part that apparently handles the asset change, it is in fact using a structure that makes a bit of sense

DVA doesn't get disappearing eyes afaik. Never seen it happen.

Spoiler

Function UpdatePlayerEyes()
	EyesLock = true  ; only one thread can modify the eyes at any one time

	Trace(Debug_Flow, "UpdatePlayerEyes: CurrentStage["+CurrentStage+"] Sex["+CurrentSex+"] NightVision["+NightVisionState+"] CombatState["+CombatState+"]")

	HeadPart newHP = none
	
	if( !IsEnabled ) ; set the eyes back to the original
		newHP = originalEyes
	elseif( CurrentStage > 0 && (ControlNightVision && NightVisionState == NightVisionActive) )
		Trace(Debug_Update, "Updating to night vision eyes!")
		if( CurrentSex == Sex_Female )
			newHP = NightVisionGlowFemale
		elseif( CurrentSex == Sex_Male )
			newHP = NightVisionGlowMale
		endif
		
	elseif( CurrentStage > 0 && (ControlCombatEyeGlow && CombatState == InCombat) )
		Trace(Debug_Update, "Updating to combat eyes!")
		if( CurrentSex == Sex_Female )
			newHP = CombatEyeGlowFemale
		elseif( CurrentSex == Sex_Male )
			newHP = CombatEyeGlowMale
		endif

	elseif( ControlEyes && CurrentStage == 0 ) ; set the eyes back to the original
		newHP = originalEyes
	
	elseif( ControlEyes && (CurrentStage >= 1 && CurrentStage <= 4) )
		Trace(Debug_Update, "Update to Vampirism Stage!")
		newHP = GetHeadPart(CurrentSex, CurrentStage)
	elseif( !ControlEyes )
		PlayerRef.RegenerateHead()
		PlayerRef.QueueNiNodeUpdate()
	else
		PlayerRef.RegenerateHead()
		PlayerRef.QueueNiNodeUpdate()
	endif
	
	if( newHP != none )
		; ActorBase base = PlayerRef.GetActorBase()
		; HeadPart oldHP = base.GetNthHeadPart(base.GetIndexOfHeadPartByType(HeadPartType_Eyes))
		
		; if( newHP != oldHP )
			PlayerRef.ChangeHeadPart(newHP)
		; else
			; Trace(Debug_Update, "Head part was same on call to UpdatePlayerEyes()")
		; endif
	else
		Trace(Debug_Warn, "UpdatePlayerEyes: newHP was none!")
	endif
		
	EyesLock = false
endFunction

Function UpdatePlayerComplexion()
	ComplexionLock = true  ; only one thread can modify the complexion at any one time
	
	Trace(Debug_Flow, "UpdatePlayerComplexion: CurrentStage["+CurrentStage+"] Sex["+CurrentSex+"] HasRecentFeed["+HasRecentFeed+"]")
	TextureSet newFace = none
	
	if( !IsEnabled )
		newFace = originalComplexion
	
	elseif( CurrentStage > 0 && (ControlBloodyMouthFX && HasRecentFeed) )
		Trace(Debug_Update, "Updating to bloody mouth!")
		newFace = GetTextureSetbyRace(CurrentSex, PlayerRef.GetRace(), 5) ; 5 is the index that the bloody mouth TS is imported
		
	elseif( ControlComplexion && CurrentStage == 0 )
		newFace = originalComplexion

	elseif( ControlComplexion && (CurrentStage >= 1 && CurrentStage <= 4) )
		Trace(Debug_Update, "UpdatePlayerComplexion: Update to Vampirism Stage!")
		newFace = GetTextureSetByRace(CurrentSex, PlayerRef.GetRace(), CurrentStage)
	elseif( !ControlComplexion ) ; we are effectively disabled
		newFace = originalComplexion
	else
		PlayerRef.RegenerateHead()
	endif
	
	if( newFace != none )
		ActorBase base = PlayerRef.GetActorBase()
		base.SetFaceTextureSet(newFace)
	else
		Trace(Debug_Warn, "UpdatePlayerComplexion: newFace was none!")
	endif
	
	ComplexionLock = false
endFunction

 

There is a lot of pre-defined variables in that thing though, I have to see if I can find them all to fully understand.

I noticed it's not using Player.ChangeHeadPart() as the current morph script is but instead stuff like newHP = NightVisionGlowFemale

 

---------

So, regarding the current texture change, altering to PlayerBase instead of Player worked to compile

I wish I knew exactly how to know when am I supposed to use Player, PlayerRef, PlayerBase or Game.GetPlayer(), as I guess it depends on the script it calls a certain function from, but I didn't notice anything on the wiki that suggested I was supposed to use PlayerBase

 

Before even fixing that, I already had the face texture feature integrated and doodled in a non-working way that now compiles. Here is the isolated code for it but it still does nothing in game, and i have no idea why.

Spoiler

TextureSet Property MorphFace Auto
TextureSet Property OriginalFace Auto

Function Morph()
    If MorphStage.GetValue() == 0
        OriginalFace = PlayerBase.GetFaceTextureSet()
        PlayerBase.SetFaceTextureSet(MorphFace)
        MorphStage.SetValue(1)
    Else
        PlayerBase.SetFaceTextureSet(OriginalFace)
        MorphStage.SetValue(0)
    EndIf
EndFunction

 

 

Posted
14 minutes ago, Myst42 said:

About the remaining disappearing minor bug... I checked the Dynamic Vampire Appearance mod's script to see if I could learn something from it. There are long paragraps of code dedicated to the conditions for the changes, relating to MCM stuff checks, seeing if player is a vampire, or in combat, what stage of vampirism, has recently fed etc...

But when I got to the part that apparently handles the asset change, it is in fact using a structure that makes a bit of sense

DVA doesn't get disappearing eyes afaik. Never seen it happen.

  Reveal hidden contents


Function UpdatePlayerEyes()
	EyesLock = true  ; only one thread can modify the eyes at any one time

	Trace(Debug_Flow, "UpdatePlayerEyes: CurrentStage["+CurrentStage+"] Sex["+CurrentSex+"] NightVision["+NightVisionState+"] CombatState["+CombatState+"]")

	HeadPart newHP = none
	
	if( !IsEnabled ) ; set the eyes back to the original
		newHP = originalEyes
	elseif( CurrentStage > 0 && (ControlNightVision && NightVisionState == NightVisionActive) )
		Trace(Debug_Update, "Updating to night vision eyes!")
		if( CurrentSex == Sex_Female )
			newHP = NightVisionGlowFemale
		elseif( CurrentSex == Sex_Male )
			newHP = NightVisionGlowMale
		endif
		
	elseif( CurrentStage > 0 && (ControlCombatEyeGlow && CombatState == InCombat) )
		Trace(Debug_Update, "Updating to combat eyes!")
		if( CurrentSex == Sex_Female )
			newHP = CombatEyeGlowFemale
		elseif( CurrentSex == Sex_Male )
			newHP = CombatEyeGlowMale
		endif

	elseif( ControlEyes && CurrentStage == 0 ) ; set the eyes back to the original
		newHP = originalEyes
	
	elseif( ControlEyes && (CurrentStage >= 1 && CurrentStage <= 4) )
		Trace(Debug_Update, "Update to Vampirism Stage!")
		newHP = GetHeadPart(CurrentSex, CurrentStage)
	elseif( !ControlEyes )
		PlayerRef.RegenerateHead()
		PlayerRef.QueueNiNodeUpdate()
	else
		PlayerRef.RegenerateHead()
		PlayerRef.QueueNiNodeUpdate()
	endif
	
	if( newHP != none )
		; ActorBase base = PlayerRef.GetActorBase()
		; HeadPart oldHP = base.GetNthHeadPart(base.GetIndexOfHeadPartByType(HeadPartType_Eyes))
		
		; if( newHP != oldHP )
			PlayerRef.ChangeHeadPart(newHP)
		; else
			; Trace(Debug_Update, "Head part was same on call to UpdatePlayerEyes()")
		; endif
	else
		Trace(Debug_Warn, "UpdatePlayerEyes: newHP was none!")
	endif
		
	EyesLock = false
endFunction

Function UpdatePlayerComplexion()
	ComplexionLock = true  ; only one thread can modify the complexion at any one time
	
	Trace(Debug_Flow, "UpdatePlayerComplexion: CurrentStage["+CurrentStage+"] Sex["+CurrentSex+"] HasRecentFeed["+HasRecentFeed+"]")
	TextureSet newFace = none
	
	if( !IsEnabled )
		newFace = originalComplexion
	
	elseif( CurrentStage > 0 && (ControlBloodyMouthFX && HasRecentFeed) )
		Trace(Debug_Update, "Updating to bloody mouth!")
		newFace = GetTextureSetbyRace(CurrentSex, PlayerRef.GetRace(), 5) ; 5 is the index that the bloody mouth TS is imported
		
	elseif( ControlComplexion && CurrentStage == 0 )
		newFace = originalComplexion

	elseif( ControlComplexion && (CurrentStage >= 1 && CurrentStage <= 4) )
		Trace(Debug_Update, "UpdatePlayerComplexion: Update to Vampirism Stage!")
		newFace = GetTextureSetByRace(CurrentSex, PlayerRef.GetRace(), CurrentStage)
	elseif( !ControlComplexion ) ; we are effectively disabled
		newFace = originalComplexion
	else
		PlayerRef.RegenerateHead()
	endif
	
	if( newFace != none )
		ActorBase base = PlayerRef.GetActorBase()
		base.SetFaceTextureSet(newFace)
	else
		Trace(Debug_Warn, "UpdatePlayerComplexion: newFace was none!")
	endif
	
	ComplexionLock = false
endFunction

 

There is a lot of pre-defined variables in that thing though, I have to see if I can find them all to fully understand.

I noticed it's not using Player.ChangeHeadPart() as the current morph script is but instead stuff like newHP = NightVisionGlowFemale

 

---------

So, regarding the current texture change, altering to PlayerBase instead of Player worked to compile

I wish I knew exactly how to know when am I supposed to use Player, PlayerRef, PlayerBase or Game.GetPlayer(), as I guess it depends on the script it calls a certain function from, but I didn't notice anything on the wiki that suggested I was supposed to use PlayerBase

 

Before even fixing that, I already had the face texture feature integrated and doodled in a non-working way that now compiles. Here is the isolated code for it but it still does nothing in game, and i have no idea why.

  Reveal hidden contents


TextureSet Property MorphFace Auto
TextureSet Property OriginalFace Auto

Function Morph()
    If MorphStage.GetValue() == 0
        OriginalFace = PlayerBase.GetFaceTextureSet()
        PlayerBase.SetFaceTextureSet(MorphFace)
        MorphStage.SetValue(1)
    Else
        PlayerBase.SetFaceTextureSet(OriginalFace)
        MorphStage.SetValue(0)
    EndIf
EndFunction

 

 

Dynamic Vampire Appearance appear a big mod, and i presume you can be a bit lost when try follow the code. I not have it, not like vampires, but is downloading and i take a look about how exactly make the change.

 

In the section that you show simply put newHP to the corresponding value depending of a lot of conditions.

But the newHP is not DEFINED in the script, only use it. And not have the function Player.ChangeHeadPart() because is called in other function, sure. But not worry, i take a loot and try help you for understand it.

 

--------------

One general rule is NEVER use Game.GetPlayer()

Is a very very very slow function that come from the first version of the game and today is a relique.

Use it only ONE TIME in each script and ALWAYS store it for re-use when need in this way:

Actor Player = Game.GetPlayer()

and use Player when need and never more call Game.GetPlayer() on the same script.

A clear example:

Spoiler

        OriginalBoots = Game.GetPlayer().GetWornForm(0x00000080) as Armor
        OriginalArmor = Game.GetPlayer().GetWornForm(0x00000004) as Armor
        OriginalGloves = Game.GetPlayer().GetWornForm(0x00000008) as Armor

Spoiler

Actor Player = Game.GetPlayer()

        OriginalBoots = Player.GetWornForm(0x00000080) as Armor
        OriginalArmor = Player.GetWornForm(0x00000004) as Armor
        OriginalGloves = Player.GetWornForm(0x00000008) as Armor

The two script make exactly the same, but the first need 3 times more time than the second.

 

In general, as i explain, all mods must have a quest and a reference alias to the player that is filled by the game in the tenth part of time need for make a Game.GetPlayer()

You can use the name of the Property linked in CK or can use your variable. The result is the same.

 

When use Player, PlayerRef, GetReference, GetReferenceAlias, GetLeveledActor, GetLeveledActorBase...

i can't say it. Must be indicated in the definition of the function, but sometimes is a bit complex.

I alert you about it in one parragraf of my long messages.

One way is change it if you get error when compile because the compiler know when must use one or the other.

 

In your script you forgot put Player.QueueNiNodeUpdate() because is strictly obligatory call this function after any change for forze the game to update it. And your script must look as:

Spoiler

Function Morph()
    If MorphStage.GetValue() == 0
        OriginalFace = PlayerBase.GetFaceTextureSet()
        PlayerBase.SetFaceTextureSet(MorphFace)
Player.QueueNiNodeUpdate()
        MorphStage.SetValue(1)
    Else
        PlayerBase.SetFaceTextureSet(OriginalFace)
Player.QueueNiNodeUpdate()
        MorphStage.SetValue(0)
    EndIf
EndFunction

 

Posted
34 minutes ago, GenioMaestro said:

In your script you forgot put Player.QueueNiNodeUpdate() because is strictly obligatory call this function after any change for forze the game to update it. And your script must look as:

  Hide contents


Function Morph()
    If MorphStage.GetValue() == 0
        OriginalFace = PlayerBase.GetFaceTextureSet()
        PlayerBase.SetFaceTextureSet(MorphFace)
Player.QueueNiNodeUpdate()
        MorphStage.SetValue(1)
    Else
        PlayerBase.SetFaceTextureSet(OriginalFace)
Player.QueueNiNodeUpdate()
        MorphStage.SetValue(0)
    EndIf
EndFunction

 

Oh, but it has those lines too. What I pasted was only the isolated extra code lines, they're still inside the bigger morph code

Spoiler

Function Morph()

    If MorphRunning == False
         MorphRunning = True
    Else
         Debug.Notification("Morph is in way... wait for see the effects...")
         Return
    Endif

    Actor Player = Game.GetPlayer()
    ActorBase PlayerBase = Player.GetLeveledActorBase()

    Utility.Wait(0.1)
    if !Player.IsInFaction (Army)
        Debug.Notification("..., then nothing. Maybe we have to wait?")
        Debug.Notification("You feel all funny during the visual effect,...")
        Player.Addspell (Phase1, false)
        HRANDOM = Utility.RandomFloat(2,8)
        Utility.WaitGameTime(HRANDOM)
        Player.Removespell (Phase1)

        Debug.Notification("You feel funny pleasant sensations in your body.")
        Player.Addspell (Phase2, false)
        HRANDOM = Utility.RandomFloat(2,8)
        Utility.WaitGameTime(HRANDOM)
        Player.Removespell (Phase2)

        Debug.Notification("You feel ligher and ligher.")
        Player.Addspell (Phase3, false)
        HRANDOM = Utility.RandomFloat(2,8)
        Utility.WaitGameTime(HRANDOM)
        Player.Removespell (Phase3)

        Debug.Notification("You feel inside your body metamorphosing.")
        Utility.Wait(2.0)
    Endif

;The actual morphing spell;
;------------------------
    Debug.Trace("MorphStage:" + MorphStage.GetValue() )
    If MorphStage.GetValue() == 0
        MiscUtil.PrintConsole("MorphStage == 0 Changing the Player")
        ;---------------------------------------------------------------------------
        ;STORING ORIGINALS
        Int NumHeadParts = Player.GetLeveledActorBase().GetNumHeadParts()
        Int i = 0
        While i < NumHeadParts
            If Player.GetLeveledActorBase().GetNthHeadPart(i).GetType() == 2
                OriginalEyes = Player.GetLeveledActorBase().GetNthHeadPart(i)
                OriginalEyes_Pos = i
            EndIf
            If Player.GetLeveledActorBase().GetNthHeadPart(i).GetType() == 3
                OriginalHair = Player.GetLeveledActorBase().GetNthHeadPart(i)
                OriginalHair_Pos = i
            EndIf
            i += 1
        EndWhile
        OriginalSkin = PlayerBase.GetSkin()
        OriginalFace = PlayerBase.GetFaceTextureSet()
        OriginalBoots = Player.GetWornForm(0x00000080) as Armor
        OriginalArmor = Player.GetWornForm(0x00000004) as Armor
        OriginalGloves = Player.GetWornForm(0x00000008) as Armor

        MiscUtil.PrintConsole("OriginalEyes:" + OriginalEyes)
        MiscUtil.PrintConsole("OriginalHair:" + OriginalHair)
        MiscUtil.PrintConsole("OriginaFace:" + OriginalFace)
        MiscUtil.PrintConsole("OriginalSkin:" + OriginalSkin)
        MiscUtil.PrintConsole("OriginalBoots:" + OriginalBoots)
        MiscUtil.PrintConsole("OriginalArmor:" + OriginalArmor)
        MiscUtil.PrintConsole("OriginalGloves:" + OriginalGloves)

        ;---------------------------------------------------------------------------

        Utility.Wait(1.0)
        If !Player.IsInFaction (Army)
            Utility.Wait(5.0)
            Player.AddToFaction(Army)
            Player.ModFactionRank(Army, 1)
        EndIf

         ;Add Bonuses;
         Player.addspell(QueenSpells)
         Player.addspell(BuffSpells)

         ;Jumpyness Set;
         MorphJumpHeight.SetValue( Game.GetGameSettingFloat("fJumpHeightMin") )
         MorphJumpFall.SetValue( Game.GetGameSettingFloat("fJumpFallHeightMin") )
         Game.SetGameSettingFloat("fJumpHeightMin", 250.0)
         Game.SetGameSettingFloat("fJumpFallHeightMin", 2000.0)

        ;---------------------------------------------------------------------------
        ;Changing the Player
        Player.ChangeHeadPart(MorphEyes)
        Player.ChangeHeadPart(MorphHair)
        PlayerBase.SetSkin(MorphSkin)
        PlayerBase.SetFaceTextureSet(MorphFace)
        Player.QueueNiNodeUpdate()

        Player.AddItem(MorphGloves, 1, True)
        Player.AddItem(MorphOutfit, 1, True)
        Player.AddItem(MorphBoots, 1, True)

        Player.EquipItem(MorphGloves, False, True)
        Player.EquipItem(MorphOutfit, False, True)
        Player.EquipItem(MorphBoots, False, True)

        ;Switch On;
        MorphStage.SetValue(1)

    Else

        MiscUtil.PrintConsole("Restoring the Player")
        MiscUtil.PrintConsole("OriginalEyes:" + OriginalEyes)
        MiscUtil.PrintConsole("OriginalHair:" + OriginalHair)
        MiscUtil.PrintConsole("OriginalSkin:" + OriginalSkin)
        MiscUtil.PrintConsole("OriginalBoots:" + OriginalBoots)
        MiscUtil.PrintConsole("OriginalArmor:" + OriginalArmor)
        MiscUtil.PrintConsole("OriginalGloves:" + OriginalGloves)
        Utility.Wait(1.0)

        ;Remove bonuses;
        Player.removespell(BuffSpells)

        ;Jumpyness Reset"
        Game.SetGameSettingFloat("fJumpHeightMin", MorphJumpHeight.GetValue() )
        Game.SetGameSettingFloat("fJumpFallMin", MorphJumpFall.GetValue() )

        ;Restore Cosmetics;
        ;---------------------------------------------------------------------------
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;PlayerBase.SetNthHeadPart(OriginalEyes, OriginalEyes_Pos)
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;PlayerBase.SetNthHeadPart(OriginalHair, OriginalHair_Pos)
        Player.ChangeHeadPart(OriginalEyes)
        Player.ChangeHeadPart(OriginalHair)
        PlayerBase.SetSkin(OriginalSkin)
        PlayerBase.SetFaceTextureSet(OriginalFace)
        Player.QueueNiNodeUpdate()

        Player.UnEquipItem(MorphGloves)
        Player.UnEquipItem(MorphOutfit)
        Player.UnEquipItem(MorphBoots)

        Player.RemoveItem(MorphGloves, 1, True)
        Player.RemoveItem(MorphOutfit, 1, True)
        Player.RemoveItem(MorphBoots, 1, True)

        If OriginalBoots != None
            Player.EquipItem(OriginalBoots, False, True)
        endif
        If OriginalArmor != None
            Player.EquipItem(OriginalArmor, False, True)
        endif
        If OriginalGloves != None
            Player.EquipItem(OriginalGloves, False, True)
        EndIf

        ;---------------------------------------------------------------------------
        ;Switch Off;
        MorphStage.SetValue(0)
    EndIf

    MorphRunning = False

EndFunction

 

I'm starting to get worried here, since the face skin should work already. I'll check again if I'm making some other dumb error I might have overlooked somewhere else, but it shouldn't be the case.

Posted

Well.... i need wrote two messages.

In this first message, i strip the code of Dynamic Vampire Appearance (DVA) and try explain why never have gliches.

In the second message, i explain you why your script is not working.

 

Talking about DVA, yesterday i not see the call to the funcion Player.ChangeHeadPart() inside the code that you paste in the spoiler, but have it... Is a problem related to my big screen resolution and this forum cut some lines inside the spoilers and not permit me see it. Is solved.

 

One of the things that you must make when read and strip the code of another mod is look HOW define the variables and properties because all the data is stored in it and a lot of times, for understand a line of code, you need know what exactly have the data. First look in the script and second, open the ESP in CK, locate the quest and the scripts and look how are LINKED the properties because a lot of times here is the key.

 

The work in DVA start in the Udate event and i copy it but remove all un-necesary lines for understand how  made the change of apareance.

Spoiler

Event OnUpdate()
...
    if( lastStage < 1 && CurrentStage >= 1 ) ; we became a vampire
        ActorBase base = PlayerRef.GetActorBase()
        ; store originals
        originalEyes = base.GetNthHeadPart(base.GetIndexOfHeadPartByType(HeadPartType_Eyes))
        originalComplexion = base.GetFaceTextureSet()
    endif
 ...
    if( dirtyFace || dirtyEyes  )
        Trace(Debug_Update, "OnUpdate: dirtyFace["+dirtyFace+"] dirtyEyes["+dirtyEyes+"]")
        ; update cached player sex
        CurrentSex = PlayerRef.GetActorBase().GetSex()
        ; update the visuals

        UpdatePlayerComplexion()
        PlayerRef.QueueNiNodeUpdate()
        ;PlayerRef.RegenerateHead()
        UpdatePlayerEyes()
    endif
...
endEvent

 

As you can see the store of the originals are made exactly equal and our made.

        ; store originals
        originalEyes = base.GetNthHeadPart(base.GetIndexOfHeadPartByType(HeadPartType_Eyes))
        originalComplexion = base.GetFaceTextureSet()

And the update the visuals  are made in the functions that you post yesterday.

        UpdatePlayerComplexion()
        PlayerRef.QueueNiNodeUpdate()
        UpdatePlayerEyes()

 

Go to see first UpdatePlayerEyes() but i must paste the complete code for understand it.

Have some tricks that must explain and can't strip any.

Spoiler

Function UpdatePlayerEyes()
    EyesLock = true  ; only one thread can modify the eyes at any one time

    Trace(Debug_Flow, "UpdatePlayerEyes: CurrentStage["+CurrentStage+"] Sex["+CurrentSex+"] NightVision["+NightVisionState+"] CombatState["+CombatState+"]")

    HeadPart newHP = none
    
    if( !IsEnabled ) ; set the eyes back to the original
        newHP = originalEyes
    elseif( CurrentStage > 0 && (ControlNightVision && NightVisionState == NightVisionActive) )
        Trace(Debug_Update, "Updating to night vision eyes!")
        if( CurrentSex == Sex_Female )
            newHP = NightVisionGlowFemale
        elseif( CurrentSex == Sex_Male )
            newHP = NightVisionGlowMale
        endif
        
    elseif( CurrentStage > 0 && (ControlCombatEyeGlow && CombatState == InCombat) )
        Trace(Debug_Update, "Updating to combat eyes!")
        if( CurrentSex == Sex_Female )
            newHP = CombatEyeGlowFemale
        elseif( CurrentSex == Sex_Male )
            newHP = CombatEyeGlowMale
        endif

    elseif( ControlEyes && CurrentStage == 0 ) ; set the eyes back to the original
        newHP = originalEyes
    
    elseif( ControlEyes && (CurrentStage >= 1 && CurrentStage <= 4) )
        Trace(Debug_Update, "Update to Vampirism Stage!")
        newHP = GetHeadPart(CurrentSex, CurrentStage)
    elseif( !ControlEyes )
        PlayerRef.RegenerateHead()
        PlayerRef.QueueNiNodeUpdate()
    else
        PlayerRef.RegenerateHead()
        PlayerRef.QueueNiNodeUpdate()
    endif
    
    if( newHP != none )
        ; ActorBase base = PlayerRef.GetActorBase()
        ; HeadPart oldHP = base.GetNthHeadPart(base.GetIndexOfHeadPartByType(HeadPartType_Eyes))
        
        ; if( newHP != oldHP )
            PlayerRef.ChangeHeadPart(newHP)
        ; else
            ; Trace(Debug_Update, "Head part was same on call to UpdatePlayerEyes()")
        ; endif
    else
        Trace(Debug_Warn, "UpdatePlayerEyes: newHP was none!")
    endif
        
    EyesLock = false
endFunction

This function have a call to GetHeadPart() that return a Headpart

Spoiler

HeadPart Function GetHeadPart(int gender, int stage)
    ; clamp the stage between 1 and 4 inclusive
    if( stage < 1 )
        stage = 1
    endif
    if( stage > 4 )
        stage = 4
    endif
    
    stage -= 1 ; convert to base 0 from base 1

    if( gender == Sex_Female ) ; as this is the most common
        return Eyes_Female.GetAt(stage) as HeadPart
    elseif( gender == Sex_Male )
        return Eyes_Male.GetAt(stage) as HeadPart
    endif
    
    return none
endFunction

But the return line are a bit complex and i need explaint it.

Eyes_Female are DEFINED as 

FormList Property Eyes_Female Auto

and when you look the LINK in CK you see that are asigned to DVA_Eyes_Female that have 5 HeadPart inside it. Look the screenshot.

DVA_eyes_female.thumb.png.0477c7c3b45d760f5e42e0320e86c949.png

Then, when the main function execute this line

        newHP = GetHeadPart(CurrentSex, CurrentStage)

the value of newHP is filled with the result of the function GetHeadPart(CurrentSex, CurrentStage)

and the return line of GetHeadPart() look inside the FormList and select ONE of the six eyes returning it as a normal HeadPart.

 

Other important trick that use is the manual way of manage Properties when are DEFINED and not use the normal way of automatic asigment by the game. Look the diference:

Spoiler

MagicEffect Property VampireSightEffect Auto
Quest Property MQ101 Auto


; this is derived from the eyes formlist as we can't set them directly
HeadPart Property CombatEyeGlowFemale Hidden
    HeadPart Function get()
        return Eyes_Female.GetAt(4) as HeadPart
    endFunction
endProperty

The two first properties are DEFINED as -Auto- at the end of the line and this mean that the game automaticaly make the get/set.

But the CombatEyeGlowFemale is DEFINED as -Hidden- at the end of the line and this mean, first not show it in CK, and second, must write code for make the get/set.

 

The return line are making the same that make the return line of GetHeadPart, the only diference is the fixed parameter in the one and the dinamic parameter in the other as you can see:

return Eyes_Female.GetAt(stage) as HeadPart

return Eyes_Female.GetAt(4) as HeadPart

 

When the game execute the line

        newHP = CombatEyeGlowFemale

appear that are making a simple variable assiment but really are calling the get function of the property that return the position 4 of the FormList Eyes_Female.

 

 

 

All of this is for explain you HOW make the eyes change DVA, but the final resumen is that use exactly the same way that we use, because finally use the same function that we use:

   PlayerRef.ChangeHeadPart(newHP)

 

 

 

 

In the function UpdatePlayerComplexion() are making near the same but use the function GetTextureSetByRace()

Spoiler

TextureSet Function GetTextureSetByRace(int gender, Race akActorRace, int stage)
    
    ; clamp the stage between 1 and 4 inclusive
    if( stage < 1 )
        stage = 1
    endif
    if( stage > 5 ) ; 5th element is used for bloody mouth
        stage = 5
    endif

    stage -= 1 ; convert to base 0 from base 1
    
    if( ElfRaces.Find(akActorRace) > -1 )
        if( gender == Sex_Female )
            return CX_Female_Elf[stage]
        elseif( gender == Sex_Male )
            return CX_Male_Elf[stage]
        endif
    elseif( OrcRaces.Find(akActorRace) > -1 )
        if( gender == Sex_Female )
            return CX_Female_Orc[stage]
        elseif( gender == Sex_Male )
            return CX_Male_Orc[stage]
        endif
    elseif( HumanRaces.Find(akActorRace) > -1 )
        if( gender == Sex_Female )
            return CX_Female_Human[stage]
        elseif( gender == Sex_Male )
            return CX_Male_Human[stage]
        endif
    else ; assume custom race (Humaniod)
        if( gender == Sex_Female )
            return CX_Female_Human[stage]
        elseif( gender == Sex_Male )
            return CX_Male_Human[stage]
        endif
    endif
    
    return none
endFunction

The return lines of this function make some similar to the eyes ussing CX_Female_Human that is DEFINED as 

TextureSet[] Property CX_Female_Human Auto

When you put two brackets like that are creating an array and when you see the LINK in CK have this:

DVA_head.png.7ffa04f85a18a59517d6afb68a550bc2.png

Why use and array and not use a FormList??? i not know... ask to the developer... The final result is the same.

 

Why have diferent skins for each race??? Probably for get a PERFECT result without glich.

 

The function UpdatePlayerComplexion have at the end the same that we have:

        ActorBase base = PlayerRef.GetActorBase()
        base.SetFaceTextureSet(newFace)

 

 

 

 

------------------------------------------------

 

 

Maybe our problem about glich is for the order in we made the changes.

Can try use the same order that have DVA that is:

        UpdatePlayerComplexion() ----------> change face TextureSet
        PlayerRef.QueueNiNodeUpdate()----> update visuals
        UpdatePlayerEyes() -------------------> change eyes

 

But we are changing more things and the exact order can be a bit diferent.

In our script, the first fase that make the morph can look as:

        ;changing the player
        PlayerBase.SetSkin(MorphSkin)
        PlayerBase.SetFaceTextureSet(MorphFace)
        Player.QueueNiNodeUpdate()

        Player.ChangeHeadPart(MorphEyes)
        Player.ChangeHeadPart(MorphHair)

 

In our script, the second fase that make the de-morph can look as:

        ;Restore Cosmetics;
        PlayerBase.SetSkin(OriginalSkin)
        PlayerBase.SetFaceTextureSet(OriginalFace)
        Player.QueueNiNodeUpdate()

        Player.ChangeHeadPart(OriginalEyes)
        Player.ChangeHeadPart(OriginalHair)

 

I not tested it in game and can give fatal un-desired errors. If have time for make test i edit the mesage.

 

EDIT: This order appear to work correctly in game.

Posted

Go to explain you WHY your script is not working. I say in my long message:

On 8/2/2018 at 6:50 PM, GenioMaestro said:

When you make a savegame all the data of all the quest is stored in the savegame and of course is restored when load it. This data include ALL the data refered by each quest, including the data from the script.

For that, when you upgrade a mod a lot of times you need a "clean save" because the game store ALL in the savegame. When a mod change some specific data in the update the saved data in the savegame take preference from the new data that come from the update, and a a "clean save" is the only solution.

 

Maybe i must be more specific about the POWER of the savegame.

 

When is say "the game store ALL in the savegame" this mean ALL, really ALL except some special values related to GameSettings like JumpHeigth, as you allready know.

 

This ALL include, for example the value of the variable MorphStage, because if you save your game when you are transformed, when load the game and launch the spell a de-morph is made. And include the rest of the variables and properties included in the scrip.

 

But this ALL include the value of the LINK made in CK.

This mean the value of the properties LINKED in the screen of CK.

 

For example, if the property MorphFace is linked to SkinHeadFemaleKhajit this link is STORED in the SaveGame.

If you open CK and change the LINK of MorphFace to SkinHeadFemaleOrc when you open your game and load the SaveGame the value of the property MorphFace is assigned to SkinHeadFemaleKhajit because that say the SAVEGAME and the game IGNORE the new value of SkinHeadFemaleOrc assigned in CK.

 

This is the POWER of the savegame.

 

The only solution is make a clean save. Go to your mod manager and unselect your esp. Load your game and the message about faulting esp show. Continue the load process and when you have control of your player make a new save. Clean the new save with ReSaver.

On your mod manager activate your esp. Load the new cleaned save and launch the spell. Now work with the NEW values asigned in CK.

 

The only way for not make this error is follow some rules while developing:

1 - Always make test in NEW GAME

2 - Never save your game while developing

3 - If you want test in active real gameplay make some firm saves before.

4 - Always delete the intermediate saves that are made while testing.

Posted
7 hours ago, GenioMaestro said:

 

I can see there is a lot of details in the first post, but on a first view (as I've been looking at the DVA scripts as well) I think that youre basically saying that:

-They're using the same functions to get and set/change eyes and head texture

-A lot of extra lines of code are about enabling the script to "get a head part" - another approach to the problem of not being able to pick the head parts from the property list menu (For which we used Tes5Edit). In this case the GetHeadPart Function is defined as return Eyes_Female.GetAt(stage) as HeadPart which would be an equivalent to PlayerBase.GetNthHeadPart(2).GetType() right?

-More extra code was made because the properties didn't point to a single item but several, as in eye list and face texture list, then the (CurrentSex, CurrentStage) in the GetHeadPart function is about choosing one from the list

 

So I guess It's instructive but technically useless for what I want since the ultimate "core" lines, so to speak, that actually get-set/change the cosmetic assets are the same.

And you imply that the more complex way DVA script is structured, has nothing to do with the fact it glitches less.

 

--------------------

 

Alright. Regarding the failed face texture  change, I should specify that I AM using a new game to test the mod

In fact my routine test process is

-New game

-I installed a Quick Start mod, so that the game begins immediately at Helgen's dungeon exit

-New character, load RaceMenu preset, play.

-Add item (the potion that starts the change)

-Wait 24 hours

-Change happens

 

I get it, Quest stores properties, but it's not very good at keeping track of changes in scripts that have changed since the game first read them

And you're saying that the script, as it is, should already be finished right?

I'll post it again in case it needs checking

Spoiler

Scriptname MorphScript extends ReferenceAlias

 

SPELL Property QueenSpells Auto
SPELL Property CombatSpells Auto
SPELL Property BuffSpells Auto
SPELL Property Phase1  Auto
SPELL Property Phase2 Auto
SPELL Property Phase3  Auto
float HRANDOM
Faction Property Army  Auto
GlobalVariable Property MorphStage auto
GlobalVariable Property MorphJumpHeight Auto
GlobalVariable Property MorphJumpFall Auto
HeadPart Property MorphHair Auto
HeadPart Property MorphEyes Auto
TextureSet Property MorphFace Auto
Armor Property MorphSkin Auto
Armor Property MorphGloves Auto
Armor Property MorphOutfit Auto
Armor Property MorphBoots Auto

;---------------------------------------------------------------------------
;From https://www.creationkit.com/index.php?title=GetType_-_HeadPart
;Number       Type
;0      Mouth
;1      Head
;2      Eyes
;3      Hair
;4      Beard
;5      Scar
;6      Brows

;Data definition for store original head parts and armors
HeadPart Property OriginalEyes Auto
HeadPart Property OriginalHair Auto
Int OriginalEyes_Pos
Int OriginalHair_Pos
TextureSet Property OriginalFace Auto
Armor Property OriginalSkin Auto
Armor Property OriginalBoots Auto
Armor Property OriginalArmor Auto
Armor Property OriginalGloves Auto


Bool MorphRunning = False

;---------------------------------------------------------------------------

Function Morph()

     Actor Player = Game.GetPlayer()
     ActorBase PlayerBase = Player.GetLeveledActorBase()

    If MorphRunning == False
         MorphRunning = True
    Else
         Debug.Notification("You're morphing...")
         Return
    Endif

    If !Player.IsInFaction (Army)
        Debug.Notification("A breeze makes you momentarily dizzy...")
        Debug.Notification("A strange power flows through you...")
        Player.Addspell (Phase1, false)
        HRANDOM = Utility.RandomFloat(2,8)
        Utility.WaitGameTime(HRANDOM)
        Player.Removespell (Phase1)

        Debug.Notification("You feel like something is changing inside you")
        Player.Addspell (Phase2, false)
        HRANDOM = Utility.RandomFloat(2,8)
        Utility.WaitGameTime(HRANDOM)
        Player.Removespell (Phase2)

        Debug.Notification("You feel a power growing inside you.")
        Player.Addspell (Phase3, false)
        HRANDOM = Utility.RandomFloat(2,8)
        Utility.WaitGameTime(HRANDOM)
        Player.Removespell (Phase3)

        Debug.Notification("You feel your body metamorphosing.")
        Utility.Wait(2.0)
    Endif

;The actual morphing spell;
;------------------------
    Debug.Trace("MorphStage:" + MorphStage.GetValue() )
        
   If MorphStage.GetValue() == 0
        MiscUtil.PrintConsole("MorphStage == 0 Changing the Player")
        ;---------------------------------------------------------------------------
        ;STORING ORIGINALS
        Int NumHeadParts = Player.GetLeveledActorBase().GetNumHeadParts()
        Int i = 0
        While i < NumHeadParts
            If Player.GetLeveledActorBase().GetNthHeadPart(i).GetType() == 2
                OriginalEyes = Player.GetLeveledActorBase().GetNthHeadPart(i)
                OriginalEyes_Pos = i
            EndIf
            If Player.GetLeveledActorBase().GetNthHeadPart(i).GetType() == 3
                OriginalHair = Player.GetLeveledActorBase().GetNthHeadPart(i)
                OriginalHair_Pos = i
            EndIf
            i += 1
        EndWhile
        OriginalSkin = PlayerBase.GetSkin()
        OriginalFace = PlayerBase.GetFaceTextureSet()
        OriginalBoots = Player.GetWornForm(0x00000080) as Armor
        OriginalArmor = Player.GetWornForm(0x00000004) as Armor
        OriginalGloves = Player.GetWornForm(0x00000008) as Armor


        MiscUtil.PrintConsole("OriginalEyes:" + OriginalEyes)
        MiscUtil.PrintConsole("OriginalHair:" + OriginalHair)
        MiscUtil.PrintConsole("OriginaFace:" + OriginalFace)
        MiscUtil.PrintConsole("OriginalSkin:" + OriginalSkin)
        MiscUtil.PrintConsole("OriginalBoots:" + OriginalBoots)
        MiscUtil.PrintConsole("OriginalArmor:" + OriginalArmor)
        MiscUtil.PrintConsole("OriginalGloves:" + OriginalGloves)

        ;---------------------------------------------------------------------------

        Utility.Wait(1.0)
        If !Player.IsInFaction (Army)
            Utility.Wait(5.0)
            Player.AddToFaction(Army)
            Player.ModFactionRank(Army, 1)
        EndIf

         ;Add Bonuses;
         Player.addspell(QueenSpells)
         Player.addspell(BuffSpells)
         Player.addspell(CombatSpells)

         ;Jumpyness Set;
         MorphJumpHeight.SetValue( Game.GetGameSettingFloat("fJumpHeightMin") )
         MorphJumpFall.SetValue( Game.GetGameSettingFloat("fJumpFallHeightMin") )
         Game.SetGameSettingFloat("fJumpHeightMin", 250.0)
         Game.SetGameSettingFloat("fJumpFallHeightMin", 2000.0)

        ;---------------------------------------------------------------------------
        ;Changing the Player
    
        PlayerBase.SetSkin(MorphSkin)
        PlayerBase.SetFaceTextureSet(MorphFace)
        Player.ChangeHeadPart(MorphEyes)
        Player.ChangeHeadPart(MorphHair)
        Player.QueueNiNodeUpdate()    
            
        Player.AddItem(MorphGloves, 1, True)
        Player.AddItem(MorphOutfit, 1, True)
        Player.AddItem(MorphBoots, 1, True)
        Player.EquipItem(MorphGloves, False, True)
        Player.EquipItem(MorphOutfit, False, True)
        Player.EquipItem(MorphBoots, False, True)

        ;Switch On;
        MorphStage.SetValue(1)

    Else

        MiscUtil.PrintConsole("Restoring the Player")
        MiscUtil.PrintConsole("OriginalEyes:" + OriginalEyes)
        MiscUtil.PrintConsole("OriginalHair:" + OriginalHair)
        MiscUtil.PrintConsole("OriginalSkin:" + OriginalSkin)
        MiscUtil.PrintConsole("OriginalBoots:" + OriginalBoots)
        MiscUtil.PrintConsole("OriginalArmor:" + OriginalArmor)
        MiscUtil.PrintConsole("OriginalGloves:" + OriginalGloves)
        Utility.Wait(1.0)

        ;Remove bonuses;
        Player.removespell(BuffSpells)
        Player.removespell(CombatSpells)

        ;Jumpyness Reset"
        Game.SetGameSettingFloat("fJumpHeightMin", MorphJumpHeight.GetValue() )
        Game.SetGameSettingFloat("fJumpFallMin", MorphJumpFall.GetValue() )

        ;Restore Cosmetics;
        ;---------------------------------------------------------------------------
        PlayerBase.SetSkin(OriginalSkin)
        PlayerBase.SetFaceTextureSet(OriginalFace)
        Player.ChangeHeadPart(OriginalEyes)
        Player.ChangeHeadPart(OriginalHair)
        Player.QueueNiNodeUpdate()

        Player.UnEquipItem(MorphGloves)
        Player.UnEquipItem(MorphOutfit)
        Player.UnEquipItem(MorphBoots)

        Player.RemoveItem(MorphGloves, 1, True)
        Player.RemoveItem(MorphOutfit, 1, True)
        Player.RemoveItem(MorphBoots, 1, True)


        If OriginalBoots != None
            Player.EquipItem(OriginalBoots, False, True)
        endif
        If OriginalArmor != None
            Player.EquipItem(OriginalArmor, False, True)
        endif
        If OriginalGloves != None
            Player.EquipItem(OriginalGloves, False, True)
        EndIf

        ;---------------------------------------------------------------------------
        ;Switch Off;
        MorphStage.SetValue(0)
    EndIf

    MorphRunning = False

EndFunction

;;;_____________________________;;;
;;;_____________________________;;;       
;Load Maintenance Failsafe;

Event OnPlayerLoadGame()
     Actor Player = Game.GetPlayer()
     ActorBase PlayerBase = Player.GetLeveledActorBase()
     If Game.GetPlayer().HasSpell(BuffSpells)
            MorphStage.SetValue (1)
            Game.SetGameSettingFloat("fJumpHeightMin", 250.0)
            Game.SetGameSettingFloat("fJumpFallHeightMin", 2000.0)
            PlayerBase.SetSkin(MorphSkin)
     Else
            MorphStage.SetValue (0)
            Game.SetGameSettingFloat("fJumpHeightMin", MorphJumpHeight.GetValue() )
            Game.SetGameSettingFloat("fJumpFallMin", MorphJumpFall.GetValue() )
            PlayerBase.SetSkin(OriginalSkin)
     EndIf
EndEvent

 

So, after some testing I have no idea where the problems come from

 

I tried changing the morph texture to something vanilla like khajiit

And the face texture change morph code is in fact working

It just refuses to change to my custom choice for some reason. I dunno what is wrong. It's nothing but an altered diffuse and some copied normals/s speculars from a completely safe texture mod replacer

 

EDIT: alrigh... so after messing with the textures, I think it is setting the custom texture correctly. But for some unknnown reason, it doesnt apply iy properly. It only applies the normal map and not the diffuse.

Game over, I guess... I'm out of ideas for this one

 

Posted
46 minutes ago, Myst42 said:

In fact my routine test process is

-New game

-I installed a Quick Start mod, so that the game begins immediately at Helgen's dungeon exit

-New character, load RaceMenu preset, play.

-Add item (the potion that starts the change)

-Wait 24 hours

-Change happens

As you say.... ALWAIS start a new game for make test.... and NEVER load a  savegame for make test...

47 minutes ago, Myst42 said:

I tried changing the morph texture to something vanilla like khajiit

And the face texture change morph code is in fact working

It just refuses to change to my custom choice for some reason. I dunno what is wrong. It's nothing but an altered diffuse and some copied normals/s speculars from a completely safe texture mod replacer

And you test with vanilla khajiit face textureset and WORK....

 

Then must be a problem with your textureset.

I'm very bad in image manipulation but at least can verify mipmaps, image format and make some test.

Post the images of your textureset for verify it and make some test.

Posted
On 8/6/2018 at 7:27 PM, GenioMaestro said:

Then must be a problem with your textureset.

I'm very bad in image manipulation but at least can verify mipmaps, image format and make some test.

Post the images of your textureset for verify it and make some test.

I don't think it's related to the textures.

On further analysis, I'm pretty sure it's because it's ONLY changing the normal map. Even when I tried with beast races face textures, I only got human toned skin plus some ugly markings instead of the green or grey toned skin of beast races.

 

 

EDIT: Found an alternate way to make it work. Traded the SetFaceTextureSet lines for a ChangeHeadPart based structure for the head... obviously now, it changes the entire head, but at least it works.

Posted

---------------

 

Hey, again. I thought to use this thread since it's still the same project

I've been looking at other scripts and I think I understand a lot more now.

 

But I keep popping these seamingly small questions I'm not sure where to find answers for.

So I'll leave it here just in case

 

1.- Trying to set up a system that causes the morph to be triggered by low health. Through newly aquired noob script skills I managed to make a simple script that calls upon another spell to be casted (needed it to make a spell that consumed and required stamina)

So I figued I'd used the "Spell that casts a spell" to create a permanent ability that upon health dropping, could call the morph spell

Well, I was wrong and nothing happened. But I think I've seen it and it is possible. So, any idea how to properly set up such a condition? Probably more CK messing than scripting though, but still.

Solved this one. Turns out the check condition had to be placed on an ability spell instead of the magic effect

 

2.- I replicated something else from the Succubus mod. Thre is a perk that removes all falling damage (multiply fall damage by 0). Thought to set is as a thing added by a spell. It works just fine EXCEPT... the fall damage immunity doesnt go away when removing the perk. I dont know if I'm doing something wrong, or I'm missing something. The perk itself, has the fall damage immunity thing on the condition that the global morph variable is set to 1. Every other thing seems to work, except that. Any ideas where should I look for?

 

EDIT

3.- Actually now I became interested i  changing the transformation sound effect, since it plays the same one as in vampire changing spells, except I didn't assign it such a thing. Can't find antything either on the spell, the magic effect or the script that sets the sound. (Magic effect already has the desired one but it still doesnt play it and plays the vampire one instead). Weird.

 

 

Posted
4 hours ago, Myst42 said:

2.- I replicated something else from the Succubus mod. Thre is a perk that removes all falling damage (multiply fall damage by 0). Thought to set is as a thing added by a spell. It works just fine EXCEPT... the fall damage immunity doesnt go away when removing the perk. I dont know if I'm doing something wrong, or I'm missing something. The perk itself, has the fall damage immunity thing on the condition that the global morph variable is set to 1. Every other thing seems to work, except that. Any ideas where should I look for?

 

Always set the Flag Recover on magic effects with changes in perks.

If you have a savegame without this flag, later changes in magic effects have no effect  (this may also be important for your second question)

Posted

Not understand how you solve the point 1, im not expert in CK, have hundreds of screens and conditions and some times im lost... Maybe you must teach me some things... 

I prefer relly on programing and is easy solved with an onupdate event...

 

About the point 2, first test the option proposed by Andy14 but not worry if not work. PSQ make it with code.

PSQ have the same that you say, a perk with a condition related to Global: 'HasWing' but have it inside the perk entries zone, you can try put the condition outside the perk zone and test. Some like:

Spoiler

perk.thumb.png.cf1db24f323528e9d043e2266c2ab820.png

Other solution can be made two perk's, one for disable the fall damage and another for re-enable it, but i not find the default value, is not indicated in the CK page about perks.

 

If PSQ make it with code must be for any motive.

The solution for make it with code is too easy. Simply put Player.AddPerk(<perk property>) in the first part of the script when make the morph and put Player.RemovePerk(<perk property>) in the second part of the script when make the de-morph.

 

And i must say the same about the sounds. PSQ make it with code.

------ DECLARATION OF THE PROPERTIES ------

Sound Property SoundHenshinMoan Auto

EffectShader Property SuccubusTransFXS Auto
EffectShader Property FireFXShader Auto
EffectShader Property ShockPlayerCloakFXShader Auto

 

------ CODE IN THE FIRST FASE WHEN MAKE THE MORPH ------

    SoundHenshinMoan.Play(Player)
    SuccubusTransFXS.Play(Player, 0.5)
    Utility.Wait(0.5)
    FireFXShader.Play(Player, 0.5)
    ShockPlayerCloakFXShader.Play(Player, 0.5)

Posted
On 8/9/2018 at 1:41 AM, Andy14 said:

 

Always set the Flag Recover on magic effects with changes in perks.

If you have a savegame without this flag, later changes in magic effects have no effect  (this may also be important for your second question)

Nope, it wasn't that. Spell (as an ability) had recover checked... even went to the trouble of finding out what it means, and apparently, that flag can be the difference between a health buff and a healing potion

 

On 8/9/2018 at 5:10 AM, GenioMaestro said:

Not understand how you solve the point 1, im not expert in CK, have hundreds of screens and conditions and some times im lost... Maybe you must teach me some things... 

I prefer relly on programing and is easy solved with an onupdate event...

 

Sure. To make a spell that auto-triggers on low health all one needs is to set the condition on the spell.

However, for what I needed there was a catch, since the morph spell works both ways, and I only wanted to trigger it on low health plus human form. This meant checking on the global morph value, but if I did that on the morph spell itself, first, it would NEED the low health as a condition to trigger, and second, it would work only one way cause the global variable would be changed. (so no de-morphing ever)

So I needed something else. A "monitor" spell, which is in this case, an ability.

First you have to have the monitor spell, like this. Having it as an ability means the conditions will trigger the effect, instead of the effect asking for conditions.

EmergencyCasting1.jpg

Second, one needs the effect to have a simple script that enables it to call upon another spell.

EmergencyCasting2.jpg

And that's it. When Health reacches less than 30% and pllyer is un-morphed, monitor spell gets the call to do it's thing and call upon the morph spell.

(Btw, it was MIRACLE, that I could find the correct syntax to call the the spell ? I still have no idea how (Actor ak Target, Actor akCaster) thingies work

 

-------------------------------------------------------------

 

On the perk...

No luck : ( Tried placing the condition everywhere I could think of. On the Perk window, on the perk's effect conditions, on the spell that called it, on the magic effect too... nothing. It just refuses to go back to normal

Yeah, I also tried, the scripted way, adding and removing the perk via morph script (and getting rid of the spell in the process, leaving only the perk and it's conditions) and it still didn't work.

I think the problem is not the perk or the spell not getting removed, it's the effect being permanent, like, on the game itself.

Maybe I messed something else I still fail to see... I should do a test with a new mod and only the perk system... last call anyway.

 

On the sound effect

Yep. That works perfectly, thanks again.

I had to add it somewere later on the sctipt though, or else the sound played too early

And here's the weird part.

The vampire change sound STILL plays with it. I dunno what causes it. Maybe it's related to model changes (And I mean the strong, kinda deaf sound from 0.13-0-17 in this vid)

Spoiler

 

But whatever. At least they're syncronized now, and I kinda like it that way.

It's kind of fuel for insanity to not know where does it even come from. So I'll just forget about it.

Posted

WOW... is a Spell of Type Ability with Constant Effect... and the game automatically verify it each second...WOW

If much more efficient than the onupdate event in script and sure put less charge in the game... THANKS...

 

9 hours ago, Myst42 said:

On the perk...

No luck : ( Tried placing the condition everywhere I could think of. On the Perk window, on the perk's effect conditions, on the spell that called it, on the magic effect too... nothing. It just refuses to go back to normal

Yeah, I also tried, the scripted way, adding and removing the perk via morph script (and getting rid of the spell in the process, leaving only the perk and it's conditions) and it still didn't work.

The perk managed by script must work... maybe have somethings colliding.... because the script is too easy:

 

------ DECLARATION OF THE PROPERTIES ------

Perk Property JumpFallPerk Auto

 

On the script put addperk when make the morph and removeperk when make the de-morph:

Spoiler

        ;---------------------------------------------------------------------------
        ;changing the player
        PlayerBase.SetSkin(MorphSkin)
        PlayerBase.SetFaceTextureSet(MorphFace)
        Player.QueueNiNodeUpdate()
        Player.ChangeHeadPart(MorphEyes)
        Player.ChangeHeadPart(MorphHair)
        
        Player.AddPerk(JumpFallPerk)
        
        Player.AddItem(MorphGloves, 1, True)
        Player.AddItem(MorphOutfit, 1, True)
        Player.AddItem(MorphBoots, 1, True)

        Player.EquipItem(MorphGloves, True, True)
        Player.EquipItem(MorphOutfit, True, True)
        Player.EquipItem(MorphBoots, True, True)

        ;Switch On;
        MorphStage.SetValue(1)
    Else
        MiscUtil.PrintConsole("restoring the player")
        MiscUtil.PrintConsole("OriginalEyes:" + OriginalEyes)
        MiscUtil.PrintConsole("OriginalHair:" + OriginalHair)
        MiscUtil.PrintConsole("OriginalSkin:" + OriginalSkin)
        MiscUtil.PrintConsole("OriginalFace:" + OriginalFace)
        MiscUtil.PrintConsole("OriginalBoots:" + OriginalBoots)
        MiscUtil.PrintConsole("OriginalArmor:" + OriginalArmor)
        MiscUtil.PrintConsole("OriginalGloves:" + OriginalGloves)
        Utility.Wait(1.0)

        ;Remove bonuses;
        Player.removespell(Buff)
        
        Player.RemovePerk(JumpFallPerk)
        
        ;Jumpyness Reset"
        Game.SetGameSettingFloat("fJumpHeightMin", MorphJumpHeight.GetValue() )
        Game.SetGameSettingFloat("fJumpFallMin", MorphJumpFall.GetValue() )

If this not work correctly must be for conditions on CK. Remove all the conditions in the Perk and NOT use the Perk in any Spell or MagicEfect, CK MUST SAY USES 0, because is used ONLY by the script.

Make test in a NEW GAME, of course. Maybe you have the perk stored in savegame.

 

9 hours ago, Myst42 said:

On the sound effect

Yep. That works perfectly, thanks again.

I had to add it somewere later on the sctipt though, or else the sound played too early

And here's the weird part.

The vampire change sound STILL plays with it. I dunno what causes it. Maybe it's related to model changes (And I mean the strong, kinda deaf sound from 0.13-0-17 in this vid)

That sound must come from CK. You must remove the sound in any Spell, MagicEfect, ShaderEffect or any thing that you have duplicate. For locate it, first verify the ID of the sound, i think is MAGVampireTransform01SD ID 000FF9E8, but if you have duplicate it can have other name and other ID. Second, open ONLY YOUR esp with tes5edit, in the selecction screen of tes5edit press left click and select none, search your esp and select ONLY YOUR esp, some like:

Spoiler

tes5edit1.thumb.png.249b68e97c5a65d5c041798d49423fcd.png

When test5edit load you have ONLY the requied esp loaded by dependencies and you can see what have you esp and you can see YOUR sound secction if you duplicate the sound or simply put the original ID in FormID and press enter for search it. Tes5edit must say you WHERE are refered the sound in easy way, like:

Spoiler

tes5edit2.thumb.png.a5b8f0fdc0bb9cbc7f5bece90500d4a9.png

I use tes5edit a lot, especially when i want see the details of the esp of another mod, because tes5edit show ONLY the things defined inside the esp grouped with the plus simbols. Is a very easy way for see what have the esp.

 

When open the esp with CK the defined items in the esp are merged with all the others items that come from the masters esp's and sometimes is very dificult find the item that i want. But when i have the reference, the name and the type from tes5edit is very easy for me.

Posted
On 8/10/2018 at 5:37 AM, GenioMaestro said:

 

So... Managed to find the bugger

Turns out it was an incompatibility issue between the feature that modded jump fall damage, and the perk that multiplied damage by 0

I should've gotten rid of the global modification system for it long ago, but I thought it was harmless. It wasnt.

Also, another plot twist. Removing the perk can be fatal for the feature

Jump immunity would work on the first transformation, deactivate on first demorph, and then stop working forever

Considering that there are no differences between the first and further morph events, the perk was being re-added correctly, it just stopped working.

So, global condition works this time. Now, the perk is permanent though, but it's effect depends on the morphing stage global.

 

Sound:

Nope. Nothing. MAGVampireTransform01SD is the sound upon transforming to a vampire by vampirism, not a vampire lord by the spell. The other sounds, like gory explosions and such, are not it either. Searched high and low for it on my magic effect list, also nothing.

Like I said... I'd like to find out why it plays, but I can let go of this one.

 

Last projects on this are

-------------------------

-Adding an area effect spell that slows enemies down notoriously. It was supposed to work with WeaponSpeed, LeftWeaponSpeed and Speed modifications, but it simply refuses to work. No matter what i do, it just does nothing. Closest I got was by adding the AV modifications via script, but then when the effect ended, it wouldn't work ever again. Tried adding it as a debuff ability too, also nothing.

 

-Adding defensive buff that both returns damage to enemies, and/or staggers them when hitting the player. I think I've seen such effects on perk mods, so I should probably just replicate the process

 

-Lastly, the one I need the most help with, is a compatibility patch of sorts. Tested the mod on a character that was a vampire, and the morph worked, but didn't change the head and eyes properly. It changed it for a second, but then it immediately returns to the other head.

I have yet to test if this is because it's an issue with vampirism itself or... because I was using Better Vampires. BV has an MCM option to reset everything, so I used it, saw my character literally loose her head, used showracemenu to regenerate her, and then the morph change worked as intended, as long as character wasn't a vampire.

 

-----------------------

 

Also I have another doubt... I understood that things like defining the variable "Player"  are always faster and better than "Game.GetPlayer()"

But, what about asking for stuff?

Like, what is better here?

Spoiler

 

Function WeaponSpeedMaintenance()
    If (Game.GetModByName("Attack Speed Fix.esp")) != 255
        Player.removespell(WeaponSpeedFix)
    ElseIf (Game.GetModByName("Better Vampires.esp")) != 255
        If Player.HasKeyword(Vampire) == 1
            Player.removespell(WeaponSpeedFix)

        Else

            Player.addspell(WeaponSpeedFix)

        EndIf
    ElseIf (Game.GetModByName("SPERG.esm")) != 255
        Player.removespell(WeaponSpeedFix)
    ElseIf (Game.GetModByName("Ordinator - Perks of Skyrim.esm")) != 255
        Player.removespell(WeaponSpeedFix)
    Else
        Player.addspell(WeaponSpeedFix) ; In this case, game adds the spell no matter what, provided the other conditions are not true
    EndIf

EndFunction

 

Or

 

Function WeaponSpeedMaintenance()
    If (Game.GetModByName("Attack Speed Fix.esp")) != 255
        Player.removespell(WeaponSpeedFix)
    ElseIf (Game.GetModByName("Better Vampires.esp")) != 255
        If Player.HasKeyword(Vampire) == 1
            Player.removespell(WeaponSpeedFix)

        Else

            Player.addspell(WeaponSpeedFix)
        EndIf
    ElseIf (Game.GetModByName("SPERG.esm")) != 255
        Player.removespell(WeaponSpeedFix)
    ElseIf (Game.GetModByName("Ordinator - Perks of Skyrim.esm")) != 255
        Player.removespell(WeaponSpeedFix)
    Else

        If Player.HasSpell(WeaponSpeedFix) == 0 ; In this case, I'm thinking the mod doesnt need to actually do the thing, just ask if it should
            Player.addspell(WeaponSpeedFix) ; So which one's better and faster?
    EndIf

EndFunction

 

 

PS: NVM this example... I'm relizing there could be some changes in it. Questions till stands, is it faster to ask or not to ask?

 

Posted
14 hours ago, Myst42 said:

...

Perk:
So, running the Perk with code works, but I do not understand if you want to have it always, as PSQ does, or if you want to have it ONLY the first time the morph is done.

 

Sound:
The only way I can help more is to look and strip your esp.

Add it to your next message, or send it by PM if you prefer.

 

Slow effect:
Put the code and I'll take a look, but I need the esp to see how you try to do it in CK.

It may be the same problem as in the Perk, a CK condition collision

 

Compatibility:
Leave it for the last step.
First, create all the new functionalities you want and make them work.
Second, make all that work in normal human races like nord, imperial, breton... can have some problems with elf(altmer, dunmer, bosmer...)
Later we will see if we can make it work with others default game races like orc, kajit, argonian... and with special races like vampire and werewolf. Of course, let custom races for the end.
But I warn you that it can be complex. Last week I saw a screenshot of a person playing at the same time as Vampire + Succubus + Virgin + many other things. Think about what can happen when add your mod.

 

Code optimization:
The same ... Leave it for the last step. 90% of the times only a few scripts need optimization.
Doing a verification more or less is indifferent, it can be a millisecond, sometimes less.
But eliminating 5 verifications and doing just one can be a remarkable difference.
The problem is that many times it is necessary perform many checks to make the mod work well.
Do not worry about that now. People prefer things that work well, even if they are slow. Nobody wants something fast that only works sometimes.

Posted
On 8/13/2018 at 7:39 AM, GenioMaestro said:

 

On the original Perk issue, the idea was to have it function as a toggleable feature, like most of the stuff that's added during the transformation, and removed on reverting to human.

Wanted fall damage immunity during morph state, vulnerability as a human. I dunno if I messed up, but the adding/removing perk dynamic just wasn't working, invulnerability worked only on the first morph and then not ever again. So instead I found a way to add the perk only once, and have it check the global condition to function or not. So it now works as intended, but the perk itself never really goes away, it's just off in human form because the global gets turned off.

 

Sound: found it. Apparently, it wasn't even a proper sound FX from a spell, it was a sound from a visual effect. Turns out I copied the absorb magic spell from the Breton race and turned it into an ability. Removed all sounds, but not the visuals. Whenever the effect became active, sound played. It's gone now. The name of the sound is MAGPowerRacialDragonskinFire2D btw.

 

On the slow, effect, there is no code, I tried in many ways to make it work, but nothing happened. I wanted a cool area slowdown effect that could be casted upon a group of enemies to make them slow, but nothing worked.

I tried "detrimental" slow time effect on "aimed" delivery, got nothing (Slow time apparently only works on self)

Tried detrimental speed, weapon speed and left weapon speed actor value modifiers and nothing happened.

Tried scripting the same actor value modifications to force them upon enemy targets, and it was a close as I got, since I saw some actual effects.

But there were other problems with that. First, the modification would not go away when the spell wore off. Figured I had to script it's end. After making some changes, it ended properly now, but the spell only worked once per enemy, and once they regained their normal value, the effect was forever unuseable.

I think, this was the script, though I'm not entirely sure... I tried some variations of it too, but none of them worked as intended.

Spoiler

Scriptname SlowSpellSccript extends activemagiceffect

Event OnEffectStart(Actor Target, Actor Caster)
	Target.Modav("WeaponSpeedMult", 0.1)
	Target.Modav("LeftWeaponSpeedMult", 0.1)
	Target.Modav("WeaponSpeedMult", 10.0)
	Utility.Wait(15) ; these lines were added later, when the effect refused to go away
	Target.Modav("WeaponSpeedMult", 1.0)
	Target.Modav("LeftWeaponSpeedMult", 1.0)
	Target.Modav("WeaponSpeedMult", 100.0)	
EndEvent

Event OnEffectFinish(Actor Target, Actor Caster) ; same as this part
	Target.Modav("WeaponSpeedMult", 1.0)
	Target.Modav("LeftWeaponSpeedMult", 1.0)
	Target.Modav("WeaponSpeedMult", 100.0)
EndEvent

 

 But I ended up dropping the idea. It's not really worth it since I already made a slow time toggleable spell. Target effect was just a gimmick idea.

 

So I guess I'm finished with what I wanted. Which leaves only minor compatibility issues.

The biggest one, I think, is vampirism. But since I found that Better Vampires has way to reset and fix everything in game, it's not critical. It's just an annoying nuissance

I'll be honest here. I wasn't expecting this to become a big public mod. It was more about me learning some scripting and making something personal for my own character.

BUT I think what has been done here could be used as a template for future transformation projects, which I would be interested in making for public use... Always cooking up new ideas...

So even if my own project doesnt really need to be compatible with beast or elven races, other transformation mods or custom races, I AM interested in learning how to do it, so maybe I could make a public one.

I'll leave this template here, since it's a morph mod that works. (Minus all the cool stuff). It's intended to be modifiable according to creator's preferences. Not perfect, and I'm pretty sure it has the exact same compatibility issues with beast races, gender and vampirism. (Untested for custom races) Morph Mod Template.rar

I'll send you the real mod's script on PM

 

As a sideways, project, I was trying to set up a gear mod, meant to play with Predators Lost Tribes, I wanted to give the helmet the ability to switch between toggleable view modes, plust a toggleable cloaking.

Cloaking, is working. Just need to take a look at the conditions to make it less overpowered, and perhaps de-cloak on combat and detected. This IS an idea meant for public use, provided it ever works.

However, I'm having issues with the Detect Life effects. Since ideally, the ability that gives special view adds detect life shaders. problem is they wont go away when the effect dissapears. I made some digging on Predator Vision mod, and it turns out it apparently also uses scripting to dispel the shaders from those affected upon terminating the effect. I think it casts a keyword-based dispel spell on the affected targets, but i'm not entirely sure.

I still fail to replicate the dispel code lines of the script. I was hoping perhaps you could take a look, since I'm pretty sure if this works, iMod shaders are all that's left to get it working.

I'll leave the whole project here Gear Functions.rar

 

Posted
3 hours ago, Myst42 said:

 

 

If the perk works as you want, perfect, leave it like that.

On 8/10/2018 at 11:37 AM, GenioMaestro said:

That sound must come from CK. You must remove the sound in any Spell, MagicEfect, ShaderEffect or any thing that you have duplicate.

 

Sound:

I had to be in CK. It is one of the problems that the CK has. You can put sounds in many places.

 

Slow effect:

Here you must have some problem.

I do not understand how you have so many problems with spells and effects. Putting that in the script is absurd.

It must be something that fails you or that you lack, and just in case, I explain it to you with screen photos.

A spell can cast multiple effects and each effect has its properties and its parameters.

When you open the screen of the effect you want to apply to the spell you have this:

Spoiler

spell.thumb.png.e7fc48499a9409d1f19a8c679d3dddf8.png

 

That duration determines how long the effect will be active.

When the spell is cast, the game calls the OnEffectStart of the script associated with the spell.

When the time expires the game calls the OnEffectFinish of the script associated with the spell.

You do not need to put a WAIT inside the start of the effect.

The game already gives you the duration you have told him.

Putting a Utility.Wait (15) inside the effectstart is the same as putting a duration of 15 seconds.

If you do not put duration the effect only lasts one millisecond.

Maybe that's why nothing you've tried has worked for you, because the effect had no duration, the effect disappeared instantaneously.

 

Final proyect:

The only way to see if it works is to do a test, test and more test.

 

New proyect.

I'll look into the predators and I'll tell you something here or by private message.

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

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