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

Dark Agility 0.8a

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
-----Dark Agility-----
Assasin is mistres in combat, granting her an ability to dodge. But she is also an adept in dark magic, granting her an ability to deal aditional magic damage based on your physical damage.

Level 1 - 15% chance, 40% additional damage, 15% dodge chance.
Level 2 - 20% chance, 80% additional damage, 20% dodge chance.
Level 3 - 25% chance, 120% additional damage, 25% dodge chance.
Level 4 - 30% chance, 160% additional damage, 30% dodge chance.

(Dealed damage doesn't lowered by armor)


paintnetimage.jpg

paintnetimage2.jpg

paintnetimage1.jpg



Credits
Daelin for his Armor Detection System
[Duos] for his Knockback System

To implement just copy all the trigs AND copy all Custom script

Please give credits if you use this skill in your map


0.8 initial release
0.8a Added Two variables for readability and changed the init trigger


Sorry for my English D:

Keywords:
Critical,Agility,Dark,Darkness,Dodge,Evasion,Damage.
Contents

Dark Agility (Map)

Reviews
12th Dec 2015 IcemanBo: For too long time as NeedsFix. Rejected. 09:42, 7th Jun 2011 Bribe: In the "begin" trigger, you are going to leak a lot of event handles over the course of the game. You need to link to the resources you use. It...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: For too long time as NeedsFix. Rejected.

09:42, 7th Jun 2011
Bribe:

In the "begin" trigger, you are going to leak a lot of event handles over the course of the game.

You need to link to the resources you use. It looks like you just posted them in the map header but that doesn't help people understand what's happening in your triggers. As far as I'm concerned it will throw syntax errors when users try to import it because you didn't tell them how to install it in their maps.
 
Level 10
Joined
Apr 25, 2009
Messages
296
Here's your triggers in English.

JASS:
//TESH.scrollpos=168
//TESH.alwaysfold=0
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ARMOR DETECTION SYSTEM>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//<<                                 >>     by DAELIN     <<                                      >>
//<<                                 >>      (v 1.0)      <<                                      >>
//<<                                 ^^^^^^^^^^^^^^^^^^^^^^^                                      >>
//<<  Description: This system is composed of four important functions, and two auxiliary .       >>
//<<               Using them you can not only detect the current armor of an unit, but you can   >>
//<<               also detect the type of armor the unit has (Small, Medium, Large, Fortified,   >>
//<<               Normal, Hero, Divine or Unarmored). You can also get the actual damage the     >>
//<<               unit could have received if it had no armor.                                   >>
//<<                                                                                              >>
//<<  Note: The system will work only if you do not play with the gameplay constants which affect >>
//<<        the amount of damage each damage type can do to the armor type, along with the damage >>
//<<        reduction an armor point does.                                                        >>
//<<                                                                                              >>
//<<  Requirements: - Copy the code of this system entirely into the header of the map.           >>
//<<                - Copy the "Armor System Auxiliary" ability into your map.                    >>
//<<                - Leave the constants of damage infliction and reduction as they are.         >>
//<<                - Leave 'Allz' (Item life bonus (least)) ability unchanged.                   >>
//<<                                                                                              >>
//<<  Known bugs: - If an unit with Large armor is magic immune, the function will wrongly return >>
//<<                "Normal". That is because the difference between the two types of armors is   >>
//<<                given by the 200% damage done by Magic attacks to Large armor. I have not     >>
//<<                succeeded yet to damage a spell immune unit with magical attack no matter     >>
//<<                the damage type.                                                              >>
//<<                                                                                              >>
//<<  Armor Codes: Instead of messing up with map's files or common.j, I have made a separate     >>
//<<               function which converts the code of the armor types returned by the            >>
//<<               GetUnitArmorType function into a string with the name of the armor type. Here  >>
//<<               is the numeric equivalence of each armor type:                                 >>
//<<                                                                                              >>
//<<                      Small (1)               Medium (2)                  Large(3)            >>
//<<                                                                                              >>
//<<                                Fortified(4)                 Normal(5)                        >>
//<<                                                                                              >>
//<<                      Hero (6)              Unarmored (7)                 Divine(8)           >>
//<<                                                                                              >>
//<<  Contact: [email][email protected][/email] - Send an email if you have questions or suggestions      >>
//<<                                                                                              >>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

constant function Armor_ID takes nothing returns integer
    return 'A000' //rawcode of the auxiliary ability
endfunction

function IsUnitInvulnerable takes unit whichUnit returns boolean
    local real life
    local boolean b
    call UnitAddAbility(whichUnit, 'allz')
    set life = GetWidgetLife(whichUnit)
    call UnitDamageTarget(whichUnit, whichUnit, 0.01, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    if GetWidgetLife(whichUnit)<life then
       set b = false
    else
       set b = true
    endif
    call SetWidgetLife(whichUnit, life)
    call UnitRemoveAbility(whichUnit, 'allz')
    return b
endfunction

//DETECT UNIT"S ARMOR
function GetUnitArmor takes unit whichUnit returns real
    local real life = GetWidgetLife(whichUnit)
    local real reduction
    local integer ID = Armor_ID() //rawcode of the auxiliary ability
    local boolean b = IsUnitInvulnerable(whichUnit)
    call UnitAddAbility(whichUnit, 'allz')
    call UnitAddAbility(whichUnit, ID)
    if b==true then
       call SetUnitInvulnerable(whichUnit, false)
    endif
    call UnitDamageTarget( whichUnit, whichUnit, 16.00, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS) 
    if b==true then
       call SetUnitInvulnerable(whichUnit, true)
    endif
    set reduction = (16.00-(life-GetWidgetLife(whichUnit)))/16.00
    call UnitRemoveAbility(whichUnit, 'allz')
    call UnitRemoveAbility(whichUnit, ID)
    call SetWidgetLife(whichUnit, life)
    return (50*reduction/(3.00-(3.00*reduction)))-30.00
endfunction

//GET DAMAGE WITHOUT ARMOR
function GetFullDamage takes real damage, real armor returns real
    if armor>=0.00 then
        return damage/(1-(((armor)*0.06)/(1.00+0.06*(armor))))
    else
        return damage/(2.00-Pow(0.94,(-armor)))
    endif
endfunction


function EvalDamage takes unit whichUnit, real damage, attacktype t, real armor returns real
    local real life = GetWidgetLife(whichUnit)
    local real cdam
    local boolean b = IsUnitInvulnerable(whichUnit)
    if b==true then
       call SetUnitInvulnerable(whichUnit, false)
    endif
    call UnitDamageTarget(whichUnit, whichUnit, damage, true, false, t, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    if b==true then
       call SetUnitInvulnerable(whichUnit, true)
    endif
    set cdam = life-GetWidgetLife(whichUnit)
    call SetWidgetLife(whichUnit, life)
    return GetFullDamage(cdam, armor)
endfunction


//DETECT THE ARMOR OF AN UNIT
function GetUnitArmorType takes unit whichUnit returns integer
    local real armor = GetUnitArmor(whichUnit)
    local real damage

    call UnitAddAbility(whichUnit, 'allz')
    set damage = EvalDamage(whichUnit, 16.00,ATTACK_TYPE_MELEE, armor)
    if (damage<=2.00 and EvalDamage(whichUnit, 16.00, ATTACK_TYPE_CHAOS, armor)>=15.98) then
        call UnitRemoveAbility(whichUnit, 'allz')
        return 8 //divine
    elseif (damage>16.02) then
        call UnitRemoveAbility(whichUnit, 'allz')
        return 2 //medium
    elseif (damage<15.98) then
        call UnitRemoveAbility(whichUnit, 'allz')
        return 4 //fortified
    endif
    
    set damage = EvalDamage(whichUnit, 16.00, ATTACK_TYPE_SIEGE, armor)
    if (damage<15.98) then
        call UnitRemoveAbility(whichUnit, 'allz')
        return 6 //hero
    elseif (damage>16.02) then
        call UnitRemoveAbility(whichUnit, 'allz')
        return 7 //unarmored
    endif

    if (EvalDamage(whichUnit,16.00,ATTACK_TYPE_PIERCE,armor)>16.02) then
        call UnitRemoveAbility(whichUnit, 'allz')
        return 1 //small
    endif

    if (EvalDamage(whichUnit,16.00,ATTACK_TYPE_MAGIC,armor)>16.02) then
        call UnitRemoveAbility(whichUnit, 'allz')
        return 3 //large
    else
        call UnitRemoveAbility(whichUnit, 'allz')
        return 5 //normal
    endif
endfunction  

//CONVERT ARMOR TYPE TO STRING
function A2S takes integer armortype returns string
    if (armortype==1) then
        return "Small"
    elseif (armortype==2) then
        return "Medium"
    elseif (armortype==3) then
        return "Large"
    elseif (armortype==4) then
        return "Fortified"
    elseif (armortype==5) then
        return "Normal"
    elseif (armortype==6) then
        return "Hero"
    elseif (armortype==7) then
        return "Unarmored"
    else 
        return "Divine"
    endif
endfunction

function KnockBackUnit_Timer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit knockbacked = LoadUnitHandle(udg_Hashtable,GetHandleId(t),0)
    local integer amount = LoadInteger(udg_Hashtable,GetHandleId(t),1)
    local real portion = LoadReal(udg_Hashtable,GetHandleId(t),2)
    local integer current = LoadInteger(udg_Hashtable,GetHandleId(t),3)
    local real angle = LoadReal(udg_Hashtable,GetHandleId(t),4) 
    local real x = GetUnitX(knockbacked) + portion * Cos(angle * 0.0174532)
    local real y = GetUnitY(knockbacked) + portion * Sin(angle * 0.0174532)
    
    call SaveInteger(udg_Hashtable,GetHandleId(t),3,current + 1)
    
    if current == amount then
        call FlushChildHashtable(udg_Hashtable,GetHandleId(t))
        call PauseTimer(t)
        call DestroyTimer(t)
    elseif current < amount then
        if IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) == false then      
            call SetUnitX(knockbacked,x)
            call SetUnitY(knockbacked,y) 
        else
            call SetUnitX(knockbacked,GetUnitX(knockbacked))
            call SetUnitY(knockbacked,GetUnitY(knockbacked))
        endif     
    endif
    
    set knockbacked = null
    set t = null
endfunction

function KnockBackUnit takes unit knockbacked, real distance, real time, real degrees, real period returns nothing
    local integer amount = R2I(time / period)
    local real portion = distance / amount 
    local timer t = CreateTimer()
    call SaveUnitHandle(udg_Hashtable,GetHandleId(t),0,knockbacked)
    call SaveInteger(udg_Hashtable,GetHandleId(t),1,amount)
    call SaveReal(udg_Hashtable,GetHandleId(t),2,portion)
    call SaveInteger(udg_Hashtable,GetHandleId(t),3,0)
    call SaveReal(udg_Hashtable,GetHandleId(t),4,degrees)
    call TimerStart(t,period,true,function KnockBackUnit_Timer)
    set t = null
endfunction
  • Begin
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Level of Darkness Agility for (Attacking unit)) Greater than 0
    • Actions
      • -------- Crit Chance --------
      • Set DA_CritChance = (10 + (5 x (Level of Darkness Agility for (Attacking unit))))
      • -------- Crit Multiplayer --------
      • Set DA_DamageMultiplierPerLVL = 0.40
      • -------- Additional damage to the crit --------
      • Set DA_AdditionalDamage = 0
      • -------- Mana Burned per strike (Does no damage) --------
      • Set DA_ManaBurn = 0.00
      • -------- Attack Type --------
      • Set DA_AttackType = Chaos
      • -------- Damage Type --------
      • Set DA_DamageType = Universal
      • -------- First SFX --------
      • Set DA_FirstSFX = Abilities\Spells\Undead\DeathandDecay\DeathandDecayTarget.mdl
      • -------- Second SFX --------
      • Set DA_SecondSFX = Abilities\Spells\Orc\MirrorImage\MirrorImageDeathCaster.mdl
      • -------- Attachment Place --------
      • Set DA_Attachment = chest
      • -------- Knockback Range (if set to -1, it will knockback the target, for damagedealed distance. 0 - off) --------
      • Set DA_Knockback = -1
      • -------- Knockback Time (in sec.) --------
      • Set DA_Knocktime = 1.50
      • -------- Knockback Period (in sec.) --------
      • Set DA_KnockPeriod = 0.03
      • -------- Begin Initialzation --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Random integer number between 1 and 100) Less than or equal to DA_CritChance
        • Then - Actions
          • Trigger - Add to Damage <gen> the event (Unit - (Triggering unit) Takes damage)
          • Unit - Add DA_Dummy to (Attacking unit)
          • Unit - Set level of DA_Dummy for (Attacking unit) to (Level of Darkness Agility for (Attacking unit))
        • Else - Actions
  • Damage
    • Events
    • Conditions
      • (Level of DA_Dummy for (Damage source)) Greater than 0
    • Actions
      • Set DA_DamageDealed = (Damage taken)
      • -------- Here we set final multiplier --------
      • Set DA_Mult = ((Real((Level of DA_Dummy for (Damage source)))) x DA_DamageMultiplierPerLVL)
      • Unit - Remove DA_Dummy from (Damage source)
      • Custom script: set udg_DA_TargetArmor = GetUnitArmor(GetTriggerUnit())
      • Custom script: set udg_DA_DamageFull = GetFullDamage(udg_DA_DamageDealed, udg_DA_TargetArmor)
      • -------- Here we set final damage. --------
      • Set DA_DamageFull = ((DA_DamageFull x DA_Mult) + (Real(DA_AdditionalDamage)))
      • Unit - Cause (Damage source) to damage (Triggering unit), dealing DA_DamageFull damage of attack type DA_AttackType and damage type DA_DamageType
      • Unit - Set mana of (Triggering unit) to ((Mana of (Triggering unit)) - DA_ManaBurn)
      • -------- Knockback --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DA_Knockback Not equal to 0
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DA_Knockback Equal to -1
            • Then - Actions
              • Custom script: call KnockBackUnit(GetTriggerUnit(), udg_DA_DamageFull, udg_DA_Knocktime, GetUnitFacing(GetEventDamageSource()), udg_DA_KnockPeriod)
            • Else - Actions
              • Custom script: call KnockBackUnit(GetTriggerUnit(), udg_DA_Knockback, udg_DA_Knocktime, GetUnitFacing(GetEventDamageSource()), udg_DA_KnockPeriod)
        • Else - Actions
      • Special Effect - Create a special effect attached to the chest of (Triggering unit) using DA_FirstSFX
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect attached to the chest of (Triggering unit) using DA_SecondSFX
      • Special Effect - Destroy (Last created special effect)
      • Set DA_AttackerPoint = (Position of (Damage source))
      • Floating Text - Create floating text that reads ((|cff8b00ff + (String((Integer(DA_DamageFull))))) + !|r) at DA_AttackerPoint with Z offset 10.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
      • Floating Text - Change (Last created floating text): Disable permanence
      • Floating Text - Set the velocity of (Last created floating text) to 32.00 towards 90.00 degrees
      • Floating Text - Change the lifespan of (Last created floating text) to 4.00 seconds
      • Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
      • Custom script: call RemoveLocation(udg_DA_AttackerPoint)
  • Hashtable
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set Hashtable = (Last created hashtable)
====================

You should set (Damage Source) to a variable - its more efficient

JASS:
    call UnitDamageTarget(whichUnit, whichUnit, damage, true, false, t, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    if b==true then
       call SetUnitInvulnerable(whichUnit, true)
When I tested the map, I found that the invulnerability was not removed from the Bandit Lord - Its likely caused from his ability, Divine Shield, made him invulnerable again...

JASS:
'allz'
Last time I checked, you should put ability's code into functions to help configurability. However, an exception may occur here.

I'd suggest changing the name of the Hashtable "Hashtable" to something descriptive, an example would be DAgilHash

=====================

Your GUI constants should be set to a variable and moved to map initialization, to help increase the configurability of the spell. Examples are "chest", "Chaos", "Abilities\Spells\Undead\DeathandDecay\DeathandDecayTarget.mdl", etc.

I'd suggest putting 'Level of Ability ""' to a variable, as well as (Triggering Unit) and (Attacking Unit) as they're used multiple times, it'll help make the spell more efficient.

=====================

Overall it was relatively efficient and I didn't find any leaks. Its very similar to Warcraft 3 Spells, which is a good thing.


Damage Detection System instead of 'Attacked Unit'
 
Last edited:
Level 3
Joined
Jul 10, 2010
Messages
50
I try adding this to a map and get 4 compile errors,
2 expected names
1. "set udg_DA_TargetArmor = GetUnitArmor(udg_DA_TriggeringUnit)"
2. "set udg_DA_DamageFull = GetFullDamage(udg_DA_DamageDealed, udg_DA_TargetArmor)"
and 2 expected function names. Could someone help me out with these problems please?
1. "call KnockBackUnit(udg_DA_TriggeringUnit, udg_DA_DamageFull, udg_DA_Knocktime, GetUnitFacing(GetEventDamageSource()), udg_DA_KnockPeriod)"
2."call KnockBackUnit(udg_DA_TriggeringUnit, udg_DA_Knockback, udg_DA_Knocktime, GetUnitFacing(GetEventDamageSource()), udg_DA_KnockPeriod)"
 
Top