• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Need an idea for handling array data in GUI

So, I need a multidimensional array data for two variables. To be clear, here is my goal:

I have a caster that casts a spell on a target unit and inflict a debuff. The debuff increases damage taken by percentage from this unit and their group. Unit Indexer is used.

In short, the scenario goes like this:

Unit A is hit by Unit B (Group B) --> Unit A takes more damage from group B
Unit A is hit by Unit C after Unit B (buff from B not expired yet) --> Unit A now also takes more damage from group C BUT at different values than group B
(say, group B deals 50% more, while group C deals 30% more)

In short, it's like the unit is inflicted with two different stacks that affect the damage taken from two different groups. I am at a lost to create a pair-like structure where
A <> B = 50%; 5 seconds
A <> C = 30%; 10 seconds

EDIT:

I realized Hashtables might lead me somewhere, but I try to not expend that 255 hashtables for this.

EDIT:

I realized I should make the pairing clearer. Refer to below:
A <> B : 50%
A <> C : 30%
D <> B : 45%
D <> C : 20%
B <> D : 15%
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
You could have a multi purpose Hashtable with clever use of keys. Like one hashtable that supports 20 different spells. Otherwise, Jass supports 2d arrays, maybe make a hybrid GUI/Jass design where it's 99% GUI and uses Custom Script to interact with the Jass arrays. Of course Lua makes all of this extremely simple but I imagine that's not an option.
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
Each instance of the buff is tracked separately. Kind of its own object. When the buff is active the unit has added to its on damage task list a job to apply/modify the bonus damage if the damage source is appropriate. When Unit A is affected by 2 buffs from different groups, it will use both to check all damage, but only the one appropriate for the damage source would boost the damage.

This breaks the problem down into a lot of small isolated elements which can be stored in a set of JASS arrays, or as a Lua table based object.
 
You could have a multi purpose Hashtable with clever use of keys. Like one hashtable that supports 20 different spells. Otherwise, Jass supports 2d arrays, maybe make a hybrid GUI/Jass design where it's 99% GUI and uses Custom Script to interact with the Jass arrays. Of course Lua makes all of this extremely simple but I imagine that's not an option.
2D Arrays as in real 2D arrays for Jass? I don't mind doing some Jass myself if need must, but I want to be certain it is not a faux 2D array trick where it is [(x) * (MAX_Y) + (y)] or something similar to that effect and truly a 2D array.
Each instance of the buff is tracked separately. Kind of its own object. When the buff is active the unit has added to its on damage task list a job to apply/modify the bonus damage if the damage source is appropriate. When Unit A is affected by 2 buffs from different groups, it will use both to check all damage, but only the one appropriate for the damage source would boost the damage.
If I catch the idea for this one right, this means that each buff applied is accounted as one instance, like spell instances. However, this can mess with calculations since the buff bonus stacks additively, not multiplicatively.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
How could it be a multidimensional array when the language literally doesn’t have those? Of course it’s just remapping like you would normally do yourself. But yes variable[ind1][ind2].
Can you not do MyVar[100][200] in Jass? I read a post from 2019 that said Jass now has 2D array support. Never seen it used before, though.

@Daffa
Just add the multiple instances together:
vJASS:
local real dmgMultiplier = 1.0
local integer i = InstanceCount[x] // tracks how many instances aka buffs the unit has on it
loop
    exitwhen i <= 0
    set dmgMultiplier = dmgMultiplier + InstanceDamageTaken[i]
    set i = i - 1
endloop
set damageTaken = damageTaken * dmgMultiplier
InstanceDamageTaken[] is the value of a given buff. These values would be divided by 100 to get you an easy to work with number. In other words, 50% bonus damage taken would be stored as 0.50 since that works nicely with the formula.

Of course it'd be more efficient to track the dmgMultiplier yourself, increasing it when a new buff is applied and decreasing it when an old buff is removed. That way you don't have to run so many calculations when a unit takes damage and can instead do something like this:
vJASS:
set damageTaken = damageTaken * DamageMultiplier[id]
id being some kind of reference to the damaged unit like it's custom value (unit indexing method).
 
Last edited:
Level 11
Joined
Nov 13, 2010
Messages
211
cant you do something like this?? some of it might be wrong
JASS:
struct Debuff
    unit source
    integer damageIncrease
    real duration
endstruct

// Define the groups and their damage increase values
constant integer DAMAGE_INCREASE_B = 50
constant integer DAMAGE_INCREASE_C = 30
// Define the duration for each debuff
constant real DURATION_B = 5.0
constant real DURATION_C = 10.0

// Array to store debuffs on units
Debuff debuffs[16] // Assuming a maximum of 16 debuffs per unit
integer debuffIndex = 0 // Current index for debuffs array

// Function to apply a debuff to a unit
function ApplyDebuff takes unit target, unit source, integer damageIncrease, real duration
    if debuffIndex < 16 then
        // Create a new debuff
        set debuffIndex = debuffIndex + 1
        set debuffs[debuffIndex].source = source
        set debuffs[debuffIndex].damageIncrease = damageIncrease
        set debuffs[debuffIndex].duration = duration
    endif
endfunction

// Function to handle debuff expiration
function DebuffTimer
    local integer i = 1
    loop
        exitwhen i > debuffIndex
        // Decrease duration of each debuff
        set debuffs[i].duration = debuffs[i].duration - 0.1
        // Check if the debuff has expired
        if debuffs[i].duration <= 0 then
            // Remove the debuff
            call RemoveDebuff(i)
        else
            // Move to the next debuff
            set i = i + 1
        endif
    endloop
endfunction

// Function to remove a debuff
function RemoveDebuff
    // Shift remaining debuffs in the array
    set integer j = index + 1
    loop
        exitwhen j > debuffIndex
        set debuffs[j - 1] = debuffs[j]
        set j = j + 1
    endloop
    // Reset the last debuff
    set debuffs[debuffIndex] = null
    set debuffIndex = debuffIndex - 1
endfunction

// Function to calculate damage taken by a unit from a specific group
function CalculateDamageTaken takes unit target, group damageGroup returns real
    local real damageTaken = 0.0
    local unit source
    local integer i = 1
    loop
        set source = FirstOfGroup(damageGroup)
        exitwhen source == null
        loop
            exitwhen i > debuffIndex
            if debuffs[i].source == source then
                // Apply damage increase
                set damageTaken = damageTaken + debuffs[i].damageIncrease
            endif
            set i = i + 1
        endloop
        call GroupRemoveUnit(damageGroup, source)
    endloop
    return damageTaken
endfunction

// Trigger to apply debuffs when a unit is hit
function InitTrig_ApplyDebuffs
    local trigger customTrigger = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(customTrigger, EVENT_PLAYER_UNIT_DAMAGED)
    call TriggerAddAction(customTrigger, function Trig_ApplyDebuffs_Actions)
endfunction

function Trig_ApplyDebuffs_Actions
    local unit target = GetTriggerUnit()
    local unit source = GetEventDamageSource()
    local group damageGroup = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(damageGroup, GetUnitLoc(target), 1000.0, null)
    if IsUnitInGroup(source, damageGroup) then
        // Apply debuff based on the source unit
        if source == UnitA then
            call ApplyDebuff(target, source, DAMAGE_INCREASE_B, DURATION_B)
            call ApplyDebuff(target, source, DAMAGE_INCREASE_C, DURATION_C)
        elseif source == UnitD then
            call ApplyDebuff(target, source, DAMAGE_INCREASE_B, DURATION_B)
            call ApplyDebuff(target, source, DAMAGE_INCREASE_C, DURATION_C)
        elseif source == UnitB then
            call ApplyDebuff(target, source, DAMAGE_INCREASE_D, DURATION_D)
        elseif source == UnitC then
            call ApplyDebuff(target, source, DAMAGE_INCREASE_D, DURATION_D)
        endif
    endif
    call DestroyGroup(damageGroup)
endfunction

// Trigger to update debuffs duration
function InitTrig_UpdateDebuffs takes
    local trigger customTrigger = CreateTrigger()
    call TriggerAddAction(customTrigger, function Trig_UpdateDebuffs_Actions)
    call TriggerRegisterTimerEventPeriodic(customTrigger, 0.1)
endfunction

function Trig_UpdateDebuffs_Actions
    call DebuffTimer()
endfunction

// Call the initialization functions
call InitTrig_ApplyDebuffs()
call InitTrig_UpdateDebuffs()
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
Can you not do MyVar[100][200] in Jass? I read a post from 2019 that said Jass now has 2D array support. Never seen it used before, though.
As far as I am aware this is a vJASS feature. It creates a virtual 2D array by some simple maths. This is why it needs a well defined size, and could potentially chain multiple arrays to get the required space back before array sizes were increased.
 
Top