- Joined
- Sep 30, 2009
- Messages
- 698
Well I made my damage totally triggered in my map. But I have a problem: Whenever I use the firebolt spell the first time the damage event doesnt trigger anymore
I use IDDS as damage detection system and all damage is triggered by another trigger. If someone could help me I will give + rep if possible 
Firebolt:
IDDS
My Damage System:
Firebolt:
JASS:
scope FireBolt initializer init
globals
private integer AbiId = 'AHtb'
private integer DummyId = 'hdf1'
endglobals
private struct Spell
static Spell array Index
static integer Total = 0
static timer t = CreateTimer()
integer level
unit caster
unit target
unit dummy
boolean TargetReached = false
real CurrentX
real CurrentY
real damage
static method CastLoop takes nothing returns nothing
local Spell d
local integer i = 0
loop
exitwhen i >= d.Total
set d = d.Index[i]
if not d.TargetReached then
set d.CurrentX = PolarProjectionX(d.CurrentX, 20, GetUnitFacing(d.dummy))
set d.CurrentY = PolarProjectionY(d.CurrentY, 20, GetUnitFacing(d.dummy))
call SetUnitX(d.dummy, d.CurrentX)
call SetUnitY(d.dummy, d.CurrentY)
if GetDistanceBetweenUnits(d.target, d.dummy) < 50 then
set d.TargetReached = true
call UnitDamageTargetEx(d.caster, d.target, d.damage, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_IGNORED, false)
endif
else
call BJDebugMsg("Stop")
call RemoveUnit(d.dummy)
call d.destroy()
// Recycling the indexer system
set d.Total = d.Total - 1
set d.Index[i] = d.Index[d.Total]
set i = i - 1
endif
set i = i + 1
endloop
if d.Total == 0 then
call PauseTimer(d.t)
endif
endmethod
endstruct
private function CastConditions takes nothing returns boolean
return GetSpellAbilityId() == AbiId
endfunction
private function CastActions takes nothing returns nothing
local Spell d = Spell.create()
set d.caster = GetTriggerUnit()
set d.dummy = CreateUnit(GetOwningPlayer(d.caster), DummyId, GetUnitX(d.caster), GetUnitY(d.caster), GetUnitFacing(d.caster))
set d.target = GetSpellTargetUnit()
set d.damage = GetUnitAbilityLevel(d.caster, AbiId) * 100
set d.CurrentX = GetUnitX(d.dummy)
set d.CurrentY = GetUnitY(d.dummy)
call IssueTargetOrder(d.dummy, "smart", d.target)
if d.Total == 0 then
call TimerStart(d.t, 0.03, true, function Spell.CastLoop)
call BJDebugMsg("Start")
endif
// Adding the struct to the indexer system
set d.Index[d.Total] = d
// Setting the total amount of structs in loop to Total + 1
set d.Total = d.Total + 1
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(t, Condition(function CastConditions))
call TriggerAddAction(t, function CastActions)
endfunction
endscope
IDDS
JASS:
library IntuitiveDamageSystem initializer Init requires Table
//******************************************************************************
//* BY: Rising_Dusk
//* (Intuitive) Damage Detection System 1.13
//*
//* This library is the core for what has come to be known as the Intuitive
//* Damage Detection System, or IDDS for short. Simply by copying this library
//* into your map somewhere, you will have access to all of its features and
//* options. Below this documentation are some global variables that can be
//* edited to make the system more useful for your map, whatever it might be.
//* Please note that you should only change those globals listed under
//* configuration constants and damage type constants.
//*
//* An important note for the system is that all non-attack damage in your map
//* MUST BE TRIGGERED using the special function call included in this system,
//* UnitDamageTargetEx. This is how the system works to detect attacks, because
//* if the only non-triggered damage in your map originates from attacks, you
//* clearly know which damage packets are attacks. This allows users to use
//* orb abilities in their maps for whatever they want.
//*
//* function UnitDamageTargetEx takes unit source, unit target, real damage, ...
//* ...attacktype attackType, integer damageType, boolean ConsiderArmor returns boolean
//*
//* This is the function with which you will deal all triggered damage in your
//* map. The damageType argument is one of the predefined integer constants that
//* you can edit or add below. Default values for this with the system are
//* DAMAGE_TYPE_ATTACK, DAMAGE_TYPE_SPELL, and DAMAGE_TYPE_EXTRA. You can
//* trigger the system to treat triggered damage like it is an attack if you
//* want to by using DAMAGE_TYPE_ATTACK. It is very easy to make new damage
//* types in the system, just follow the instructions in the configuration
//* constants area. In addition, be sure that the constants you define do not
//* conflict with the predefined Blizzard constants. (ie. DAMAGE_TYPE_FIRE) If
//* these conflicts do exist, you will encounter multiply defined syntax errors.
//* The AttackType argument is the same as in the regular UnitDamageTarget
//* native. Also, the system allows you to consider armor when dealing damage or
//* not. Set the ConsiderArmor boolean argument to false if you want to ignore
//* armor for that damage, or true if you want to factor it in.
//*
//* function TriggerUnregisterDamageEvent takes trigger trg returns boolean
//* function TriggerRegisterDamageEvent takes trigger trg, integer priority returns boolean
//*
//* The TriggerRegisterDamageEvent function is used when initializing a damage
//* detection response trigger. By using this, it allows you to use a syntax
//* structure nigh-identical to the standard JASS2. It returns a boolean for
//* your convenience that is false if you pass it a null trigger. The system
//* also allows you to pass a positive, zero-inclusive integer to it as that
//* trigger's priority. The higher the number you pass, the later on in the
//* trigger executions it will fire. This is useful if you want shield
//* abilities, as you will want their priorities low so that they can block the
//* damage before it gets to other things. You are also allowed to unregister
//* a trigger from the system at any time if you want; this will likely never
//* have to be done for most maps.
//*
//* function SetDamage takes real dmg returns nothing
//* function SetDamageType takes integer dmgtype returns boolean
//*
//* With this function, you can modify the damage the system interprets for its
//* triggers. This function DOES NOT ACTUALLY CHANGE THE DAMAGE BEING DEALT, it
//* is merely a tool for users to use to change the internal variables. The user
//* will need to modify the damage himself by some other means. Similarly, the
//* SetDamageType function internally changes the damage type of a given packet
//* of damage. This can be useful if you want to convert DAMAGE_TYPE_ATTACK into
//* something else or if you want dynamic damagetypes in-game.
//*
//* function SetTriggerPriority takes trigger trg, integer priority returns boolean
//* function GetTriggerPriority takes trigger trg returns integer
//*
//* These functions let you set or get a given trigger's priority at will. These
//* functions both require that the trigger being passed to it is registered to
//* the IDDS system. If you pass an unregistered trigger to GetTriggerPriority,
//* it will return -1. If you pass a similar trigger to SetTriggerPriority, it
//* will return false.
//*
//* function IgnoreHigherPriority takes nothing returns boolean
//*
//* This function is one of the most important reasons for priorities to exist.
//* With it, you can tell the system to ignore higher priority triggers. This
//* is useful, for instance, if you have a triggered evasion ability and don't
//* want anything else to be done with that damage because it was dodged. Other,
//* similar damage-preventing routines will also find this function useful.
//*
//* function RegisterDamageType takes nothing returns integer
//*
//* This function is useful for declaring your own DAMAGE_TYPE_ETC constants
//* external to the system. By declaring your global variable and then calling
//* this on it as follows, you can register new damage types on the fly. This
//* is very useful if you want other systems or spells to introduce new damage
//* types that are either ignored or do special things for that application.
//*
//* function GetTriggerDamageType takes nothing returns integer
//* function GetTriggerDamageSource takes nothing returns unit
//* function GetTriggerDamageTarget takes nothing returns unit
//* function GetTriggerDamageBase takes nothing returns real
//* function GetTriggerDamage takes nothing returns real
//*
//* Like normal WC3 damage detection, the system has event responses for the
//* damage source, the target of the damage, the amount of damage dealt, and
//* other things. It also permits the detection of damage type, which is
//* something standard WC3 does not have. This lets you create on-attack spells
//* very easily whereas without the system it would be very difficult and
//* computationally costly. GetTriggerDamageBase returns the amount of damage
//* the unit was dealt at the beginning of a given trigger series, whereas
//* GetTriggerDamage returns whatever damage the unit has left to receive, if
//* it has been modified in any way with the SetDamage function mentioned
//* earlier.
//*
//* Once you understand all of the aforementioned aspects of the system, you're
//* ready to put it to use. I know it can be tricky to require all spells be
//* triggered, but this is the way of many great maps anyways, so such a
//* requirement is not so unreasonable. If you have any questions regarding the
//* system, please go to [url]www.wc3c.net[/url] and send a private message to the account
//* Rising_Dusk and I will respond as soon as I can. This system may only be
//* released at [url]www.wc3c.net[/url] and its existence on any other website is against
//* the author's will.
//*
//* Enjoy!
//*
globals
//* Configuration constants
private integer DamageTypeCount = 4
//* These are the damagetype constant globals for ease of use
constant integer DAMAGE_TYPE_ATTACK = 0
constant integer DAMAGE_TYPE_SPELL = 1
constant integer DAMAGE_TYPE_EXTRA = 2
constant integer DAMAGE_TYPE_IGNORED = 3
//* To add new constants, simply follow the naming convention and increment
//* the number accordingly. You shouldn't change or remove the first of the
//* damage types, since it is a special case, but you can change the others
//* however you'd like.
//* These are static constants used by the system and shouldn't be changed
private trigger RunTrigger = CreateTrigger()
private trigger AddTrigger = CreateTrigger()
private integer Count = 0
private Table TrigTable = 0
private Table RegiTable = 0
private boolean IgnPrior = false
private integer array NewDamageType
private real array NewDamage
private trigger array Trg
private integer array Priority
//* Temporary variables used by the system
private unit DamageSource = null
private unit DamageTarget = null
private integer DamageType = 0
private integer DamageId = 0
private real DamageBase = 0.
private real Damage = 0.
endglobals
//******************************************************************************
//******************************************************************************
//* Returns the integer index of a given handle object (Updated for 1.24)
private function H2I takes handle h returns integer
return GetHandleId(h)
endfunction
//* Use an insertion sort algorithm to sort the trigger stack based on priority
private function TriggerSort takes nothing returns boolean
local integer i = 1
local integer j = 0
local integer p = 0
local trigger t = null
loop
exitwhen i >= Count
set t = Trg[i]
set p = Priority[i]
set j = i-1
loop
exitwhen j < 0 or Priority[j] <= p
set Priority[j+1] = Priority[j]
set Trg[j+1] = Trg[j]
set TrigTable[H2I(Trg[j])] = j+1
set j = j - 1
endloop
set Priority[j+1] = p
set Trg[j+1] = t
set TrigTable[H2I(t)] = j+1
set i = i + 1
endloop
set t = null
return true
endfunction
//******************************************************************************
//******************************************************************************
//* The function to call when you want to end a damage's trigger series
function IgnoreHigherPriority takes nothing returns boolean
if DamageSource != null then
//Make sure it was called in the right place
set IgnPrior = true
endif
return IgnPrior
endfunction
//* Changes the base damage for a trigger series on the fly
function SetDamage takes real dmg returns boolean
if DamageSource != null and dmg >= 0 then
//Make sure it was called in the right place
set NewDamage[DamageId] = dmg
set Damage = dmg
return true
endif
return false
endfunction
//* Changes the base damage type of the series
function SetDamageType takes integer dmgtype returns boolean
if DamageSource != null and dmgtype >= 0 then
//Make sure it was called in the right place
set NewDamageType[DamageId] = dmgtype
set DamageType = dmgtype
return true
endif
return false
endfunction
//* Returns the given trigger's priority if it's loaded to the system
function GetTriggerPriority takes trigger trg returns integer
if RegiTable[H2I(trg)] == 0 then
return -1
endif
return Priority[TrigTable[H2I(trg)]]
endfunction
//* Sets the given trigger's priority if it's loaded to the system
function SetTriggerPriority takes trigger trg, integer priority returns boolean
if RegiTable[H2I(trg)] == 0 or priority < 0 then
return false
endif
set Priority[TrigTable[H2I(trg)]] = priority
return TriggerSort()
endfunction
//******************************************************************************
//******************************************************************************
//* The new damage function used by the system
function UnitDamageTargetEx takes unit source, unit target, real damage, attacktype attackType, integer damageType, boolean ConsiderArmor returns boolean
local boolean b = false
set DamageType = damageType
set DamageSource = source
if ConsiderArmor then
set b = UnitDamageTarget(source, target, damage, false, false, attackType, DAMAGE_TYPE_NORMAL, null)
else
set b = UnitDamageTarget(source, target, damage, false, false, attackType, DAMAGE_TYPE_UNIVERSAL, null)
endif
if not b then
set DamageType = 0
set DamageSource = null
endif
return b
endfunction
//* The method by which one registers a trigger with the system
function TriggerRegisterDamageEvent takes trigger trg, integer priority returns boolean
if trg == null or priority < 0 then
return false
endif
if RegiTable[H2I(trg)] == 0 then
set RegiTable[H2I(trg)] = 1
endif
set Trg[Count] = trg
set Priority[Count] = priority
set TrigTable[H2I(trg)] = Count
set Count = Count + 1
return TriggerSort()
endfunction
//* The method by which one unregisters a trigger from the system
function TriggerUnregisterDamageEvent takes trigger trg returns boolean
local integer i = 0
if trg == null then
return false
endif
set i = TrigTable[H2I(trg)]
if trg != Trg[i] then
return false
endif
set Trg[i] = Trg[Count]
set Priority[i] = Priority[Count]
set TrigTable[H2I(Trg[i])] = i
set RegiTable[H2I(trg)] = 0
set Count = Count - 1
return TriggerSort()
endfunction
//* Initialization shorthand to register a new damage type externally
function RegisterDamageType takes nothing returns integer
local integer i = DamageTypeCount
set DamageTypeCount = DamageTypeCount + 1
return i
endfunction
//******************************************************************************
//******************************************************************************
//* Wrappers for the system that can get inlined anyways
function GetTriggerDamageType takes nothing returns integer
return DamageType
endfunction
function GetTriggerDamageSource takes nothing returns unit
return DamageSource
endfunction
function GetTriggerDamageTarget takes nothing returns unit
return DamageTarget
endfunction
function GetTriggerDamageBase takes nothing returns real
return DamageBase
endfunction
function GetTriggerDamage takes nothing returns real
return Damage
endfunction
//******************************************************************************
//******************************************************************************
private function RunConditions takes nothing returns boolean
//* The conditions for what must be true for damage detection to run
return GetEventDamage() >= 0.0001 and DamageType != DAMAGE_TYPE_IGNORED
endfunction
private function AddConditions takes nothing returns boolean
//* The conditions for registering a unit with the damage system
return true
endfunction
private function PreloadConditions takes unit u returns boolean
//* The conditions for preloading a unit to the damage system
return true
endfunction
//******************************************************************************
//******************************************************************************
globals
private integer array IDStack
private integer IDC = 0
private integer IDN = 0
endglobals
private function Run takes nothing returns nothing
local unit u = GetEventDamageSource()
local unit s = DamageSource
local unit t = GetTriggerUnit()
local integer i = 0
local integer id = 0
local integer d = DamageType
local real r = GetEventDamage()
local real b = r
//Allocate an id for this damage packet
if IDN > 0 then
set id = IDStack[IDN]
set IDN = IDN - 1
else
set id = IDC
set IDC = IDC + 1
endif
if DamageSource == null then
//Damage is of type attack
set d = DAMAGE_TYPE_ATTACK
set s = u
endif
loop
exitwhen i > Count or IgnPrior
//Ensure all variables are correct for nesting
set Damage = r
set DamageBase = b
set DamageTarget = t
set DamageSource = s
set DamageType = d
set DamageId = id
set NewDamage[id] = 0.
set NewDamageType[id] = -1
if IsTriggerEnabled(Trg[i]) and TriggerEvaluate(Trg[i]) then
call TriggerExecute(Trg[i])
endif
if NewDamage[id] > 0. then
//Update damage if it was changed
set r = NewDamage[id]
endif
if NewDamageType[id] >= 0 then
//Update damagetype if it was changed
set d = NewDamageType[id]
endif
set i = i + 1
endloop
set Damage = 0.
set DamageBase = 0.
set DamageTarget = null
set DamageSource = null
set DamageType = 0
set DamageId = 0
set IgnPrior = false
set NewDamage[id] = 0.
//Return id to the stack
set IDN = IDN + 1
set IDStack[IDN] = id
set u = null
set s = null
set t = null
endfunction
private function Load takes nothing returns nothing
call TriggerRegisterUnitEvent(RunTrigger, GetEnteringUnit(), EVENT_UNIT_DAMAGED)
endfunction
//******************************************************************************
//******************************************************************************
private function PreloadUnits takes nothing returns boolean
if PreloadConditions(GetFilterUnit()) then
call TriggerRegisterUnitEvent(RunTrigger, GetFilterUnit(), EVENT_UNIT_DAMAGED)
endif
return false
endfunction
private function Init takes nothing returns nothing
local rect r = GetWorldBounds()
local region re = CreateRegion()
local boolexpr b = Condition(function PreloadUnits)
local group g = CreateGroup()
//* Create the tables for use with the system
set TrigTable = Table.create()
set RegiTable = Table.create()
call TriggerAddAction(RunTrigger, function Run)
call TriggerAddCondition(RunTrigger, Condition(function RunConditions))
call GroupEnumUnitsInRect(g, r, b)
call RegionAddRect(re, r)
call TriggerRegisterEnterRegion(AddTrigger, re, null)
call TriggerAddAction(AddTrigger, function Load)
call TriggerAddCondition(AddTrigger, Condition(function AddConditions))
call RemoveRect(r)
call DestroyGroup(g)
call DestroyBoolExpr(b)
set re = null
set g = null
set b = null
set r = null
endfunction
endlibrary
My Damage System:
JASS:
scope DealAttackDamage initializer init
globals
private attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
private integer LEVEL
private integer UNIT_ID
private real DAMAGE
private unit SOURCE
private unit TARGET
private real ARMOR
private real DAMAGE_BONI
private integer DAMAGE_BASE
private integer DAMAGE_SIDESPERDIE
private integer DAMAGE_DICES
private constant integer HERO_DAMAGE_BASE = 30
private constant integer HERO_DAMAGE_SIDESPERDIE = 4
private constant integer HERO_DAMAGE_DICES = 2
private constant integer ID_BASH = 'A002'
private constant integer ID_CRITICALHIT = 'A001'
private constant integer ID_EVASION = 'A004'
private constant integer ID_FEEDBACK = 'A000'
private constant integer ID_WAVESTRIKE = 'A003'
private constant integer ID_HARDSKIN = 'A007'
private constant integer ID_WARPATTACK = 'A008'
endglobals
//###########################################################################################//
private function CriticalHit takes nothing returns nothing
local texttag te = CreateTextTag()
set DAMAGE = DAMAGE + DAMAGE * LEVEL
call SetTextTagText(te, I2S(R2I(DAMAGE)) + "!", 0.024)
call SetTextTagPos(te, GetUnitX(SOURCE), GetUnitY(SOURCE) + 20, 0.00)
call SetTextTagColor(te, 255, 0, 0, 255)
call SetTextTagVelocity(te, 0, 0.04)
call SetTextTagVisibility(te, true)
call SetTextTagFadepoint(te, 2)
call SetTextTagLifespan(te, 4)
call SetTextTagPermanent(te, false)
endfunction
//###########################################################################################//
private function Bash takes nothing returns nothing
set DAMAGE = DAMAGE + GetHeroStr(SOURCE, true) / 2 + LEVEL * 10.00
if not IsUnitType(TARGET, UNIT_TYPE_DEAD) then
call StunUnitTimed(TARGET, 1.5 + LEVEL)
endif
endfunction
//###########################################################################################//
globals
private group TEMP = CreateGroup()
endglobals
private struct Spell
static Spell array Index
static integer Total = 0
static timer t = CreateTimer()
group g = CreateGroup()
integer distance = 0
integer level
real x
real y
real f
real dam
unit caster
unit target
unit wave
static method Loop takes nothing returns nothing
local Spell d
local integer i = 0
local unit u
loop
exitwhen i >= Spell.Total
set d = Spell.Index[i]
if d.distance < 600 then
set d.x = PolarProjectionX(d.x, 20, d.f)
set d.y = PolarProjectionY(d.y, 20, d.f)
call SetUnitX(d.wave, d.x)
call SetUnitY(d.wave, d.y)
call GroupEnumUnitsInRange(TEMP, d.x, d.y, 125, null)
loop
set u = FirstOfGroup(TEMP)
if not IsUnitInGroup(u, d.g) then
call GroupAddUnit(d.g, u)
if IsUnitEnemy(u, GetOwningPlayer(d.caster)) then
//Damage
call UnitDamageTargetEx(d.caster, u, d.dam, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_IGNORED, false)
endif
endif
call GroupRemoveUnit(TEMP, u)
exitwhen u == null
endloop
call GroupClear(TEMP)
set d.distance = d.distance + 20
else
call RemoveUnit(d.wave)
call d.destroy()
// Recycling the indexer system
set Spell.Total = Spell.Total - 1
set Spell.Index[i] = Spell.Index[d.Total]
set i = i - 1
endif
set i = i + 1
endloop
if d.Total == 0 then
call PauseTimer(Spell.t)
endif
set u = null
endmethod
endstruct
private function WaveStrike takes nothing returns nothing
local Spell d = Spell.create()
set d.caster = SOURCE
set d.target = TARGET
set d.level = LEVEL
set d.f = GetUnitFacing(d.caster)
set d.x = PolarProjectionX(GetUnitX(d.caster), 150, d.f)
set d.y = PolarProjectionY(GetUnitY(d.caster), 150, d.f)
set d.wave = CreateUnit(GetOwningPlayer(d.caster), 'h003', d.x, d.y, d.f)
set d.dam = GetHeroStr(SOURCE, true) + LEVEL * 20.00
if Spell.Total == 0 then
call TimerStart(Spell.t, 0.03, true, function Spell.Loop)
endif
// Adding the struct to the indexer system
set Spell.Index[Spell.Total] = d
// Setting the total amount of structs in loop to Total + 1
set Spell.Total = Spell.Total + 1
endfunction
//###########################################################################################//
private function Feedback takes nothing returns nothing
if GetUnitState(GetTriggerDamageTarget(), UNIT_STATE_MANA) > (20 + 10.00 * LEVEL) then
set DAMAGE = DAMAGE + (20 + 10 * LEVEL)
call SetUnitState(TARGET, UNIT_STATE_MANA, GetUnitState(TARGET, UNIT_STATE_MANA) - (20 + 10 * LEVEL))
else
set DAMAGE = DAMAGE + GetUnitState(TARGET, UNIT_STATE_MANA)
call SetUnitState(TARGET, UNIT_STATE_MANA, 0)
endif
if IsUnitType(GetTriggerDamageTarget(), UNIT_TYPE_SUMMONED) then
set DAMAGE = DAMAGE + 100 + 50 * LEVEL
endif
endfunction
//###########################################################################################//
private function Evasion takes nothing returns nothing
local texttag te = CreateTextTag()
call SetTextTagText(te, "Miss", 0.024)
call SetTextTagPos(te, GetUnitX(SOURCE), GetUnitY(SOURCE) + 20, 0.00)
call SetTextTagColor(te, 255, 0, 0, 255)
call SetTextTagVelocity(te, 0, 0.04)
call SetTextTagVisibility(te, true)
call SetTextTagFadepoint(te, 1.5)
call SetTextTagLifespan(te, 3)
call SetTextTagPermanent(te, false)
set DAMAGE = 0
endfunction
private function HardSkin takes nothing returns nothing
set DAMAGE = DAMAGE - 10 * LEVEL
endfunction
private function WarpAttack takes nothing returns nothing
local real x = GetUnitX(SOURCE)
local real y = GetUnitY(SOURCE)
local real face = GetUnitFacing(SOURCE)
call StunUnitTimed(TARGET, LEVEL)
call SetUnitX(SOURCE, GetUnitX(TARGET) + 100 * Cos((GetUnitFacing(TARGET)-180)))
call SetUnitY(SOURCE, GetUnitY(TARGET) + 100 * Sin((GetUnitFacing(TARGET)-180)))
call SetUnitFacing(SOURCE, GetUnitFacing(TARGET))
endfunction
//###########################################################################################//
private function Actions takes nothing returns nothing
set SOURCE = GetTriggerDamageSource()
set TARGET = GetTriggerDamageTarget()
set ARMOR = GetUnitArmor(TARGET)
set DAMAGE_BONI = GetUnitBonus(SOURCE, BONUS_DAMAGE)
set UNIT_ID = GetUnitTypeId(SOURCE)
if IsUnitType(SOURCE, UNIT_TYPE_HERO) then
set DAMAGE = HERO_DAMAGE_BASE + GetRandomInt(1, HERO_DAMAGE_SIDESPERDIE) * HERO_DAMAGE_DICES + DAMAGE_BONI + GetPrimaryAttributeValue(SOURCE)
else
set DAMAGE_BASE = LoadInteger(h, UNIT_ID, HASH_UNIT_DAMAGE_BASE)
set DAMAGE_SIDESPERDIE = LoadInteger(h, UNIT_ID, HASH_UNIT_DAMAGE_SIDESPERDIE)
set DAMAGE_DICES = LoadInteger(h, UNIT_ID, HASH_UNIT_DAMAGE_DICES)
set DAMAGE = DAMAGE_BASE + GetRandomInt(1, DAMAGE_SIDESPERDIE) * DAMAGE_DICES + DAMAGE_BONI
endif
set DAMAGE = GetReducedDamage(DAMAGE, ARMOR)
//###########################################################################################//
//ABILITIES ~ Defensive
//Evasion
set LEVEL = GetUnitAbilityLevel(TARGET, ID_EVASION)
if GetRandomInt(1, 10) <= LEVEL and not IsUnitType(TARGET, UNIT_TYPE_STRUCTURE) then
call Evasion()
return
endif
set LEVEL = GetUnitAbilityLevel(TARGET, ID_HARDSKIN)
if LEVEL > 0 then
call HardSkin()
endif
if DAMAGE <= 0 then
return
endif
//###########################################################################################//
//ABILITIES ~ Offensive
//CriticalHit
set LEVEL = GetUnitAbilityLevel(SOURCE, ID_CRITICALHIT)
if GetRandomInt(1, 10) <= LEVEL and not IsUnitType(TARGET, UNIT_TYPE_STRUCTURE) then
call CriticalHit()
endif
//Feedback
set LEVEL = GetUnitAbilityLevel(SOURCE, ID_FEEDBACK)
if LEVEL > 0 and not IsUnitType(TARGET, UNIT_TYPE_STRUCTURE) then
call Feedback()
endif
//Bash
set LEVEL = GetUnitAbilityLevel(SOURCE, ID_BASH)
if GetRandomInt(1, 10) <= LEVEL and not IsUnitType(TARGET, UNIT_TYPE_STRUCTURE) then
call Bash()
endif
//###########################################################################################//
call UnitDamageTargetEx(SOURCE, TARGET, DAMAGE, ATTACK_TYPE, DAMAGE_TYPE_IGNORED, false)
//###########################################################################################//
//Abilities ~ AfterDamage
//Warp Attack
set LEVEL = GetUnitAbilityLevel(SOURCE, ID_WARPATTACK)
if GetRandomInt(1, 10) <= LEVEL and not IsUnitType(TARGET, UNIT_TYPE_STRUCTURE) and not IsUnitIllusion(SOURCE) and not IsUnitType(TARGET, UNIT_TYPE_DEAD) then
call WarpAttack()
endif
//WaveStrike
set LEVEL = GetUnitAbilityLevel(SOURCE, ID_WAVESTRIKE)
if GetRandomInt(1, 10) <= LEVEL and not IsUnitType(TARGET, UNIT_TYPE_STRUCTURE) then
call WaveStrike()
endif
//###########################################################################################//
set SOURCE = null
set TARGET = null
set DAMAGE = 0
set ARMOR = 0
set LEVEL = 0
set DAMAGE_BONI = 0
set DAMAGE_BASE = 0
set DAMAGE_SIDESPERDIE = 0
set DAMAGE_DICES = 0
endfunction
//###########################################################################################//
private function condition takes nothing returns boolean
return GetTriggerDamageType() == DAMAGE_TYPE_ATTACK
endfunction
//###########################################################################################//
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterDamageEvent(t, 0)
call TriggerAddCondition(t, Condition(function condition))
call TriggerAddAction(t, function Actions)
endfunction
endscope