Jump to content

Make one MagicEffect Dispel Another?


Recommended Posts

I would like to make any LGHT (Light) spells dispel NEYE (Night-eye) spells and vice versa. Same with WABR (Waterbreathing) and WAWA (Waterwalking).

 

I tried to add them to each other's "Counter Effects", but cannot figure out how to actually do that in the MagicEffect editor pop-up. Is that possible? Would this make the spell dispel the spell that is in the list of Counter Effects?

 

Another way may be to add a script to each MagicEffect that makes it dispel the other with (player.dispel NEYE). Is it possible to add a script to the four effects I want to change to dispel their counter effect?

 

Or, a third way, is that I write a quest script that keeps track of when those spells are active on the player and dispels one when the other is detected. I know how to do this one, but can't stop thinking there has to be a simpler way.

 

This was really easy to do in Skyrim BTW.

 

Thanks!!

Edited by GamerRick
Link to comment
Share on other sites

I too couldn't edit Counter Effects tab and even wiki doesn't mention it, so I think it's not editable by normal means. I have an idea of two things:

 

1. Add to each spell script effect part which use Script Effect Start block, IsSpellTarget and Dispell command.

2. With OBSE using GetMagicEffectCounters/SetMagicEffectCounters. Running quest and script will still be needed, but I think it would be necessary to run it only at restart of Oblivion, so this script can be very light on performance.

Link to comment
Share on other sites

Anything is possible with scripts. Lets make 1 spell to start with. Describe exactly what you want it to do.

Lets start with Waterwalking/Waterbreathing. To make it duration independent, make 2 abilities. We need a quest script or a global variable but a quest script is more suitable, well lets keep it simple. Make a Global variable called GamToggleWater, so click the menu GamePlay and Global Variables and rightclick and make a new Short Global Variable called GamToggleWaterGLOB or GamerToggleWaterGLOB. :smile:

Make 2 abilities and call them
GamWaterWalkSPL
GamWaterBreathSPL

Make a spell called GamToggleWaterSPL

So lets make the script and make sure you save it as a Magic Effect, not Object Script. There is a pull down menu to toggle between them + Quest Scripts.

As it is abilities, we do not need to cast them, just have them added and removed to and from the player.

scn GamToggleWaterSCR

Begin ScriptEffectStart 

	If ( GamToggleWaterGLOB == 0 )   ;Removes all spells
		Player.RemoveSpell GamWaterWalkSPL
		Player.RemoveSpell GamWaterBreathSPL
		Set GamToggleWaterGLOB to 1
		
	ElseIf ( GamToggleWaterGLOB == 1 ) ; Adds the Water walking, removes the Water Breathing
		Player.AddSpell GamWaterWalkSPL
		Player.RemoveSpell GamWaterBreathSPL
		Set GamToggleWaterGLOB to 2		

	Else        ; Adds the Water Breathing, removes the Water Walking
		Player.RemoveSpell GamWaterWalkSPL
		Player.AddSpell GamWaterBreathSPL
		Set GamToggleWaterGLOB to 0
	EndIf

End

No need to dispell anything with this setup, as the 2 spells are abilities.

Edited by Pellape
Link to comment
Share on other sites

I wanted to know if it was possible to put a Magic Effect Script on the MGEF item, so it would run whenever any spell with that effect ran. In turn, the ME Script would remove the other MGEF effect from the, it wouldn't matter if it were a spell I bought or crafted myself. I couldn't find a way to do this.

 

I then tried to write a ME script that would loop through the active effects on the player, and remove the other effect (or dispel the Spell it came from), but I found no way to do this.

 

So, I just did the thing I know how to do already, which is to write a ME Script that I would put on all standard NightEye spells that dispells all standard Light spells, and vice versa for Light Spells dispelling all NightEye Spells. It obviously won't work with crafted spells.

 

I can't figure out how you would loop through the active effects that are one the player. I tested the various OBSE and vanilla commands that look they might work, but couldn't figure it out.

 

One of the scripts I cam up with is this one:

scn GRLightDispelNightEyeMEScript

begin ScriptEffectStart
    player.Dispel GRNightEyeNovice              ; My Novice spell
    player.Dispel StandardNightEye2Apprentice
    player.Dispel StandardNightEye3Journeyman
    player.Dispel GRStandardNightEye4Expert     ; My Expert spell
    player.Dispel DarkNightEyes
end

It's working great. I will just have ol' Edgar sell my new spells!

Edited by GamerRick
Link to comment
Share on other sites

It seems that using OBSE's CounterEffect commands isn't way to go. I made script which adds counter effect to spell's Counter Effects field, but Oblivion is simply ignoring them. Oh well, here it is anyway - at least there are lines to convert the effect codes to string, so it can be still some worth. It's script for a spell and also straight copy from CS editor.

scn RRSetCounterEffectScript

short checked
short found
array_var c_effects
string_var code
string_var hex_code
string_var ascii_code
int ef_code
int temp
int char_pos
int cut_right
ref magiceffect
ref magiceffect2
int size
int index

begin ScriptEffectStart
	; first check, if counter effect is already set
	if checked == 0
		let size := ar_Size c_effects
		if size == -1
			let c_effects := ar_Construct array
		endif
		set found to 0
		set magiceffect to LGHT ; light
		let c_effects := GetMagicEffectCounters magiceffect
		let size := ar_size c_effects
		if size > 0
			; test
			;print "There are "+$size+" counter effect(s)."
			set index to 0
			while index < size
				let ef_code := c_effects[index]
				let hex_code := NumToHex ef_code
				let ascii_code := ""
				; convert it to readable ascii
				set char_pos to 0
				while char_pos < 8 
					set cut_right to char_pos + 2
					let code := hex_code
					if cut_right > char_pos && cut_right != 8
						sv_Erase code cut_right
					endif
					if char_pos > 0
						sv_Erase code 0 char_pos
					endif
					let ef_code := ToNumber $code 1
					let code := AsciiToChar ef_code
					if eval (sv_Length ascii_code == 0)
						let ascii_code := $code
					else
						sv_Insert $code ascii_code 0
					endif
					set char_pos to char_pos + 2
				loop
				; and check
				if eval (ascii_code == "NEYE")
					set found to 1
				endif
				set index to index + 1
			loop			
		endif
		set checked to 1
	endif
	; setting counter effect for light
	if checked != 0 && found == 0
		set magiceffect2 to NEYE
		AddMagicEffectCounter magiceffect2 magiceffect
		print "Night Eye is set as counter effect to Light." 
	endif
	if checked && found
		print "Night Eye is already set as counter effect to Light."
	endif
	; check for night eye
	set checked to 0
	ar_Resize c_effects 0
	set magiceffect to NEYE
	set found to 0 
	let c_effects := GetMagicEffectCounters magiceffect
	let size := ar_size c_effects
	if size > 0
		; test
		;print "There are "+$size+" counter effect(s)."
		set index to 0
		while index < size
			let ef_code := c_effects[index]
			let hex_code := NumToHex ef_code
			let ascii_code := ""
			; convert it to readable ascii
			set char_pos to 0
			while char_pos < 8 
				set cut_right to char_pos + 2
				let code := hex_code
				if cut_right > char_pos && cut_right != 8
					sv_Erase code cut_right
				endif
				if char_pos > 0
					sv_Erase code 0 char_pos
				endif
				let ef_code := ToNumber $code 1
				let code := AsciiToChar ef_code
				if eval (sv_Length ascii_code == 0)
					let ascii_code := $code
				else
					sv_Insert $code ascii_code 0
				endif
				set char_pos to char_pos + 2
			loop
			; and check
			if eval (ascii_code == "LGHT")
				set found to 1
			endif
			set index to index + 1
		loop			
	endif
	set checked to 1
	; setting counter effect
	if checked != 0 && found == 0
		set magiceffect2 to LGHT
		AddMagicEffectCounter magiceffect2 magiceffect
		print "Light is set as counter effect to Night Eye." 
	endif
	if checked && found
		print "Light is already set as counter effect to Night Eye."
	endif
	; cleanup
	sv_Destruct code hex_code ascii_code
	ar_Resize c_effects 0
	let c_effects := ar_Null
end
Link to comment
Share on other sites

I don't think it's possible given the commands we have:

GetActiveEffectCount - Use this to loop through the Active Effects

for each active effect on the player
      GetNthActiveEffectCode index - Get first next code  (I could not get this command to work!  I GOT 0 trying this)

     (Assuming there is a way to actually get the current code.....)
     If effect code == LGHT && (The effect came from a spell.  IS THERE A WAY TO DO THIS?? Can't remove light effects from enchantments or portions afterall.))
          DispelNthActiveEffect - Dispel the current active effect
           continue ; There should only be one light spell on the player
     endif
loop

Or Maybe you can get the spell this way???
      GetNthActiveEffectMagicItem - Get the item that caused the Effect  Does it return a ref to the SPELL if it came from a SPELL??  Is there a way to get the SPELL that the effect came from????
      player.dispel that_Spell

It looks easy, but I could not make it work.

 

I AM DONE WITH THIS!!!! I already exhausted the gumption and energy I had to try and figure it out, given that I was able to solve it the way I ended up doing it. If someone else would like to try, I need the actual code that will work to solve the actual problem I originally asked about.

 

Thanks for trying though!

Edited by GamerRick
Link to comment
Share on other sites

Ok, another one - this time it scans all active effects on target actor and if it finds active Night Eye effect from any source, it dispels all spells and lesser powers which contains Light effect. This script was made for external test spell, but I believe there will be no trouble to adapt it for quest or something else. So far testing gave good results and is working also for crafted spells (as long they're using standard Magic Effects).

scn RRDispelLightScript

array_var activeeffects
array_var lightindexes
int index
int lightindex
int size
int eff_code
string_var ascii_code
ref me
ref item
ref caster
short nighteye
short light
short nighteye_item
short light_item
int magic_type

begin ScriptEffectStart
	let size := ar_Size activeeffects
	if size == -1
		let activeeffects := ar_Construct array
	endif
	let size := ar_Size lightindexes
	if size == -1
		let lightindexes := ar_Construct array
	endif
	set me to GetSelf
	if me != 0
		let activeeffects := me.GetActiveEffectCodes
		let size := ar_Size activeeffects
	endif
	if size > 0
		;print $me+" has "+$size+" active spell effects on him."
		; searching for night eye
		set index to 0
		set nighteye to 0
		set nighteye_item to 0
		while index < size
			let eff_code := activeeffects[index]
			let ascii_code := GetMagicEffectCharsC eff_code
			if eval ( ascii_code == "NEYE" )
				set item to 0
				let item := GetNthActiveEffectEnchantObject index
				if item != 0
					;print $me+" has active Night Eye effect coming from "+$item+" as enchanted item."
					set nighteye_item to 1
				else
					;print $me+" has active Night Eye effect coming from other source than enchanting."
					set nighteye to 1
				endif				
			endif
			set index to index + 1
		loop
		; now searching for light
		if nighteye != 0 || nighteye_item != 0
			set index to 0
			set lightindex to 0
			set light to 0
			set light_item to 0
			while index < size
				let eff_code := activeeffects[index]
				let ascii_code := GetMagicEffectCharsC eff_code
				if eval (ascii_code == "LGHT")
					set item to 0
					let item := GetNthActiveEffectEnchantObject index
					if item != 0
						;print $me+" has also Light effect coming from "+$item+" as enchated item."
						set light_item to 1 
					else
						set caster to 0
						let caster := GetNthActiveEffectMagicItem index
						if caster != 0
							set magic_type to 0
							let magic_type := GetMagicItemType caster
							if magic_type == 1 ; we want disable spells
								let magic_type := GetSpellType caster
								if magic_type == 0 || magic_type == 3 ;disable only normal spell or lesser power
									;print $magic_type
									;print $me+" has also Light effect coming from spell or lesser power."
									set light to 1
									let lightindexes[lightindex] := index
									set lightindex to lightindex + 1
								endif
							endif
						endif
					endif
				endif
				set index to index + 1
			loop
			; found light as spell or power	
			if light 
				;print "Trying to dispell all Light spells and powers."
				let size := ar_Size lightindexes
				set lightindex to 0
				while lightindex < size
					let index := lightindexes[lightindex]
					me.DispelNthActiveEffect index
					set lightindex to lightindex + 1
				loop
			endif
		endif
	endif
	; cleanup
	sv_Destruct ascii_code
	ar_Resize activeeffects 0
	let activeeffects := ar_Null
	ar_Resize lightindexes 0
	let lightindexes := ar_Null
end
Link to comment
Share on other sites

Directly editing vanilla spells can be nullified by any mod later in load order. A solution is to use the OnSpellCast EventHandler bound to Player.

OnSpellCast hands the aruments of Caster and Spell - we know the Caster but Spell provides a solution.

The requirement is Dispel by Effect however it is a Many to Many relationship - each effect belongs to many spells and a spell can have many effects. The solution is to use mapping functions for each Effect that should Dispel any other Spell by any other Effect.

It may be easier to do in Skyrim Creation Kit but I have to ask, would it be anywhere near the challenge or fun of making Oblivion bow to your will?

 

Pseudo code...

scn QstHandleEventsScript

Begin GameMode

   if GetGameLoaded
   ;__This binds the event handler to player on new, quick or load game.
      PlayerRef.SetEventHandler "OnSpellCast", FnOnSpellCastPlayer
      
   endif
   
End

 

scn FnOnSpellCastPlayer

ref refCaster
ref refSpell

Begin Function { refCaster, refSpell }
;__once bound, this always runs when the player casts a spell
   if MagicItemHasEffect ABAT, refSpell
      call FnDispelConflicts "ABAT"
   elseif MagicItemHasEffect ...
      call FnDispelConflicts ...
   endif
   
End

 

scn FnDispelConflicts

string_var strEffect

Begin Function { strEffect }
;__this does the Dispel(s) - each could be factored out to other functions for readability and tidiness
   if strEffect == "ABAT"
      PlayerRef.Dispel BSWarriorFarting
      PlayerRef.Dispel ...
   endif
End

 

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

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