Jump to content

Best Way to Detect a Concentration Spell During a OnSpellCast Event?


Recommended Posts

I've been working on a mod for a while now, trying to get back into understanding coding by working through Papyrus and modifying scripts.

One of the issues that I have come across is within my OnSpellCast Event, as I am not too sure how I should go about detecting whether or not the caster is using a concentration spell. I'll drop the source down below:
 

Scriptname MAS_PerkCastingFever_StacksCalc extends ActiveMagicEffect
{How the perk "Casting Fever"'s stacks are calculated.}

import Spell
import PO3_SKSEFunctions
; Scripts that have been imported. SKSE and PO3 Extender required.

GlobalVariable Property MAS_PerkCastingFever_Stacks Auto
; Actual stacks that determine the overall Magicka-reduction.

Int iStackTime = 4
; iStackTime is duration.

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

Event OnEffectStart (Actor akTarget, Actor akCaster)
	MAS_PerkCastingFever_Stacks.Value = 0
EndEvent
; When effect starts, stacks reset back down to zero.

Event OnEffectFinish (Actor akTarget, Actor akCaster)
	MAS_PerkCastingFever_Stacks.Value = 0
	debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
EndEvent
; When effect ends, stacks reset back down to zero.

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

Event OnSpellCast (Form akSpell)

	If (akSpell as Spell)
		Spell castedSpell = akSpell as Spell
		If (castedSpell.GetNthEffectMagicEffect(0).GetAssociatedSkill() == "Destruction")
			If (MAS_PerkCastingFever_Stacks.Value < 5) ; Does not increase stacks beyond 5.
				;BOTCHED CODE
				If (IsCasting(akSpell) == true)
					While IsCasting(castedSpell) == true
						MAS_PerkCastingFever_Stacks.Value += 1
						debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
						registerForSingleUpdate(iStackTime)
					EndWhile
				Else
				;BOTCHED CODE
					MAS_PerkCastingFever_Stacks.Value += 1
					debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
					registerForSingleUpdate(iStackTime)
				EndIf
			EndIf
		Else
			MAS_PerkCastingFever_Stacks.Value = 0
			debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
		EndIf
	EndIf

EndEvent
; Whenever a casted Spell's first Magic Effect is from the Destruction school, the effect activates. It deactivates if it is from a different school.
; Next, if the Global Variable's value is lesser than 5, the stack is increased. The timer is also refreshed/triggered.

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

Event OnUpdate()
	MAS_PerkCastingFever_Stacks.Value = 0
	debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
EndEvent

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

Besides the code inbetween ;BOTCHED CODE, everything else stacks as it should based off of every first initial cast. However, concentration spells only trigger the OnSpellCast Event once, which is normal but not wanted. How would I be able to achieve the while loop I am aiming for within an OnSpellCast, and if it cannot be achieved within the event, what would?

Edited by DevTheDev
Link to comment
Share on other sites

Answering the headline real quick since didnt see this mentioned

Event OnSpellCast(Form akSpell)

Int FirstEffectCastType = (akSpell as Spell).GetNthEffectMagicEffect(0).GetCastingType()

; Constant Effect     0
; Fire And Forget     1
; Concentration       2

So if the above Int = Two you know it is concentration so do whatever. Anything other than two do nada

  • Like 1
Link to comment
Share on other sites

Posted (edited)
4 hours ago, Sphered said:

Answering the headline real quick since didnt see this mentioned

Event OnSpellCast(Form akSpell)

Int FirstEffectCastType = (akSpell as Spell).GetNthEffectMagicEffect(0).GetCastingType()

; Constant Effect     0
; Fire And Forget     1
; Concentration       2

So if the above Int = Two you know it is concentration so do whatever. Anything other than two do nada


Thank you so much, that's exactly what I needed to get this to work! I think I tried coding it in before, but didn't properly know how to format it.
Right now I'll post the state the code is in right now, but it still has some hiccups with resetting the stack if the player is no longer casting the concentration spell. I'll probably make another post regarding that specific issue.

Scriptname MAS_PerkCastingFever_StacksCalc extends ActiveMagicEffect
{How the perk "Casting Fever"'s stacks are calculated.}

import Spell
import PO3_SKSEFunctions
; Scripts that have been imported. SKSE and PO3 Extender required.

GlobalVariable Property MAS_PerkCastingFever_Stacks Auto
; Actual stacks that determine the overall Magicka-reduction.

Int iStackTime = 4
; iStackTime is duration.

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

Event OnEffectStart (Actor akTarget, Actor akCaster)
	MAS_PerkCastingFever_Stacks.Value = 0
EndEvent
; When effect starts, stacks reset back down to zero.

Event OnEffectFinish (Actor akTarget, Actor akCaster)
	MAS_PerkCastingFever_Stacks.Value = 0
	debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
EndEvent
; When effect ends, stacks reset back down to zero.

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

Event OnSpellCast (Form akSpell)

	If (akSpell as Spell)
		Spell castedSpell = akSpell as Spell
		If (castedSpell.GetNthEffectMagicEffect(0).GetAssociatedSkill() == "Destruction")
			If (MAS_PerkCastingFever_Stacks.Value < 5) ; Does not increase stacks beyond 5.
				If (castedSpell.GetNthEffectMagicEffect(0).GetCastingType() == 2)
					; Stuck While loop
					While (castedSpell.GetNthEffectMagicEffect(0).GetCastingType() == 2)
						If (MAS_PerkCastingFever_Stacks.Value < 5)
							MAS_PerkCastingFever_Stacks.Value += 1
							debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
							registerForSingleUpdate(iStackTime)
						ElseIf (MAS_PerkCastingFever_Stacks.Value == 5)
							registerForSingleUpdate(iStackTime)
						EndIf
					EndWhile
					; Stuck While loop
				Else
					MAS_PerkCastingFever_Stacks.Value += 1
					debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
					registerForSingleUpdate(iStackTime)
				EndIf
			ElseIf (MAS_PerkCastingFever_Stacks.Value == 5)
				registerForSingleUpdate(iStackTime)
			EndIf
		Else
			MAS_PerkCastingFever_Stacks.Value = 0
			debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
		EndIf
	EndIf

EndEvent
; Whenever a casted Spell's first Magic Effect is from the Destruction school, the effect activates. It deactivates if it is from a different school.
; Next, if the Global Variable's value is lesser than 5, the stack is increases. The timer is also refreshed/triggered.
; Concentration spells work differently, stacking up to their max quickly. It's broken in it's current state though, causing the stack to permanetly stay at 5.

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

Event OnUpdate()
	MAS_PerkCastingFever_Stacks.Value = 0
	debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
EndEvent

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

Before I make that post though...
 

 

On 4/10/2024 at 1:57 AM, dylbill said:

My first thought would be to use animation events to detect when stopping casting. 

https://ck.uesp.net/wiki/Animation_Events 

 

How would I go about implementing this within my OnSpellCast Event? When I was previously looking through other similar posts on the forums, almost all instances of this method being used were only using the OnAnimationEvent to detect concentration casting.
I'm not too sure how to nest this event into the OnSpellCast Event, but if there are any references or ideas, I would love to know.

EDIT: Just realized the while statement is a constantly true statement, somehow that didn't click in my head lmao

Edited by DevTheDev
Link to comment
Share on other sites

Posted (edited)

So I actually was able to crack this after finally figuring out how to pull a variable from OnEffectStart (it was easy, I just didn't know squat lmao)

I want to make sure that the spell works for NPCs once I find an apt subsitute for the GlobalVariable, but my final code ended up being this:
 

Scriptname MAS_PerkCastingFever_StacksCalc extends ActiveMagicEffect
{How the perk "Casting Fever"'s stacks are calculated.}

import Spell
import PO3_SKSEFunctions
; Scripts that have been imported. SKSE and PO3 Extender required.

GlobalVariable Property MAS_PerkCastingFever_Stacks Auto
; Actual stacks that determine the overall Magicka-reduction.

Int iStackTime = 4
ObjectReference spellCaster
; iStackTime is duration. spellCaster is used as a reference.

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

Event OnEffectStart (Actor akTarget, Actor akCaster)
	MAS_PerkCastingFever_Stacks.Value = 0
	spellCaster = akCaster as ObjectReference
EndEvent
; When effect starts, stacks reset back down to zero and grab the active actor as the spellCaster.

Event OnEffectFinish (Actor akTarget, Actor akCaster)
	MAS_PerkCastingFever_Stacks.Value = 0
	debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
EndEvent
; When effect ends, stacks reset back down to zero.

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

Event OnSpellCast (Form akSpell)

	If (akSpell as Spell)
		Spell castedSpell = akSpell as Spell
		If (castedSpell.GetNthEffectMagicEffect(0).GetAssociatedSkill() == "Destruction")
			If (MAS_PerkCastingFever_Stacks.Value  < 5) ; Does not increase stacks beyond 5.
				If (castedSpell.GetNthEffectMagicEffect(0).GetCastingType() == 2)
					While (IsCasting(spellCaster, akSpell) == true)
						If (MAS_PerkCastingFever_Stacks.Value < 5)
							Stacker()
						ElseIf (MAS_PerkCastingFever_Stacks.Value == 5)
							registerForSingleUpdate(iStackTime)
						EndIf
					EndWhile
				Else
					Stacker()
				EndIf
			ElseIf (MAS_PerkCastingFever_Stacks.Value == 5)
				registerForSingleUpdate(iStackTime)
			EndIf
		Else
			MAS_PerkCastingFever_Stacks.Value = 0
			debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
		EndIf
	EndIf

EndEvent
; Whenever a casted Spell's first Magic Effect is from the Destruction school, the effect activates. It deactivates if it is from a different school.
; Next, if the Global Variable's value is lesser than 5, the stacks increase. The timer is also refreshed/triggered on every cast if its stack is at 5.
; Concentration spells work differently, stacking up to their max quickly as long as the spell is active.

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

Event OnUpdate()
	MAS_PerkCastingFever_Stacks.Value = 0
	debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
EndEvent

Function Stacker()
	MAS_PerkCastingFever_Stacks.Value += 1
	debug.Notification("Casting Fever Stack: " + MAS_PerkCastingFever_Stacks.Value)
	registerForSingleUpdate(iStackTime)
EndFunction

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

I used the IsCasting function from PO3's Extender to check if the spell was still active, getting the original Form akSpell found within OnSpellCast and the ObjectReference casted from OnEffectStart's Actor.
Thank you though for all of your help, I'd say at this point my script's in a good state to finally add in a non-Global Variable way to distribute the bonuses, mainly so that other casters have their own incremental reductions in Magicka.

EDIT: Changed the code with a function for better readability, mainly for other modders.

Edited by DevTheDev
Updated code for future reference if people are interested
Link to comment
Share on other sites

  • Recently Browsing   0 members

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