HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Stackable instances for a unit

06-30-2009, 10:34 AM#1
wraithseeker
Stated above.

Collapse JASS:
scope Overseermight initializer Init

globals
    private constant integer DMGAURA = 'A00F'
    private constant integer SPELLBOOK = 'A00V'
    private constant integer SPELL = 'A00U'
    private constant string EFFECT = "Abilities\\Spells\\Items\\AIco\\CrownOfCmndTarget.mdl"
    private constant string BLINK = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"
endglobals

private struct data
    implement AutoData
    static group Done = CreateGroup()
    unit target
    integer instances
    integer agi
    integer atkspeed
    integer life
    
static method create takes unit target returns data
    local data d = data.allocate()
    set d.instances = 0
    set d.agi = 0
    set d.atkspeed = 0
    set d.life = 0
    set data[target] = d
    return d     
endmethod
endstruct

private function LConditions takes nothing returns boolean
    return GetLearnedSkill() == SPELL
endfunction

private function LActions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer i = GetUnitAbilityLevel(u,SPELL)
    if GetLearnedSkill() > 0 then
        call UnitAddAbility(u,SPELLBOOK)
    endif
    call SetUnitAbilityLevel(u,DMGAURA,i)
    set u = null
endfunction

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SPELL
endfunction

private function Actions takes nothing returns nothing  
    local unit u = GetTriggerUnit()
    local data d = data[u]
    local unit t = GetSpellTargetUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real tx = GetUnitX(t)
    local real ty = GetUnitY(t)
    if d == 0 then
        set d = data.create(u)
    endif
    call SetUnitX(t,x)
    call SetUnitY(t,y)
    call DestroyEffect(AddSpecialEffect(BLINK,x,y))
    call SetUnitX(u,tx)
    call SetUnitY(u,ty)
    call DestroyEffect(AddSpecialEffect(BLINK,tx,ty))
    call AddTimedEffectTarget(EFFECT,u,"overhead",5)
    set d.agi = DelayedAgi(u,15,5) // d.agi is the struct instance of the agi struct and same goes for the rest
    set d.life = DelayedMaxLife(u,200,5)
    set d.atkspeed = DelayedAttackSpeed(u,40,5)
    set d.instances = d.instances + 1 // what am I doing with this and not using a boolean? Well I don't know, i am currently thinking of how to make it stackable
    set u = null
    set t = null
endfunction

private function ConditionDeath takes nothing returns boolean
    local unit u = GetKillingUnit()
    local unit a = GetTriggerUnit()
    local integer i = GetUnitAbilityLevel(u,SPELL)
    local data d = data[u]
    if IsUnitEnemy(a,GetOwningPlayer(u)) and i > 0 and d.instances > 0 then
        call BJDebugMsg("Adding") 
        call AddAgiDuration(d.agi,1) // increase duration of the instance by 1
        call AddMaxLifeDuration(d.life,1) // same thing..
        call AddAttackSpeedDuration(d.atkspeed,1)
       // auto data overwrites the existing struct so it isn't multiple unit instances for a specific unit 2 times and more
     endif
     set u = null
     set a = null
    return false
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        exitwhen i > 12
        call SetPlayerAbilityAvailable(Player(i),SPELLBOOK,false)
        set i = i + 1
    endloop
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_HERO_SKILL)
    call TriggerAddAction(t, function LActions )
    call TriggerAddCondition(t,Condition(function LConditions))
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(t, function Actions)
    call TriggerAddCondition(t,Condition(function Conditions))
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(t,Condition(function ConditionDeath))
endfunction
endscope


I wrote the problems in the comments but to sum it up. Right now it's not stackable and how do I make it so? Making huge arrays in the struct make less instances possible.

EDIT: Would using table for a struct instance work well or is there any other good alternatives?

EDIT2:
Collapse JASS:
scope Overseermight initializer Init

globals
    private constant integer DMGAURA = 'A00F'
    private constant integer SPELLBOOK = 'A00V'
    private constant integer SPELL = 'A00U'
    private constant string EFFECT = "Abilities\\Spells\\Items\\AIco\\CrownOfCmndTarget.mdl"
    private constant string BLINK = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"
endglobals

private struct data
    implement AutoData
    static group Done = CreateGroup()
    Table Agi
    Table AttackSpeed
    Table MaxLife
    unit target
    integer Count = 0
    
static method create takes unit target returns data
    local data d = data.allocate()
    set d.target = target
    set d.Agi = Table.create()
    set d.MaxLife = Table.create()
    set d.AttackSpeed = Table.create()
    set data[target] = d
    return d     
endmethod
endstruct

private function LConditions takes nothing returns boolean
    return GetLearnedSkill() == SPELL
endfunction

private function LActions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer i = GetUnitAbilityLevel(u,SPELL)
    if GetLearnedSkill() > 0 then
        call UnitAddAbility(u,SPELLBOOK)
    endif
    call SetUnitAbilityLevel(u,DMGAURA,i)
    set u = null
endfunction

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SPELL
endfunction

private function Actions takes nothing returns nothing  
    local unit u = GetTriggerUnit()
    local data d = data[u]
    local unit t = GetSpellTargetUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real tx = GetUnitX(t)
    local real ty = GetUnitY(t)
    if d == 0 then
        set d = data.create(u)
    endif
    call SetUnitX(t,x)
    call SetUnitY(t,y)
    call DestroyEffect(AddSpecialEffect(BLINK,x,y))
    call SetUnitX(u,tx)
    call SetUnitY(u,ty)
    call DestroyEffect(AddSpecialEffect(BLINK,tx,ty))
    call AddTimedEffectTarget(EFFECT,u,"overhead",5)
    set d.Agi[d.Count] = DelayedAgi(u,15,5)
    set d.MaxLife[d.Count] = DelayedMaxLife(u,200,5)
    set d.AttackSpeed[d.Count] = DelayedAttackSpeed(u,40,5)
    set d.Count = d.Count + 1
    set u = null
    set t = null
endfunction

private function ConditionDeath takes nothing returns boolean
    local unit u = GetKillingUnit()
    local unit a = GetTriggerUnit()
    local integer i = GetUnitAbilityLevel(u,SPELL)
    local integer j = 0
    local data d = data[u]
    if IsUnitEnemy(a,GetOwningPlayer(u)) and i > 0 and d.instances > 0 then
        loop
            exitwhen j >= d.Count
            call AddAgiDuration(d.agi,1)
            call AddMaxLifeDuration(d.life,1)
            call AddAttackSpeedDuration(d.atkspeed,1)
            set j = j + 1
        endloop
     endif
     set u = null
     set a = null
    return false
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        exitwhen i > 12
        call SetPlayerAbilityAvailable(Player(i),SPELLBOOK,false)
        set i = i + 1
    endloop
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_HERO_SKILL)
    call TriggerAddAction(t, function LActions )
    call TriggerAddCondition(t,Condition(function LConditions))
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(t, function Actions)
    call TriggerAddCondition(t,Condition(function Conditions))
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(t,Condition(function ConditionDeath))
endfunction

endscope

Tried a Table verison but I got confused and it wouldn't work, when would I set d.Count to d.Count - 1, I don't want to modify the UP Delayed Script.
06-30-2009, 01:08 PM#2
Blubb-Tec
what are "stackable instances for a unit"? I don't get what your system does. and please give some explanation about the internal working of your system. also, maybe you have some ideas where in your script the bug may be located, so that we have a starting point for our search.
06-30-2009, 01:24 PM#3
wraithseeker
Collapse JASS:
library DelayedUPRemoval requires TimerUtils, OperatorWrappers

//! textmacro UP takes name

function interface Face$name$ takes D$name$ d returns nothing

struct D$name$
    unit target
    timer t
    real value
    Face$name$ face
    
static method Remove takes nothing returns nothing
    local D$name$ this = GetTimerData(GetExpiredTimer())
    call UnitModify$name$(.target,-.value)
    call .face.execute(this)
    call .destroy()
endmethod
    
static method create takes unit u, real r, real time returns D$name$
    local D$name$ this = D$name$.allocate()
    set .target = u
    set .t = NewTimer()
    set .value = r
    set .face = 0
    call SetTimerData(.t,this)
    call UnitModify$name$(.target,.value)
    call TimerStart(.t,time,false,function D$name$.Remove)
    return this
endmethod

method onDestroy takes nothing returns nothing
    call ReleaseTimer(.t)
endmethod
endstruct

function Delayed$name$ takes unit u, real r, real time returns integer
    local D$name$ d = D$name$.create(u,r,time)
    return d
endfunction

function Add$name$Duration takes D$name$ d, real dur returns nothing
    local real remaining = TimerGetRemaining(d.t)
    call ReleaseTimer(d.t)
    set d.t = NewTimer()
    call SetTimerData(d.t,d)
    call TimerStart(d.t,dur+remaining,false,function D$name$.Remove)
endfunction

function Delayed$name$Code takes D$name$ c, Face$name$ d returns nothing
    set c.face = d
endfunction
//! endtextmacro

//! runtextmacro UP("Agi")
//! runtextmacro UP("Int")
//! runtextmacro UP("Str")
//! runtextmacro UP("LifeRegen")
//! runtextmacro UP("ManaRegen")
//! runtextmacro UP("ManaRegenPercent")
//! runtextmacro UP("Armor")
//! runtextmacro UP("Damage")
//! runtextmacro UP("AttackSpeed")
//! runtextmacro UP("MoveSpeed")
//! runtextmacro UP("AttackEvasion")
//! runtextmacro UP("AttackMiss")
//! runtextmacro UP("MaxLife")
//! runtextmacro UP("MaxMana")


endlibrary

You can ignore the effects call, it has nothing to do with the problem.


I wrote comments on the code but let me say it here so it's easire to view, AutoData overwrites the existing struct on a unit meaning that it cannot be multiple instances available a unit so my method would fail if 2 instances on a unit was running.

EDIT: Now I fixed the coding and tell me if the code is good or not

Collapse JASS:
scope Overseermight initializer Init

globals
    private constant integer DMGAURA = 'A00F'
    private constant integer SPELLBOOK = 'A00V'
    private constant integer SPELL = 'A00U'
    private constant string EFFECT = "Abilities\\Spells\\Items\\AIco\\CrownOfCmndTarget.mdl"
    private constant string BLINK = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"
endglobals

private struct data
    implement AutoData
    static group Done = CreateGroup()
    Table Agi
    Table AttackSpeed
    Table MaxLife
    unit target
    integer Count = 0
    
static method create takes unit target returns data
    local data d = data.allocate()
    set d.target = target
    set d.Agi = Table.create()
    set d.MaxLife = Table.create()
    set d.AttackSpeed = Table.create()
    set data[target] = d
    return d     
endmethod
endstruct

private function LConditions takes nothing returns boolean
    return GetLearnedSkill() == SPELL
endfunction

private function LActions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer i = GetUnitAbilityLevel(u,SPELL)
    if GetLearnedSkill() > 0 then
        call UnitAddAbility(u,SPELLBOOK)
    endif
    call SetUnitAbilityLevel(u,DMGAURA,i)
    set u = null
endfunction

private function RemovalAttackSpeed takes unit target returns nothing
   local data c = data[target]
   call BJDebugMsg(I2S(c.Count))
   set c.Count = c.Count - 1
      call BJDebugMsg(I2S(c.Count))
endfunction

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SPELL
endfunction

private function Actions takes nothing returns nothing  
    local unit u = GetTriggerUnit()
    local data d = data[u]
    local unit t = GetSpellTargetUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real tx = GetUnitX(t)
    local real ty = GetUnitY(t)
    if d == 0 then
        set d = data.create(u)
    endif
    call SetUnitX(t,x)
    call SetUnitY(t,y)
    call DestroyEffect(AddSpecialEffect(BLINK,x,y))
    call SetUnitX(u,tx)
    call SetUnitY(u,ty)
    call DestroyEffect(AddSpecialEffect(BLINK,tx,ty))
    call AddTimedEffectTarget(EFFECT,u,"overhead",5)
    set d.Agi[d.Count] = DelayedAgi(u,15,5)
  //  call DelayedAgiCode(d.Agi[d.Count],RemovalAgi)
    set d.MaxLife[d.Count] = DelayedMaxLife(u,200,5)
  //  call DelayedMaxLifeCode(d.MaxLife[d.Count],RemovalMaxLife)
    set d.AttackSpeed[d.Count] = DelayedAttackSpeed(u,40,5)
    call DelayedAttackSpeedCode(d.AttackSpeed[d.Count],RemovalAttackSpeed)
    set d.Count = d.Count + 1
    call GroupAddUnit(d.Done,u)
    set u = null
    set t = null
endfunction

private function ConditionDeath takes nothing returns boolean
    local unit u = GetKillingUnit()
    local unit a = GetTriggerUnit()
    local integer i = GetUnitAbilityLevel(u,SPELL)
    local integer j = 0
    local data d = data[u]
    if IsUnitEnemy(a,GetOwningPlayer(u)) and i > 0 and IsUnitInGroup(u,d.Done) then
        loop
            exitwhen j >= d.Count
            call AddAgiDuration(d.Agi[j],1)
            call AddMaxLifeDuration(d.MaxLife[j],1)
            call AddAttackSpeedDuration(d.AttackSpeed[j],1)
            set j = j + 1
        endloop
     endif
     set u = null
     set a = null
    return false
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        exitwhen i > 12
        call SetPlayerAbilityAvailable(Player(i),SPELLBOOK,false)
        set i = i + 1
    endloop
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_HERO_SKILL)
    call TriggerAddAction(t, function LActions )
    call TriggerAddCondition(t,Condition(function LConditions))
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(t, function Actions)
    call TriggerAddCondition(t,Condition(function Conditions))
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(t,Condition(function ConditionDeath))
endfunction

endscope
06-30-2009, 04:04 PM#4
Anitarf
I thin you need the UnitListModule.
06-30-2009, 04:06 PM#5
Here-b-Trollz
Which doesn't compile.
06-30-2009, 07:14 PM#6
Anitarf
Well, grim001 should fix it soon enough.
06-30-2009, 10:17 PM#7
grim001
It's updated.

If you can't figure out how to make it work, post your best try here, and maybe you will get help.