native UnitAlive takes unit id returns boolean
//! zinc
library ArtisticMind requires Missile, TimedUnitScale, TimerUtils, GroupTools, StunEngine {
constant real GROW_TIME = 1;
constant real CAST_TIME = 1;
constant integer SPELL_ID = 'A003';
constant string GROUND_FX = "Aphs Cast Effect.mdx";
constant string MANIFEST_SPAWN_EFFECT = "Aphs Normal Effect.mdx";
constant string MANIFEST_SPAWN_MISSILE = "Aphs Link Effect.mdx";
constant real MANIFEST_COLOR = 80;
constant real MANIFEST_SHRINK = 10;
constant real MANIFEST_DURATION = 10;
constant real MANIFEST_DURATION_INC = 2;
integer lvl;
hashtable hash = InitHashtable();
group g;
private function stun(unit u, real dur) {
udg_STE_TARGET = u;
udg_STE_DURATION = dur;
udg_STE_STACK_TIME = true;
udg_STE_ADD_STUN = true;
TriggerEvaluate(udg_STE_TRIGGER);
}
private function getDuration(integer level) -> real {
return 10 + (level * MANIFEST_DURATION_INC);
}
private struct Spawn {
static method onFinish (Missile missile) -> boolean {
timer t;
integer h;
integer level = LoadInteger(hash, missile, 0);
unit target = LoadUnitHandle(hash, missile, 1);
integer id = GetUnitTypeId(target);
unit u = CreateUnit(Player(13), id, missile.x, missile.y, missile.angle);
DestroyEffect(AddSpecialEffect(MANIFEST_SPAWN_EFFECT, GetUnitX(u), GetUnitY(u)));
stun(u, GROW_TIME);
SetUnitInvulnerable(u, true);
SetUnitVertexColorBJ(u, MANIFEST_COLOR, MANIFEST_COLOR, MANIFEST_COLOR, 60);
SetUnitScalePercent(u, MANIFEST_SHRINK, MANIFEST_SHRINK, MANIFEST_SHRINK);
UnitScale[u].apply(1, GROW_TIME);
t = NewTimer();
h = GetHandleId(t);
SaveBoolean(hash, GetHandleId(u), 1, true);
SaveUnitHandle(hash, h, 0, u);
SaveUnitHandle(hash, h, 1, target);
SaveInteger(hash, h, 2, level);
TimerStart(t, GROW_TIME, false, function() {
timer t = GetExpiredTimer();
integer id = GetHandleId(t);
unit u = LoadUnitHandle(hash, id, 0);
unit origin = LoadUnitHandle(hash, id, 1);
integer level = LoadInteger(hash, id, 2);
IssueTargetOrder(u, "attack", origin);
SetUnitInvulnerable(u, false);
UnitApplyTimedLife(u, 'BTLF', getDuration(level));
FlushChildHashtable(hash, id);
ReleaseTimer(t);
SaveUnitHandle(hash, GetHandleId(u), 0, origin);
t = null;
u = null;
origin = null;
});
FlushChildHashtable(hash, missile);
u = null;
target = null;
t = null;
return true;
}
module MissileStruct;
}
private function groupLoop() {
unit u = GetEnumUnit();
real x = GetUnitX(u);
real y = GetUnitY(u);
Missile m = Missile.create(x, y, 75, GetRandomReal(0, 360), 400, 50);
SaveInteger(hash, m, 0, lvl);
SaveUnitHandle(hash, m, 1, u);
m.speed = 10.;
m.model = MANIFEST_SPAWN_MISSILE;
m.arc = bj_PI/4;
Spawn.launch(m);
u = null;
}
private function isManifestation(unit u) -> boolean{
return LoadBoolean(hash, GetHandleId(u), 1);
}
private function onCastFilter(unit u, player p) -> boolean {
return UnitAlive(u) && !isManifestation(u) && IsUnitEnemy(u, p);
}
private function onDelay() {
timer t = GetExpiredTimer();
integer h = GetHandleId(t);
real x = LoadReal(hash, h, 1);
real y = LoadReal(hash, h, 2);
unit u = LoadUnitHandle(hash, h, 0);
DestroyEffect(LoadEffectHandle(hash, h, 3));
FlushChildHashtable(hash, h);
ReleaseTimer(t);
t = null;
g = NewGroup();
GroupUnitsInArea(g, x, y, 300);
h = GetHandleId(g);
SavePlayerHandle(hash, h, 0, GetOwningPlayer(u));
ForGroup(g, function () {
unit u = GetEnumUnit();
player p = LoadPlayerHandle(hash, GetHandleId(g), 0);
if(!onCastFilter(u, p)) {
GroupRemoveUnit(g, u);
}
p = null;
u = null;
});
FlushChildHashtable(hash, h);
lvl = GetUnitAbilityLevel(u, SPELL_ID);
ForGroup(g, function groupLoop);
ReleaseGroup(g);
}
private function onCast() {
real x = GetSpellTargetX();
real y = GetSpellTargetY();
unit u = GetSpellAbilityUnit();
timer t = NewTimer();
integer h = GetHandleId(t);
SaveEffectHandle(hash, h, 3, AddSpecialEffect(GROUND_FX, x, y));
SaveUnitHandle(hash, h, 0, u);
SaveReal(hash, h, 1, x);
SaveReal(hash, h, 2, y);
TimerStart(t, CAST_TIME, false, function onDelay);
u = null;
t = null;
}
private function filter() -> boolean{
return GetSpellAbilityId() == SPELL_ID;
}
private function isSet(unit u) -> boolean {
return u != null;
}
private function onDamage() {
unit origin = LoadUnitHandle(hash, GetHandleId(udg_DamageEventSource), 0);
if (origin != udg_DamageEventTarget && isSet(origin)) {
udg_DamageEventAmount = 0.00;
}
origin = null;
}
private function onDeathFilter() -> boolean{
return isManifestation(GetFilterUnit());
}
private function onDeath() {
FlushChildHashtable(hash, GetHandleId(GetTriggerUnit()));
}
private function onInit() {
trigger t = CreateTrigger();
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
TriggerAddCondition(t, Condition(function filter));
TriggerAddAction(t, function onCast);
t = CreateTrigger();
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH);
TriggerAddCondition(t, Condition(function onDeathFilter));
TriggerAddAction(t, function onDeath);
t = CreateTrigger();
TriggerRegisterVariableEvent(t, "udg_DamageModifierEvent", EQUAL, 1.00);
TriggerAddAction(t, function onDamage);
t = null;
}
}
//! endzinc