Jump to content

Durai

Recommended Posts

Essentially I'm attaching a script to a spell that will grant the caster up to several beneficial effects based on the number of diseases they have at the start of the effect. My issue is I don't know if this can be done with a formlist or if it has to be several If/elseif statements. Every example of formlist I find is about adding a spell from the list to the player or adding a new form to an existing list. Is what I'm trying to accomplish even possible?

Link to comment
Share on other sites

Yes this is possible you could use something like this

Scriptname xxMyScript extends ActiveMagicEffect

Formlist Property DiseaseList Auto

Event OnEffectStart(Actor akTarget, Actor akCaster)
	int i = DiseaseList.GetSize()
	while i ; loop through the formlist
		i -= 1 ;loop counter variable
		Spell iSpell = DiseaseList.GetAt(i) as Spell ; get the nth form from the list as spell 
		if iSpell && akTarget.hasSpell(iSpell) ; test if iSpell is a valid spell and if the target has it
			;do stuff - count spells, apply spells etc.
		endif
	endwhile
EndEvent

Reading the creationKit Wiki would also help you with examples: https://www.creationkit.com/index.php?title=GetSize_-_FormList

Link to comment
Share on other sites

As testiger2 pointed out, this is possible.

Although, i think a more reliable approach would be to not use "FormList" since it's quite slow, and since there aren't so many Diseases (if i remember correctly, only four) you can put them all in a "If" statment.
Link to comment
Share on other sites

@maxarturo

I wouldn't call formlist less reliable but yes formlists are definetly slower

the tradeoff is speed vs memory as arrays and normal properties are stored into memory individually while with formlists only the pointer to the list is stored.

But with only 4 or 5 entries either way the performance difference between the two methods should be almost irrelevant.

Formlists have the benefit of beeing able to expand the list later without editing the script again(good for patches with other mods)

With SKSE there is also Form[] toArray() if speed is important

Link to comment
Share on other sites

@ testiger2.

Yes, you are definitely correct, i just suggested the use of a single "If" statement because it is used in a spell and having all the "Spell Diseases" in the script's property is much faster and speed is the essence here, taking always in account that "Formilsts" can cause delay in the execution of the script if at the same time some other scripts may be running from/at the Player/Npc or in the background (while the PC is quite busy).


* By reliable i meant the speed of it, with a spell you need to do its thing when it's supposed to, and time lag can have a bad effect on your gameplay, that's all i meant.

* As for Form toArray, i can't express my opinion since i haven't tested it.

Edited by maxarturo
Link to comment
Share on other sites

I'd use the FormList, for the extensibility. If speed becomes a concern, but SKSE requirement is not, ToArray it and run the searches on that. Remember to safety-proof for the player having more diseases than expected.

 

I don't think there's a way in the condition system to avoid code, since you're interested in the absolute count here.

Edited by foamyesque
Link to comment
Share on other sites

Thank you all for your speedy responses! Two quick questions:

 

1. Would creating a RefAlias for the player and attaching a seperate script that counts the diseases (Formlist and GlobalVariable), let the spell execute faster? There is a bit of a delay by having all of the code in just the one script, so maybe splitting the difference might help? If not then I'll leave the script as is.

 

2. I've been studying one of the scripts from Apocalypse spell mod (Pale Shadow I think) and have a spell that has a script to summon a shade (like from Kilkreath) when the player reanimates a corpse. It works fairly well, however I'm having a little trouble getting it so that if the player reanimates a new corpse before the effect finishes, the previous shade gets removed (unless their command actor limit is two or more). In short, when the reanimated corpse dies (again) they shade needs to go bye-bye.

 

 

Float Property AC_Update Auto
Bool Property AC_Retaliate Auto
Faction Property PartyFaction Auto
Formlist Property AC_ShadeList Auto

Actor TheTarget
Actor TheCaster
Actor TheShade

Event OnEffectStart(Actor akTarget, Actor akCaster)

 

int RandomNPC = Utility.RandomInt(0, (AC_ShadeList.GetSize() - 1))

TheShade = akCaster.PlaceActorAtMe(AC_ShadeList.GetAt(RandomNPC) as ActorBase, 1) ; place one

TheShade.Disable()
TheShade.AddToFaction(PartyFaction)

TheShade.SetRelationshipRank(Game.GetPlayer(), 3)
TheShade.SetPlayerTeammate(true, false)

TheShade.AllowPCDialogue(false)
TheShade.Enable()

 

If akTarget.IsHostileToActor(akCaster)
TheShade.StartCombat(akTarget)
If AC_Retaliate
akTarget.StartCombat(TheShade)
EndIf
EndIf

TheTarget = akTarget
TheCaster = akCaster
RegisterForUpdate(AC_Update)

EndEvent

Event OnEffectFinish(Actor akTarget, Actor akCaster)

Utility.Wait(1.0)
TheShade.Disable()
TheShade.delete()

EndEvent

Event OnDying(Actor akKiller)

Utility.Wait(1.0)
TheShade.Disable()
TheShade.delete()

EndEvent


Event OnUpdate()

Utility.Wait(1.0)
If !TheShade || TheShade.IsDead()
Dispel()
EndIf

EndEvent

 

I'm not sure what even or function I need (if even possible). Thanks in advance!

Link to comment
Share on other sites

Durai wrote: "I'm having a little trouble getting it so that if the player reanimates a new corpse before the effect finishes, the previous shade gets removed"

not understand.. You have to describe exactly how is the current effect working and how it should looks like?

 

You could use a GlobalVariable or an effect Keyword to determine is the TheShade still alive or not

 

 

  Faction  Property PartyFaction auto
  Formlist Property AC_ShadeList auto

  Float Property AC_Update    auto
  Bool  Property AC_Retaliate auto

  Actor TheShade


; -- EVENTs -- 3

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
;==================
    TheShade = myF_PlaceShade()

IF ( TheShade )
ELSE
    self.Dispel()
    RETURN    ; - STOP -
ENDIF
;---------------------
    TheShade.DisableNoWait()

    TheShade.AddToFaction(PartyFaction)
    TheShade.SetRelationshipRank(Game.GetPlayer(), 3, None)        ; player should be akCaster !
    TheShade.SetPlayerTeammate(TRUE, False)
    TheShade.AllowPCDialogue(False)
    TheShade.Enable(TRUE)
    Utility.Wait(0.1)

    IF akTarget.IsHostileToActor(akCaster)                ; if target is hostile to player
        TheShade.StartCombat(akTarget)                    ; let shade fighting the target
        IF ( AC_Retaliate )
            akTarget.StartCombat(TheShade)                ; if special bool is TRUE, make target aggressive
        ENDIF
    ENDIF
ENDEVENT


EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
;===================
IF ( TheShade )
    myF_CleanUp()
ENDIF
ENDEVENT


EVENT OnDying(Actor akKiller)
;============
IF ( TheShade )
    self.Dispel()
    myF_CleanUp()
ENDIF
EndEvent


; -- FUNCTIONs -- 2

;-------------------------
Actor FUNCTION myF_Place()
;-------------------------
    int i = Utility.RandomInt(0, AC_ShadeList.GetSize() - 1)

; https://www.creationkit.com/index.php?title=PlaceActorAtMe_-_ObjectReference
    actor aRef = akCaster.PlaceActorAtMe(AC_ShadeList.GetAt(i) as ActorBase, 1)     ; place a shade of medium level

    RETURN aRef
ENDFUNCTION


;---------------------
FUNCTION myF_CleanUp()
;---------------------
    actor aRef = TheShade    ; save to function variable
    TheShade = None          ; remove script variable

IF ( aRef )
    Utility.Wait(1.0)        ; !!?
    aRef.Disable(TRUE)
    aRef.Delete()
    aRef = None
ENDIF
ENDFUNCTION

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

Rule of thumb: If you have to use more than 2 If statement use ElseIf 's ... If you have to use more than 6-ish ElseIf 's find a better way. But this don't always apply. In this case with only 4 it's an easy choice.
God knows I've used way more at times ...

Edited by NexusComa
Link to comment
Share on other sites

  • Recently Browsing   0 members

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