• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Spell] Zinc Ability

Level 14
Joined
Jan 24, 2017
Messages
280
I have this Zinc Ability in my map that uses a custom missile system. It shoots a missile, which when hit slows the targets in an aoe and makes them take more damage. I just found out it only works on the main target. The slow works on all targets, because that is not triggered. I cant make the Hit function take all enemies units in the area, because of my very limited zinc knowledge. I would really appreciate if someone could change it so the damage amplification is applied to all enemies in a range of 300+20*level.

Code:
//! zinc

library GanjaGanja requires Missile {


// The effect to be used by the missile
// ------------------------------------
constant string FX_PATH = "GanjaSmoke.mdx";


// The ability-code that triggers the spell
// ----------------------------------------
function Conditions() -> boolean {
    return GetSpellAbilityId() == 'A0AD';
}

// Abiliy and buff codes
// ---------------------------------------
constant integer CASTER_ABILITY = 'A0AD';
constant integer DUMMY_ABILITY = 'A0IU';
constant integer DUMMY_ABILITY_BUFF = 'B023';
constant integer NEGATIVE_RESISTANCE = 'A0K4';

group affectedUnits;
timer loopTimer;
boolean loopIsRunning = false;

struct GGData {
    unit caster;
    integer abilityLevel;
    method onDestroy() {
        caster = null;
    }
}

function LoopPerUnit() {

    unit u = GetEnumUnit();
    boolean hasBuff = (GetUnitAbilityLevel(u, DUMMY_ABILITY_BUFF) > 0);
    //BJDebugMsg("LoopPerUnitTrue");
    if(hasBuff == false) {
        GroupRemoveUnit(affectedUnits, u);
        UnitRemoveAbility(u, NEGATIVE_RESISTANCE);
        //BJDebugMsg("LoopPerUnitFalse");
    }

    u = null;
}

function Loop() {

    boolean groupHasUnits = (FirstOfGroup(affectedUnits) != null);
    ForGroup(affectedUnits, function LoopPerUnit);
    //BJDebugMsg("LoopRun");
    if(groupHasUnits == false) {
        PauseTimer(GetExpiredTimer());
        loopIsRunning = false;
        //BJDebugMsg("LoopStop");
    }
}

function Hit(unit target, GGData data) {

    unit dummyCaster = CreateUnit(GetOwningPlayer(data.caster), 'h03N', GetUnitX(target),GetUnitY(target), 0.0);
    UnitAddAbility(dummyCaster, DUMMY_ABILITY);
    SetUnitAbilityLevel(dummyCaster, DUMMY_ABILITY, data.abilityLevel);
    IssueTargetOrder(dummyCaster, "drunkenhaze", target);
    UnitDamageTargetBJ( data.caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC );
    UnitApplyTimedLifeBJ( 1.0, 'BTLF', dummyCaster);
    UnitAddAbility(target, NEGATIVE_RESISTANCE);

    GroupAddUnit(affectedUnits, target);

    //BJDebugMsg("HitFuckYou");
    if(!loopIsRunning)
    {
        TimerStart(loopTimer, 0.3, true, function Loop);
        loopIsRunning = true;
        //BJDebugMsg("HitLoopStart");
    }

    data.destroy();
    dummyCaster = null;
}

function Actions() {
    GGData data = GGData.create();
    Dummy dummy;

    data.caster = GetTriggerUnit();
    data.abilityLevel = GetUnitAbilityLevel(data.caster, CASTER_ABILITY);

    dummy = DummyBuilder
        .create(GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), FX_PATH)
        .scale(1.0)
        .height(32.0)
        .facingPoint(GetUnitX(GetSpellTargetUnit()), GetUnitY(GetSpellTargetUnit()))
        .createDummy();

    Missile.create(dummy)
        .constantSpeed(1200.0)
        .collisionSize(16.0)
        .targetUnit(GetSpellTargetUnit(), Hit)
        .setData(data)
        .go();
}

function onInit() {

    trigger trg = CreateTrigger();
    TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_SPELL_EFFECT );
    TriggerAddCondition( trg, Condition( function Conditions ) );
    TriggerAddAction( trg, function Actions );

    loopTimer = CreateTimer();
    affectedUnits = CreateGroup();
}

}

//! endzinc
 
I don't have JNGP running, so this code likely contains some syntax errors--but essentially you'll want to enumerate the units in range and add them to the group "affectedUnits". Just note that the code seems to rely on them having the slow debuff in order for them to have the NEGATIVE_RESISTANCE debuff, so you'll want to make sure the range of your drunkenhaze dummy ability matches up with the (300 + 20*level) that you described.

Here is roughly what the code looked like--I can't quite remember the Zinc syntax but it should look roughly like this (see the part after // Apply debuff to units in range):
JASS:
//! zinc

library GanjaGanja requires Missile {


// The effect to be used by the missile
// ------------------------------------
constant string FX_PATH = "GanjaSmoke.mdx";


// The ability-code that triggers the spell
// ----------------------------------------
function Conditions() -> boolean {
    return GetSpellAbilityId() == 'A0AD';
}

// Abiliy and buff codes
// ---------------------------------------
constant integer CASTER_ABILITY = 'A0AD';
constant integer DUMMY_ABILITY = 'A0IU';
constant integer DUMMY_ABILITY_BUFF = 'B023';
constant integer NEGATIVE_RESISTANCE = 'A0K4';

group affectedUnits;
group aoeUnits;
timer loopTimer;
boolean loopIsRunning = false;

struct GGData {
    unit caster;
    integer abilityLevel;
    method onDestroy() {
        caster = null;
    }
}

function LoopPerUnit() {

    unit u = GetEnumUnit();
    boolean hasBuff = (GetUnitAbilityLevel(u, DUMMY_ABILITY_BUFF) > 0);
    //BJDebugMsg("LoopPerUnitTrue");
    if(hasBuff == false) {
        GroupRemoveUnit(affectedUnits, u);
        UnitRemoveAbility(u, NEGATIVE_RESISTANCE);
        //BJDebugMsg("LoopPerUnitFalse");
    }

    u = null;
}

function Loop() {

    boolean groupHasUnits = (FirstOfGroup(affectedUnits) != null);
    ForGroup(affectedUnits, function LoopPerUnit);
    //BJDebugMsg("LoopRun");
    if(groupHasUnits == false) {
        PauseTimer(GetExpiredTimer());
        loopIsRunning = false;
        //BJDebugMsg("LoopStop");
    }
}

function Hit(unit target, GGData data) {

    unit enumUnit = null;
    unit dummyCaster = CreateUnit(GetOwningPlayer(data.caster), 'h03N', GetUnitX(target),GetUnitY(target), 0.0);
    UnitAddAbility(dummyCaster, DUMMY_ABILITY);
    SetUnitAbilityLevel(dummyCaster, DUMMY_ABILITY, data.abilityLevel);
    IssueTargetOrder(dummyCaster, "drunkenhaze", target);
    UnitDamageTargetBJ( data.caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC );
    UnitApplyTimedLifeBJ( 1.0, 'BTLF', dummyCaster);
    UnitAddAbility(target, NEGATIVE_RESISTANCE);

    // Apply debuffs to units in range
    GroupEnumUnitsInRange(aoeUnits, GetUnitX(target), GetUnitY(target), 300 + 20*data.abilityLevel, null);
    enumUnit = FirstOfGroup(aoeUnits);
    while (enumUnit != null)
    {
        if ((GetUnitAbilityLevel(enumUnit, NEGATIVE_RESISTANCE) == 0) && IsUnitEnemy(enumUnit, GetOwningPlayer(data.caster)) && (GetWidgetLife(enumUnit) > 0.405))
        {
            UnitAddAbility(enumUnit, NEGATIVE_RESISTANCE);
            GroupAddUnit(affectedUnits, enumUnit);
        }

        GroupRemoveUnit(aoeUnits, enumUnit);
        enumUnit = FirstOfGroup(aoeUnits);
    }

    GroupAddUnit(affectedUnits, target);

    //BJDebugMsg("HitFuckYou");
    if(!loopIsRunning)
    {
        TimerStart(loopTimer, 0.3, true, function Loop);
        loopIsRunning = true;
        //BJDebugMsg("HitLoopStart");
    }

    data.destroy();
    dummyCaster = null;
}

function Actions() {
    GGData data = GGData.create();
    Dummy dummy;

    data.caster = GetTriggerUnit();
    data.abilityLevel = GetUnitAbilityLevel(data.caster, CASTER_ABILITY);

    dummy = DummyBuilder
        .create(GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), FX_PATH)
        .scale(1.0)
        .height(32.0)
        .facingPoint(GetUnitX(GetSpellTargetUnit()), GetUnitY(GetSpellTargetUnit()))
        .createDummy();

    Missile.create(dummy)
        .constantSpeed(1200.0)
        .collisionSize(16.0)
        .targetUnit(GetSpellTargetUnit(), Hit)
        .setData(data)
        .go();
}

function onInit() {

    trigger trg = CreateTrigger();
    TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_SPELL_EFFECT );
    TriggerAddCondition( trg, Condition( function Conditions ) );
    TriggerAddAction( trg, function Actions );

    loopTimer = CreateTimer();
    affectedUnits = CreateGroup();
    aoeUnits = CreateGroup();
}

}

//! endzinc
 
Level 14
Joined
Jan 24, 2017
Messages
280
I don't have JNGP running, so this code likely contains some syntax errors--but essentially you'll want to enumerate the units in range and add them to the group "affectedUnits". Just note that the code seems to rely on them having the slow debuff in order for them to have the NEGATIVE_RESISTANCE debuff, so you'll want to make sure the range of your drunkenhaze dummy ability matches up with the (300 + 20*level) that you described.

Here is roughly what the code looked like--I can't quite remember the Zinc syntax but it should look roughly like this (see the part after // Apply debuff to units in range):
JASS:
//! zinc

library GanjaGanja requires Missile {


// The effect to be used by the missile
// ------------------------------------
constant string FX_PATH = "GanjaSmoke.mdx";


// The ability-code that triggers the spell
// ----------------------------------------
function Conditions() -> boolean {
    return GetSpellAbilityId() == 'A0AD';
}

// Abiliy and buff codes
// ---------------------------------------
constant integer CASTER_ABILITY = 'A0AD';
constant integer DUMMY_ABILITY = 'A0IU';
constant integer DUMMY_ABILITY_BUFF = 'B023';
constant integer NEGATIVE_RESISTANCE = 'A0K4';

group affectedUnits;
group aoeUnits;
timer loopTimer;
boolean loopIsRunning = false;

struct GGData {
    unit caster;
    integer abilityLevel;
    method onDestroy() {
        caster = null;
    }
}

function LoopPerUnit() {

    unit u = GetEnumUnit();
    boolean hasBuff = (GetUnitAbilityLevel(u, DUMMY_ABILITY_BUFF) > 0);
    //BJDebugMsg("LoopPerUnitTrue");
    if(hasBuff == false) {
        GroupRemoveUnit(affectedUnits, u);
        UnitRemoveAbility(u, NEGATIVE_RESISTANCE);
        //BJDebugMsg("LoopPerUnitFalse");
    }

    u = null;
}

function Loop() {

    boolean groupHasUnits = (FirstOfGroup(affectedUnits) != null);
    ForGroup(affectedUnits, function LoopPerUnit);
    //BJDebugMsg("LoopRun");
    if(groupHasUnits == false) {
        PauseTimer(GetExpiredTimer());
        loopIsRunning = false;
        //BJDebugMsg("LoopStop");
    }
}

function Hit(unit target, GGData data) {

    unit enumUnit = null;
    unit dummyCaster = CreateUnit(GetOwningPlayer(data.caster), 'h03N', GetUnitX(target),GetUnitY(target), 0.0);
    UnitAddAbility(dummyCaster, DUMMY_ABILITY);
    SetUnitAbilityLevel(dummyCaster, DUMMY_ABILITY, data.abilityLevel);
    IssueTargetOrder(dummyCaster, "drunkenhaze", target);
    UnitDamageTargetBJ( data.caster, target, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC );
    UnitApplyTimedLifeBJ( 1.0, 'BTLF', dummyCaster);
    UnitAddAbility(target, NEGATIVE_RESISTANCE);

    // Apply debuffs to units in range
    GroupEnumUnitsInRange(aoeUnits, GetUnitX(target), GetUnitY(target), 300 + 20*data.abilityLevel, null);
    enumUnit = FirstOfGroup(aoeUnits);
    while (enumUnit != null)
    {
        if ((GetUnitAbilityLevel(enumUnit, NEGATIVE_RESISTANCE) == 0) && IsUnitEnemy(enumUnit, GetOwningPlayer(data.caster)) && (GetWidgetLife(enumUnit) > 0.405))
        {
            UnitAddAbility(enumUnit, NEGATIVE_RESISTANCE);
            GroupAddUnit(affectedUnits, enumUnit);
        }

        GroupRemoveUnit(aoeUnits, enumUnit);
        enumUnit = FirstOfGroup(aoeUnits);
    }

    GroupAddUnit(affectedUnits, target);

    //BJDebugMsg("HitFuckYou");
    if(!loopIsRunning)
    {
        TimerStart(loopTimer, 0.3, true, function Loop);
        loopIsRunning = true;
        //BJDebugMsg("HitLoopStart");
    }

    data.destroy();
    dummyCaster = null;
}

function Actions() {
    GGData data = GGData.create();
    Dummy dummy;

    data.caster = GetTriggerUnit();
    data.abilityLevel = GetUnitAbilityLevel(data.caster, CASTER_ABILITY);

    dummy = DummyBuilder
        .create(GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), FX_PATH)
        .scale(1.0)
        .height(32.0)
        .facingPoint(GetUnitX(GetSpellTargetUnit()), GetUnitY(GetSpellTargetUnit()))
        .createDummy();

    Missile.create(dummy)
        .constantSpeed(1200.0)
        .collisionSize(16.0)
        .targetUnit(GetSpellTargetUnit(), Hit)
        .setData(data)
        .go();
}

function onInit() {

    trigger trg = CreateTrigger();
    TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_SPELL_EFFECT );
    TriggerAddCondition( trg, Condition( function Conditions ) );
    TriggerAddAction( trg, function Actions );

    loopTimer = CreateTimer();
    affectedUnits = CreateGroup();
    aoeUnits = CreateGroup();
}

}

//! endzinc
Thanks a lot! :)
 
Top