Defend (Remaked) v0.2

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
When activate, it blocks attacks that come from the front and gives a chance to bash nearby attacking enemies.
I suggest using this spell for some bosses and mini-bosses in RPG maps. It can be used in Castle Defend maps too.
The first five functions are editable constraints, includes:
-Ability ID
-Chance to stun
-Stun range
-Mana cost
-Block Angle
You can leave the last four of them the way they are, but editing ability ID constraint is required to get the spell work.
How to use:
-Copy "Defend" category in Trigger Editor and custom ability in Object Editor from this map to yours.
-Get custom ability ID
-Change the fifth line of the trigger "Defend" to "returns <your ID>"
-Version 0.0:Spell Uploaded.
-Version 0.1:
+Added stun effect.
+Added special effects.
+Added mana cost.
+Change attack blocking method from using dummies spell to using triggers
-Version 0.2:
+Uses Jass instead of GUI triggers.
+Uses Weep's GUI Friendly Damage Detection.
+Uses The_Witcher's Stun Unit System instead of dummies.
+Added Configurables.
I hope it will be useful for your maps.
Sorry for my bad English.

// Configurables:

function ID takes nothing returns integer
// Write ID of custom "defend" in your map here, mine was 'A001'
        return 'A001'

function BashChance takes nothing returns integer
// This is the chance (%) to bash. For example, if the following line is "return 25", the chance to bash is 25%.
// Note: It is an integer
        return 25 

function BashDistance takes nothing returns real
// To get an attacking enemy bashed, you have to get close enough, so this is the distance between the defending unit and
// it's attackers, from which it will bash. I choose 150.00 because it's melee range and pretty far so almost melee attackers
// can't avoid it
        return 150.00

function ManaCost takes nothing returns real
// Mana cost used here is 10.00, it's the amount of mana you use for blocking each attack
        return 10.00

function Angle takes nothing returns real
// This "determine" which direction is the front, from which defending units can block. For Example: if Angle returns 40.00,
// defending units can block attacks come from maximum of 40 degree from it's front to it's side. if it's 180.00, they can
// block attacks come from any directions.
        return 40.00

// Spell code:

function Trig_Deactivate_Conditions takes nothing returns boolean
    if ( not ( GetIssuedOrderId() == String2OrderIdBJ("undefend") ) ) then
        return false
    if ( not ( GetUnitAbilityLevel(GetTriggerUnit(), ID()) >= 1 ) ) then
        return false
    return true

function Trig_Deactivate_Actions takes nothing returns nothing
    call GroupRemoveUnitSimple( GetOrderedUnit(), udg_Defending )


function Trig_Activate_Conditions takes nothing returns boolean
    if ( not ( GetIssuedOrderId() == String2OrderIdBJ("defend") ) ) then
        return false
    if ( not ( GetUnitAbilityLevel(GetTriggerUnit(), ID()) >= 1 ) ) then
        return false
    return true

function Trig_Activate_Actions takes nothing returns nothing
    call GroupAddUnitSimple( GetOrderedUnit(), udg_Defending )


function AddHP takes nothing returns nothing
        call SetUnitState( udg_u, UNIT_STATE_LIFE, ( GetUnitStateSwap(UNIT_STATE_LIFE, udg_u) + udg_dam ) )

function Trig_Attack_Block_Conditions takes nothing returns boolean
        return IsUnitInGroup(udg_GDD_DamagedUnit,udg_Defending)

function Trig_Attack_Block_Actions takes nothing returns nothing
    local unit dummy
    local texttag txt = CreateTextTag()
    local real x1 = GetLocationX(GetUnitLoc(udg_GDD_DamagedUnit))
    local real y1 = GetLocationY(GetUnitLoc(udg_GDD_DamagedUnit))
    local real x2 = GetLocationX(GetUnitLoc(udg_GDD_DamageSource))
    local real y2 = GetLocationY(GetUnitLoc(udg_GDD_DamageSource))
    local real A = bj_RADTODEG*Atan2(y2-y1,x2-x1)
    local real maxlife = GetUnitStateSwap(UNIT_STATE_MAX_LIFE, udg_GDD_DamagedUnit)
    local real life = GetUnitStateSwap(UNIT_STATE_LIFE, udg_GDD_DamagedUnit)
    local real mana = GetUnitStateSwap(UNIT_STATE_MANA, udg_GDD_DamagedUnit)
    local real deltaA = RAbsBJ(GetUnitFacing(udg_GDD_DamagedUnit)-A)
    if ((deltaA <= Angle()) or ((360.00-deltaA) <= Angle())) then
        set udg_dam = (udg_GDD_Damage - (maxlife - life))
        call SetUnitState( udg_GDD_DamagedUnit, UNIT_STATE_LIFE, (life + udg_GDD_Damage))
        call DestroyEffect( AddSpecialEffectTarget(  "Abilities\\Spells\\Human\\Defend\\DefendCaster.mdl", udg_GDD_DamagedUnit, "origin" ) )
        call SetTextTagText( txt, "blocked", 0.01955 )
        call SetTextTagPos( txt, x2, y2, 0.00 )
        call SetTextTagColor( txt, 255, 25, 25, 255)
        call SetTextTagPermanent( txt, false )
        call SetTextTagLifespan( txt, 2.00 )
        call SetTextTagFadepoint( txt, 0.75 )
        call SetTextTagVelocityBJ( txt, 64, 90 )
        if (GetBooleanAnd((GetRandomInt(1, 100)<= BashChance()),GetBooleanAnd((SquareRoot((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))<= BashDistance()),GetBooleanAnd(not (IsUnitType(udg_GDD_DamageSource,UNIT_TYPE_STRUCTURE)),GetBooleanOr(IsUnitType(udg_GDD_DamageSource, UNIT_TYPE_GROUND), IsUnitType(udg_GDD_DamageSource, UNIT_TYPE_SNARED)))))) then
            call StunUnit(udg_GDD_DamageSource, 1.00, false)
            call UnitDamageTarget(udg_GDD_DamagedUnit, udg_GDD_DamageSource, 40, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl", udg_GDD_DamagedUnit, "chest" ) )
        if ( GetUnitStateSwap(UNIT_STATE_MANA, udg_GDD_DamagedUnit) >= ManaCost() ) then
            call SetUnitState( udg_GDD_DamagedUnit, UNIT_STATE_MANA, ( GetUnitStateSwap(UNIT_STATE_MANA, udg_GDD_DamagedUnit) - ManaCost() ) )
            call SetUnitState( udg_GDD_DamagedUnit, UNIT_STATE_LIFE, ( GetUnitStateSwap(UNIT_STATE_LIFE, udg_GDD_DamagedUnit) - ( ( ( ManaCost() - GetUnitStateSwap(UNIT_STATE_MANA, udg_GDD_DamagedUnit) ) / ManaCost() ) * udg_GDD_Damage ) ) )
            call IssueImmediateOrder( udg_GDD_DamagedUnit, "undefend" )
            call SetUnitState( udg_GDD_DamagedUnit, UNIT_STATE_MANA, 0.00 )
        if ( udg_dam > 0.00 ) then
            set udg_u = udg_GDD_DamagedUnit
            call TimerStart(udg_t, 0.01, false, function AddHP )
    set deltaA = 0.00
    set A = 0.00
    set mana = 0
    set life = 0
    set maxlife = 0
    set x1 = 0.00
    set y1 = 0.00
    set x2 = 0.00
    set y2 = 0.00
    set txt = null
    set dummy = null

function InitTrig_Defend takes nothing returns nothing
    set gg_trg_Defend = CreateTrigger(  )
    call TriggerRegisterVariableEvent( gg_trg_Defend, "udg_GDD_Event", EQUAL, 0 )
    call TriggerAddCondition( gg_trg_Defend, Condition(function Trig_Attack_Block_Conditions))
    call TriggerAddAction( gg_trg_Defend, function Trig_Attack_Block_Actions )
    set udg_Deactivate = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( udg_Deactivate, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddCondition( udg_Deactivate, Condition( function Trig_Deactivate_Conditions ) )
    call TriggerAddAction( udg_Deactivate, function Trig_Deactivate_Actions )
    set udg_Activate = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( udg_Activate, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddCondition( udg_Activate, Condition( function Trig_Activate_Conditions ) )
    call TriggerAddAction( udg_Activate, function Trig_Activate_Actions )

Defend, miss, Knight, block, blocked, Darknut

Defend v0.2 (Map)

12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 21 Feb 2012 Bribe: Required: You need to prefix your variable & function names relevant to the library. Required: Remove the GUI-style blocks. If you don't already know how to fix them...




12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

21 Feb 2012
Bribe: Required: You need to prefix your variable & function names relevant to the library.

Required: Remove the GUI-style blocks. If you don't already know how to fix them then you should be coding in GUI, not in JASS.

Optional: Remove the BJ's. They are pointless.

Optional: Use a better stun system.


10 Feb 2012
Bribe: imo this is too map-specific. If you want a resource that you want people to use as a standalone thing you should be considering:

1) Using Weeps's GUI Friendly Damage Detection System

2) Not using waits

3) Making some configurables for people to change the settings here

4) Fix your memory leaks
Level 7
Apr 12, 2011
Please post codes by using

You can copy the trigger by using "copy as text"
Select the trigger, move your mouse inside the trigger, scroll up, right click the name an select "Copy as text"
Level 10
Apr 25, 2009
  • Unit - Create 1 Caster Dummy for (Owner of (Attacked unit)) at (Position of (Attacking unit)) facing Default building facing degrees
Leaks a point. Set the point to a variable and then destroy it.

Set (Last Created Unit) to a variable, its more efficient.

Make the Dummy Unit explode on death, it'll make sure it doesn't leak.

Triggering Unit > Attacked Unit
Triggering Unit > Ordered Unit

I believe its too simple, I'd suggest adding special effects, or something...