- Joined
- Jul 19, 2007
- Messages
- 824
I have imported a spell from a spellpack that has 3 levels and it seems to work like it should in level 1 but when using this spell in level 2 and 3, the special effect created on affected units doesn't seems to be gone, it only removes the special effect from the caster and that's very strange. Anyone knows what's the cause of this? Pls try help. I love this spell and I don't want to remove it from my map just because of the bug 
JASS:
//TESH.scrollpos=30
//TESH.alwaysfold=0
/*
**********************************************************************************************************
Installation:
1) Copy this trigger and 'DD Library' to your map
2) Copy Nature Blessing abilitie to your map
3) Export and Import 'GaiaShield.mdx', 'GaiaMissile.mdx', 'NatureExplosion.mdx' sound from this map to yours
4) Modify constants to your liking below
5) Made on Warcraft III v1.30
**********************************************************************************************************
*/
//! zinc
library NatureBlessing requires DDLib
{
// This is the main raw code of ability Nature Blessing
// Default: 'Nbls'
constant integer NATURE_BLESSING = 'A0FX';
// Natures shield effect model path
// Default: "Spells\\NatureBlessing\\GaiaShield.mdx"
constant string NATURE_SHIELD_EFFECT = "Spells\\NatureBlessing\\GaiaShield.mdx";
// Natures missile effect model path
// Default: "Spells\\NatureBlessing\\GaiaMissle.mdx"
constant string NATURE_MISSILE_EFFECT = "Spells\\NatureBlessing\\GaiaMissle.mdx";
// Natures explosion model effect path
// Default: "Spells\\NatureBlessing\\NatureExplosion.mdx"
constant string NATURE_EXPLOSION_EFFECT = "Spells\\NatureBlessing\\NatureExplosion.mdl";
// Natures missile fire sound path (this sound is played when missiles start to move)
// Default: "Abilities\\Spells\\NightElf\\Tranquility\\TranquilityTarget1.wav"
constant string NATURE_SHOOT_SOUND = "Abilities\\Spells\\NightElf\\Tranquility\\TranquilityTarget1.wav";
constant real NATURE_SHOOT_SOUND_VOL = 100.;
constant real NATURE_SHOOT_SOUND_PITCH = 1.5;
constant real NATURE_SHOOT_SOUND_MAX_DISTANCE = 3500.;
// Nature explosion sound file path (is played when nature explosion is caused)
// Default: "Abilities\\Spells\\NightElf\\Tranquility\\Tranquility.wav"
constant string NATURE_EXPLOSION_SOUND = "Abilities\\Spells\\NightElf\\Tranquility\\Tranquility.wav";
constant real NATURE_EXPLOSION_SOUND_VOL = 90.;
// This is number of nature missiles created
// Default: 12
constant integer MISSILES_COUNT = 12;
// Default: 1.2
constant real MISSILE_SIZE = 1.2;
// This is min and max distance from caster to missiles start point
// Default: 400 / 600
constant real MISSILE_MIN_DISTANCE = 400.;
constant real MISSILE_MAX_DISTANCE = 600.;
// This is min and max finish height / caster position of missiles
// Default: 75 / 400
constant real MISSILE_MIN_HEIGHT = 40.;
constant real MISSILE_MAX_HEIGHT = 400.;
// This is missiles value which tells how much time they need to reach caster and how long it takse for them to manifest
// Default: 0.75 / 0.5
constant real MISSILE_TRAVEL_TIME = .9;
constant real MISSILE_BIRTH_TIME = 0.5;
// Default: 50
constant real MISSILE_INITIAL_HEIGHT = 10.;
// Default: 0.2 seconds
constant real HEAL_INTERVAL = .2;
// --------------------------------------------------------------
// *** Do not edit level variables here edit them below ***
real EXPLOSION_AOE[];
real SHIELD_PROTECT[];
real HEAL_PERC_AMOUNT[];
real SPELL_DURATION[];
// -----------------------------------------------------------------
// *** Edit level data here ***
function NatureBlessingLevelSetup() {
// This is AOE of explosion "effect"
// Default: 410 / 530 / 650
EXPLOSION_AOE[01] = 550.;
EXPLOSION_AOE[02] = 550.;
EXPLOSION_AOE[03] = 550.;
// Shield protection is amount of damage reduced in percentage
// Default: 15 / 25 / 35
SHIELD_PROTECT[01] = 20.;
SHIELD_PROTECT[02] = 30.;
SHIELD_PROTECT[03] = 40.;
// This is heal amount in percentage per point of life missing
// Default: 5 / 7 / 9
HEAL_PERC_AMOUNT[01] = 5.;
HEAL_PERC_AMOUNT[02] = 7.;
HEAL_PERC_AMOUNT[03] = 9.;
// This is how long spell lasts in seconds
// Default: 10 / 10 / 10
SPELL_DURATION[01] = 10.;
SPELL_DURATION[02] = 10.;
SPELL_DURATION[03] = 10.;
}
function PickUnitsFilter(unit f, player owner) -> boolean {
return IsUnitAlly(f, owner) &&
!IsUnitType(f, UNIT_TYPE_DEAD) &&
!IsUnitType(f, UNIT_TYPE_STRUCTURE) &&
!BlzIsUnitInvulnerable(f) &&
!DDIsUnitWard(f) &&
!IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE) &&
!IsUnitType(f, UNIT_TYPE_MECHANICAL);
}
// #####################################################################################
// #####################################################################################
timer Tim = null;
group Grp = null;
struct unitdata {
real dur, heal, shield;
effect e;
static thistype Att[];
}
struct missiles {
ddeffect m[MISSILES_COUNT];
p_real pos[MISSILES_COUNT];
p_real spd[MISSILES_COUNT];
integer cnt;
real X, Y;
player owner;
integer lvl;
static method create(unit c) -> thistype {
thistype this = allocate();
integer i;
real x = GetWidgetX(c), y = GetWidgetY(c);
real rad = 0., d;
X = x; Y = y;
owner = GetOwningPlayer(c);
lvl = GetUnitAbilityLevel(c, NATURE_BLESSING);
cnt = R2I((MISSILE_TRAVEL_TIME-.1) / DD_INTERVAL);
for(i=00; i < MISSILES_COUNT; i+=01) {
rad += bj_PI/6.;
d = GetRandomReal(MISSILE_MIN_DISTANCE, MISSILE_MAX_DISTANCE);
pos[i] = pVector(x + d * Cos(rad), y + d * Sin(rad), MISSILE_INITIAL_HEIGHT);
spd[i] = pVector(-Cos(rad) * DD_INTERVAL * d / MISSILE_TRAVEL_TIME,
-Sin(rad) * DD_INTERVAL * d / MISSILE_TRAVEL_TIME,
DD_INTERVAL * (GetRandomReal(MISSILE_MIN_HEIGHT, MISSILE_MAX_HEIGHT)-MISSILE_INITIAL_HEIGHT) / MISSILE_TRAVEL_TIME);
m[i] = ddeffect.createZ(NATURE_MISSILE_EFFECT, pos[i][00], pos[i][01], pos[i][02] + DDTerrZ(pos[i][00], pos[i][01]), rad, MISSILE_SIZE);
}
return this;
}
method destroy() {
integer i;
for(i=00; i < MISSILES_COUNT; i+=01) {
m[i].destroy();
pos[i].destroy();
spd[i].destroy();
}
deallocate();
}
method Step() -> boolean {
integer i;
for(i=00; i < MISSILES_COUNT; i+=01) {
pos[i][00] += spd[i][00];
pos[i][01] += spd[i][01];
pos[i][02] += spd[i][02];
m[i].PositionZ(pos[i][00], pos[i][01], pos[i][02]);
//m[i].Y = pos[i][01];
//m[i].Z = pos[i][02];
}
cnt -= 01;
return (cnt == 00);
}
}
// ==========================================================================================
function onInit() {
trigger t = CreateTrigger();
Grp = CreateGroup();
NatureBlessingLevelSetup();
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
TriggerAddCondition(t, Condition(function() -> boolean {
missiles ms;
unit u;
if (GetSpellAbilityId() != NATURE_BLESSING)
return false;
u = GetTriggerUnit();
ms = missiles.create(u);
// Play sound and shake camera for players within spell cast range
DDGenericSound(NATURE_SHOOT_SOUND, NATURE_SHOOT_SOUND_VOL, GetWidgetX(u), GetWidgetY(u), NATURE_SHOOT_SOUND_MAX_DISTANCE, NATURE_SHOOT_SOUND_PITCH);
DDStartTim(MISSILE_BIRTH_TIME, false, ms, function() {
DDStartTim(DD_INTERVAL, true, DDTimData(), function() {
missiles ms = DDTimData();
trigger t;
if (ms.Step()) {
DDGenericSound(NATURE_EXPLOSION_SOUND, NATURE_EXPLOSION_SOUND_VOL, ms.X, ms.Y, NATURE_SHOOT_SOUND_MAX_DISTANCE, 1.8);
ddeffect.create(NATURE_EXPLOSION_EFFECT, ms.X, ms.Y, GetRandomReal(0., bj_PI*2.), EXPLOSION_AOE[ms.lvl]/250.).destroyx(3.);
DDGroupFilterArea(ms.X, ms.Y, EXPLOSION_AOE[ms.lvl], ms, function() -> boolean {
unitdata ud;
missiles ms = DDGFilterData();
unit f = GetFilterUnit();
if (PickUnitsFilter(f, ms.owner)) {
if (ud.Att[GetHandleId(f)-0x100000] == p_null) {
ud = unitdata.create();
ud.Att[GetHandleId(f)-0x100000] = ud;
ud.e = AddSpecialEffectTarget(NATURE_SHIELD_EFFECT, f, "origin");
GroupAddUnit(Grp, f);
} else
ud = ud.Att[GetHandleId(f)-0x100000];
ud.heal = HEAL_PERC_AMOUNT[ms.lvl] / 100.;
ud.shield = SHIELD_PROTECT[ms.lvl] / 100.;
ud.dur = SPELL_DURATION[ms.lvl];
}
f = null;
return false;
});
if (Tim == null) {
Tim = DDLoadTim();
TimerStart(Tim, HEAL_INTERVAL, true, function() {
ForGroup(Grp, function() {
unit e = GetEnumUnit();
unitdata ud = unitdata.Att[GetHandleId(e)-0x100000];
SetWidgetLife( e, GetWidgetLife(e) + (HEAL_INTERVAL * ud.heal * (GetUnitState(e, UNIT_STATE_MAX_LIFE)-GetWidgetLife(e))) );
ud.dur -= .2;
if (ud.dur < 0. || IsUnitType(e, UNIT_TYPE_DEAD)) {
GroupRemoveUnit(Grp, e);
ud.Att[GetHandleId(e)-0x100000] = p_null;
DestroyEffect(ud.e);
ud.e = null;
ud.destroy();
if (FirstOfGroup(Grp) == null) {
DDRecycleTim(Tim);
Tim = null;
}
}
e = null;
});
});
}
ms.destroy();
DDQuitTim();
}
});
DDQuitTim();
});
u = null;
return false;
}));
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
t = CreateTrigger();
DDTriggerRegisterAnyUnitDamaged(t);
TriggerAddCondition(t, Condition(function() -> boolean {
unit u = GetTriggerUnit();
unitdata ud = unitdata.Att[GetHandleId(u)-0x100000];
if (ud == p_null) {
u = null;
return false;
}
SetWidgetLife(u, GetWidgetLife(u) + (GetEventDamage() * ud.shield));
u = null;
return false;
}));
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
//! endzinc