Aller au contenu

Photo

DelayEvent in Spellscript


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

#1
Anomaly-

Anomaly-
  • Members
  • 366 messages
Ok, so the concept behind this spell is that it deals physical damage for a while, then when that wears off it deals nature damage. Unfortunately, I have not been able to figure out how to make the latter happen. The closest I've come is using DelayEvent somehow, but I've really no idea how. The following code was a total shot in the dark and, as such, it doesn't work:

case EVENT_TYPE_SPELLSCRIPT_IMPACT:
        {
            struct EventSpellScriptImpactStruct stEvent = Events_GetEventSpellScriptImpactParameters(ev);

            if (CheckSpellResistance(stEvent.oTarget, stEvent.oCaster, stEvent.nAbility) == FALSE)
            {
                float fDamage = (50.0f + GetCreatureSpellPower(stEvent.oCaster)) * 4.0f;
                ApplyEffectDamageOverTime(stEvent.oTarget, stEvent.oCaster, stEvent.nAbility, fDamage, 15.0f, DAMAGE_TYPE_PHYSICAL, Ability_GetImpactObjectVfxId(stEvent.nAbility));
                effect eEffect = Effect(EFFECT_TYPE_DUMMY_HOSTILE);
                ApplyEffectOnObject(EFFECT_DURATION_TYPE_TEMPORARY, eEffect, stEvent.oTarget, 25.0f, stEvent.oCaster, stEvent.nAbility);
                DelayEvent(15.0f, stEvent.oTarget, Event(EVENT_TYPE_SPELLSCRIPT_AFTER_EFFECTS), "spell_infestation.ncs");
            } else
            {
                UI_DisplayMessage(stEvent.oTarget, UI_MESSAGE_RESISTED);
            }

            break;
        }
case EVENT_TYPE_SPELLSCRIPT_AFTER_EFFECTS:
        {
            struct EventSpellScriptAfterEffectsStruct stEvent = Events_GetEventSpellScriptAfterEffectsParameters(ev);

            float fDamage = (50.0f + GetCreatureSpellPower(stEvent.oCaster)) * 4.0f;
            ApplyEffectDamageOverTime(stEvent.oTarget, stEvent.oCaster, stEvent.nAbility, fDamage, 10.0f, DAMAGE_TYPE_NATURE);

            break;
        }

So basically, I made a new event type called EVENT_TYPE_SPELLSCRIPT_AFTER_EFFECTS, and used DelayEvent from within EVENT_TYPE_SPELLSCRIPT_IMPACT to call it. However, the nature damage never takes effect.  Any help would be greatly appreciated. Thanks in advance.

Modifié par Anomaly-, 13 janvier 2011 - 09:49 .


#2
Proleric

Proleric
  • Members
  • 2 355 messages
AFAIK the second event won't automatically inherit the first event's parameters, so the contents of stEvent may be invalid.

You might need to use SetEventCreator and SetEventInteger to store the spellcaster and ability respectively on the new event before the DelayEvent, then use the corresponding Get functions in ApplyEffectDamageOverTime.

Easily verified by displaying a message in the second event to show the event creator and ability values from stEvent.

#3
Anomaly-

Anomaly-
  • Members
  • 366 messages

Proleric1 wrote...

AFAIK the second event won't automatically inherit the first event's parameters, so the contents of stEvent may be invalid.

You might need to use SetEventCreator and SetEventInteger to store the spellcaster and ability respectively on the new event before the DelayEvent, then use the corresponding Get functions in ApplyEffectDamageOverTime.

Easily verified by displaying a message in the second event to show the event creator and ability values from stEvent.


Thanks for the reply. Sorry, I should have specified that I essentially duplicated every instance of EVENT_TYPE_SPELLSCRIPT_IMPACT for EVENT_TYPE_SPELLSCRIPT_AFTEREFFECTS in events_h. The script I showed was all contained in the custom spell script. Anyway, I'll fool around a bit more and see what I can find. I've just never played with events before, so I don't really know how they or DelayEvent work.

Edit: I've added a ui message right at the very beginning of the new event, and it is not appearing ingame. This leads me to believe that the event is never being triggered. Is there anything else I need to do to make a new event work? All I've done is duplicate the entries for EVENT_TYPE_SPELLSCRIPT_IMPACT in events_h, and add an entry in for it in engineevents.gda. Is there something I'm missing? I notice that ability_core seems to handle these events, but I haven't added anything there for my custom event. I really don't know how events work <_<.

Modifié par Anomaly-, 15 janvier 2011 - 02:07 .


#4
Proleric

Proleric
  • Members
  • 2 355 messages
Doh! Sorry, I just realised that you have .ncs in the script name in DelayEvent. You just need "spell_infestation".

In general, the extension is always omitted from resource names unless the function parameter specifies Resource format (R"spell_infestation.ncs").

If you correct the syntax, you should find that the script executes. The event scripts specified as default in the 2DA and on the resource template are simply ignored if the script parameter is specified on DelayEvent.

Previous comment still stands.

#5
Anomaly-

Anomaly-
  • Members
  • 366 messages
Nah, even with that correction I still don't see the ui message. Does it matter that its all within the same script? ie: SPELLSCRIPT_IMPACT, which calls the DelayEvent pointing to "spell_infestation"; and SPELLSCRIPT_AFTER_EFFECTS itself are all within spell_infestation?

#6
Proleric

Proleric
  • Members
  • 2 355 messages
It's normal practice to centralise cases for related events in one script, as you have done.

Are you certain that the first event is firing?

Have you used a unique event number for the second event?

If that doesn't help, as a temporary measure you could make a standalone script for the second event that executes unconditionally (i.e. no case statement). Then, in DelayEvent, specify Event(EVENT_TYPE_INVALID) and the standalone script. I've found that always works. I'd be interested to know the outcome.

#7
Anomaly-

Anomaly-
  • Members
  • 366 messages

Proleric1 wrote...

It's normal practice to centralise cases for related events in one script, as you have done.

Are you certain that the first event is firing?


Yeah, the ui message I put in the first event was displaying, and the damage was applying from there, as well.

Have you used a unique event number for the second event?


Yep.

If that doesn't help, as a temporary measure you could make a standalone script for the second event that executes unconditionally (i.e. no case statement). Then, in DelayEvent, specify Event(EVENT_TYPE_INVALID) and the standalone script. I've found that always works. I'd be interested to know the outcome.


I tried this and at first it didn't work, but after playing around with it I managed to get it to work. For some reason, it would not recognize Target and Caster using GetEventObject or nAbility using GetEventInteger. Instead, I had to use GetEventCreator and GetEventTarget, and hard-code the id of the ability. Not sure why. Anyway, the final code for the standalone script looks like this:
void main()
{
    event ev = GetCurrentEvent();
    int nEventType = GetEventType(ev);
    struct EventSpellScriptAfterEffectsStruct stEvent = Events_GetEventSpellScriptAfterEffectsParameters(ev);
    object oCaster = GetEventCreator(ev);
    object oTarget = GetEventTarget(ev);
    //int nAbility = GetEventInteger(ev, 0);

    float fDamage = (50.0f + GetCreatureSpellPower(oCaster)) * 1.5f;
    ApplyEffectDamageOverTime(oTarget, oCaster, ABILITY_SPELL_INFESTATION, fDamage, 10.0f, DAMAGE_TYPE_NATURE);
}

Thanks again for the help. Now on to the next dilemma...

Modifié par Anomaly-, 17 janvier 2011 - 11:40 .


#8
Proleric

Proleric
  • Members
  • 2 355 messages
Glad it works now.

I suspect the ability issue is that event properties are not inherited when one event triggers another. In particular, you can't use Events_GetEventSpellScriptImpactParameters for the second event without defining them first.

To work around this,

                event evEvent2 = Event(EVENT_TYPE_SPELLSCRIPT_AFTER_EFFECTS);
                SetEventInteger(evEvent2, 0, stEvent.nAbility);
                DelayEvent(15.0f, stEvent.oTarget, evEvent2, "spell_infestation");


You could then use GetEventInteger in the second script to obtain the ability.

Since the standalone script now works, have you tried using the same code as a case in the original script? It would be useful to know if there's an issue with that.

#9
Anomaly-

Anomaly-
  • Members
  • 366 messages

Proleric1 wrote...

To work around this,

                event evEvent2 = Event(EVENT_TYPE_SPELLSCRIPT_AFTER_EFFECTS);
                SetEventInteger(evEvent2, 0, stEvent.nAbility);
                DelayEvent(15.0f, stEvent.oTarget, evEvent2, "spell_infestation");


You could then use GetEventInteger in the second script to obtain the ability.

Since the standalone script now works, have you tried using the same code as a case in the original script? It would be useful to know if there's an issue with that.


I'm not sure how thats supposed to work. Where do I declare those? They have to be outside of the case statements, because they need to be recognized by both the Impact Event to delay them, as well as the After Effects Event in order to handle them, but if I declare outside of the case statements, it says variable defined without type because of stEvent.nAbility.

#10
Proleric

Proleric
  • Members
  • 2 355 messages
The snippet is intended to go in the first case.

When the script is called for the second event, the current event will be ev, not evEvent2.

If you prefer to declare everything at the start of the script, you can declate evEvent2 without an initial value, but you need to assign it in the first case.

#11
Anomaly-

Anomaly-
  • Members
  • 366 messages

Proleric1 wrote...

The snippet is intended to go in the first case.

When the script is called for the second event, the current event will be ev, not evEvent2.

If you prefer to declare everything at the start of the script, you can declate evEvent2 without an initial value, but you need to assign it in the first case.


Thanks for clearing that up. Now that I've tried it, though, same problem. I still have to use GetEventCreator and GetEventTarget, and hard-code the ability. I now know why I wasn't seeing the ui message before though, it's because I was applying it to stEvent.oCaster, which I had defined with GetEventObject. Weird.

#12
Proleric

Proleric
  • Members
  • 2 355 messages
Events_GetEventSpellScriptAfterEffectsParameters won't work for every event (only those which have been through the full gamut of spell processing). All your second event can refer to are the parameters you set in the first event.

However, SetEventInteger and GetEventInteger should pass the ability. If that part's not working, you might like to post your script.

#13
Anomaly-

Anomaly-
  • Members
  • 366 messages
case EVENT_TYPE_SPELLSCRIPT_IMPACT:
{
     struct EventSpellScriptImpactStruct stEvent = Events_GetEventSpellScriptImpactParameters(ev);
     event evEvent2 = Event(EVENT_TYPE_SPELLSCRIPT_AFTER_EFFECTS);
     SetEventInteger(evEvent2, 0, stEvent.nAbility);

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

     if (CheckSpellResistance(stEvent.oTarget, stEvent.oCaster, stEvent.nAbility) == FALSE)
     {
         float fDamage = (50.0f + GetCreatureSpellPower(stEvent.oCaster)) * 1.5f;
         ApplyEffectDamageOverTime(stEvent.oTarget, stEvent.oCaster, stEvent.nAbility, fDamage, 15.0f,           DAMAGE_TYPE_PHYSICAL, Ability_GetImpactObjectVfxId(stEvent.nAbility));
         effect eEffect = Effect(EFFECT_TYPE_DUMMY_HOSTILE);
         ApplyEffectOnObject(EFFECT_DURATION_TYPE_TEMPORARY, eEffect, stEvent.oTarget, 27.0f, stEvent.oCaster, stEvent.nAbility);
         DelayEvent(16.0f, stEvent.oTarget, evEvent2, "spell_infestation");
    } else
    {
          UI_DisplayMessage(stEvent.oTarget, UI_MESSAGE_RESISTED);
    }

     break;
}
case EVENT_TYPE_SPELLSCRIPT_AFTER_EFFECTS:
{
     struct EventSpellScriptAfterEffectsStruct stEvent = Events_GetEventSpellScriptAfterEffectsParameters(ev);

     object oCaster = GetEventCreator(ev);
     object oTarget = GetEventTarget(ev);
     int nAbility = GetEventInteger(ev, 0);
     UI_DisplayMessage(oCaster, UI_MESSAGE_BACKSTAB);

     float fDamage = (50.0f + GetCreatureSpellPower(oCaster)) * 1.5f;
     ApplyEffectDamageOverTime(oTarget, oCaster, nAbility, fDamage, 10.5f, DAMAGE_TYPE_NATURE);

     break;
}

Modifié par Anomaly-, 21 janvier 2011 - 11:45 .


#14
Proleric

Proleric
  • Members
  • 2 355 messages
Hm... that looks about right. Have you confirmed that stEvent.nAbility contains the correct value in the first event?

#15
Anomaly-

Anomaly-
  • Members
  • 366 messages

Proleric1 wrote...

Hm... that looks about right. Have you confirmed that stEvent.nAbility contains the correct value in the first event?


Yes, otherwise the damage over time effect in the first event wouldn't apply.

#16
Proleric

Proleric
  • Members
  • 2 355 messages
Try this:

evEvent2 = SetEventInteger(evEvent2, 0, stEvent.nAbility);

#17
Anomaly-

Anomaly-
  • Members
  • 366 messages

Proleric1 wrote...

Try this:

evEvent2 = SetEventInteger(evEvent2, 0, stEvent.nAbility);


Haha.

Yeah, that works. Don't know why I didn't try that before. Anyway thanks again, you've been most helpful.