• 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.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

New to vJass - Issue with custom combat system: looking for guidance

Level 2
Joined
May 16, 2021
Messages
5
Hi, I'm Bloom. Recently, I've been looking into vJass and the whole Warcraft3 coding and map making and got an idea: what if I make my custom combat system inside the game. Definitely easy for a rookie like me. So I put together some code, but the results, surprisingly, weren't ideal. It does not work, and I have no idea why.

What each lib does:
OriginCommands/SmallScriptA: This is where I defined all the custom functions I use for the later systems. Fuctions that help me get and set my custom values.
OriginDamageSystem/SmallScriptB: This is where I define what integer each value has, calculate damage, and execute said damage.
UnitValueStorage/SmallScriptC: This is where I set values to specific unit types. So it should be like: All Footmen(hfoo) have Blaze origin, Force damage type and X% Resistances.

How the code should behave: So I'm making classic rock, paper, scissors combat system with some added special elements (called origins inside the code). What I want it to do is:
A: Set origin, damage type and resistances to this all units of this unit type.

B: When damage is dealt, take origin of the attacker/caster and target, and calculate damage based on a certain logic (for example, Blaze origin unit attacking Growth origin unit should deal bonus +30% damage).

C: Show the damage as a text (works).

Problem: No values are being set, even though they should be... And many more problems, I'm trying to debug this code 3 days, and this is the simplest iteration of it... before, it at least set the values, now it doesn't even do that...

Additional info: I'm also using Bribe's Damage Engine 5.A.0.0 to register damage. I'm on the newest Warcraft3 version (unfortunately). I'm using the editor that comes with the wc3 version.

Below, I'm attaching files with the code and some additional pictures. Yes, this post is me basically asking, please run me through this thing. Or at least tell me if I'm on the right track or should never touch my keyboard again. For any advice or comment, thanks in advance.

The System In-depth:
Each unit has a Origin. They define Counters - bonus damage dealt. For example: Blaze deals bonus damage to Growth, but deals reduced damage to Tide.
Each unit deals either Force or Energy Damage.
Each unit has both Force and Energy Resistance, which reduce Force and Energy damage respectively.
The damage formula should be like this: BaseDamage the ability does * counter bonus * resistance reduction.
JASS:
library OriginCommands
    globals
        //This hashtable stores all the custom values of the combat system for each unittype present
        //in the campaign.
        hashtable CustomValues = InitHashtable()
        //Child keys for CustomValues. Parent key is the specific unit's unittype ex: hfoo
        constant integer KEY_ORIGIN = 0
        constant integer KEY_DMGTYPE = 1
        constant integer KEY_FRES = 2
        constant integer KEY_ERES = 3
    endglobals
    //Getters
    function getUOrigin takes unit u returns integer //get unit's u Origin
        return LoadInteger(CustomValues, GetUnitTypeId(u), KEY_ORIGIN)
    endfunction
    function getUDmgType takes unit u returns integer //get unit's u DmgType
        return LoadInteger(CustomValues, GetUnitTypeId(u), KEY_DMGTYPE)
    endfunction
    function getUFRES takes unit u returns real //get unit's u Force Resistance
        return LoadReal(CustomValues, GetUnitTypeId(u), KEY_FRES)
    endfunction
    function getUERES takes unit u returns real //get unit's u Energy Resistance
        return LoadReal(CustomValues, GetUnitTypeId(u), KEY_ERES)
    endfunction
    //Setters - 't' is unittype, so all unit's of one type will get the value. All Footman will have same values.
    function setUOrigin takes integer t, integer origin returns nothing //set's t's origin
        call SaveInteger(CustomValues, t, KEY_ORIGIN, origin)
    endfunction
    function setUDmgType takes integer t, integer dmgtype returns nothing //set's t's dmgtype
        call SaveInteger(CustomValues, t, KEY_DMGTYPE, dmgtype)
    endfunction
    function setUFRes takes integer t, real fres returns nothing //set's t's force res
        call SaveReal(CustomValues, t, KEY_FRES, fres)
    endfunction
    function setUERes takes integer t, real eres returns nothing //set's t's energy res
        call SaveReal(CustomValues, t, KEY_ERES, eres)
    endfunction
endlibrary
JASS:
library OriginDamageSystem initializer InitOriginDamageSystem requires DamageEngine, OriginCommands, UnitValueStorage
    //META
    globals
        //counter Multipliers
        constant real COUNTERS = 1.3 //When unit counters another
        constant real COUNTERED = 0.9 //When unit is countered by another
        constant real BASE = 1.0 //Normal damage without counter multipliers
        constant real LDCOUNTERS = 1.15 //Light and Decay only deal +15% Dmg when countering another
        constant real BUILTRES = 0.5 //Built takes -50% dmg from Force and Energy
        constant real BUILTMULT = 1.5 //Siege dmg deals +50% dmg to Built origin
        //origins
        constant integer NORMAL = 1
        constant integer PURE = 2
        constant integer BLAZE = 3
        constant integer TIDE = 4
        constant integer GROWTH = 5
        constant integer LIGHT = 6
        constant integer DECAY = 7
        constant integer BUILT = 8 //For special units eg.: Buildings, Battle Mechanisms, Siege Weapons, etc.
        //damage types
        constant integer FORCE = 1
        constant integer ENERGY = 2
        constant integer SIEGE = 3 //Special kind for dealing damage to Built Origin
    endglobals

    //Counter Damage Logic: Rock, Paper, Scissors, Nuclear Bomb
    function CounterLogic takes unit src, unit tgt returns real
        local integer caster = getUOrigin(src)
        local integer target = getUOrigin(tgt)
        local integer casterdmgtype = getUDmgType(src)
        if target == BUILT then  //if target is Built, then it doesn't matter what Origin is caster
            if casterdmgtype == SIEGE then
                return BUILTMULT
            else                    //If caster has Siege damage type, then it gains bonus, otherwise, penalty
                return BUILTRES
            endif

        elseif caster == NORMAL or caster == PURE then //NORMAL and PURE deal neutral damage to all,
            if target != LIGHT and target != DECAY then //but are countered by LIGHT and DECAY
                return COUNTERED
            else
                return BASE
            endif

        elseif caster == BLAZE then //BLAZE counters GROWTH, but is countered by TIDE
            if target == GROWTH then
                return COUNTERS
            elseif target == TIDE then
                return COUNTERED
            else
                return BASE
            endif

        elseif caster == TIDE then //TIDE counters BLAZE, but is countered by GROWTH
            if target == BLAZE then
                return COUNTERS
            elseif target == GROWTH then
                return COUNTERED
            else
                return BASE
            endif

        elseif caster == GROWTH then //GROWTH counters TIDE, but is countered by BLAZE
            if target == TIDE then
                return COUNTERS
            elseif target == BLAZE then
                return COUNTERED
            else
                return BASE
            endif

        elseif caster == LIGHT or caster == DECAY then //LIGHT and DECAY counter all (but itself) and
            if caster != target then                   //are immune to damage penalty.
                return LDCOUNTERS
            else
                return BASE
            endif
        endif
    return 0.0 //unit has no Origin
    endfunction
    //Resistances.
    function ResistanceLogic takes unit src, unit tgt returns real
        local integer caster = getUDmgType(src)
        local real targetFRes = getUFRES(tgt)
        local real targetERes = getUERES(tgt)
        local real resist = 0.0
        if caster == SIEGE then
            return resist
        elseif caster == FORCE then
            set resist = targetFRes
        else
            set resist = targetERes
        endif
    return resist
    endfunction
    function CalculateSystemDmg takes unit src, unit tgt returns real
        local real base = udg_DamageEventAmount //DamageEngine 5.A.0.0 var, should store damage dealt
        local real mult = CounterLogic(src, tgt)
        local real res = ResistanceLogic(src,tgt)
        local real final = 0.0
        set final = base*mult*(1-res) //base damage * counter multiplier * corresponding resistance
        return final
    endfunction
    function OnDamageTaken takes nothing returns nothing
        local real final
        // only run for basic attacks
        if not BlzGetEventIsAttack() then
            return
        endif
        // calculate damage
        set final = CalculateSystemDmg(GetEventDamageSource(), BlzGetEventDamageTarget())
        // debug log it
        call BJDebugMsg("OnDamageCustom fired!")
        call BJDebugMsg(R2S(final))
        // apply damage
        call BlzSetEventDamage(final)
    endfunction
    private function InitOriginDamageSystem takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DAMAGING)
        call TriggerAddAction(t, function OnDamageTaken)
        set t = null
        // EVENT_PLAYER_UNIT_DAMAGING // "About to take damage"
        // EVENT_PLAYER_UNIT_DAMAGED  // "Takes damage"
    endfunction
endlibrary
JASS:
library UnitValueStorage initializer InitValueStorage requires OriginCommands
    function setValues takes integer u, integer origin, integer dmgtype, real fr, real er returns nothing
        call setUOrigin(u, origin)
        call setUDmgType(u, dmgtype)
        call setUFRes(u, fr)
        call setUERes(u, er)
    endfunction
    function InitValueStorage takes nothing returns nothing
        call BJDebugMsg("ValueStorage initialized")
        call setValues('hfoo', BLAZE, FORCE, 0.0, 0.0) //Footman
        call BJDebugMsg("Now UnitOrigin['hfoo'] = " + I2S(UnitOrigin['hfoo']))
        call setValues('hpea', GROWTH, FORCE,0.0 ,0.0) //Peasant
        call BJDebugMsg("Now UnitOrigin['hpea'] = " + I2S(UnitOrigin['hpea']))
    endfunction
endlibrary

Edit 2.12.2025: Updated the code in the spoiler and attachments to reflect the up to date version Nichilus and Uncle helped me with.
 

Attachments

  • obrázok_2025-11-30_230734221.png
    obrázok_2025-11-30_230734221.png
    10.9 KB · Views: 18
  • Snímka obrazovky 2025-11-30 230604.png
    Snímka obrazovky 2025-11-30 230604.png
    173.8 KB · Views: 28
  • Snímka obrazovky 2025-11-30 230641.png
    Snímka obrazovky 2025-11-30 230641.png
    299.4 KB · Views: 22
  • Snímka obrazovky 2025-11-30 230651.png
    Snímka obrazovky 2025-11-30 230651.png
    36.3 KB · Views: 23
  • SmallScriptA.j
    SmallScriptA.j
    1.9 KB · Views: 26
  • SmallScriptC.j
    SmallScriptC.j
    620 bytes · Views: 19
  • smallscriptE.j
    smallscriptE.j
    5.2 KB · Views: 25
Last edited:
I did not dig too deep, so there may be other issues, but the first issue I see completely breaks the entire script and will require a rewrite.
Below is (part of) what is executed by your debug trigger:
JASS:
// in UnitValueStorage
function InitValueStorage takes nothing returns nothing
    ...    
   call setValues('hfoo', BLAZE, FORCE, 0.0, 0.0) //Footman
    ...

// in UnitValueStorage
function setValues takes integer u, integer origin, integer dmgtype, real fr, real er returns nothing
   ...
   call setUOrigin(u, origin)
   ...

// in OriginCommands
function setUOrigin takes integer t, integer origin returns nothing //set t's Origin to origin
    set UnitOrigin[t] = origin

// in OriginCommands globals:
globals
    integer array UnitOrigin //Stores Origin
   ...
The issue is rather simple: You use unit's unit-type id as an index to an array - that will not work. The string 'hfoo' translates to integer 1751543663. Yet the max allowed value for an array index is ~32767. Your unit's index is completely out of bounds and so no data are stored.

A solution could be
  • to rewrite your script to use hashtable instead of arrays, as hashtable can store large interger like 1751543663 as a key.
  • or, if you want to use arrays, make a mapping table/function, where the input is unit id and output is index for the array. It would basically be a large chain of "if-elseif" statements... that could get quite annoying to keep track of.
  • or you could actually use a struct which you instantiate. This instance would hold all your data. The disadvantage of this approach is that you would be constantly searching through all instances to find the correct instance for given unit... although this disadvantage could also be limited by, for example, cleverly using unit's custom value field.
 
I did not dig too deep, so there may be other issues, but the first issue I see completely breaks the entire script and will require a rewrite.
Below is (part of) what is executed by your debug trigger:
JASS:
// in UnitValueStorage
function InitValueStorage takes nothing returns nothing
    ...   
   call setValues('hfoo', BLAZE, FORCE, 0.0, 0.0) //Footman
    ...

// in UnitValueStorage
function setValues takes integer u, integer origin, integer dmgtype, real fr, real er returns nothing
   ...
   call setUOrigin(u, origin)
   ...

// in OriginCommands
function setUOrigin takes integer t, integer origin returns nothing //set t's Origin to origin
    set UnitOrigin[t] = origin

// in OriginCommands globals:
globals
    integer array UnitOrigin //Stores Origin
   ...
The issue is rather simple: You use unit's unit-type id as an index to an array - that will not work. The string 'hfoo' translates to integer 1751543663. Yet the max allowed value for an array index is ~32767. Your unit's index is completely out of bounds and so no data are stored.

A solution could be
  • to rewrite your script to use hashtable instead of arrays, as hashtable can store large interger like 1751543663 as a key.
  • or, if you want to use arrays, make a mapping table/function, where the input is unit id and output is index for the array. It would basically be a large chain of "if-elseif" statements... that could get quite annoying to keep track of.
  • or you could actually use a struct which you instantiate. This instance would hold all your data. The disadvantage of this approach is that you would be constantly searching through all instances to find the correct instance for given unit... although this disadvantage could also be limited by, for example, cleverly using unit's custom value field.
Thank you very much for answering! The system now properly registers Unit's custom values (to think this was the culprit).

However, I found another problem: The damage dealt to units is not the one it should be. I store my custom damage in a variable 'final' and then call udg_DamageEventAmount = final, however, the damage dealt is not the number in the final. Rather, it's the one in base(So unit's base damage because I set all armor reduction/amp to be 1.0). Maybe I'm registering something wrongly with DDS?. I even debuged it and 'final' does not change until new damage is being calculated.

This is the part of the code that should apply the damage:
Code:
function OnDamageCustom takes nothing returns nothing
        local unit src = udg_DamageEventSource
        local unit tgt = udg_DamageEventTarget
        local real final = CalculateSystemDmg(src, tgt)

        //apply custom damage
        set udg_DamageEventAmount = final

        //debug
        call BJDebugMsg("OnDamageCustom fired!")

        set src = null
        set tgt = null
    endfunction

    private function InitOriginDamageSystem takes nothing returns nothing
        call BJDebugMsg("OriginDamageSystem initialized")
        call RegisterDamageEngine(function OnDamageCustom, "Modifier", 1.0 )
    endfunction

endlibrary
 
I don't have much experience with the DDS's vjass api, but my guess is that call RegisterDamageEngine(function OnDamageCustom, "Modifier", 1.0 ) detects when unit is about to take damage, i.e. it is the pure calculated damage amount. However after that WC3 engine will modify the damage based on target unit's armor value as well as attack type of the incoming damage vs target's defense type.
For example: attack type "Pierce" deals double damage to defense type "Small" and attack type "Spells" deals 70% damage to defense type "Hero".

So unit takes 100 damage. You modify it via your system so that it deals only 90 damage, but because it is attack type Pierce and target's defense type is Small, it will deal 180 damage. That is then reduced by target's armor value, which is for example 25%, so the final damage is 135.... or something like that.

How much each attack type deals to each defense type can be changed via gameplay constants (WE's top bar menu -> advanced -> gameplay constants, there update the "Combat - Damage Bonus Table - {attack type}" fields).
 
I don't have much experience with the DDS's vjass api, but my guess is that call RegisterDamageEngine(function OnDamageCustom, "Modifier", 1.0 ) detects when unit is about to take damage, i.e. it is the pure calculated damage amount. However after that WC3 engine will modify the damage based on target unit's armor value as well as attack type of the incoming damage vs target's defense type.
For example: attack type "Pierce" deals double damage to defense type "Small" and attack type "Spells" deals 70% damage to defense type "Hero".

So unit takes 100 damage. You modify it via your system so that it deals only 90 damage, but because it is attack type Pierce and target's defense type is Small, it will deal 180 damage. That is then reduced by target's armor value, which is for example 25%, so the final damage is 135.... or something like that.

How much each attack type deals to each defense type can be changed via gameplay constants (WE's top bar menu -> advanced -> gameplay constants, there update the "Combat - Damage Bonus Table - {attack type}" fields).
I understand. All damage bonus tables are set to 1.0, so native Wc3 armor, damage and atttack type does not interfere with Base damage a unit should deal. The problem is, the system ignores "mult" and "res". I have a classic Footman with 12 damage. The footman always deals this damage, even though the system shows it should be 14.5 when testing against weaker element.

One thing I tried is changing "Modifier" in call RegisterDamageEngine(function OnDamageCustom, "Modifier", 1.0 ) to "After". I also have Floating Text system which shows damage dealt. After changing that string, the floating text shows the right value it should dealt, however the damage is still 12.

One way I could remedy this problem is using dummy units, but I would like to know why the code does not work. However, thanks for sticking till now.

(Also if any mod is curious why I edited the name of the post 2 times, it is because I thought the problem is solved and was too trigger happy)
 
Assuming you're on 1.31+, you could avoid using Damage Engine for now and test things using a barebones setup:
vJASS:
library DamageExample initializer Init

    private function OnDamageTaken takes nothing returns nothing
        local real final
        // only run for basic attacks
        if not BlzGetEventIsAttack() then
            return
        endif
        // calculate damage
        set final = CalculateSystemDmg(GetEventDamageSource(), BlzGetEventDamageTarget())
        // debug log it
        call BJDebugMsg("OnDamageCustom fired!")
        call BJDebugMsg(R2S(final))
        // apply damage
        call BlzSetEventDamage(final)
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DAMAGING)
        call TriggerAddAction(t, function OnDamageTaken)
        set t = null
        // EVENT_PLAYER_UNIT_DAMAGING // "About to take damage"
        // EVENT_PLAYER_UNIT_DAMAGED  // "Takes damage"
    endfunction

endlibrary
This would be a lot more efficient if this is the only thing you want out of the damage events.
 
Last edited:
I see. I re-checked triggers from your original post and I think I see an issue:
JASS:
// on init:
call RegisterDamageEngine(function OnDamageCustom, "Modifier", 1.0 )

// callback:
function OnDamageCustom takes nothing returns nothing
        local unit src = udg_DamageEventSource
        local unit tgt = udg_DamageEventTarget
        local real final = CalculateSystemDmg(src, tgt)
        //prevent native wc3 damage
        set udg_DamageEventAmount = 0.0
        //apply custom damage
        call UnitDamageTarget(src, tgt, final, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
The DDS internally listens to "Unit about to take damage" and "Unit takes damage" events, then it fires its own logic, before running your registered callbacks.
In the piece of code above, you calculate new damage which should be about right, as you've printed correct values/shown them via floating text.
However you set "udg_DamageEventAmount to zero", so no actual damage is done. Next you call "UnitDamageTarget", which essentially triggers both "Unit about to take damage" and "Unit takes damage" events again. So it would once again run your OnDamageCustom callback function, which would again null the damage and call UnitDamageTarget, etc. etc. :D

You could try to get rid of "call UnitDamageTarget", instead set udg_DamageEventAmount to the calculated value and call it a day. I think that DDS also allows you to change the attack and damage type using similarly named variables.
 
Assuming you're on 1.31+, you could avoid using Damage Engine for now and test things using a barebones setup:
vJASS:
library DamageExample initializer Init

    private function OnDamageTaken takes nothing returns nothing
        local real final
        // only run for basic attacks
        if not BlzGetEventIsAttack() then
            return
        endif
        // calculate damage
        set final = CalculateSystemDmg(GetEventDamageSource(), BlzGetEventDamageTarget())
        // debug log it
        call BJDebugMsg("OnDamageCustom fired!")
        call BJDebugMsg(R2S(final))
        // apply damage
        call BlzSetEventDamage()
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DAMAGING)
        call TriggerAddAction(t, function OnDamageTaken)
        set t = null
        // EVENT_PLAYER_UNIT_DAMAGING // "About to take damage"
        // EVENT_PLAYER_UNIT_DAMAGED  // "Takes damage"
    endfunction

endlibrary
This would be a lot more efficient if this is the only thing you want out of the damage events.
Version 2.0.3. This did the charm. The units deal damage they are supposed to. I mainly wanted to use DDS for future custom abilities, but it looks like it is not compatible with the newest version(?). Thank you for the script and help. I'm still new, so not everything in it is understandable for me at the moment, but I'll go through it and look around the scripting section. Tbh, I should familiarize myself with the basic wc API... Everything I know now is thanks to GUI, and even then I went straight from making basic Missile spells to a custom system with vJass.
I see. I re-checked triggers from your original post and I think I see an issue:
JASS:
// on init:
call RegisterDamageEngine(function OnDamageCustom, "Modifier", 1.0 )

// callback:
function OnDamageCustom takes nothing returns nothing
        local unit src = udg_DamageEventSource
        local unit tgt = udg_DamageEventTarget
        local real final = CalculateSystemDmg(src, tgt)
        //prevent native wc3 damage
        set udg_DamageEventAmount = 0.0
        //apply custom damage
        call UnitDamageTarget(src, tgt, final, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
The DDS internally listens to "Unit about to take damage" and "Unit takes damage" events, then it fires its own logic, before running your registered callbacks.
In the piece of code above, you calculate new damage which should be about right, as you've printed correct values/shown them via floating text.
However you set "udg_DamageEventAmount to zero", so no actual damage is done. Next you call "UnitDamageTarget", which essentially triggers both "Unit about to take damage" and "Unit takes damage" events again. So it would once again run your OnDamageCustom callback function, which would again null the damage and call UnitDamageTarget, etc. etc. :D

You could try to get rid of "call UnitDamageTarget", instead set udg_DamageEventAmount to the calculated value and call it a day. I think that DDS also allows you to change the attack and damage type using similarly named variables.
Sorry, but I made a lot of changes to the code, and did not update the files. I should've provided the correct up to date code, that's on me. Your answer is valid and I did do it, however it didn't work. The function looks like this currently:
JASS:
function OnDamageCustom takes nothing returns nothing
        local unit src = udg_DamageEventSource
        local unit tgt = udg_DamageEventTarget
        local real final = CalculateSystemDmg(src, tgt)
        //apply custom damage
        set udg_DamageEventAmount = final
        //debug
        call BJDebugMsg("OnDamageCustom fired!")
        set src = null
        set tgt = null
    endfunction
    private function InitOriginDamageSystem takes nothing returns nothing
        call BJDebugMsg("OriginDamageSystem initialized")
        call RegisterDamageEngine(function OnDamageCustom, "Modifier", 1.0 )
    endfunction
endlibrary
Again, sorry for not updating the code I posted here, that was dumb of me...
Anyway, the system does work thanks to Nichilus and Uncle, so I think this is solved. Thank you very much to all who participated, big respect. Even though I still don't know why the DDS version of the system didn't work. I'll try to do something more with the DDS and see if it is really imcompatible (which I doubt but wouldn't be the first time my version of Wc breaks everything made by others) or something else, more devilish is at play with the abominable code I made.

If this thread really does get closed, then I hope you all have wonderful rest of the week/weekend.
 
Version 2.0.3. This did the charm. The units deal damage they are supposed to. I mainly wanted to use DDS for future custom abilities, but it looks like it is not compatible with the newest version(?). Thank you for the script and help. I'm still new, so not everything in it is understandable for me at the moment, but I'll go through it and look around the scripting section. Tbh, I should familiarize myself with the basic wc API... Everything I know now is thanks to GUI, and even then I went straight from making basic Missile spells to a custom system with vJass.
It should be compatible, seems like you're making a mistake somewhere. I would try a later damage step and/or revisit what Nichilus suggested.

Anyway, the main thing you'll want for your custom spells is damage recursion, which Damage Engine provides. This is a features that prevents infinite loops that occur when you deal another instance of damage in response to a Damage Event. A unit Takes damage -> Deal damage -> Takes damage -> Deal damage -> Repeat infinitely.

If you don't need that protective measure then I'd suggest avoiding Damage Engine until you hit a wall where it seems necessary.
 
Last edited:
It should be compatible, seems like you're making a mistake somewhere. I would try a later damage step.

Anyway, the main thing you'll want for your custom spells is damage recursion, which Damage Engine provides. This is a features that prevents infinite loops that occur when you deal another instance of damage in response to a Damage Event. Takes damage -> Deals damage -> Takes damage -> Deals damage -> Repeat infinitely.

If you don't need than then I'd suggest avoiding Damage Engine until you hit a wall where it seems necessary.
I think so as well. I'll look into some code on the forums and maybe I'll find something that could help me learn how to do properly.
 
Back
Top