• Check out the results of the Techtree Contest #19!
  • Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

Defend (Remaked) v0.2

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: Mortimm
Description:
When activate, it blocks attacks that come from the front and gives a chance to bash nearby attacking enemies.
------------------
Suggestion:
I suggest using this spell for some bosses and mini-bosses in RPG maps. It can be used in Castle Defend maps too.
------------------
Configurables:
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>"
------------------
Changelog:
-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.
------------------
Credits:
-Weep
-The_Witcher
------------------
I hope it will be useful for your maps.
Sorry for my bad English.



JASS:
// Configurables:

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

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 
endfunction

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
endfunction

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
endfunction

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
endfunction

//===========================================================================
// Spell code:

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

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

//===========================================================================

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

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

//===========================================================================

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

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

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" ) )
        endif
        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() ) )
        else
            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 )
        endif
        if ( udg_dam > 0.00 ) then
            set udg_u = udg_GDD_DamagedUnit
            call TimerStart(udg_t, 0.01, false, function AddHP )
        endif
    endif
    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
endfunction

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 )
endfunction


Keywords:
Defend, miss, Knight, block, blocked, Darknut
Contents

Defend v0.2 (Map)

Reviews
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
 
  • 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...
 
Back
Top