• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS] Counting Times hit in a struct variable, is there a better way?

Status
Not open for further replies.
Level 13
Joined
Jul 26, 2008
Messages
1,009
Uses AutoIndex, TimerUtils, xe 0.8

Alright so I have a skill called poison daggers. It throws knives out in a fan shape over an area. Problem is it works like a shotgun. Up close it does ridiculous damage, but far away it's near useless.

I wanted to remedy that by making the spell only hit units at max twice. So I decided to use AutoIndex to help count how many times a unit has been hit by a knife and stop it at two. Well, now the spell doesn't work at all. :\ I kept my attempt in, and will have to revert back to an earlier version of the spell til I can figure it out. I'm having a similar problem with another spell where I want to limit the number of times a unit can be hit.

JASS:
scope PoisonDaggers initializer init

globals
    private constant integer SPELLID        = 'afok'
    private constant real tick              = 1
endglobals

public struct Data extends xecollider

    unit caster
    unit t
//    group g
    timer tim
    real dur
    integer array counted[8194]

/*    static method empty takes nothing returns nothing//Was thinking of grouping units and setting their variable to 0 when the struct ended.
     local unit e = GetEnumUnit()
        set .counted[GetUnitId(e)] = 0
    endmethod*/

    static method Timer takes nothing returns nothing//This one does the poison damage over time
     local thistype this = GetTimerData(GetExpiredTimer())
     local xedamage d= xedamage.create()
     local integer lvl = GetUnitAbilityLevel(.caster, SPELLID)
     local real dam = 2+3*lvl

        set .dur = .dur + tick

        if .dur <= 5 and not IsUnitType(.t, UNIT_TYPE_DEAD ) then
            call d.useSpecialEffect(GetAbilityEffectById(SPELLID, EFFECT_TYPE_AREA_EFFECT, 1),"origin")
            set d.dtype = DAMAGE_TYPE_POISON
            set d.atype = ATTACK_TYPE_NORMAL
            call d.damageTarget(.caster,.t, dam)
        else
            set .caster = null
            set .t = null
            call ReleaseTimer(.tim)
            call .terminate()
        endif
        call d.destroy()
    endmethod

/*    method onDestroy takes nothing returns nothing//Was thinking of grouping then calling forgroup at the end of the struct
        call ForGroup(.g, function thistype.empty)
    endmethod*/

    method onUnitHit takes unit target returns nothing
     local xedamage d= xedamage.create()
     local Data D
     local integer id = GetUnitId(target)
     local integer lvl = GetUnitAbilityLevel(.caster, SPELLID)
     local real dam = (GetHeroAgi(.caster,true)*0.1)*(9+4*lvl)
        set .counted[id] = 1
//            set .counted[id] = .counted[id] + 1//This is where the issue takes place, I was trying to use an if statement for this but it wouldn't work
        if IsUnitEnemy(target, GetOwningPlayer(.caster)) and not IsUnitType(target,UNIT_TYPE_STRUCTURE) then
            call DestroyEffect(AddSpecialEffectTarget(GetAbilityEffectById(SPELLID, EFFECT_TYPE_AREA_EFFECT, 0), target, "origin"))
//            call GroupAddUnit(this.g, target)
            set d.dtype = DAMAGE_TYPE_POISON
            set d.atype = ATTACK_TYPE_NORMAL
            call d.damageTarget(this.caster,target, dam)
            call d.destroy()
            set .t = target
            set .tim = NewTimer()
            call SetTimerData(.tim,this)
            call TimerStart(.tim, tick, true, function Data.Timer)//call the poison on damage on targets
            call .hiddenDestroy()//Hidden destroy, so I do not terminate the struct and cause issues.
         endif
    endmethod

    static method Actions takes nothing returns nothing
     local unit c = GetTriggerUnit()
     local integer i = 0
     local integer lvl = GetUnitAbilityLevel(c, SPELLID)
     local real angle = bj_RADTODEG*Atan2( GetSpellTargetY() - GetUnitY(c) , GetSpellTargetX() - GetUnitX(c) ) + (15+10*lvl)/2
     local real cone = (15+10*lvl)/(1+lvl)
     local Data xc

        loop
        exitwhen i == 2+lvl
            set xc = Data.create( GetUnitX(c), GetUnitY(c), bj_DEGTORAD*(angle - cone*i) )
            set xc.caster           = c
            set xc.fxpath           = GetAbilityEffectById(SPELLID, EFFECT_TYPE_MISSILE, 0)
            set xc.speed            = 900
            set xc.expirationTime   = 1.
            set xc.collisionSize    = 32
            set xc.dur              = 0
            set i = i + 1
        endloop
     set c = null
    endmethod

    static method Conditions takes nothing returns boolean
        if GetSpellAbilityId() == SPELLID then
            call thistype.Actions()
        endif
     return false
    endmethod

endstruct

//===========================================================================
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, function Data.Conditions )
    call XE_PreloadAbility(SPELLID)
 set t = null
endfunction

endscope
 
Status
Not open for further replies.
Top