• 🏆 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!

New Damage Detection System. Asking for beta testers.

Status
Not open for further replies.
Level 24
Joined
Aug 1, 2013
Messages
4,657
Hi all.

This might sound weird but yes I want beta testers for my new Damage Detection System.

I am very new to WC3 triggering and JASS. (I started about august 2014.)
And I don't really know what should work wrong and what not.
I am very good at logics and I am learning game development but next to that I am a total noob.

So I made this DDS... No it is not a normal DDS.
This one was designed to change a unit's attack-type and even damage-type for basic attacks and change them for spells.
It is also designed to know how much damage the attacker wanted to deal to the targeted unit.

But as I said I am a very noob, I cannot test it and this is something that has to be finished.
I see a lot of people asking how to change a unit's attack-type for example.
Or change the damage-type of spells.

Now I hope I didn't scare you off with that I am a very noob because (imo) this system is very good and there is a lot of explaination within it.

  • DDS Initialize Global Variables
    • Events
    • Conditions
    • Actions
      • -------- ------------------------------------------------------------------------------------------- --------
      • -------- This must be the ability that has 2 spell damage reduction. --------
      • Set DDS_Ability_Revert_Spell_Dmg = DDS_Ability_Revert_Spell_Dmg
      • -------- ------------------------------------------------------------------------------------------- --------
      • -------- --------------------------------------------------------------------------- --------
      • -------- This must be the ability that gives infinite health. --------
      • Set DDS_Ability_Cheat_Death = DDS_Ability_Cheat_Death
      • -------- --------------------------------------------------------------------------- --------
      • -------- --------------------------------------------------------------------------- --------
      • -------- This will be the duration between each cleanup. --------
      • Set DDS_Reset_Interval = 5.00
      • -------- --------------------------------------------------------------------------- --------
      • -------- ------------------------------------------------------------------------------------------------------------------ --------
      • -------- Here you can change the effect type integers. --------
      • -------- There is no real benefit of what numbers they are. --------
      • -------- It is just for comfort and to easily see what damage effect types there are. --------
      • -------- DO NOT SET ANY OF THESE TO 0!!! --------
      • Set DDS_DET_Physical = 1
      • Set DDS_DET_Spell = 2
      • Set DDS_DET_Coded = 3
      • -------- ------------------------------------------------------------------------------------------------------------------ --------
  • DDS Initialize Standard Attack Damage Types
    • Events
    • Conditions
    • Actions
      • Set DDS_Unit_Type = Mortar Team
      • Set DDS_New_Attack_Type = Siege
      • Trigger - Run DDS_Trigger_Save_AT_DT (ignoring conditions)
      • Set DDS_Unit_Type = Siege Engine
      • Set DDS_New_Attack_Type = Siege
      • Trigger - Run DDS_Trigger_Save_AT_DT (ignoring conditions)
      • Set DDS_Unit_Type = Sorceress
      • Set DDS_New_Attack_Type = Magic
      • Trigger - Run DDS_Trigger_Save_AT_DT (ignoring conditions)
      • Set DDS_Unit_Type = Priest
      • Set DDS_New_Attack_Type = Magic
      • Trigger - Run DDS_Trigger_Save_AT_DT (ignoring conditions)
      • Set DDS_Unit_Type = Phoenix
      • Set DDS_New_Attack_Type = Magic
      • Trigger - Run DDS_Trigger_Save_AT_DT (ignoring conditions)
      • Set DDS_Unit_Type = Siege Engine (Barrage)
      • Set DDS_New_Attack_Type = Siege
      • Trigger - Run DDS_Trigger_Save_AT_DT (ignoring conditions)
JASS:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Wietlol's Damage Detection System 1.4b 24/01/2015
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Description:
//      This is a normal Damage Detection System that has the best features and most GUI friendly configuration.
//      The idea to create this system is to change a unit's attack-type or damage-type
//      and know how much damage a unit actually wanted to deal.
//      All standard functions of a decent DDS are included together with the special features designed by Wietlol.
//      To make use of this system, you are required to follow some rules. Every rule has his reasons why it exists.
//      Most rules are made because some features rely on that some things are just how they should be.
//      There is no ability or effect that is not supported or is no workaround for.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  How to install:
//      1. Copy or create all variables that are used in this map into your map.
//      2. Copy all triggers from the Damage Detection System (DDS) category and paste it into your map.
//      3. Create or copy the 2 custom abilities that are used in this map.
//         The Ability Cheat Death has a value that exceeds the standard maximum.
//         To increase the max life above the standard maximum open the field by pressing shift + enter.
//         Then set the value to 1.000.000
//      4. Set the abilities to their global variables in the Initialize Global Variable trigger.
//      5. Enjoy your Damage Detection System.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Feature list:
//      This system:
//      - allows you to change a unit-type's attack-type and damage-type of basic attacks through triggers. (In general.)
//      - allows you to change the attack-type and damage-type of spells on certain conditions. (On the OnDamage event.)
//      - allows you to change the attack-type and damage-type of unit's basic attacks on certain conditions. (On the OnDamage event.)
//      - allows you to create the following events:
//          - A unit takes physical damage -> Game - DDS_Event_Unit_Takes_Damage becomes Equal to 1 (By default*)
//          - A unit takes spell damage -> Game - DDS_Event_Unit_Takes_Damage becomes Equal to 2 (By default*)
//          - A unit takes coded damage -> Game - DDS_Event_Unit_Takes_Damage becomes Equal to 3 (By default*)
//          - A unit takes any damage -> Game - DDS_Event_Unit_Takes_Damage becomes Equal to 0
//          - A unit has taken physical damage -> Game - DDS_Event_Unit_Took_Damage becomes Equal to 1 (By default*)
//          - A unit has taken spell damage -> Game - DDS_Event_Unit_Took_Damage becomes Equal to 2 (By default*)
//          - A unit has taken coded damage -> Game - DDS_Event_Unit_Took_Damage becomes Equal to 3 (By default*)
//          - A unit has taken any damage -> Game - DDS_Event_Unit_Took_Damage becomes Equal to 0
//              * The values can be changed for the comfort of the map maker.
//                They can also be changed during gametime but that is dangerous and I don't know why you would do that.
//      - allows you to know the amount of damage, the attacker wanted to deal.
//      - allows you to modify that damage. (Only before damage.)
//      - allows you to change the attacker or target of the damage. (Only before damage.)
//      - allows you to know the amound of damage, the target has taken. (Only after damage.)
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Rules:
//      To make the features and the calculations work, you must follow some rules to use this system properly.
//      First of all, all units must have a default attack-type:
//          - Heroes must have Hero as attack-type.
//          - Melee units must have Normal as attack-type.
//          - Ranged units must have Pierce as attack-type.
//          You can modify the standard attack-type of units in the Initialize Standard Attack Damage Types.
//          You can also change the unit's damage type there and you can also change a unit's attack-type and damage-type
//          during gametime. These rules sounds fair.
//      Next to that, you may not use standard abilities that have a random effect on a unit's attacks.
//          These abilities must be triggered. Otherwise the calculations of original damage and actual damage dealt will fail.
//          There are examples of how you can trigger the abilities that are not allowed.
//          Remember only random effects are not allowed.
//          If you have an ability with 100% change, then you can use it.
//      You are also not allowed to use the standard spell damage reduction abilities. They won't work anyway.
//          These must also be made via triggers and there is a trigger that shows how you can do it.
//      Also triggered damage must be done via the DealDamage trigger.
//          This is because triggered damage is different from normal damage.
//          Therefor the system must know what you have used as damage modifiers to have a standard.
//          It is not hard to change and you have a lot of examples. So everyone can do it.
//      Last but not least. You are not allowed to play a map with this system without having fun.
//          I have my reasons. - Wietlol
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Variable explaination:
//////////////////////////
//      Map Initialization:
//      - DDS_Ability_Cheat_Death       - ability (integer in JASS)
//          This variable refers to the ability "Ability Cheat Death"
//          Ability id's can change between maps so this must be configurated on initialization.
//          
//      - DDS_Ability_Revert_Spell_Dmg  - ability (integer in JASS)
//          This variable refers to the ability "Ability Revery Spell Dmg"
//          Ability id's can change between maps so this must be configurated on initialization.
//          
//      - DDS_Hashtable                 - hashtable
//          This variable refers to the hashtable that is used to store data.
//          
//      - DDS_Reset_Interval            - real
//          This variable is set to a duration.
//          It is the duration between each re-initialization.
//          The lower, the more cleanups but don't set it too low.
//          A 60 seconds cleanup is about the minimum.
//          A 900 seconds cleanup is about the maximum.
//      
//      - DDS_Trigger_On_Damage         - Trigger
//          This is the trigger that runs the damage events.
//          This variable is modified and used within the system.
//          Don't change anything on it.
//
//////////////////////////
//      Event Response:
//      - DDS_Source                    - unit
//          This unit refers to the unit that deals the damage.
//          This variable can be changed on the before damage event.
//          
//      - DDS_Target                    - unit
//          This unit refers to the unit that will take the damage.
//          This variable can be changed on the before damage event.
//          
//      - DDS_Attack_Type               - attack-type
//          This is the attack type of the attack
//          This variable can be changed on the before damage event.
//          
//      - DDS_Damage_Type               - damage-type
//          This is the damage type of the attack.
//          This variable can be changed on the before damage event.
//          
//      - DDS_Weapon_Type               - combat sound (aka weapon-type)
//          This is the weapon type of the attack.
//          It only creates a sound but that could be nice too.
//          This variable can be changed on the before damage event.
//          
//      - DDS_Requested_Damage          - real
//          This is the amount of damage that a unit wants to deal.
//          This variable can be changed on the before damage event.
//          
//      - DDS_Dealt_Damage              - real
//          This is the damage that a unit has taken.
//          This variable can be read on the after damage event.
//          Modifying anything on the after damage event has no effect.
//          
//      - DDS_Damage_Effect_Type        - integer
//          This is an integer that tells what damage effect type the attack is.
//          If the attack is a basic attack then this is equal to DDS_DET_Physical
//          If the attack is from a spell then this is equal to DDS_DET_Spell
//          If the attack is coded then this is equal to DDS_DET_Coded
//          
//      - DDS_DET_Physical              - integer
//          This is the variable that refers to damage from basic attacks.
//          
//      - DDS_DET_Spell                 - integer
//          This is the variable that refers to damage from spells.
//          
//      - DDS_DET_Coded                 - integer
//          This is the variable that refers to coded damage.
//          
//////////////////////////
//      Events
//      - DDS_Event_Unit_Takes_Damage   - real
//          This event is called before damage is dealt. It is also known as the onDamage event.
//          When this variable becomes equal to DDS_DET_Physical, a unit is hit by a basic attack.
//          When this variable becomes equal to DDS_DET_Spell, a unit is hit by a spell.
//          When this variable becomes equal to DDS_DET_Coded, a unit is hit by a coded attack.
//          When this variable becomes equal to 0, a unit is hit by any form of damage.
//          
//      - DDS_Event_Unit_Took_Damage    - real
//          This event is called after damage is dealt. It is also known as the after damage event.
//          When this variable becomes equal to DDS_DET_Physical, a unit is hit by a basic attack.
//          When this variable becomes equal to DDS_DET_Spell, a unit is hit by a spell.
//          When this variable becomes equal to DDS_DET_Coded, a unit is hit by a coded attack.
//          When this variable becomes equal to 0, a unit is hit by any form of damage.
//          
//////////////////////////
//      Orders
//      - DDS_Trigger_Deal_Coded_Damage - Trigger (use TriggerExecute())
//          This trigger runs coded damage. It must be called instead of "damage target" for example.
//          It required the following variables to run:
//          - DDS_New_Source                - unit
//              The source of the coded damage.
//          - DDS_New_Target                - unit
//              The target of the coded damage.
//          - DDS_New_Damage                - real
//              The damage the source wants to deal.
//          - DDS_New_Attack_Type           - attack-type
//              The attack type that is used to deal the damage.
//          - DDS_New_Damage_Type           - damage-type
//              The damage type that is used to deal the damage.
//          (optional)
//          - DDS_New_Weapon_Type           - combat sound (aka weapon-type)
//              The sound that is played when you deal the damage.
//              This variable is optional.
//          
//      - DDS_Trigger_Save_AT_DT        - Trigger (use TriggerExecute() or Run (Trigger) (ignoring conditions))
//          This trigger saves a unit's attack type and/or damage type in the hashtable.
//          It requires the following variables to run:
//          - DDS_Unit_Type                 - unit-type (integer in JASS)
//              The unit type on which the new attack-type or damage-type is saved.
//          (optional)
//          - DDS_New_Attack_Type           - attack type
//              The attack type that the unit will use with basic attacks from now.
//              This variable is optional.
//          (optional)
//          - DDS_New_Damage_Type           - damage type
//              The damage type that the unit will use with basic attacks from now.
//              This variable is optional.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Changelog:
//      1.4a - Upload on the Hive for concept display.
//          - First release.
//          
//      1.4b - Upload on the Hive for beta test.
//          Documentation:
//          - Added the complete documentation.
//
//          Added Features:
//          - Deal coded damage.
//          - Change unit's standard attack-type and damage-type
//
//          Bug Fixes:
//          - Fixed a bug where new damage would occur before the timer on that unit expired. Resulting in infinite health for the unit.
//          - Fixed a lot of leaks and stupid code.
//
//      Upcoming release:
//          - Be able to tell the difference between ranged and melee units properly.
//          - Finish the spell reduction workaround. (Yes I said in the description that this already exist :D )
//          - Make examples for ability workarounds. (Yes I said in the description that they already exist :D )
//          - Adding all standard units in the Initialize Standard Attack Damage Types
//          - Create new features.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Known bugs:
//      - The check if a unit is melee bugs if a ranged unit will attack it,
//        then transform to a melee unit and then attacks a unit before the missile hits its target.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This code is handling the damage events and health resets.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This function resets the unit's health to the proper value after the WC3 standard damage is taken.
function Trig_DDS_Remove_Standard_Damage takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local unit u = LoadUnitHandle(udg_DDS_Hashtable, id, 0)
    local real health = LoadReal(udg_DDS_Hashtable, id, 1)
    
    //Set unit's health back to normal.
    call UnitRemoveAbility(u, udg_DDS_Ability_Cheat_Death)
    call SetUnitState(u, UNIT_STATE_LIFE, health)
    
    //Remove stuff
    call DestroyTimer(t)
    call FlushChildHashtable(udg_DDS_Hashtable, id)
    call FlushChildHashtable(udg_DDS_Hashtable, GetHandleId(u))
    set t = null
    set u = null
endfunction

//This function is reverting the damage to what the attacker wanted to deal.
function Get_Original_Damage takes nothing returns nothing
    local real originalHealth = GetUnitState(udg_DDS_Target, UNIT_STATE_LIFE)
    local real health = originalHealth
    local real totalFactor
    call UnitRemoveAbility(udg_DDS_Target, udg_DDS_Ability_Revert_Spell_Dmg)
    
    if health < 25 then
        call SetUnitState(udg_DDS_Target, UNIT_STATE_LIFE, 25)
        set health = GetUnitState(udg_DDS_Target, UNIT_STATE_LIFE)
    endif
    
    call UnitDamageTarget(udg_DDS_Target, udg_DDS_Target, 10, true, false, udg_DDS_Attack_Type, udg_DDS_Damage_Type, WEAPON_TYPE_WHOKNOWS)
    set totalFactor = (health - GetUnitState(udg_DDS_Target, UNIT_STATE_LIFE)) / 10
    
    call SetUnitState(udg_DDS_Target, UNIT_STATE_LIFE, originalHealth)
    call UnitAddAbility(udg_DDS_Target, udg_DDS_Ability_Revert_Spell_Dmg)
    set udg_DDS_Requested_Damage = udg_DDS_Requested_Damage / totalFactor
endfunction

//This function calculates the damages, calls the events and deals the actual damage.
function Trig_DDS_On_Damage takes unit source, unit target, real damage returns nothing
    //Set some required variables
    local boolean coded
    local boolean timerNotExpired
    local integer i
    local integer id = GetUnitTypeId(source)
    local real health
    local timer t
    local unit u
    
    //These variables are used to restore onDamage events that made this damage event.
    local unit oldSource
    local unit oldTarget
    local real oldRequestedDamage
    local real oldDealtDamage
    local integer oldDamageEffectType
    local attacktype oldAttackType
    local damagetype oldDamageType
    local weapontype oldWeaponType
    
    //Removing 0. damage attacks.
    //Attacks that deal 0 damage are ussually buff placers.
    //For abilities that have a 0 damage and triggered damage can be changed so they will use this system instead.
    if damage == 0. then
        return
    endif
    
    //If the timer of the last OnDamage event of this unit did not expire yet.
    //Run the actions and make sure that there will be a new timer.
    set t = LoadTimerHandle(udg_DDS_Hashtable, GetHandleId(target), 0)
    if t != null then
        set timerNotExpired = true
        call UnitRemoveAbility(u, udg_DDS_Ability_Cheat_Death)
        set health = LoadReal(udg_DDS_Hashtable, GetHandleId(t), 1)
        call SetUnitState(u, UNIT_STATE_LIFE, health)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_DDS_Hashtable, id)
        call FlushChildHashtable(udg_DDS_Hashtable, GetHandleId(u))
    endif
    
    //Make sure that the old values are correctly set to the variables before changing any.
    set oldSource = udg_DDS_Source
    set oldTarget = udg_DDS_Target
    set oldRequestedDamage = udg_DDS_Requested_Damage
    set oldDealtDamage = udg_DDS_Dealt_Damage
    set oldDamageEffectType = udg_DDS_Damage_Effect_Type
    set oldAttackType = udg_DDS_Attack_Type
    set oldDamageType = udg_DDS_Damage_Type
    set oldWeaponType = udg_DDS_Weapon_Type
    
    //Now we set the new values.
    set udg_DDS_Source = source
    set udg_DDS_Target = target
    set udg_DDS_Requested_Damage = damage
    
    //Determine what damage effect type the attack is.
    if udg_DDS_Damage_Effect_Type == udg_DDS_DET_Coded then
        set coded = true
        set udg_DDS_Attack_Type = udg_DDS_New_Attack_Type
        set udg_DDS_Damage_Type = udg_DDS_New_Damage_Type
        set udg_DDS_Weapon_Type = udg_DDS_New_Weapon_Type
    else
        set coded = false
        if damage < 0. then
            //Spell attacks are always NORMAL (Spell) and MAGIC (Magic).
            //Spell damage is reverted by the Spell Resistant ability and must be re-reverted to positive damage again.
            set udg_DDS_Attack_Type = ATTACK_TYPE_NORMAL
            set udg_DDS_Damage_Type = DAMAGE_TYPE_MAGIC
            set udg_DDS_Damage_Effect_Type = udg_DDS_DET_Spell
            set udg_DDS_Requested_Damage = udg_DDS_Requested_Damage * -1
        else
            //Normal attacks are basic attacks.
            //According to the rules, Heroes deal HERO (Hero) damage,
            //Melee units deal MELEE (Normal) damage and ranged units deal PIERCE (Pierce) damage.
            if IsUnitType(udg_DDS_Source, UNIT_TYPE_HERO) then
                set udg_DDS_Attack_Type = ATTACK_TYPE_HERO
            else
                if IsUnitType(udg_DDS_Source, UNIT_TYPE_RANGED_ATTACKER) then
                    set udg_DDS_Attack_Type = ATTACK_TYPE_PIERCE
                else
                    set udg_DDS_Attack_Type = ATTACK_TYPE_MELEE
                endif
            endif
            set udg_DDS_Damage_Type = DAMAGE_TYPE_NORMAL
            set udg_DDS_Damage_Effect_Type = udg_DDS_DET_Physical
        endif
        //Non-coded damage is already reduced. With this function, the DDS_Requested_Damage will restore to the original damage.
        //This trigger must be disabled of course. Enabling it again after the calculation does not need explaination does it?
        call DisableTrigger(udg_DDS_Trigger_On_Damage)
        call Get_Original_Damage()
        call EnableTrigger(udg_DDS_Trigger_On_Damage)
        set udg_DDS_Weapon_Type = WEAPON_TYPE_WHOKNOWS
    endif
    
    //Set the attack-type and damage-type to the attack and damage type that is specified in the hashtable.
    //These are configurable by the DDS_Trigger_Save_AT_DT trigger.
    set i = LoadInteger(udg_DDS_Hashtable, id, 0)
    if i > 0 then
        set udg_DDS_Attack_Type = ConvertAttackType(i - 1)
    endif
    set i = LoadInteger(udg_DDS_Hashtable, id, 1)
    if i > 0 then
        set udg_DDS_Damage_Type = ConvertDamageType(i - 1)
    endif
    
    //Fire the before damage events.
    set udg_DDS_Event_Unit_Takes_Damage = udg_DDS_Damage_Effect_Type
    set udg_DDS_Event_Unit_Takes_Damage = 0
    
    //Deal the damage and calculate the difference for the Dealt Damage variable.
    set health = GetUnitState(udg_DDS_Target, UNIT_STATE_LIFE)
    if udg_DDS_Requested_Damage > 0 then
        call DisableTrigger(udg_DDS_Trigger_On_Damage)
        call UnitRemoveAbility(udg_DDS_Target, udg_DDS_Ability_Revert_Spell_Dmg)
        call UnitDamageTarget(udg_DDS_Source, udg_DDS_Target, udg_DDS_Requested_Damage, true, false, udg_DDS_Attack_Type, udg_DDS_Damage_Type, udg_DDS_Weapon_Type)
        call UnitAddAbility(udg_DDS_Target, udg_DDS_Ability_Revert_Spell_Dmg)
        call EnableTrigger(udg_DDS_Trigger_On_Damage)
    endif
    set udg_DDS_Dealt_Damage = health - GetUnitState(udg_DDS_Target, UNIT_STATE_LIFE)
    
    //Fire the after damage event.
    set udg_DDS_Event_Unit_Took_Damage = 1
    set udg_DDS_Event_Unit_Took_Damage = 0
    
    //Create a 0 second timer.
    //This timer calls a function that will remove the WC3 standard attacks.
    //Coded damage has not ran a standard attack so then it will not create this action.
    if not(coded) or timerNotExpired then
        //Create the timer.
        set t = CreateTimer()
        call TimerStart(t, 0, false, function Trig_DDS_Remove_Standard_Damage)
        
        //Save the variables.
        set id = GetHandleId(t)
        set health = GetUnitState(target, UNIT_STATE_LIFE)
        
        //Save stuff to timer.
        call SaveUnitHandle(udg_DDS_Hashtable, id, 0, target)
        call SaveReal(udg_DDS_Hashtable, id, 1, health)
        
        //Save the timer to the unit.
        //If the unit is attacked before the timer expires, this will refer to the required data.
        call SaveTimerHandle(udg_DDS_Hashtable, GetHandleId(target), 0, t)
        
        //The unit may not die from that damage.
        call UnitAddAbility(target, udg_DDS_Ability_Cheat_Death)
    endif
    
    //Reset the values to the original damage source.
    set udg_DDS_Source = oldSource
    set udg_DDS_Target = oldTarget
    set udg_DDS_Requested_Damage = oldRequestedDamage
    set udg_DDS_Dealt_Damage = oldDealtDamage
    set udg_DDS_Damage_Effect_Type = oldDamageEffectType
    set udg_DDS_Attack_Type = oldAttackType
    set udg_DDS_Damage_Type = oldDamageType
    set udg_DDS_Weapon_Type = oldWeaponType
    
    //Fixing leaks... again.
    set source = null
    set target = null
    set t = null
    set u = null
    set oldSource = null
    set oldTarget = null
    set oldAttackType = null
    set oldDamageType = null
    set oldWeaponType = null
endfunction

//The function via the "(unit) takes damage" events.
function Trig_DDS_Taking_Damage takes nothing returns boolean
    call Trig_DDS_On_Damage(GetEventDamageSource(), GetTriggerUnit(), GetEventDamage())
    return false
endfunction

function Trig_DDS_Deal_Coded_Damage takes nothing returns nothing
    //Make sure that the events are properly executed.
    set udg_DDS_Event_Unit_Takes_Damage = 0
    set udg_DDS_Event_Unit_Took_Damage = 0
    
    //Deal the damage.
    call Trig_DDS_On_Damage(udg_DDS_New_Source, udg_DDS_New_Target, udg_DDS_New_Damage)
    
    //Don't force people to set a combat sound for each coded damage event.
    set udg_DDS_Weapon_Type = WEAPON_TYPE_WHOKNOWS
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This code creates the onDamage handler and add events to it.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This function runs for every unit that enters the map.
function Trig_DDS_Add_Entering_Units takes nothing returns boolean
    local unit u = GetEnteringUnit()
    
    //Add the entering unit to the onDamage trigger.
    call TriggerRegisterUnitEvent(udg_DDS_Trigger_On_Damage, u, EVENT_UNIT_DAMAGED)
    call UnitAddAbility(u, udg_DDS_Ability_Revert_Spell_Dmg)
    
    //Leak fixes.
    set u = null
    return false
endfunction

//This function adds all units on the map to the onDamage trigger.
function Trig_DDS_Add_Unit_From_Group takes nothing returns nothing
    local unit u = GetEnumUnit()
    
    //Add the picked unit to the onDamage trigger.
    call TriggerRegisterUnitEvent(udg_DDS_Trigger_On_Damage, u, EVENT_UNIT_DAMAGED)
    call UnitAddAbility(u, udg_DDS_Ability_Revert_Spell_Dmg)
    
    set u = null
endfunction

//This function (re)creates the onDamage trigger.
function Trig_DDS_Init_Damage_System takes nothing returns boolean
    local group g = CreateGroup()
    
    //Create a clean trigger.
    call DestroyTrigger(udg_DDS_Trigger_On_Damage)
    set udg_DDS_Trigger_On_Damage = CreateTrigger()
    
    //Add the events to the trigger.
    call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
    call ForGroup(g,function Trig_DDS_Add_Unit_From_Group)
    call DestroyGroup(g)
    set g = null
    
    //Add the action to the clean trigger.
    call TriggerAddCondition(udg_DDS_Trigger_On_Damage, Filter(function Trig_DDS_Taking_Damage))
    
    //Well it is still a condition ya know.
    return false
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This part is for saving the attack-type and damage-type of basic attacks on a unit-type.
//
//  In normal Warcraft, every unit-type can have its own attack-type.
//  With this system you can change the attack-type via triggers and even change the damage-type of basic attacks too.
//  What you have to do is set udg_DDS_Unit_Type to the unit that you want to give a different stat.
//  Then set udg_DDS_New_Attack_Type to the attack-type that you want your unit to have.
//  And set udg_DDS_New_Damage_Type to the damage-type that you want your unit to have.
//  After that, you run udg_DDS_Trigger_Save_AT_DT "TriggerExecute()".
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This function is saving a unit-type's basic attack-type and damage-type.
function Trig_DDS_Save_AT_DT_Actions takes nothing returns nothing
    if udg_DDS_Unit_Type > 0 then
        if udg_DDS_New_Attack_Type != null then
            call SaveInteger(udg_DDS_Hashtable, udg_DDS_Unit_Type, 0, ConvertAttackTypeReverse(udg_DDS_New_Attack_Type) + 1)
            set udg_DDS_New_Attack_Type = null
        endif
        if udg_DDS_New_Damage_Type != null then
            call SaveInteger(udg_DDS_Hashtable, udg_DDS_Unit_Type, 1, ConvertDamageTypeReverse(udg_DDS_New_Damage_Type) + 1)
            set udg_DDS_New_Damage_Type = null
        endif
        set udg_DDS_Unit_Type = 0
    endif
endfunction

//This function is making the trigger that runs the Trig_DDS_Save_AT_DT_Actions function.
function Trig_DDS_Initialize_Save_AT_DT takes nothing returns nothing
    set udg_DDS_Trigger_Save_AT_DT = CreateTrigger()
    call TriggerAddAction(udg_DDS_Trigger_Save_AT_DT, function Trig_DDS_Save_AT_DT_Actions)
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This code is the initialization of the triggers.
//
//  On map Initialization, the global variables are set in the gg_trg_DDS_Initialize_Global_Variables.
//  Every variable that can change between maps is set there next to some user preferences.
//  
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This function runs the configuration and initializes the system.
function Trig_DDS_System_Initialize takes nothing returns boolean
    local region rectRegion = CreateRegion()
    local trigger t = CreateTrigger()
    
    //Runs the configuration trigger. (gg_trg_DDS_Initialize_Global_Variables)
    set udg_DDS_Hashtable = InitHashtable()
    call TriggerExecute(gg_trg_DDS_Initialize_Global_Variables)
    
    //Create the attack-type and damage-type saving trigger. Then run the standard attack-type configuration trigger.
    call Trig_DDS_Initialize_Save_AT_DT()
    call TriggerExecute(gg_trg_DDS_Initialize_Standard_Attack_Damage_Types)
    
    //Initialize the Deal Coded Damage trigger.
    //This trigger is runned to deal coded damage.
    set udg_DDS_Trigger_Deal_Coded_Damage = CreateTrigger()
    call TriggerAddAction(udg_DDS_Trigger_Deal_Coded_Damage, function Trig_DDS_Deal_Coded_Damage)
    
    //Create the cleaning scedule and create the first system.
    call TriggerRegisterTimerEvent(t, udg_DDS_Reset_Interval, false)
    call TriggerAddCondition(t, Filter(function Trig_DDS_Init_Damage_System))
    call Trig_DDS_Init_Damage_System()
    
    //Create the handler for units that enter the entire map.
    set t = CreateTrigger()
    call RegionAddRect(rectRegion, GetWorldBounds())
    call TriggerRegisterEnterRegion(t, rectRegion, null)
    call RemoveRegion(rectRegion)
    call TriggerAddCondition(t, Filter(function Trig_DDS_Add_Entering_Units))
    
    //Some data leak fixes.
    set rectRegion = null
    set t = null
    call DestroyTrigger(gg_trg_DDS_System)
    return false
endfunction

//This is the initial function.
function InitTrig_DDS_System takes nothing returns nothing
    set gg_trg_DDS_System = CreateTrigger()
    call TriggerAddCondition(gg_trg_DDS_System, Filter(function Trig_DDS_System_Initialize))
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  End of the gg_trg_DDS_System trigger.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
And the map is in the attachments.

Don't mind the Game Time System.
That is merely for testing.

I hope I said everything that I wanted to say.

Thanks in advantage.

EDIT: Woops... wanted to post it in Project Recruitment... can someone place it there?
 

Attachments

  • Damage Detection System 1.4b.w3x
    39.5 KB · Views: 77
Level 31
Joined
Jul 10, 2007
Messages
6,306
This actually belongs in The Lab ; ).

Already notified mods.


There is actually a pretty cool script for handling types

https://github.com/nestharus/JASS/blob/master/jass/Systems/Type/script.j


Your took damage event is also bugged : (. It's supposed to run in reverse order /cry. Don't know how you're going to fix that. If you run it in the order you're running it right now, you'll destroy dependencies between data.

Stuff runs like this

Code:
enter A
    enter B
        enter C
        leave C
    leave B
leave A

All events that run "after" should run in reverse order. All events that run "before" or "during" should run in order.


Right now you have it running like this

Code:
enter A
    enter B
        enter C
leave A
    leave B
        leave C

Suppose A has data that B needs and B has data that C needs. in "leave A," A's data is destroyed, so B and C are now corrupt and won't run right.

In a full DDS with phases, it might be something like this

Code:
onDamage
    setup combat
    setup damage table (relies on combat)
    setup effects (relies on damage table)

onAfterDamage
    destroy effects
    destroy damage table
    destroy combat

How I fixed it for GUI was running through a list, but it was only a partial fix. Really not sure what you would do for GUI >.<.

Keep in mind that the stuff is registered by order of dependence, so it registers like this

combat
damage table
effects

for onDamage, it should be added in order of registration
for onAfterDamage, it should be added in reverse order of registration



This is a quick bug I can identify by looking at your code w/o even testing it : ).


I can simulate the bug by creating a scenario like I outlined. In that scenario, my data will become corrupt and my system that relies on this will fatal error.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
This actually belongs in The Lab ; ).
Ah I see... Well to be honest I never have seen that forum before.

There is actually a pretty cool script for handling types

https://github.com/nestharus/JASS/blob/master/jass/Systems/Type/script.j
Sorry but I already told you, I cannot read vJASS. I am sorry.

Your took damage event is also bugged : (. It's supposed to run in reverse order /cry. Don't know how you're going to fix that. If you run it in the order you're running it right now, you'll destroy dependencies between data.

How I fixed it for GUI was running through a list, but it was only a partial fix. Really not sure what you would do for GUI >.<.

So you say that I should change it into:

Set value = 1
Set value = 0

Like that and then it is fixed?

Sorry but this is not the same as entering a region.
These are actually 4 events.

Set value before damage = (>0)
Set value before damage = 0
Set value after damage = (>0)
Set value after damage = 0

These 4 events can be called in any order but this is the only good one.
It is not a bug until you can prove it to me via game response.
I am sorry but that is way faster than explaining it to me.

Today I learned from Xonok about phases... It is a very good idea.
I suppose that that replaces the evets.
Next to that... It is awesome.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
That won't fix it. You actually have to reverse the order of events on the trigger, which is impossible. The alternative is evaluating a list of triggers, but that'll break your API.


The idea of Type is to create new types for whatever. You can make types extend off of other types and then see if two types have a relation.

For example

magic damage
physical damage

elemental extends magic
fire extends elemental
water extends elemental

You can then do

Is my damage elemental damage? (would work with elemental, fire, or water)
Is my damage fire damage? (would work with fire)

etc

However, when you get into this, you start getting into damage tables. See, an attack is actually an aggregate of damage. Each piece of damage is a different type. Warcraft 3 has simple attacks where each attack is only one type of damage. In reality, each attack is a damage table. The damage table is modified and what not and then the damage is summed up and applied =). An attack also has various effects on it. It's a lot more complicated ; P. Type is just the first thing when you get into that. This is when you start crafting a combat system.

Long story short, a DDS shouldn't handle damage types. That belongs in a combat system =).
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
So I made this DDS... No it is not a normal DDS.
This one was designed to change a unit's attack-type and even damage-type for basic attacks and change them for spells.

As I told you, this is already possible with the existing DDS. For example in PDDS its basically just a 3-liner:

JASS:
private function OnDamage takes nothing returns nothing
	if ( PDDS.damageType == PHYSICAL and PDDS.source == <your unit>) then
		set PDDS.amount = 0.0
		call UnitDamageTargetEx(PDDS.source, PDDS.target, PDDS.amount, true, false, <your attacktype>, <your damagetype>, null)
	endif
endfunction

That will basically transform your attack-damage to an arbitrary damage- and attacktype of your choice.

So, to give you an advice, you should first overthink and outline what specific things will make your DDS unique and/or special over other already existing DDS. Because to me it seems that you don't know yet what already can be done with a good DDS and knowing that would be crucial if you really want to code your own.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
As I told you, this is already possible with the existing DDS. For example in PDDS its basically just a 3-liner:
So you want to change it into coded attacks... could do that yes.
Still I think that mine is easier to use.

EDIT: Next to that, yours bugs. Your damage is reduced twice.
1: (Unit) takes damage. (already reduced damage)
2: You use a different damage type than universal... attack type is also a bit restricted.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
So you want to change it into coded attacks... could do that yes.

You seem to refuse any constructive critique.

Your system also uses coded attacks. Its btw to only way to do this. And 3 lines is basically as easy as it can get.

Still I think that mine is easier to use.

I can't see any usage in your map where you change the damage/attacktype. But I see constraints like:

- Heroes must have Hero as attack-type.
- Melee units must have Normal as attack-type.
- Ranged units must have Pierce as attack-type.
- Next to that, you may not use standard abilities that have a random effect on a unit's attacks.


Thats a joke, right?

EDIT: Next to that, yours bugs. Your damage is reduced twice.
1: (Unit) takes damage. (already reduced damage)
2: You use a different damage type than universal... attack type is also a bit restricted.

No it doesn't bug. The damage amount calculation is up the user because it is map specific. And whether one should use damage type universal also totally depends of the actual map.

But I'm out now, this discussion doesn't make any sense.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Of course it is not... You can set a unit's attack-type and damage-type to anything you want.
The problem is you have to do it via triggers.
In the object editor though, every unit must have those attack-types as specified.

A random effect is affecting the actual data of the attacks, but not always. That's why you have to trigger it.
You got a DDS so it is no big deal.

In my DDS you set the attack-type and damage-type like this:
  • DDS Test 5
    • Events
      • Game - DDS_Event_Unit_Takes_Damage becomes Equal to 1.00
    • Conditions
      • (Unit-type of DDS_Source) Equal to Mountain King
    • Actions
      • Set DDS_Attack_Type = Spells
      • Set DDS_Damage_Type = Universal
This one does not have the already reduced damage.

The rules make the difference.
Yours is reduced damage, mine is not. If the rules are followed.

EDIT: The concept is simple: You follow my rules, you may use my system to have a BETTER workaround for what my rules limit you.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
One question


Do you want to code a legit DDS or not? : )


You can either learn the hard way when stuff breaks, or you can learn the easy way and accept comments from people who have already coded DDS's : P

My recommendation is to drop onTookDamage or whatever as right now it's broken and I don't see any way of fixing it while supporting GUI at the same time ; )

My next recommendation is to not do DDS_Attack_Type and DDS_Damage_Type. These are specific to a combat system. The more definitions you have, the more map specific your resource is. Try to keep it as broad as possible.

For example, your features would be completely useless with a damage table ; ).

If I can find something that your base resource doesn't support while it does support other things (like your damage type stuff), then those features should be dropped.

Basic damage types: JASS vs Physical vs Spell, can support absolutely everything. It's like the lowest level you can go. As soon as you go up one level, you get into map specific nonsense.

Melee/Ranged detection is cool and all, but there is no such thing as melee or ranged damage. Those are attacks. Do attacks belong in a DDS? Probably not.

Take it from someone that has built I think 4 DDS's.


Also, each restriction you place on your system is another major reason to not use it. LFH had to really argue with the community for detecting spell damage with magic resistance. In the end, we all concluded that it was worth it ; ).

Everyone gets put through the wringer. It's like a right of passage here. You end up coming out as a much better coder ;o. People no longer fight over me with my vJASS stuff, but people certainly do fight with me over c++ and such because I have less experience.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
You can either learn the hard way when stuff breaks, or you can learn the easy way and accept comments from people who have already coded DDS's : P
I do... but those people do not understand my comments on theirs.
He said he could change attack type and damage type.
I said: Yes that is good.
Then he sais: You are doing equal as bad.
Now who is toxic?

My recommendation is to drop onTookDamage or whatever as right now it's broken and I don't see any way of fixing it while supporting GUI at the same time ; )
As I said. I CANNOT see a way how it is broken. Show me with triggers/JASS.
I can tell you that it is not broken because I know how this one works.
It is not reliant on the other. It is a self constructive event... Until you prove me wrong ofcourse.

My next recommendation is to not do DDS_Attack_Type and DDS_Damage_Type. These are specific to a combat system. The more definitions you have, the more map specific your resource is. Try to keep it as broad as possible.

For example, your features would be completely useless with a damage table ; ).
It doesn't matter if someone changes the damage table of WC3.
Neither does it matter if someone uses his self created damage table.
So I dont get your point.

If I can find something that your base resource doesn't support while it does support other things (like your damage type stuff), then those features should be dropped.
Sounds fair. As long as those base resources are not able to restore with not much more work.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Melee/Ranged detection is cool and all, but there is no such thing as melee or ranged damage. Those are attacks. Do attacks belong in a DDS? Probably not.
So ranged units must also have the normal attack type.
more configuration.
Better reliability.
But I am still working on it and I might finish my melee/ranged check within a few days.


Also, each restriction you place on your system is another major reason to not use it. LFH had to really argue with the community for detecting spell damage with magic resistance. In the end, we all concluded that it was worth it ; ).
I am too new to have experienced that discussion...
But for every restriction there is a workaround.
And who can tell how much damage the attacker wanted to do without reverting the damage?

Everyone gets put through the wringer. It's like a right of passage here. You end up coming out as a much better coder ;o. People no longer fight over me with my vJASS stuff, but people certainly do fight with me over c++ and such because I have less experience.
I don't fight anyone if it concerns vJASS... because I won't have anything to say at all.
For real languages, I only talk about Java or C# as I only have learned those two and I am still not very good at it.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
I do... but those people do not understand my comments on theirs.
He said he could change attack type and damage type.
I said: Yes that is good.
Then he sais: You are doing equal as bad.
Now who is toxic?

You are perverting the facts here. You said one reason you make this DDS is that you can change the damagetype and attacktype of damage. I responded that this is already supported by existing DDS.

Your DDS btw doesn't do any better btw. You have here:

JASS:
call UnitDamageTarget(udg_DDS_Source, udg_DDS_Target, udg_DDS_Requested_Damage, true, false, udg_DDS_Attack_Type, udg_DDS_Damage_Type, udg_DDS_Weapon_Type)

which is basically the same thing as in my DDS. With the difference that the user has to set global variables instead of using one single function call. And this method has exactly the same problems with double damage reduction as any other DDS.


As I said. I CANNOT see a way how it is broken. Show me with triggers/JASS.

First you learn whats a widget. Then come again.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
A damage table in DDS would be a table of damage, not multipliers.

When I attack with my flaming sword, it has two types of damage on it. Fire damage and physical damage.

Let's say that the flaming sword does 75 fire damage and 125 physical damage.

table[fire] = 75
table[physical] = 125

These values can't be written unless the table is constructed.


library CombatSystem
library DamageTable requires CombatSystem
library MyItem requires DamageTable
library FireDamage requires DamageTable
library PhysicalDamage requires DamageTable
library DamageTag requires DamageTable

That is a set of libraries, otherwise known as resources. They are ordered by requirements. The order defines code execution and what not, so the above is executed in the following order during map initialization.

CombatSystem
DamageTable
MyItem
DamageTag

CombatSystem registers to the damage event. It needs to be able to both set up a combat system and then clean it, so it registers twice, once to on take damage and once to on took damage.

onTake.register(CombatSystem)
onTook.register(CombatSystem)

DamageTable is the same way

onTake.register(DamageTable)
onTook.register(DamageTable)


after we do all of registration, we run this code in this order


onTake.register(CombatSystem)
onTook.register(CombatSystem)
onTake.register(DamageTable)
onTook.register(DamageTable)
onTake.register(MyItem)
onTook.register(DamageTag)


DamageTag is used to display a texttag of damage taken. Cool huh?

This is the order in which the registered code is run on your two events.

onTake
-CombatSystem
-DamageTable
-MyItem

onTook
-CombatSystem
-DamageTable
-DamageTag

Seems ok, right?

So, now let's analyze what happens when damage happens

-begin onTake
1. Combat system creates an environment
2. Damage table created
3. My item applies damage to the damage table (fire, physical)
-begin onTook
4. Combat system is destroyed (uh oh)
5. Damage table tries to create damage and send it to the combat system, but a fatal error occurs because the combat system is no longer in memory. Damage table is destroyed if this fatal error doesn't happen.
6. Damage tag tries to output data from the damage table, but it's gone, thus Damage Tag fatal errors.


This is the order that the code should run in

onTake
-CombatSystem
-DamageTable
-MyItem

onTook
-DamageTag
-DamageTable
-CombatSystem


This means that you need to evaluate a trigger in reverse. If you run it in the above order, a fatal error won't occur. The code will still be registered in the same order, you just run some of it in reverse.

Now, we can argue about this all day, but this won't fix your event. The above problem I just outlined will still be there, meaning that anyone that dares to use your new cool event will just get a crash.



This means that unless you fix onTook, you are just going to get fatal errors whenever you use it. If all you get is a fatal error by using it, it should be dropped. If you aren't going to implement it right, don't implement it at all.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
And this method has exactly the same problems with double damage reduction as any other DDS.
Ok now I got permission to kill you.
MY SYSTEM IS DESIGNED TO FIND OUT HOW MUCH DAMAGE THE ATTACKER WANTED TO DEAL. AND IT WORKS!!!
Do you understand?
That is why every unit must have pre-determined attack-types in the object-editor.
That is why this system had the requirement to change a unit-types attack and damage type.
(without if then else every onDamage event)

Sorry I try not to be toxic right now but you just shout empty statements.

First you learn whats a widget. Then come again.
I asked... noone answers.
I said I am a new and dont understand everything of JASS.
So explain or give me a link where I can find out exacly what it is.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Level 24
Joined
Aug 1, 2013
Messages
4,657
-begin onTake
1. Combat system creates an environment
2. Damage table created
3. My item applies damage to the damage table (fire, physical)
-begin onTook
4. Combat system is destroyed (uh oh)
5. Damage table tries to create damage and send it to the combat system, but a fatal error occurs because the combat system is no longer in memory. Damage table is destroyed if this fatal error doesn't happen.
6. Damage tag tries to output data from the damage table, but it's gone, thus Damage Tag fatal errors.
That makes sense... but if you explain it to me like that, I can assume that you can do this:

Event -> BeforeDamage:
Action:
set system = CreateCombatSystem()
set table = CreateDamageTable(system)
set item = CreateItem(table)

Event -> AfterDamage
Actions:
call DestroyItem(item)
call DestroyDamageTable(table)
call DestroyCombatSystem(system)

I would like to believe you but my mind sais that the logic is not right.
The afterDamage event is a simple game-event.
There is nothing to fix about a game-event.
But to recall I said I would be trouble if you wanted to explain.
If you can give me an example where the test crashes... I finally understand what you say.

Information on a widget can be found on thehelper wiki and common.j =)

http://wiki.thehelper.net/wc3/jass/common.j/widget
http://wiki.thehelper.net/wc3/jass/common.j/Widget_API

JASS:
type widget             extends     agent  // an interactive game object with life
type unit               extends     widget  // a single unit reference
type destructable       extends     widget
type item               extends     widget
It is not like there is any event that handles "a widget takes damage" is there?
Or what can a widget do more than a unit?
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
Ok now I got permission to kill you.

Its not my fault that you don't understand/missinterpred everything. You are just agressive and throwing around with insults and assumptions but expect people to help you. Although you even admit you have no idea about many game internals. Thats not how things work.

MY SYSTEM IS DESIGNED TO FIND OUT HOW MUCH DAMAGE THE ATTACKER WANTED TO DEAL. AND IT WORKS!!!

This works in all DDS. You understand? Someone using PDDS can also just setup the damage table/types such that it fits his needs and his specific map.

Sorry I try not to be toxic right now but you just shout empty statements.

Your system is just badly bugged. Even such a simple thing like damage blocking doesn't work:

  • OnDamage
    • Events
      • Game - DDS_Event_Unit_Takes_Damage becomes Equal to 1.00
    • Conditions
    • Actions
      • Set DDS_Requested_Damage = 0.00
doesn't work reliable. Take a Mountain King, set his bash skill to maximum (100% chance in the object editor) and attack a unit. You will see the blocking doesn't work.

Maybe fix those basics first before going on a rampage here...
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
That makes sense... but if you explain it to me like that, I can assume that you can do this:

Event -> BeforeDamage:
Action:
set system = CreateCombatSystem()
set table = CreateDamageTable(system)
set item = CreateItem(table)

Event -> AfterDamage
Actions:
call DestroyItem(item)
call DestroyDamageTable(table)
call DestroyCombatSystem(system)

I can't do it like that though. Every resource is completely independent. You can't mix/match how they are registered. The first resource is registered completely, then the second, and so on. It's impossible to do it any other way.

Also, you are proposing that you just hardcode all of these general purpose systems into one resource. I seriously don't recommend that.

The only way you can register them is in this order

onTake.register(CombatSystem)
onTook.register(CombatSystem)
onTake.register(DamageTable)
onTook.register(DamageTable)
onTake.register(MyItem)
onTook.register(DamageTag)

There is no other way. That's the order you get.

Your system, with that order, gives you this

onTake
-CombatSystem
-DamageTable
-MyItem

onTook
-CombatSystem
-DamageTable
-DamageTag

That's what your system gets. You can't say your system gives you something else or that the user should somehow make it give something else because your system gives you that and the user is powerless to do anything about it.

The resources are cnp'd into a map. They don't about the others and they have no access to private members or how each other resource is registered. They each run themselves and dependencies just state that one resource relies on the data of another resource.

You can't expect a user to take 50 resources and then cut them apart and mash them into one resource (a ton of recoding) just to get your system to work. Now just imagine if one of these resources is updated, they get to do it again. That's ridiculous to expect a user to do that.

Just fix your bloody event.

And I already gave you an example. The only code I'd write is vJASS and I'd use Trigger to showcase what I mean with ErrorMessage, but you won't read it or run it so I'm not even going to bother. Why? Because you have this weird attitude that vJASS is the root of all evil.


I told you that your event was broken and I told you why plus I gave an in-depth example. I'm done here. Your resource will never be approved on this site so long as you do what you are doing and it'll be rejected for the reasons me, lfh, and edo494 have pointed out, so have fun using your broken resource for yourself. Nobody else will use it and it won't be approved anywhere. I've explained everything with great detail and you still just say no. Why? Because in your mind, a user should be responsible for taking apart all of the code they use from all resources they use and making 1 super giant all powerful resource out of it that does everything and is super hard coded. If one component gets updated, they get to start over. That is the only way the scenario you mentioned will ever be able to occur. That's not how we roll on THW.

You're on your own bro. Talking to you is pointless ; ).

Also, given your approach, you should just drop all events and have users cnp code into your functions. After all, that's what you seem to be advocating with using it. Unless you are just saying that if something's broken, it's not your problem? -.-
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
This works in all DDS. You understand? Someone using PDDS can also just setup the damage table/types such that it fits his needs and his specific map.
I cannot see it.
Where is it?

Your system is just badly bugged. Even such a simple thing like damage blocking doesn't work:

  • OnDamage
    • Events
      • Game - DDS_Event_Unit_Takes_Damage becomes Equal to 1.00
    • Conditions
    • Actions
      • Set DDS_Requested_Damage = 0.00
doesn't work reliable. Take a Mountain King, set his bash skill to maximum (100% chance in the object editor) and attack a unit. You will see the blocking doesn't work.

Maybe fix those basics first before going on a rampage here...

So mine is badly bugged...
Can I ask you something?
What does this do?
  • Test
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
      • (Unit-type of PDD_source) Equal to Mountain King
    • Actions
      • Set PDD_amount = 0.00
Why? Because you have this weird attitude that vJASS is the root of all evil.
WAAAAAT???
That is what you say.
I only say that I use plain JASS because everyone is able to run it.
And because JASS could do the same. It just takes more time.
That is why I don't bother difficult systems.


I told you that your event was broken and I told you why plus I gave an in-depth example. I'm done here. Your resource will never be approved on this site so long as you do what you are doing and it'll be rejected for the reasons me, lfh, and edo494 have pointed out, so have fun using your broken resource for yourself. Nobody else will use it and it won't be approved anywhere. I've explained everything with great detail and you still just say no. Why? Because in your mind, a user should be responsible for taking apart all of the code they use from all resources they use and making 1 super giant all powerful resource out of it that does everything and is super hard coded. If one component gets updated, they get to start over. That is the only way the scenario you mentioned will ever be able to occur. That's not how we roll on THW.

You're on your own bro. Talking to you is pointless ; ).

Also, given your approach, you should just drop all events and have users cnp code into your functions. After all, that's what you seem to be advocating with using it. Unless you are just saying that if something's broken, it's not your problem? -.-
hmm...
 
Last edited:
Level 23
Joined
Apr 16, 2012
Messages
4,041
so lets do a summary, you bitch about other DDSs being limiting, yet you force people to basically limit attack types, and you also have to manually registed units with siege attacks.

It doesnt matter if you can change them with triggers, if you make every unit have normal attack, noone will expect priests to have magical attack, even if you change it with triggers.

Also I can bet this will flicker the health bars.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
so lets do a summary, you bitch about other DDSs being limiting, yet you force people to basically limit attack types, and you also have to manually registed units with siege attacks.

It doesnt matter if you can change them with triggers, if you make every unit have normal attack, noone will expect priests to have magical attack, even if you change it with triggers.
I do not limit units with attack types.
I just change the location where it is made.
If a priest wants a magical attack, it can have it.
You just do not set it in the object editor.
What is so hard to understand about that?

Also I can bet this will flicker the health bars.
I was actually surprised that it is unnoticeable.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
Imagine you play a game, and it says prist has Piercing attack. You most likely wont even think about the unit having different attack type behind the scenes, so it is totally unintuitive.

Edit: So in conclusion, you are far more limiting, because while the other DDS systems dont allow you to use Wait, which is horrible anyway, but there is workaround(Timers), meanwhile you just force units to visually appear with fixed attack type, and it seems quite useless, because it has the very same problem that I mentioend(morphing).
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Imagine you play a game, and it says prist has Piercing attack. You most likely wont even think about the unit having different attack type behind the scenes, so it is totally unintuitive.
Now you said something that has not been said before.
I have not thought about that... mostly because I never read that thing.
Well I could do it in another way.
It is actually the same... but I rely on different things.
But fair enough. I tell people in the UI that a priest deals pierce damage when he doesn't. So it must be changed.
In the next update, I will not have a fixed attack type on ranged units but rather an attack type fixed on unit type.

because it has the very same problem that I mentioend(morphing).
Do you mean when telling the difference between melee and ranged units?
Because that will be implemented as soon as possible.

Oh yea, trigger actions are like 20% slower or something than trigger evaluations. I don't remember exactly what it was, I just remember that it was a lot more than .001% : P


trigger actions are significantly slower ;D

Good thing that I dont use Actions in mine isn't it?
at least none which are called by events.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
I cannot see it.
Where is it?

Learn how it works, then you will see it on your own. One can notice that you just Copy and Pasted this stuff together without an understanding what really happens in the internals.


So mine is badly bugged...
Can I ask you something?
What does this do?

You are missusing the system. Put the if inside the action and everything works. In contrary to that, your system doesn't work even without any condition. It is even broken for just pure damage detection.

Look in the testmap. Take the rifleman and attack the grunt. Displayed damage is 31.25, dealt damage is 62.5. Although no modifiers are involved, just a simple display damage:

  • TookDamage
    • Events
      • Game - DDS_Event_Unit_Took_Damage becomes Equal to 0.00
    • Conditions
    • Actions
      • Game - Display to (All players) the text: (Damage dealt is: + (String(DDS_Dealt_Damage)))
You bawl around here

IT WORKS!!!

Nothing works. Not even simple plain damage detection.

This system is deeply broken. What happens if a unit has less than 10 max HP? It will die due to your detection. But you don't listen to anybody anyways.

EDIT:
Just to let you know, there are much more heavy problems with your approach:

- Setting every ranged unit to piercing kills the purpose of the armor table - how should a Meta-DH deal damage to divine armor without chaos damage?
- From the first point directly follows that you have to index all units on the map to adapt their damage accordingly. This breaks the purpose of having an attack/damagetype detection.
- Setting all ranged attacks to piercing also breaks siege units. Take an orc destroyed and attack the grunt - it will not explode due to not having siege damage. Thats not acceptable because its gameplay changing.
- Your modification also fails for ultimates: Even though I set Requested_Damage to zero, ultimates still deal damage, making them basically unblockable.
- Your detection also fails for ultimates, as they usually don't have DAMAGE_TYPE_MAGIC - good luck detecing whether a spell damage was an ultimate or not.
- Whats going on with spirit link? Doesn't work at all in your uploaded map.
 

Attachments

  • BrokenDDS.w3x
    38.5 KB · Views: 59
Last edited:
Level 24
Joined
Aug 1, 2013
Messages
4,657
I know that most people in here have more knowledge about wc3 and can code better and have more experience in jass.

*grabs popcorn* best comedy film ever *grabs popcorn*

On my perspective,it is Wietlol who misunderstood things here. Wait until DSG kicks your ass. Nestharus kicked your ass now.

Moral lesson:
Never challenge the guy who created the no. 1 Resource of all time

If you want to know why I cannot believe what Nestharus said. I will be glad to explain.
But then you got to read all.

He said that my event "after damage" was bugged because it would run stuff in the wrong order.
If stuff is runned in the wrong order and it crashes it is a serious bug indeed.
However the event does not run anything. It is an event.
Imagine this:
  • Untitled Trigger 001
    • Events
      • Map initialization
      • Unit - A unit Dies
      • Player - Player 1 (Red) Selects a unit
      • Time - Every 2.00 seconds of game time
    • Conditions
    • Actions
How can that bug?
That is in fact what Nestharus tells me all the time.

However, an event can bug. But it only does if it should be called but is not or when it is called when it shouldn't.

He also said that if I would remove the event "after damage", it would all be fixed.
So he actually knew that it was not the event.
It was how the response to that event would have been set up.
But fair enough. I will remove it.
So it is all fixed.
Now I add it again.
Nothing in the entire world will use it because everyone thought it was removed.
So it is not used and so it does not bug.

To be honest. The "after damage" event did have a bug.
But as I explained it was because it didnt call itself properly.
It was this: set udg_DDS_Event_Unit_Took_Damage = 1.
But it should have been set to the variable instead. (after getting it from a local variable if people were so smart to change that global variable in the "takes damage" response)


EDIT: Now that I think of the phases events again. I do see why Nestharus blamed it on my event.
In a phases system that would not occur.
However, if I can assume that the combat system, damage table and item stuff is made to match with each other.
I am sure that the combat system knows that it has to destroy its childs too.

onTake.register(CreateCombatSystem)
onTook.register(DestroyCombatSystem)
onTake.register(CreateDamageTable)
CombatSystem.onDestroy.register(DestroyDamageTable)
onTake.register(CreateMyItem)
DestroyDamageTable.onDestroy.register(DestroyDamageTag)

I would think of something like this.
Even though. After talking to Xonok for a while, I will create the phases stuff.
In that case you could do this:

onTake(1).register(CreateCombatSystem)
onTook(3).register(DestroyCombatSystem)
onTake(2).register(CreateDamageTable)
onTook(2).register(DestroyDamageTable)
onTake(3).register(CreateMyItem)
onTook(1).register(DestroyDamageTag)

which result in this:

onTake(1).register(CreateCombatSystem)
onTake(2).register(CreateDamageTable)
onTake(3).register(CreateMyItem)
onTook(1).register(DestroyDamageTag)
onTook(2).register(DestroyDamageTable)
onTook(3).register(DestroyCombatSystem)

--------------------------------------------------------------------------------------------------------------------------------------------------

This system is deeply broken. What happens if a unit has less than 10 max HP? It will die due to your detection. But you don't listen to anybody anyways.
Here looking_for_help sais something that I thought I removed but apparently didn't.
I think that I had too much on my mind at the time I thought about that.

- Your modification also fails for ultimates: Even though I set Requested_Damage to zero, ultimates still deal damage, making them basically unblockable.
- Your detection also fails for ultimates, as they usually don't have DAMAGE_TYPE_MAGIC - good luck detecing whether a spell damage was an ultimate or not.
That is something I didn't knew.
I never took a very deep look into what damage types a specific attack has.
I searched on the web and people said that abilities did spell attack, magic damage

- Whats going on with spirit link? Doesn't work at all in your uploaded map.
It seems that spirit link uses a different attack-type or damage type than regular spells.
I will have to find out what one it has.

Look in the testmap. Take the rifleman and attack the grunt. Displayed damage is 31.25, dealt damage is 62.5. Although no modifiers are involved, just a simple display damage:
Now I see something that is actually feedback.
A unit is attacked but the damage display is not right.
The damage modifiers are 100% and he sais that the damage is somehow doubled.
So I go to my map and try it myself.
In the map you posted... it never run the timer. So the unit's health will not be restored from the regular damage.
However on my version (which I modify all over the time). It does run the timer properly.
I actually didn't specificly fix that bug because I didn't knew. Somehow it still got fixed.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Eh, what you are talking about are priorities ;).

Phases are a single trigger with subdivisions. However, your problem isn't in phases, and phases won't save you. For your problem, you only need two phases, onDamage and onAfterDamage (essentially your two events). Your problem is simply that you are not running onAfterDamage in reverse order.

If you used phases (not priorities), it would still be broken. Also, the systems should be able to register to just those two events, no other parameters needed.

For example, in DDS, you can register to the two events and it will all run correctly. The user doesn't have to create anything extra, they can just work in the phases provided by the system, which only has one more phase than yours does (if I remember right). It has onDamageBefore (global), onDamage (local), and onDamageAfter (global). It might have one more ; ). There might be like 3-4 phases for a given module. However, the user would still just register (in my example) to onDamageBefore and onDamageAfter, which are essentially your event.

(what's the difference between a phase and an event? Phases are the stages of an event. You have two stages for a damage event, thus you are using phases. Yours are just rather limited as yours can't be expanded on with no overhead ^)^.)

So what makes my DDS different from yours? Why doesn't mine break? It's very simple. I run onDamageAfter in reverse order.

All I literally do is something along the lines of TriggerEvaluate(onDamageAfter), except that when I run my trigger, it runs in reverse. Pretty cool, huh?


So this isn't a problem with not having enough events. This isn't a problem with priorities. The problem is that you don't handle events that run at the end correctly. My DDS doesn't spam new events for every resource. A resource doesn't have to spam events to run correctly unless they want control over enable/disable. Also, in either case, triggers are not spammed. Every complete event (at the core) is 1 trigger. Even if new phases are added, it's still one trigger ; ).

Also, my example was kind of unfair. In reality, such a system would create a new event, register itself to the current event, and then run its own event. This is because it performs better this way. That doesn't change the fact that events that run last should run in reverse order though.

You can think of it like a coil. You wind the coil up as you do your events, then you unwind it as you do your "after" events (post events). Running it this way is actually the natural way it should run ;).
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
So you say that "a unit finishes casting an ability" runs in reverse order too?
And if I would be able to make it run something in reverse order, then all the other event responses are completely broken aren't they?

About what Xonok called phases is not what you described of phases.
I see how both can be called that way so I will not judge on anything of that.
However what I meant is that both events, as they are actually separate events, will have priorities.
As far as I have used events in both GUI and JASS, this parameter is already given but it only has a different meaning at this moment.

Doesn't look like a DDS to me, more like a Damage Modifier system.
This one was designed to change a unit's attack-type and even damage-type for basic attacks and change them for spells.
You bet.
Maybe the name is wrong but yea you know.
If you want to change the damage dealt, why can't you know how much damage that is?
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Nobody said Blizzard was perfect.

However, I realize now that post global events should run in two phases. Continued processing and destruction. Destruction runs in reverse; it's special. I always just did it with one ;).


edit


If you look through my docs: https://github.com/nestharus/JASS/blob/master/jass/Systems/DDS/DamageEvent/script.j

I call onDamageAfter clean up. Only global system initialization and destruction use global events. Everything else is local. A combat system also uses these 2 events (my example was right, my bad). There are cases when you do something that's not destruction in a post event though, like damage display. Nothing depends on it and it depends on only some glibal systems, but it must run after everything else. However, it will run correctly in reverse as its dependencies will still be destroyed after it, so 1 phase is enough to handle post.

You don't do consecutive in order transformations in post. It's always clean up or analyzing output from systems in a global way. Now I suppose you might have something like a global point system. Two post phases should possibly be done actually ;). Well, even then, I'd still do points locally, otherwise modifiers won't work.

Give me an example of a global post event thing that should run in order and will break in reverse. It needs to be global***. One will do. I have yet to come up with one myself that shouldn't be done locally. You do that and I'll be ok with running *some* things in order in a global post event, but very few. It'd be something special.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
So I need 8 events?
I got 4 at this moment:
1: A unit will take specific damage (physical, spell, coded)
2: A unit will take any form of damage
3: A unit has taken specific damage (physical, spell, coded)
4: A unit has taken any form of damage

So I need another event for every one of them that will be the after-event?
1before: A unit will take specific damage (physical, spell, coded)
1after: A unit will take specific damage (physical, spell, coded) (reverse)
2b: A unit will take any form of damage
2a: A unit will take any form of damage (reverse)
3b: A unit has taken specific damage (physical, spell, coded)
3a: A unit has taken specific damage (physical, spell, coded) (reverse)
4b: A unit has taken any form of damage
4a: A unit has taken any form of damage (reverse)

Like that?

Still I make an event by doing this:
set global_variable = (real/integer)
I know that it is hard to run something in reverse order otherwise people would have done that anyway, but is it even possible?

Like this:
There is a battlefield.
The leader of the army sais "Attack!".
Every soldier then attacks.
But what if he said "!kcattA".
I mean the way how the events are set up do not run anything they just say something, the soldiers (responses) run something.
To make something do in a specific order I would have to implement priorities (what I called phases before).
That would remove the need of reversed and even doubled events.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
If I had 8 functions 1-8

trigger a
trigger b
trigger c

a in order
b in reverse
c in order

execute the following instructions in order

add 1 to a
add 2 to a
add trigger b to a
add 3 to a
add 4 to b
add trigger c to b
add 5 to b
add 6 to c
add 7 to c
add 8 to c

run a

output will be

out 1
out 2
out 5
out 6
out 7
out 8
out 4
out 3


:)

Or(fuction B, function A) is your hint for running in reverse and adding triggers to triggers.

Already coded in vJASS (VERY COMPLICATED), but you hate vJASS. Oh well ;).

And yes, the triggers I run are a lot (even faster than raw JASS ones with conditions) faster than yours (aww), allows me to unregister things, can be run in reverse, and can have code or triggers added to them (aww). I have bettet tools :p, so I can do stuff that you can only dream about doing ;).

I guess you'll have to settle for your crappy JASS triggers and crappy static events :(. The thing I outlined above is trivial to do with the triggers I use, muahahahaha.



You should really learn vJASS, then yiu can use the same steroid triggers :).
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
but you hate vJASS. Oh well ;).
Not entirely true.
All I want is that people who haven't got NewGen can use everything that I make.
Next to that, it is JASSHelper who hates me.
I reinstalled NewGen yesterday evening but it still is not the latest version.

And yes, the triggers I run are about 5% faster than yours (aww), allows me to unregister things, can be run in reverse, and can have code or triggers added to r
them (aww). I have bettet tools :p, so I can do stuff that you can only dream about doing ;).
Yea I figured that every existing DDS already has better performance than I will get on mine. I accepted that.
As long as it is unnoticeable, I will be happy with it.
 
There's literally nobody on this site that doesn't use Newgen.

Newgen is an infection, I don't use it as well. :thumbs_up:

I don't get what you mean as well Nes. VJASS == JASS anyways so whats your point? VJASS only gives you an edited syntax to work with and limits to who can edit your triggers in an open map. I'd use GDD by weep any day over yours as well.

No matter what 5% means nothing. JASS is one of the slowest syntax's/scripting language's of the decade. 150% would mean something though WC3 was never designed to be fast so the engine/core code likely sucks as well.

Point being don't be an egomaniac. Be a helping-maniac instead. You do make the best vjass systems, just it'd be nice if you could help someone without over-boasting.
 
all features that vJass offers allow you to use your maps in B.net. Please go check what vJass allows before commenting on compatibility

VJASS has to convert to JASS no matter what therefore I don't get what your trying to say. I did check and know what it allows, its an easier way to type JASS. Well compatibility has to be the same otherwise you would need a modded WC3 for a modded language.... Otherwise we could see really epic projects on Bnet. Such as RtC... WarCom. Sadly that isn't the case.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
native UnitAlive takes unit u returns boolean

There is no way to forward declare natives from common.ai without using JassHelper(appart from udg_ crap)

JASS:
globals
    integer i = 5
endglobals

There is no way to declare global variables yourself without using JassHelper.

hook CreateUnit CreateUnitUserFunc

There is no way to call user-made function every time a native is called without using JassHelper(without forcing all users of given spell/system to manually call it instead of the native one)

JASS:
library /* scope */ L
    private function f takes nothing returns nothing
    endfunction
endlibrary /* endscope */

There is only one scope in Jass, + you have no control over the code placement, whereas with vJass you can perfectly predict which piece of code will appear where in the resulting map script.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
There is no way to declare global variables yourself without using JassHelper.
You can export your war3map.j and re-import it lol. That's how ancients did it back in the stone age.
 
Status
Not open for further replies.
Top