-
Apprentice
How to create VFX with separated origin and instigator?
Hey,
First of all thanks to all the modders around here, I would not have gotten nearly as far with my little mod without the massive amount of ready-made script bits and discussion on these forums.
So I'm looking at the function Wld_PlayEffect, which takes a parameter often called originVob.
This parameter determines where the VFX originates and who instigated it. I don't know if the engine differentiates these two roles.
The first role is obvious and the second is important for the AI to notice that "ok, THAT guys VFX hit me".
I want to separate these two, to have the instigator still be the same originVob, but the origin of the effect something else.
Think of Circle 4 "Lightning" spell. You shoot a bolt out of your hand that brings down a lightning when it hits something. I want to remove that intermediary bolt and just bring down the lightning from the sky instantly.
I will try to explain it using some examples:
Code:
Wld_PlayEffect("someFX", target, target, 0, 100, DAM_MAGIC, FALSE);
- GOOD: Creates VFX around target.
- BAD: Hits the caster and AI doesn't know caster is responsible.
Code:
Wld_PlayEffect("someFX", caster, target, 0, 100, DAM_MAGIC, FALSE);
- GOOD: Does not hit the caster and AI responds correctly.
- BAD: Creates VFX around caster.
How can I combine the good bits from both of these examples? I thought of having some kind of invisible super fast projectile that creates the actual colliding VFX on a delay, but to be honest working with the visual effects of Gothic II is pretty much trial and error for me, even if I'm starting to understand it a little. I can't figure this one out...
Thanks in advance for any help.
-
25.09.2019 20:42
#2
Wld_PlayEffect("spellFX", oth, slf, 2, 100, DAM_MAGIC, FALSE);
-
One line answers are never really helpful. In fact, the only thing you seem to have changed is a parameter going from 0 to 2 and I'm not sure that even helps. If it does: Please explain the answer.
-
In GFA mud-freak does more or less the opposite of what you want:
https://github.com/szapp/GothicFreeA...n/spell.d#L286
(changes the target of the vfx, you want to change the origin)
There might be a suitable engine function you could call in an analogous way.
edit:
Or you send a damage perception when the spell triggers:
Code:
Wld_PlayEffect("someFX", target, target, 0, 100, DAM_MAGIC, FALSE); // vfx created at target
Npc_SendSinglePerc(caster, target, PERC_ASSESSDAMAGE); // make target react to damage from caster
NPC_SendPassivePerc(caster, PERC_ASSESSFIGHTSOUND, target, caster); // make onlookers react to fight caster <-> target
Geändert von Cryp18Struct (26.09.2019 um 00:55 Uhr)
-
Apprentice
One explanation for that parameter i found is the following:
effectLevel: If you specify effectLevel, it searches for a VisualFX instance called _L and uses it if it is
was found. (it still needs to have a VisualFX instance defined by name!)
Im not sure how that would help..?
The idea to send additional passive percs is great, ill have to look into that. It wont be quite that simple, since the vfx can hit multiple creatures, but i think i can maybe do it using the 'ondmg' hooks..
-
Apprentice
Well, for single target this works fine:
Code:
func void Spell_Cast_Focus(var C_NPC slf, var C_NPC oth, var int manaCost, var int spellDamage, var string spellFX)
{
Wld_PlayEffect(spellFX, oth, oth, 0, 0, 0, FALSE);
B_MagicHurtNpc(slf, oth, spellDamage);
if (oth.attribute[ATR_HITPOINTS] > 0)
{
Npc_SendSinglePerc(slf, oth, PERC_ASSESSDAMAGE);
NPC_SendPassivePerc(slf, PERC_ASSESSFIGHTSOUND, oth, slf);
}
else
{
Npc_SendPassivePerc (slf, PERC_ASSESSMURDER, oth, slf);
};
slf.attribute[ATR_MANA] -= manaCost;
slf.aivar[AIV_SelectSpell] += 1;
};
You can then just call this function from Spell_Cast_LightningFlash (or any other spell), while making sure the _KEY_CAST of that spells VFX doesn't additionally fire the regular projectile from the casters hand.
I couldn't figure out how to get similar functionality for spells that should hit multiple targets, but for now I can live with this. Thanks for the help!
-
Maybe give broadcasts a try:
https://forum.worldofplayers.de/foru...1#post17232705
You could check for all NPCs (in the active AI-Area[30m around hero]) if they are close enough to the primary target and then treat them.
-
Apprentice
So, this function has evolved quite a bit since the last post here. I have a bit of an interesting mystery for those interested, but first...
Here is the current version that I am quite happy with.
Damage is calculated and delivered OK and AI responds as expected.
(note: all spells in my mod deal magic type damage, but the function should be easy to adjust for other scenarios)
Code:
func void Spell_Cast_Focus(var C_NPC slf, var C_NPC oth, var int spellID, var int spellCat, var int spellDamage, var string spellFX)
{
// Backup self/other and reverse slf/oth in their place
var C_NPC selfTemp; selfTemp = Hlp_GetNpc (self);
var C_NPC otherTemp; otherTemp = Hlp_GetNpc (other);
self = Hlp_GetNpc(oth); other = Hlp_GetNpc(slf);
// Handle collision, if no collision restore backup self/other and return
var int coll; coll = C_CanNpcCollideWithSpell(spellID);
if (coll == COLL_DONOTHING)
{
self = Hlp_GetNpc(selfTemp); other = Hlp_GetNpc(otherTemp);
return;
};
// Collided, set last hit spell and assess magic
var oCNpc selfOC; selfOC = Hlp_GetNpc(self);
//Print(IntToString(selfOC.lastHitSpellID));
selfOC.lastHitSpellID = spellID;
selfOC.lastHitSpellCat = spellCat;
B_AssessMagic();
// Restore backup self/other, use slf/oth from now on
self = Hlp_GetNpc(selfTemp); other = Hlp_GetNpc(otherTemp);
// Calculate and apply damage
if (coll & COLL_APPLYDOUBLEDAMAGE) { spellDamage *= 2; };
if (coll & COLL_APPLYHALVEDAMAGE) { spellDamage /= 2; };
spellDamage -= oth.protection[PROT_MAGIC];
if (spellDamage > 0) { B_MagicHurtNpc(slf, oth, spellDamage); };
// Play vfx
Wld_PlayEffect(spellFX, oth, oth, 0, 0, 0, FALSE);
};
Now if you look closely there is a commented line in there:
Code:
Print(IntToString(selfOC.lastHitSpellID));
This prints the "last hit spell id" before I set it for the spell being "focus cast", which is necessary for B_AssessMagic. There is a strange behavior that I don't quite understand, and I'm just a bit concerned that it might have some side effects.
I use this method for SPL_LightningFlash, for instance (spell id 29).
I was testing with SPL_Firebolt (spell id 19), which is using the normal engine/vfx method of spell delivery (I haven't touched it).
In all tests I target an NPC that has not been hit by any spell.
If I cast spell 29 twice, I get printed -1 and 29. This seems OK, no spell hit the NPC before the first one and then its 29, as can be expected.
If I cast 19 followed with 29, I get printed -1. This could also be OK, makes me think that the engine clears the last hit spell ID at some point before the second spell hit the NPC. I could easily just clear the id that I set after calling B_AssessMagic in my function.
But before I did that I did additional test, and now comes the weird part.
If I cast 29 -> 19 -> 29, I get printed -1 and 29. No I'm lost!
If the engine clears the last hit spell ID after handling the spell 19... Why is the hit id 29 still there when I get to casting 29 again? If the engine clears the last hit spell id the expected prints would be -1 and -1.
Maybe I am missing something obvious, and maybe I am worrying over nothing... But if anyone can offer some insight into this that would be much appreciated!
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|