• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

[vJASS] (Solved) Dummy parasite spell not working for AI players only

Status
Not open for further replies.
Level 13
Joined
Jun 23, 2009
Messages
300
I got a spell that applies Parasite after the targeted units are hit by a Rain Of Fire FX, this works 100% with no issues for at least Player 1 but when an AI hero uses it the dummies don't cast Parasite on the targets, I tried a bunch of stuff, giving the dummy base spell more range, giving dummies some more timed life, changing base spell from the Naga Parasite to the Neutral Parasite, changing the base spell to Black Arrow (this totally broke it), using a different dummy (which actually confirmed through animations they wouldn't cast it for AI), preloading all skills and buffs through xepreload, nothing worked.

Actually, that's not true, the only thing I tested that works is giving the AI player a bunch of Naga Sirens so they cast Parasite on units, after they've done that the spell worked as intended for them.

I've spent a bunch of hours already trying to figure out a solution for this with little result. Any ideas? Heck, I'd settle for a clean, invisible way to use the Naga Siren workaround.

Here's the code, although I feel there's nothing inherently wrong with it:
vJASS:
scope FireBarrage initializer Init

globals
    private constant integer SPELL = 'Bek4'
    private constant integer DUMMY_SPELL = 'Bem4'
    private constant integer Damage = 50
    private constant integer Times = 2 //+ spell level
    private constant real Range = 600.00

    private group ENUM
    private unit CASTER
    private player OP
    private integer T
    private integer L
    private boolean Existing = false
endglobals

private struct fire
    unit t
    unit c
    integer l

    static method create takes unit target, unit caster, integer level returns fire
        local fire fy = fire.allocate()
        set fy.t = target
        set fy.c = caster
        set fy.l = level
        return fy
    endmethod

endstruct

private function Effect takes nothing returns nothing
local fire f = GetTimerData(GetExpiredTimer())
local unit dummy = CreateUnit(GetOwningPlayer(f.c), TWKDummy, GetUnitX(f.t), GetUnitY(f.t), bj_UNIT_FACING)
    call UnitDamageTarget(f.c, f.t, Damage * f.l, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
    call UnitAddAbility(dummy, DUMMY_SPELL)
    call IssueTargetOrder(dummy, "parasite", f.t)
    call UnitApplyTimedLife(dummy, 'BTLF', 1)
    call ReleaseTimer(GetExpiredTimer())
    call f.destroy()
endfunction

private function Target takes nothing returns boolean
local fire f
local timer t = null
if T != 0 and IsUnitEnemy(GetFilterUnit(), OP) and GetWidgetLife(GetFilterUnit()) > 0.405 and not (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) or IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) or IsUnitType(GetFilterUnit(), UNIT_TYPE_ANCIENT) or IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO) or IsTWKDummy(GetFilterUnit())) and (GetOwningPlayer(GetFilterUnit()) != Player(bj_PLAYER_NEUTRAL_EXTRA) and GetOwningPlayer(GetFilterUnit()) != Player(PLAYER_NEUTRAL_PASSIVE) and GetOwningPlayer(GetFilterUnit()) != Player(bj_PLAYER_NEUTRAL_VICTIM)) then
    set T = T - 1
    set f = fire.create(GetFilterUnit(), CASTER, L)
    set t = NewTimer()
    call SetTimerData(t, f)
    call TimerStart(t, 0.8, false, function Effect)
    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Demon\\RainOfFire\\RainOfFireTarget.mdl", GetFilterUnit(), "origin"))
endif
return false
endfunction

private function Main takes nothing returns boolean
if GetSpellAbilityId() == SPELL then
    set OP = GetOwningPlayer(GetTriggerUnit())
    set CASTER = GetTriggerUnit()
    set L = GetUnitAbilityLevel(GetTriggerUnit(), SPELL)
    set T = Times + L
    call GroupEnumUnitsInRange(ENUM, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), Range, Condition(function Target))
endif
return false
endfunction

private function TargetsCheck takes nothing returns boolean
if not Existing and IsUnitEnemy(GetFilterUnit(), OP) and GetWidgetLife(GetFilterUnit()) > 0.405 and not (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) or IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) or IsUnitType(GetFilterUnit(), UNIT_TYPE_ANCIENT) or IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO) or IsTWKDummy(GetFilterUnit())) and (GetOwningPlayer(GetFilterUnit()) != Player(bj_PLAYER_NEUTRAL_EXTRA) and GetOwningPlayer(GetFilterUnit()) != Player(PLAYER_NEUTRAL_PASSIVE) and GetOwningPlayer(GetFilterUnit()) != Player(bj_PLAYER_NEUTRAL_VICTIM)) then
    set Existing = true
endif
return false
endfunction

private function TargetsExist takes nothing returns boolean
if GetIssuedOrderId() == OrderId("starfall") and GetUnitAbilityLevel(GetOrderedUnit(), SPELL) != 0 then
    set OP = GetOwningPlayer(GetOrderedUnit())
    set Existing = false
    call GroupEnumUnitsInRange(ENUM, GetUnitX(GetOrderedUnit()), GetUnitY(GetOrderedUnit()), Range, Condition(function TargetsCheck))
    if not Existing then
        call AbortSpell(GetOrderedUnit(), SPELL_TARGET_ERROR, " ")
    endif
endif
return false
endfunction

private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
set ENUM = CreateGroup()

    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function TargetsExist))

    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Main))

endfunction

endscope
 
Level 13
Joined
Jun 23, 2009
Messages
300
Create the Dummy for Neutral Hostile and see if that works.
Assuming you mean something like this:
JASS:
private function Effect takes nothing returns nothing
local fire f = GetTimerData(GetExpiredTimer())
local unit dummy = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), TWKDummy, GetUnitX(f.t), GetUnitY(f.t), bj_UNIT_FACING)
//local unit dummy = CreateUnit(GetOwningPlayer(f.c), TWKDummy, GetUnitX(f.t), GetUnitY(f.t), bj_UNIT_FACING)
    call UnitDamageTarget(f.c, f.t, Damage * f.l, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
    call UnitAddAbility(dummy, DUMMY_SPELL)
    call IssueTargetOrder(dummy, "parasite", f.t)
    call UnitApplyTimedLife(dummy, 'BTLF', 1)
    call ReleaseTimer(GetExpiredTimer())
    call f.destroy()
endfunction
It fails to work for any player as far as I've seen. Even if it did work it would be rather inconvenient for me as, I forgot to specify, I'm using Parasite specifically both for its DPS and for its unit summoning properties.

To be perfectly clear, the dummy always spawned in my previous tests, it just didn't cast Parasite unless it was for Player 1.

EDIT: made the dummies visible (with some sword guys) to see what they do when Neutral Hostile:
FBTest.png

I imagine it's the owner of the Dummy that's causing the issue.
I think so too tbh

Oh, forgot to add, I'm on 1.31.1, I dunno if that changes stuff.

EDITEDIT: Actually, the player having used Parasite before doesn't seem to work now. Anyway after making dummies visible the ones for Player 1 cast the spell then die while the AI ones just run away (but that might be because of the unit I'm using as a dummy?)
 
Last edited:
Level 13
Joined
Jun 23, 2009
Messages
300
Manually casting gives me no issues whatsoever for all targets (after having added "Self" and "Player Units" as valid targets), I've just tried setting the spell's valid targets to the broadest possible:
1643749001160.png

It still only works for player 1 for some reason.

EDIT: I've also tried making the dummy use the actual Parasite spell and it doesn't work, CPU dummies just seem to ignore the "parasite" order, I think I'll just give in, make a dummy that casts a dps debuff and another dummy that summons a unit through an "On Death" event.

EDITEDIT: After trying a bunch of other base spells (acid bomb, thunderbolt, poison arrows) it turns out call UnitApplyTimedLife() stopped the order for all AI players that are not bj_PLAYER_NEUTRAL_EXTRA... for some reason, might be the wonders of 1.31.

JASS:
private function Effect takes nothing returns nothing
local fire f = GetTimerData(GetExpiredTimer())
local unit dummy
    call UnitDamageTarget(f.c, f.t, Damage * f.l, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
    if GetWidgetLife(f.t) > 0.405 then
        set dummy = CreateUnit(GetOwningPlayer(f.c), TWKDummy, GetUnitX(f.t), GetUnitY(f.t), bj_UNIT_FACING)
        call UnitAddAbility(dummy, DUMMY_SPELL)
        call UnitApplyTimedLife(dummy, 'BTLF', 1)
        call IssueTargetOrder(dummy, "parasite", f.t)
    endif
    call ReleaseTimer(GetExpiredTimer())
    call f.destroy()
endfunction
In other words doing this worked.
 
Last edited:
Status
Not open for further replies.
Top