Aller au contenu

Photo

Anti Magic Zone?


  • Veuillez vous connecter pour répondre
16 réponses à ce sujet

#1
Jackson Flynn

Jackson Flynn
  • Members
  • 40 messages

A plot line I've got that I'm considering using involves a mine where a rare mineral used by wizards is dug out of the Earth.
The story goes that because this mineral reacts violently with magic, (and when forged into items can increase the power of spells and items etc) the whole area surrounding the mine is covered with a special "Anti Magic Field". Which prohibits spells and spell like effects from working.

 

(The Wizards Guild has lost contact with the mine, and the anti magic zone is really a logic plot device to prevent a bunch of wizards teleporting in and resolving it, and instead needing the player and his/her pals to go by foot.)

 

Is there a simple function to accommodate this?

 

Would it require something like a bespoke script on the heartbeat of the area that checks for spells being cast and simply cancels them, or is there a way to stop them working at all?



#2
Jezla

Jezla
  • Members
  • 173 messages

It'll take three scripts: an OnEnter, OnExit, and HB.  Look at the Duskwood area in the OC (mod name 2200_Port_Llast) for scripts that will do this, I used them for my Underdark areas to disrupt arcane magic.  If you want ALL magic to fail (divine and magic items), it will be much more involved.



#3
Guest_Iveforgotmypassword_*

Guest_Iveforgotmypassword_*
  • Guests
void main()
{
object oPC=GetEnteringObject();
if(!GetIsPC(oPC))return;
object oTarget;
oTarget=oPC;
effect eEffect;
eEffect=EffectSpellFailure(100,SPELL_SCHOOL_GENERAL);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect,oTarget);
}

On enter for the area.

void main()
{
object oPC=GetExitingObject();
if(!GetIsPC(oPC))return;
object oTarget;
oTarget=oPC;
effect eEffect;
eEffect=GetFirstEffect(oTarget);
while(GetIsEffectValid(eEffect))
{
if(GetEffectType(eEffect)==EFFECT_TYPE_SPELL_FAILURE)RemoveEffect(oTarget,eEffect);
eEffect=GetNextEffect(oTarget);
}
}

On exit for the area is what I used before but I'm no scripter and can't remember if this works for the whole party or whether it was just for the PC. Either way I think it was from Lilac Souls script generator as most of my scripts come from there and with a bit of tweaking you could get it to work for everybody probably by just removing the PC part and making it completely general.

#4
Dann-J

Dann-J
  • Members
  • 3 161 messages

I have a wild magic area in a module I'm working on which applies 25% spell failure to all party members (spell hooking takes care of the backlashes and spell warping). Instead of creating OnEnter and OnExit scripts for the area, I simply had the area HB script constantly apply temporary spell failure effects for 6.1 seconds. That way the effect wears off by itself when you leave the area.

 

There's nothing worse than applying an effect permanently, only to have the OnExit script that removes it fail. I suppose if the area only has one exit, you could create a backup OnClientEnter script in the next area just to be safe.


  • rjshae aime ceci

#5
kevL

kevL
  • Members
  • 4 070 messages

It'll take three scripts: an OnEnter, OnExit, and HB. Look at the Duskwood area in the OC (mod name 2200_Port_Llast) for scripts that will do this, I used them for my Underdark areas to disrupt arcane magic. If you want ALL magic to fail (divine and magic items), it will be much more involved.


for fun i looked at it and parsed/modified these out of it:
 
// 'spellfail_inc'

const int ID_SPELL_FAIL = 83903;

// removes SUBTYPE_MAGICAL Effects
void RemoveMagicalEffects(object oCreature);
// applies SpellFailure
void ApplySpellFailure(object oCreature);
// removes SpellFailure
void RemoveSpellFailure(object oCreature);


// removes SUBTYPE_MAGICAL Effects
void RemoveMagicalEffects(object oCreature)
{
    effect eMagicEffect = GetFirstEffect(oCreature);
    while (GetIsEffectValid(eMagicEffect))
    {
        if (GetEffectSubType(eMagicEffect) == SUBTYPE_MAGICAL)
        {
            RemoveEffect(oCreature, eMagicEffect);
            eMagicEffect = GetFirstEffect(oCreature);
        }
        else
            eMagicEffect = GetNextEffect(oCreature);
    }
}

// applies SpellFailure
void ApplySpellFailure(object oCreature)
{
    effect eSpellFail = EffectSpellFailure();
    eSpellFail = SupernaturalEffect(eSpellFail);
    eSpellFail = SetEffectSpellId(eSpellFail, ID_SPELL_FAIL);

    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSpellFail, oCreature);
}


// removes SpellFailure
void RemoveSpellFailure(object oCreature)
{
    effect eSpellFail = GetFirstEffect(oCreature);
    while (GetIsEffectValid(eSpellFail))
    {
        if (GetEffectSpellId(eSpellFail) == ID_SPELL_FAIL)
        {
            RemoveEffect(oCreature, eSpellFail);
            eSpellFail = GetFirstEffect(oCreature);
        }
        else
            eSpellFail = GetNextEffect(oCreature);
    }
}

// 'spellfail_areaenter'

#include "spellfail_inc"

void main()
{
    object oCreature = GetEnteringObject();
    if (GetObjectType(oCreature) == OBJECT_TYPE_CREATURE)
    {
        RemoveMagicalEffects(oCreature);
        ApplySpellFailure(oCreature);
    }
}

// 'spellfail_areaexit'

#include "spellfail_inc"

void main()
{
    object oCreature = GetExitingObject();
    if (GetObjectType(oCreature) == OBJECT_TYPE_CREATURE)
    {
        RemoveSpellFailure(oCreature);
    }
}

// 'spellfail_areahb'

#include "spellfail_inc"

void main()
{
    object oPC = GetFirstPC();
    int bDone = FALSE;

    object oFM = GetFirstFactionMember(oPC, FALSE);
    while (GetIsObjectValid(oFM))
    {
        if (GetArea(oFM) == OBJECT_SELF)
        {
            RemoveMagicalEffects(oFM);

            effect eSpellFail = GetFirstEffect(oFM);
            while (GetIsEffectValid(eSpellFail))
            {
                if (GetEffectSpellId(eSpellFail) == ID_SPELL_FAIL)
                {
                    bDone = TRUE;
                    break;
                }

                eSpellFail = GetNextEffect(oFM);
            }

            if (!bDone)
                ApplySpellFailure(oFM);
        }

        bDone = FALSE;
        oFM = GetNextFactionMember(oPC, FALSE);
    }
}


#6
Jackson Flynn

Jackson Flynn
  • Members
  • 40 messages

Cheers guys. I will look at those solutions, ideally all magic, both friendly and unfriendly, and all spells and item effects would cease to work, but stuff like weapon and armour bonuses would continue to work.

 

I doubt I'm going to get exactly what i want, but those ideas certainly give me something to start with.

 

I also found this.
Has anyone used it before?

I'm going to have a play with it, and will report back.

DannJ, it might be of use to you?



#7
Claudius33

Claudius33
  • Members
  • 258 messages

You may call the function below in the OnConnect  script (not sure of the translation my toolset in French) of the area for every party member and creatures in the area (if relevant) to prevent magic :

 

void NoMagic(object oCreature)
{
    effect eAnti = EffectSpellFailure(100);
    eAnti = SupernaturalEffect(eAnti);
 
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eAnti, oCreature);
}

 

And call the function below in the OnExit script for party members (and creatures if relevant)  to restore magic: 
 
void Magic(object oCreature)
{
   effect eEffect = GetFirstEffect(oCreature);
   while (GetIsEffectValid(eEffect) == TRUE)
  {
     if (GetEffectSubType(eEffect) == SUBTYPE_SUPERNATURAL)
     {
          if (GetEffectType(eEffect) == EFFECT_TYPE_SPELL_FAILURE)
         {
             RemoveEffect(oCreature, eEffect);
         }
      }
     eEffect = GetNextEffect(oCreature);
   }
}
Armors and weapons bonuses should keep working.


#8
kevL

kevL
  • Members
  • 4 070 messages

in case anyone's wondering, why a HB if onEnter and onExit set the effect? A note in the OC says it's there because effects could get removed if a character dies/resurrects/reloads in the area (which seems to depend on other things..)


A better question would be: Why bother with an onEnter if there's a HB



#9
rjshae

rjshae
  • Members
  • 4 497 messages

in case anyone's wondering, why a HB if onEnter and onExit set the effect? A note in the OC says it's there because effects could get removed if a character dies/resurrects/reloads in the area (which seems to depend on other things..)


A better question would be: Why bother with an onEnter if there's a HB

 

There could be up to a 6 second pause before the HB runs--long enough to get off an attack spell.



#10
Dann-J

Dann-J
  • Members
  • 3 161 messages

You would have to pause immediately on entering the area in order to slip in ahead of the HB script. In my experience in my own wild magic area (which only uses an HB script), you almost never get enough time to do that. Even if you do, if there are no hostiles to greet you straight away then the best you can do is cast some sort of buff on yourself, and only one per caster at the most.

 

The only situation where you're likely to exploit this is if you lead a powerful hostile creature to an area exit, then repeatedly leave and re-enter the area in order to chip away at them with the occasionally successful spell. I've done something similar with a solo rogue once, since if you pause immediately on entering an area and there is a hostile right on top of you, the first attack you get in is always a sneak attack (even if the creature is facing you). It requires a special degree of patience and perseverance on the part of a player to have to put up with so many load screens though, just for a second or two of combat every now and then.



#11
Tchos

Tchos
  • Members
  • 5 063 messages

Perhaps a spellcasting party member might detect enemies before the load screen goes away (before you can see it) and automatically cast a spell (assuming AI is turned on) before the heartbeat kicks in.  If nothing else, it would be a detriment to the immersion that we're in a no-magic zone, and not just having a script applied to us.



#12
Dann-J

Dann-J
  • Members
  • 3 161 messages

Then again, there's no reason to think a dead magic zone would start suddenly and sharply. It could be fuzzy at the edges, where spells are just difficult to cast rather than completely impossible. Admittedly, I'm probably just trying to justify my own scripting laziness. :)

 

Although, a script that applies casting failure percentages depending on how close you are to a particular spot might be interesting. As you get closer to the source of the dead magic, your failure rate could increase. Once you get *really* close it could start stripping your buffs, draining charges from wands, or adding equal but opposite enhancement penalty properties to your magical armour and weapons.


  • andysks et Jackson Flynn aiment ceci

#13
kevL

kevL
  • Members
  • 4 070 messages

Although, a script that applies casting failure percentages depending on how close you are to a particular spot might be interesting. As you get closer to the source of the dead magic, your failure rate could increase. Once you get *really* close it could start stripping your buffs, draining charges from wands, or adding equal but opposite enhancement penalty properties to your magical armour and weapons.


now that's cool

#14
Jackson Flynn

Jackson Flynn
  • Members
  • 40 messages

Although, a script that applies casting failure percentages depending on how close you are to a particular spot might be interesting. As you get closer to the source of the dead magic, your failure rate could increase. Once you get *really* close it could start stripping your buffs, draining charges from wands, or adding equal but opposite enhancement penalty properties to your magical armour and weapons.

Ooh... Now THAT has potential.
That would allow the field protecting the mine to be strong around it's focal point (100% failure), yet allow for variance further away.

That, in itself, could act as a plot guide to the player to realise they are getting closer to the target.

 

If I use the plot that I've written for the novel, there are several encounter areas in the woods between the East Coast and the Mountains. (Where I could apply a % drop out on magic)
Then there would be a huge final exterior location where several separate enemy factions would be located and the party would have to find a safe route to the Redoubt, (mine) but as they get closer to the hub, their magic drops off to zero...

If anyone has any ideas on how to do this, (and maybe even how to use it as a Trigger so that the varying areas could be painted down) I'm willing to write up my mod as a "How To" use such a thing and share it on the forum!
(I might not be able to invent the stuff, but I CAN write coherent and understandable How To's)
 



#15
Morbane

Morbane
  • Members
  • 1 883 messages

Then again, there's no reason to think a dead magic zone would start suddenly and sharply. It could be fuzzy at the edges, where spells are just difficult to cast rather than completely impossible. Admittedly, I'm probably just trying to justify my own scripting laziness. :)

 

Although, a script that applies casting failure percentages depending on how close you are to a particular spot might be interesting. As you get closer to the source of the dead magic, your failure rate could increase. Once you get *really* close it could start stripping your buffs, draining charges from wands, or adding equal but opposite enhancement penalty properties to your magical armour and weapons.

 

i see something like this working in stacked and progressively tighter ipoint aoe's - that that would be just one area.

 

the op suggested it take place over several areas, if i followed correctly? that would be easier and it would wind up kind of blocky area by area, but the effect would be easier to step up or down - 

 

i'm not sure if overlapping aoe's would work the way i suggested above but it is possible but if the scripts were too demanding , at zero magic the game might go choppy during big encounters.



#16
kevL

kevL
  • Members
  • 4 070 messages

well... i think i did it. dropbox : kL_SpellFail

It uses a waypoint, similar area Enter/Exit/HB scripts as above ( #include on Pastebin ). Plonk down the waypoint, it has 3 variables.

- antimagic potency at the core
- how fast it drops off as one moves away
- and an option to reduce the rate of removing buffs (item-buffs included), since firing on every heartbeat would quickly remove everything.

The included spellhook should also be set to prevent casts from potions, scrolls, etc.


... an interesting quirk is that if potency is set to say 200, and dropoff at 5% per meter, the zone of 100% antimagic surrounds the wp to a radius of uhh.. 20 meters. But to get a sudden dropoff from 100% to 0% might be possible by playing around with two waypoints in an area (not sure).

( supposedly a guy could even do a negative dropoff and plonk down waypoints that create stronger antimagic at the periphery, lessening as one gets closer -- multiple waypoints in an area should be np too, scripts just choose the close one )


if you, Jack, or anyone checks it out, pls post back on if WAI (working as intended) or buggy. If nothing else it should print an occasional message to chat about buffs removed ... if the system actually works I'll likely plop 'er into Vault2

/acknowledgements to the OC and pelhikano.


oh, kinda proud of this line:

j = StringToInt(GetStringRight(sVar, GetStringLength(sVar) - 11)) + 1;

ps. Debug is still showing, figure it out a bit and it can help set things up.


  • Morbane et Rolo Kipp aiment ceci

#17
kevL

kevL
  • Members
  • 4 070 messages

forgot to mention that "X2_L_WILD_MAGIC" needs to be set TRUE on an area for the spellhook to affect non-Owned characters ...

 

it could be set in the onEnterArea script i suppose.