Aller au contenu

Photo

Reading number of spell effects on target


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

#1
Kesaru

Kesaru
  • Members
  • 130 messages
I would like to make Mana Cleanse into a passive improvement to Mana Drain which causes it to remove all spell effects  from the target and grant you extra mana for each removed.
The problem is I don't know how to read the number of spell effects specifically the target has on them.
As far as I know the GetEffects function can only look for either any effect at all, or oddly specific ones like Confusion or Damage over Time.

The script effect_dispel_magic_h references spell effects the way I want, but the way it's done confuses the hell out of me and I can't just copy the code directly.

Modifié par Kesaru, 31 mars 2010 - 07:53 .


#2
TimelordDC

TimelordDC
  • Members
  • 923 messages
Actually, you can copy the code directly since it is pretty straightforward:
1. Get the current effects on the object
2. Get the ability id associated with the effect
3. If the ability is of type ABILITY_TYPE_SPELL, remove it
In your case, (3) would be modified to increment a counter and give the caster of Mana Cleanse (counter * mana increase value) mana.

I don't understand why they have 2 loops since both accomplish the same thing.

Modifié par TimelordDC, 31 mars 2010 - 08:09 .


#3
Kesaru

Kesaru
  • Members
  • 130 messages
What would the counter look like?
I've never made or seen one in this game's scripting language before.

Maybe

    arSpell = GetEffects(OBJECT_SELF);
    nSize = GetArraySize (arSpell);
    for (i = 0; i < nSize; i++)
    {
        nId = GetEffectAbilityID(arSpell[i]);

        if (Ability_GetAbilityType(nId) == ABILITY_TYPE_SPELL)
        {
            RemoveEffect(OBJECT_SELF,arSpell[i]);
            nCounter = nCounter + 1
        }
    }

Should that work?

Modifié par Kesaru, 31 mars 2010 - 08:21 .


#4
Kesaru

Kesaru
  • Members
  • 130 messages
I tried copying it over even before adding the counter to see if it'd work, and there are errors everywhere.
Nearly every line of that code seems to be having issues with "Variable defined without type".

-Edit- Nevermind. The previous loop defines the variable types. I had to add that in.
The only problem left is how the counter should look.

Couldn't I just multiply the mana bonus by nSize though? I assume if there are 3 effects that should return 3, 1 effect returns 1 etc.

Modifié par Kesaru, 31 mars 2010 - 09:48 .


#5
Craig Graff

Craig Graff
  • Members
  • 608 messages

TimelordDC wrote...
I don't understand why they have 2 loops since both accomplish the same thing.


Order is important because removing the upkeep effects triggers code in effect_upkeep_h, mostly to remove effects that are applied to the whole party or upkeep effects on the caster.

Modifié par Craig Graff, 01 avril 2010 - 02:49 .


#6
Craig Graff

Craig Graff
  • Members
  • 608 messages

Kesaru wrote...
The only problem left is how the counter should look.

Couldn't I just multiply the mana bonus by nSize though? I assume if there are 3 effects that should return 3, 1 effect returns 1 etc.

The counter you have is fine, but you should consider leaving the two loops intact.
Without the counter you will be giving a bigger mana bonus than you intend because there are likely effects applied to the creature that aren't spell abilities and some spells have associated upkeep abilities, which means that the array size is larger than the number of spells affecting the creature.
Without the two loops you may be leaving upkeep effects on the caster.

Modifié par Craig Graff, 01 avril 2010 - 02:49 .


#7
Kesaru

Kesaru
  • Members
  • 130 messages
I used the second loop, but removed the section that removes the spell effects and replaced it with regular EffectDispelMagic since I only needed the loop to determine how many effects were on the target, and used nSize.

From what you're saying though, the only way to accurately determine the number of effects would be for me to completely replicate both dispel magic loops inside my spell script, and use the counter to determine the number of effects?

This is what my current script for Drain Mana looks like:
// -----------------------------------------------------------------------------
// talent_single_target.nss
// -----------------------------------------------------------------------------
/*
    Generic Ability Script for single target abilities
*/
// -----------------------------------------------------------------------------
// georg / petert
// -----------------------------------------------------------------------------

#include "log_h"
#include "abi_templates"
#include "sys_traps_h"
#include "spell_constants_h_arcarts"
#include "plt_cod_aow_spellcombo6"

const int DRAIN_MANA_PROJECTILE = 136;

void main()
{
    event ev = GetCurrentEvent();
    int nEventType = GetEventType(ev);

    switch(nEventType)
    {
        case EVENT_TYPE_SPELLSCRIPT_PENDING:
        {
            Ability_SetSpellscriptPendingEventResult(COMMAND_RESULT_SUCCESS);

            break;
        }

        case EVENT_TYPE_SPELLSCRIPT_CAST:
        {
            // Get a structure with the event parameters
            struct EventSpellScriptCastStruct stEvent = Events_GetEventSpellScriptCastParameters(ev);

            // Hand this through to cast_impact
            SetAbilityResult(stEvent.oCaster, stEvent.nResistanceCheckResult);

            break;
        }

        case EVENT_TYPE_SPELLSCRIPT_IMPACT:
        {
            // Get a structure with the event parameters
            struct EventSpellScriptImpactStruct stEvent = Events_GetEventSpellScriptImpactParameters(ev);

            Log_Trace(LOG_CHANNEL_COMBAT_ABILITY, GetCurrentScriptName() + ".EVENT_TYPE_SPELLSCRIPT_IMPACT",Log_GetAbilityNameById(stEvent.nAbility));

            effect[] arSpell = GetEffects(stEvent.oTarget);
            int nSize = GetArraySize (arSpell);
            int i;
            int nId;
            for (i = 0; i < nSize; i++)
            {
                nId = GetEffectAbilityID(arSpell[i]);
            }


            // if target is spellcaster or has spell effects
            if (IsMagicUser(stEvent.oTarget) == TRUE || (Ability_GetAbilityType(nId) == ABILITY_TYPE_SPELL && HasAbility(stEvent.oCaster, ABILITY_SPELL_MANA_CLEANSE) == TRUE))
            {
                if (CheckSpellResistance(stEvent.oTarget, stEvent.oCaster, stEvent.nAbility) == FALSE)
                {
                    // Mana Cleanse spell removal
                    if (Ability_GetAbilityType(nId) == ABILITY_TYPE_SPELL)
                    {
                        effect eEffect = EffectDispelMagic();
                        ApplyEffectOnObject(EFFECT_DURATION_TYPE_INSTANT, eEffect, stEvent.oTarget, 0.0f, stEvent.oCaster, stEvent.nAbility);
                    }


                    float fManaMax = (100.0f + GetCreatureSpellPower(stEvent.oCaster)) * MANA_DRAIN_FACTOR;
                    float fManaSpell = ((100.0f + GetCreatureSpellPower(stEvent.oCaster)) * MANA_CLEANSE_FACTOR) * nSize;
                    float fTargetMana = IntToFloat(GetCreatureMana(stEvent.oTarget));
                    if (fTargetMana > 0.0f)
                    {
                        float fMana;

                        // spell combo - vulnerability hex
                        if (GetHasEffects(stEvent.oTarget, EFFECT_TYPE_INVALID, ABILITY_SPELL_MASS_SLOW) == TRUE)
                        {
                            fManaMax = (100.0f + GetCreatureSpellPower(stEvent.oCaster)) * IMPROVED_DRAIN_MANA_FACTOR;

                            effect eEffect = EffectVisualEffect(IMPROVED_DRAIN_MANA_VFX);
                            ApplyEffectOnObject(EFFECT_DURATION_TYPE_INSTANT, eEffect, stEvent.oTarget, 0.0f, stEvent.oCaster, stEvent.nAbility);

                            // combo effect codex - improved drain
                            if (IsFollower(stEvent.oCaster) == TRUE)
                            {
                                WR_SetPlotFlag(PLT_COD_AOW_SPELLCOMBO6, COD_AOW_SPELLCOMBO_6_STEAM_CLOUD, TRUE);
                            }
                        }

                        fMana = MinF(fManaMax, fTargetMana);

                        if (IsMagicUser(stEvent.oTarget) == TRUE)
                        {
                            // mana loss
                            effect eEffect = EffectModifyManaStamina(fMana * -1.0f);
                            eEffect = SetEffectEngineInteger(eEffect, EFFECT_INTEGER_VFX, Ability_GetImpactObjectVfxId(stEvent.nAbility));
                            ApplyEffectOnObject(EFFECT_DURATION_TYPE_INSTANT, eEffect, stEvent.oTarget, 0.0f, stEvent.oCaster, stEvent.nAbility);
                        }

                        fMana = MinF(fManaMax, fTargetMana) + fManaSpell;

                        //Mana Clash effects
                        if (HasAbility(stEvent.oCaster, ABILITY_SPELL_MANA_CLASH) == TRUE)
                        {
                            effect eEffect = EffectDamage(fMana, DAMAGE_TYPE_SPIRIT, DAMAGE_EFFECT_FLAG_NONE, Ability_GetImpactObjectVfxId(stEvent.nAbility));
                            ApplyEffectOnObject(EFFECT_DURATION_TYPE_INSTANT, eEffect, stEvent.oTarget, 0.0f, stEvent.oCaster, stEvent.nAbility);
                        }

                        // create event
                        event ev = Event(90210);
                        ev = SetEventInteger(ev, 0, stEvent.nAbility);
                        ev = SetEventObject(ev, 0, stEvent.oCaster);
                        ev = SetEventObject(ev, 1, stEvent.oCaster);
                        ev = SetEventFloat(ev, 0, fMana);

                        // fire projectile
                        vector v = GetPosition(stEvent.oTarget);
                        v.z += 1.5f;
                        object oProjectile = FireHomingProjectile(DRAIN_MANA_PROJECTILE, v, stEvent.oCaster, 0,  stEvent.oCaster);
                        SetProjectileImpactEvent(oProjectile, ev);
                    }
                } else
                {
                    UI_DisplayMessage(stEvent.oTarget, UI_MESSAGE_RESISTED);
                }
            } else
            {
                UI_DisplayMessage(stEvent.oTarget, UI_MESSAGE_OUT_OF_MANA);
            }

            break;
        }

        case 90210:
        {
            // Get a structure with the event parameters
            struct EventSpellScriptImpactStruct stEvent = Events_GetEventSpellScriptImpactParameters(ev);

            // mana gain
            float fMana = GetEventFloat(ev, 0);
            effect eEffect = EffectModifyManaStamina(fMana);
            eEffect = SetEffectEngineInteger(eEffect, EFFECT_INTEGER_VFX, MANA_DRAIN_CASTER_VFX);
            ApplyEffectOnObject(EFFECT_DURATION_TYPE_INSTANT, eEffect, stEvent.oCaster, 0.0f, stEvent.oCaster, stEvent.nAbility);

            break;
        }
    }
}

So I have to add in the first loop as well, change DispelMagic back to RemoveEffect, add a counter after that, and replace the nSize multiplication with nCounter?
I'm a little confused on how the "loop" actually occurs, rather than the code just running once after I activate the spell and making the counter always return either 0 or 1.
If the loop does function in that code above then I assume using DispelMagic would likely stop it from passing through a second time :P

Modifié par Kesaru, 01 avril 2010 - 04:01 .


#8
TimelordDC

TimelordDC
  • Members
  • 923 messages

Craig Graff wrote...

TimelordDC wrote...
I don't understand why they have 2 loops since both accomplish the same thing.


Order is important because removing the upkeep effects triggers code in effect_upkeep_h, mostly to remove effects that are applied to the whole party or upkeep effects on the caster.

I thought about that but only went as far as spells/abilities requiring pre-requisite spells; never thought of effects. Thanks for clearing that up.

@Kesaru, at first glance, you need to include both loops if you want an accurate count and you have to use the counter.
Also, the current code won't work since the loop will run without doing anything and the rest of the code will work off the last Ability ID returned.
Instead, move the "if target is spellcaster" and spell-resistance checks before getting the effects and get the effects array only when the checks pass/fail (whichever is appropriate). After getting the array of effects, do the specific checks for ABILITY_TYPE_SPELL and caster having Mana Cleanse and make sure these checks are done within the for loop so that the code actually checks each Ability ID tied to an effect on the target.