Name | Type | is_array | initial_value |
CargoEvent | real | No | |
CargoTransportGroup | group | Yes | |
CargoTransportUnit | unit | Yes | |
CEvBlock | boolean | Yes | |
CEvNext | integer | Yes | |
CEvPrev | integer | Yes | |
CEvSpecial | boolean | Yes | |
CEvUnloadTimer | timer | No | |
CI__DealtDmgFactor | real | No | |
CI__dealtFactor | real | Yes | |
CI__dummy | unit | No | |
CI__dummyCaster | unit | No | |
CI__dummyID | unitcode | No | |
CI__dummyItem | item | No | |
CI__IllusionFacing | real | No | |
CI__IllusionLocation | location | No | |
CI__IllusionOwner | player | No | |
CI__IllusionType | unitcode | No | |
CI__IllusionUnit | unit | No | |
CI__isIllusion | boolean | Yes | |
CI__itemID | itemcode | No | |
CI__LastCreatedIllusion | unit | No | |
CI__onDeindexTrigger | trigger | No | |
CI__onDmgTrigger | trigger | No | |
CI__onIndexTrigger | trigger | No | |
CI__spellID | abilcode | No | |
CI__TakenDmgFactor | real | No | |
CI__takenFactor | real | Yes | |
CI__tempDex | integer | No | |
CI__tempLoc | location | No | |
CI__wantDetect | boolean | No | |
DDD__CodeDetector | boolean | No | |
DDD__DamageTypeCode | integer | No | |
DDD__DamageTypePhysic | integer | No | |
DDD__DamageTypeSpell | integer | No | |
DDD__Enabled | boolean | No | |
DDD__Event__Amount | real | No | |
DDD__Event__Source | unit | No | |
DDD__Event__Target | unit | No | |
DDD__Event__Trigger | real | No | |
DDD__Event__Type | integer | No | |
DDD__Group__Counter | integer | Yes | |
DDD__Group__Group | group | Yes | |
DDD__Group__Index | integer | No | |
DDD__Group__Trigger | trigger | Yes | |
DDD__IsDetectionEnabled | boolean | No | |
DDD__Protect__Health | real | Yes | |
DDD__UnitDetectionState | boolean | Yes | |
DDD__UnitIndex | integer | Yes | |
DeathEvent | real | No | |
DEvAbility | abilcode | No | |
DEvBlock | boolean | Yes | |
DEvList | integer | Yes | |
DEvRemoved | boolean | Yes | |
DEvTimer | timer | No | |
IsUnitAlive | boolean | Yes | |
IsUnitReincarnating | boolean | Yes | |
tempGroup | group | No | |
TempInteger | integer | No | |
tempUnit | unit | No | |
UDex | integer | No | |
UDexGen | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexRecycle | integer | No | |
UDexUnits | unit | Yes | |
UDexWasted | integer | No | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No |
=====================
HOW TO INSTALL
=====================
1. Import dummy.mdx at import manager
2. Install all required systems correctly
3. Copy Dummy, ILLUSION_ITEM, ILLUSION_ABILITY_1 & ILLUSION_ABILITY_2 at Object Editor
4. Make sure ILLUSION's ability is ILLUSION_ABILITY_2
5. Configure the system
===========================
HOW TO CREATE IMAGE
===========================
(Use custom script)
1. Create a new mirror image
call ExecuteFunc("CI__Create")
uses variables:
CI__IllusionType => created image type
CI__IllusionFacing => facing angle of created image
CI__IllusionOwner => owner of created image
CI__IllusionLocation => where the image will be created
CI__DealtDmgFactor => multiplier of dealt damage
CI__TakenDmgFactor => multiplier of taken damage
2. Create mirror image based on an existing unit
call ExecuteFunc("CI__Copy")
uses variable:
CI__IllusionUnit => which unit that you want to copy from (base unit)
CI__IllusionFacing
cI__IllusionOwner
CI__IllusionLocation
CI__DealtDmgFactor
CI__TakenDmgFactor
Use variable CI__LastCreatedIllusion to access the last created custom illusion
Check demo triggers for examples.
//x=============================================================== //
//x
// Dalv's Damage Detection
// v1.7.1
//
//x=============================================================== //
//x
// Advantages:
// - Lite & fast
// - GUI friendly
// - Low requirement
// - Supports damage type detection
// - Efficient memory usage
//
//
// Requirement(s):
// - Bribe's UnitIndexer
//
//
// How to install:
// - Copy DDD_ABILITY_1 ability to your map
// - Copy DDD_ABILITY_2 ability to your map
// - Copy the DDD trigger folder to your map
// - Delete VarCreator trigger
// - Install required systems correctly
// - Configure the system correctly
//
//
// User API:
// 1. Register a unit into the system, will ignore unit filtering.
// | function DDD__RegisterUnit takes unit whichUnit returns boolean
//
//
// 2. Remove a unit from the system.
// | function DDD__UnregisterUnit takes unit whichUnit returns boolean
//
//
// 3. Catch the damage event.
// | DDD__Event__Trigger EQUAL 1.00
//
//
// 4. Event responses (customizable).
// | DDD__Event__Source => source of damage (attacker)
//
// | DDD__Event__Target => target of damage (attacked)
//
// | DDD__Event__Amount => amount of damage
//
// | DDD__Event__Type => type of damage
// - DDD__DamageTypeSpell
// - DDD__DamageTypePhysic
// - DDD__DamageTypeCode
//
//
// 5. All damages by this function will be classified as "code" damage.
// | function DDD__DealCodeDamage takes unit source, widget target, reeal amount, boolean attack, boolean ranged,
// attacktype attackType, damagetype damageType, weapontype weaponType returns nothing
//
//
// 6. Turn on/off the damage detection.
// | function DDD__EnableDetection takes boolean enable returns boolean
// - true => on
// - false => off
//
// To check whether the detection is currently on/off (do not modify!)
// | DDD_IsDetectionEnabled
//
//
// 7. Turn on/off damage detection for a specific unit.
// | function DDD__EnableDetectionForUnit takes unit whichUnit, boolean enable returns boolean
// - true => on
// - false => off
//
//
// 8. Ignore (avoid) damage, damage won't be dealt completely.
// | set DDD__IgnoreThisEvent = true
//
//
// (You are not recommended to use any function or
// variable that is not mentioned in user API.)
//
//
// Credits:
// - Bribe for his GUI friendly UnitIndexer and UnitEvent.
//
// - Nestharus for his get spell resistance method
// and for his guidances.
//
// - Special thanks to looking_for_help for his
// damage type detection method.
//
//x=============================================================== //
//x
// CONFIGURATION //
//
// DDD_ABILITY_1's raw code at Object Editor
constant function DDD__Ability_1 takes nothing returns integer
return 'A002'
endfunction
// DDD_ABILITY_2's raw code at Object Editor
constant function DDD__Ability_2 takes nothing returns integer
return 'A003'
endfunction
// Number of units for each group.
// Higher value will increase the memory usage efficiency
// but will slow down the trigger clean up process
constant function DDD__GroupMaxMember takes nothing returns integer
return 25
endfunction
// If true, all classified unit will be registered automatically to
// the system
constant function DDD__EnableAutoRegister takes nothing returns boolean
return true
endfunction
// Classification for units that can be automatically registered to
// the system
function DDD__FilterUnit takes unit whichUnit returns boolean
return true // Currently it allows any unit to be registered
endfunction
//
//x=============================================================== //
// Enable/disable detection for specific unit
function DDD__EnableDetectionForUnit takes unit whichUnit, boolean enable returns boolean
local integer data = GetUnitUserData(whichUnit)
// If unit is registered
if udg_DDD__UnitIndex[data] != 0 and enable != udg_DDD__UnitDetectionState[data] then
set udg_DDD__UnitDetectionState[data] = enable
// Add or remove damage type detector
if enable and UnitAddAbility(whichUnit, DDD__Ability_1()) and UnitMakeAbilityPermanent(whichUnit, true, DDD__Ability_1()) then
elseif GetUnitAbilityLevel(whichUnit, DDD__Ability_1()) > 0 and UnitRemoveAbility(whichUnit, DDD__Ability_1()) then
endif
endif
return udg_DDD__UnitDetectionState[data]
endfunction
// Enable/disable detection for all registered units
function DDD__EnableDetection takes boolean enable returns boolean
local integer i = 1
local group tempGroup
local unit first
if enable != udg_DDD__IsDetectionEnabled then
loop
exitwhen i > udg_DDD__Group__Index
// Enable/disable detection triggers
if enable then
call EnableTrigger(udg_DDD__Group__Trigger[i])
else
call DisableTrigger(udg_DDD__Group__Trigger[i])
endif
// Disable detection for all registered units
set tempGroup = CreateGroup()
loop
set first = FirstOfGroup(udg_DDD__Group__Group[i])
exitwhen first == null
call GroupRemoveUnit(udg_DDD__Group__Group[i], first)
call GroupAddUnit(tempGroup, first)
call DDD__EnableDetectionForUnit(first, enable)
endloop
// Recycle group
call DestroyGroup(udg_DDD__Group__Group[i])
set udg_DDD__Group__Group[i] = tempGroup
set tempGroup = null
set i = i + 1
endloop
set udg_DDD__IsDetectionEnabled = enable
endif
return udg_DDD__IsDetectionEnabled
endfunction
// Function to obtain unit's spell resistance
function DDD__GetSpellResistance takes unit whichUnit returns real
local real life = GetWidgetLife(whichUnit)
local real max = GetUnitState(whichUnit, UNIT_STATE_MAX_LIFE)
local real result
call SetWidgetLife(whichUnit, max)
// Deal test damage
set udg_DDD__Enabled = false
call UnitDamageTarget(whichUnit, whichUnit, -max/2, false, false, null, DAMAGE_TYPE_UNIVERSAL, null)
set udg_DDD__Enabled = true
// Calculate resistance based on collected data
set result = 2*(max-GetWidgetLife(whichUnit))/max
call SetWidgetLife(whichUnit, life)
return result
endfunction
// Detect damage type
function DDD__GetDamageType takes nothing returns integer
if udg_DDD__CodeDetector then
set udg_DDD__CodeDetector = false
return udg_DDD__DamageTypeCode
elseif udg_DDD__Event__Amount < 0 then
set udg_DDD__Event__Amount = -udg_DDD__Event__Amount
return udg_DDD__DamageTypeSpell
else
return udg_DDD__DamageTypePhysic
endif
return 0
endfunction
// Remove protection
function DDD__Deprotect takes nothing returns boolean
local unit u = GetTriggerUnit()
// Remove health bonus
if GetUnitAbilityLevel(u, DDD__Ability_2()) > 0 and UnitRemoveAbility(u, DDD__Ability_2()) then
endif
// Refresh life
call SetWidgetLife(u, udg_DDD__Protect__Health[GetUnitUserData(u)])
call DestroyTrigger(GetTriggeringTrigger())
set u = null
return false
endfunction
// Protect unit from a native damage
function DDD__Protect takes unit whichUnit, real damage returns nothing
local trigger t = CreateTrigger()
local real life = GetWidgetLife(whichUnit)
local real max = GetUnitState(whichUnit, UNIT_STATE_MAX_LIFE)
set udg_DDD__Protect__Health[GetUnitUserData(whichUnit)] = life
// If the unit needs additional hp
if life + RAbsBJ(damage) > max then
call UnitAddAbility(whichUnit, DDD__Ability_2())
endif
// If physical damage
if damage > 0 then
call SetWidgetLife(whichUnit, life+damage)
call TriggerRegisterUnitStateEvent(t, whichUnit, UNIT_STATE_LIFE, LESS_THAN, life+damage/2)
else
call SetWidgetLife(whichUnit, life)
call TriggerRegisterUnitStateEvent(t, whichUnit, UNIT_STATE_LIFE, GREATER_THAN, life-damage/2)
endif
call TriggerAddCondition(t, Condition(function DDD__Deprotect))
set t = null
endfunction
function DDD__killTarget takes nothing returns nothing
call DDD__EnableDetectionForUnit(udg_DDD__Event__Target, false)
call UnitDamageTarget(udg_DDD__Event__Source, udg_DDD__Event__Target, 10000000, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null)
call DDD__EnableDetectionForUnit(udg_DDD__Event__Target, true)
endfunction
// Executed on damage event
function DDD__onDamage takes nothing returns boolean
local real resistance
local real life
local real damage
local unit target
local unit ptarget
local unit psource
local real pamount
local integer ptype
local integer data
if udg_DDD__Enabled then
// Original target
set target = GetTriggerUnit()
set data = GetUnitUserData(target)
// If target is registered in the system
if udg_DDD__UnitIndex[data] != 0 and udg_DDD__UnitDetectionState[data] then
// Original damage
set damage = GetEventDamage()
// Previous data
set ptarget = udg_DDD__Event__Target
set psource = udg_DDD__Event__Source
set pamount = udg_DDD__Event__Amount
set ptype = udg_DDD__Event__Type
// If spell damage is detected
if damage < 0 then
set resistance = DDD__GetSpellResistance(target)
if resistance > 1 then
set damage = damage*resistance
endif
endif
// Modifiable data
set udg_DDD__Event__Target = target
set udg_DDD__Event__Amount = damage
set udg_DDD__Event__Source = GetEventDamageSource()
set udg_DDD__Event__Type = DDD__GetDamageType()
// Fire the damage event
set udg_DDD__Event__Trigger = 1
set udg_DDD__Event__Trigger = 0
// Substract life by damage amount
set life = GetWidgetLife(udg_DDD__Event__Target) - udg_DDD__Event__Amount
if life > 0.405 then
call SetWidgetLife(udg_DDD__Event__Target, life)
endif
// If event target isn't modified
if target == udg_DDD__Event__Target then
// If need to be protected
if life > 0.405 then
if RAbsBJ(damage) > 0.01 then
call DDD__Protect(target, damage)
endif
// If need damage to kill
elseif damage < 0 then
call DDD__killTarget()
else
call SetWidgetLife(target, damage)
endif
else
// If need to be protected
if RAbsBJ(damage) > 0.01 then
call DDD__Protect(target, damage)
endif
// If need damage to kill
if life <= 0.405 then
call DDD__killTarget()
endif
endif
// Reset the data
set udg_DDD__Event__Source = psource
set udg_DDD__Event__Target = ptarget
set udg_DDD__Event__Amount = pamount
set udg_DDD__Event__Type = ptype
// Remove leak
set psource = null
set ptarget = null
endif
set target = null
endif
return false
endfunction
// Register a unit into the system
function DDD__RegisterUnit takes unit whichUnit returns boolean
local integer data = GetUnitUserData(whichUnit)
// If unit hasn't been registered yet
if udg_DDD__UnitIndex[data] == 0 then
// If new node is required then create it
if udg_DDD__Group__Counter[udg_DDD__Group__Index] == DDD__GroupMaxMember() then
set udg_DDD__Group__Index = udg_DDD__Group__Index + 1
set udg_DDD__Group__Group[udg_DDD__Group__Index] = CreateGroup()
set udg_DDD__Group__Trigger[udg_DDD__Group__Index] = CreateTrigger()
call TriggerAddCondition(udg_DDD__Group__Trigger[udg_DDD__Group__Index], Condition(function DDD__onDamage))
endif
// Register unit into the current node
set udg_DDD__UnitDetectionState[data] = true
set udg_DDD__UnitIndex[data] = udg_DDD__Group__Index
set udg_DDD__Group__Counter[udg_DDD__Group__Index] = udg_DDD__Group__Counter[udg_DDD__Group__Index] + 1
// Add damage type detector ability
if UnitAddAbility(whichUnit, DDD__Ability_1()) and UnitMakeAbilityPermanent(whichUnit, true, DDD__Ability_1()) then
endif
call GroupAddUnit(udg_DDD__Group__Group[udg_DDD__Group__Index], whichUnit)
call TriggerRegisterUnitEvent(udg_DDD__Group__Trigger[udg_DDD__Group__Index], whichUnit, EVENT_UNIT_DAMAGED)
return true
endif
return false
endfunction
// Remove a unit from the system
function DDD__UnregisterUnit takes unit whichUnit returns boolean
local integer data = GetUnitUserData(whichUnit)
local integer index = udg_DDD__UnitIndex[data]
local unit first
// If unit is registered
if index > 0 then
// Remove from current node
call GroupRemoveUnit(udg_DDD__Group__Group[index], whichUnit)
set udg_DDD__Group__Counter[index] = udg_DDD__Group__Counter[index] - 1
set udg_DDD__UnitDetectionState[data] = false
set udg_DDD__UnitIndex[data] = 0
// Check whether unit is in the latest node or not
if index == udg_DDD__Group__Index then
// If node is empty then destroy it
if udg_DDD__Group__Counter[index] == 0 then
// Remove leaks
call DestroyTrigger(udg_DDD__Group__Trigger[index])
call DestroyGroup(udg_DDD__Group__Group[index])
set udg_DDD__Group__Trigger[index] = null
set udg_DDD__Group__Group[index] = null
set udg_DDD__Group__Index = udg_DDD__Group__Index - 1
endif
// If unit isn't located in the last node and
// that node is empty already, then destroy
elseif udg_DDD__Group__Counter[index] == 0 then
call DestroyTrigger(udg_DDD__Group__Trigger[index])
// Transfer data from last node to the destroyed node
loop
set first = FirstOfGroup(udg_DDD__Group__Group[udg_DDD__Group__Index])
exitwhen first == null
call GroupRemoveUnit(udg_DDD__Group__Group[udg_DDD__Group__Index], first)
call GroupAddUnit(udg_DDD__Group__Group[index], first)
set udg_DDD__UnitIndex[GetUnitUserData(first)] = index
endloop
set udg_DDD__Group__Trigger[index] = udg_DDD__Group__Trigger[udg_DDD__Group__Index]
set udg_DDD__Group__Counter[index] = udg_DDD__Group__Counter[udg_DDD__Group__Index]
// Remove leaks
call DestroyGroup(udg_DDD__Group__Group[udg_DDD__Group__Index])
set udg_DDD__Group__Trigger[udg_DDD__Group__Index] = null
set udg_DDD__Group__Group[udg_DDD__Group__Index] = null
set udg_DDD__Group__Index = udg_DDD__Group__Index - 1
endif
return true
endif
return false
endfunction
// All damages caused by this function will be classified as "code" damage
function DDD__DealCodeDamage takes unit source, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns nothing
set udg_DDD__CodeDetector = true
call UnitDamageTarget(source, target, amount, attack, ranged, attackType, damageType, weaponType)
endfunction
// Executed on index event
function DDD__onIndex takes nothing returns boolean
if DDD__FilterUnit(udg_UDexUnits[udg_UDex]) then
call DDD__RegisterUnit(udg_UDexUnits[udg_UDex])
endif
return false
endfunction
// Executed on deindex event
function DDD__onDeindex takes nothing returns boolean
call DDD__UnregisterUnit(udg_UDexUnits[udg_UDex])
return false
endfunction
function InitTrig_DDD takes nothing returns nothing
local trigger t
// Init damage types
set udg_DDD__DamageTypePhysic = 1
set udg_DDD__DamageTypeSpell = 2
set udg_DDD__DamageTypeCode = 3
set udg_DDD__Enabled = true
set udg_DDD__Group__Counter[0] = DDD__GroupMaxMember()
if DDD__EnableAutoRegister() then
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
call TriggerAddCondition(t, Condition(function DDD__onIndex))
endif
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_DeathEvent", EQUAL, 3.00)
call TriggerAddCondition(t, Condition(function DDD__onDeindex))
set t = null
endfunction