Name | Type | is_array | initial_value |
FuseAbil | abilcode | No | A000 |
FuseAbilChan | abilcode | No | A001 |
FusedAnim | string | No | Stand Victory |
FusedSfx | string | No | Abilities\Spells\Demon\DarkConversion\ZombifyTarget.mdx |
FusedUnit | unitcode | No | Hamg |
FuseDuration | real | No | 5.00 |
FuseHashtable | hashtable | No | |
FuseImmune | boolean | No | true |
FuseRange | real | No | 10000.00 |
FuseSfx | string | No | Abilities\Spells\Undead\Unsummon\UnsummonTarget.mdx |
// DISPLAY ERROR
function Fuse__ErrorMsg takes player plr, string msg returns nothing
local sound SND_ERR = CreateSound("Sound\\Interface\\Error.wav", false, false, false, 10, 10, "DefaultEAXON")
if plr == GetLocalPlayer() then
if not GetSoundIsPlaying(SND_ERR) then
call StartSound(SND_ERR)
call KillSoundWhenDone(SND_ERR)
endif
call ClearTextMessages()
call DisplayTimedTextToPlayer(plr, 0.512, 0, 10, "|cffffcc00"+msg+".|r")
endif
set SND_ERR = null
endfunction
// CREATE FUSED UNIT
function Fuse__CreateFused_Conditions takes nothing returns boolean
local trigger trg = GetTriggeringTrigger()
local integer trgId = GetHandleId(trg)
local effect sfx = null
// Create new unit
local unit fused = CreateUnit(LoadPlayerHandle(udg_FuseHashtable, trgId, 0), udg_FusedUnit, LoadReal(udg_FuseHashtable, trgId, 1), LoadReal(udg_FuseHashtable, trgId, 2), bj_UNIT_FACING)
// Show effect
if StringLength(udg_FusedSfx) > 0 then
set sfx = AddSpecialEffectTarget(udg_FusedSfx , fused, "origin")
call DestroyEffect(sfx)
set sfx = null
endif
// Set unit state
call SetUnitState(fused, UNIT_STATE_LIFE, LoadReal(udg_FuseHashtable, trgId, 3))
call SetUnitState(fused, UNIT_STATE_MANA, LoadReal(udg_FuseHashtable, trgId, 4))
if StringLength(udg_FusedAnim) > 0 then
call SetUnitAnimation(fused, udg_FusedAnim)
endif
call DestroyTrigger(trg)
call FlushChildHashtable(udg_FuseHashtable, trgId)
set trg = null
set fused = null
return false
endfunction
// FUSE ABIL CAST OR FUSE CHANNEL FINISHED
function Trig_Fuse_Conditions takes nothing returns boolean
local unit one = null
local unit two = null
local trigger trg = null
local integer oneId
local integer trgId
local integer spellId = GetSpellAbilityId()
// Unit has finished channeling fusion
if spellId == udg_FuseAbilChan then
set one = GetSpellAbilityUnit()
set oneId = GetHandleId(one)
set two = LoadUnitHandle(udg_FuseHashtable, oneId, 0)
// Destroy damage/death trigger and effect
set trg = LoadTriggerHandle(udg_FuseHashtable, oneId, 1)
call FlushChildHashtable(udg_FuseHashtable, GetHandleId(trg))
call DestroyTrigger(trg)
if HaveSavedHandle(udg_FuseHashtable, oneId, 2) then
call DestroyEffect(LoadEffectHandle(udg_FuseHashtable, oneId, 2))
endif
call FlushChildHashtable(udg_FuseHashtable, oneId)
call FlushChildHashtable(udg_FuseHashtable, GetHandleId(two))
// Save fused unit data
set trg = CreateTrigger()
set trgId = GetHandleId(trg)
call SavePlayerHandle(udg_FuseHashtable, trgId, 0, GetOwningPlayer(one))
call SaveReal(udg_FuseHashtable, trgId, 1, (GetUnitX(one) + GetUnitX(two))/2)
call SaveReal(udg_FuseHashtable, trgId, 2, (GetUnitY(one) + GetUnitY(two))/2)
call SaveReal(udg_FuseHashtable, trgId, 3, GetUnitState(one, UNIT_STATE_LIFE)+GetUnitState(two, UNIT_STATE_LIFE))
call SaveReal(udg_FuseHashtable, trgId, 4, GetUnitState(one, UNIT_STATE_MANA)+GetUnitState(two, UNIT_STATE_MANA))
// Remove original units
call SetUnitPathing(one, false)
call SetUnitPathing(two, false)
call RemoveUnit(one)
call RemoveUnit(two)
// Delayed fused unit create
call TriggerRegisterTimerEvent(trg, 0, false)
call TriggerAddCondition(trg, Condition(function Fuse__CreateFused_Conditions))
set one = null
set two = null
set trg = null
else
// Fuse spell is cast -> Continue to actions
return spellId == udg_FuseAbil
endif
return false
endfunction
// DISTRIBUTE DAMAGE DONE TO FUSING UNITS
function Fuse__AdjustDamage_Conditions takes nothing returns boolean
local trigger trg = GetTriggeringTrigger()
local integer trgId = GetHandleId(trg)
local unit one = LoadUnitHandle(udg_FuseHashtable, trgId, 0)
local unit two = LoadUnitHandle(udg_FuseHashtable, GetHandleId(one), 0)
local real dmg = LoadReal(udg_FuseHashtable, trgId, 1)
call DestroyTrigger(trg)
call FlushChildHashtable(udg_FuseHashtable, trgId)
// Apply the HP changes
call SetUnitState(one, UNIT_STATE_LIFE, GetUnitState(one, UNIT_STATE_LIFE)+dmg)
call SetUnitState(two, UNIT_STATE_LIFE, GetUnitState(two, UNIT_STATE_LIFE)-dmg)
set trg = null
set one = null
set two = null
return false
endfunction
// UNIT DIES OR IS DAMAGED
function Fuse__DeathDamage_Conditions takes nothing returns boolean
local unit one = GetDyingUnit()
local integer oneId
local unit two = null
local trigger trg = null
local integer trgId
// Unit dies
if one != null then
call DestroyTrigger(GetTriggeringTrigger())
set oneId = GetHandleId(one)
set two = LoadUnitHandle(udg_FuseHashtable, oneId, 0)
// Kill other unit
call KillUnit(two)
// Destroy effect
if HaveSavedHandle(udg_FuseHashtable, oneId, 2) then
call DestroyEffect(LoadEffectHandle(udg_FuseHashtable, oneId, 2))
endif
call FlushChildHashtable(udg_FuseHashtable, oneId)
call FlushChildHashtable(udg_FuseHashtable, GetHandleId(two))
set one = null
set two = null
// Unit is damaged
else
set trg = CreateTrigger()
set trgId = GetHandleId(trg)
call SaveUnitHandle(udg_FuseHashtable, trgId, 0, GetTriggerUnit())
call SaveReal(udg_FuseHashtable, trgId, 1, GetEventDamage()/2)
// Adjust damage after delay
call TriggerRegisterTimerEvent(trg, 0, false)
call TriggerAddCondition(trg, Condition(function Fuse__AdjustDamage_Conditions))
set trg = null
endif
return false
endfunction
// START THE FUSION
function Fuse__StartFusion_Conditions takes nothing returns boolean
local trigger trg = GetTriggeringTrigger()
local integer trgId = GetHandleId(trg)
local unit one = LoadUnitHandle(udg_FuseHashtable, trgId, 0)
local unit two = LoadUnitHandle(udg_FuseHashtable, trgId, 1)
local integer oneId = GetHandleId(one)
local integer twoId = GetHandleId(two)
local effect sfx = null
call DestroyTrigger(trg)
call FlushChildHashtable(udg_FuseHashtable, trgId)
// Add triggers for damage (distribute) and death (kill other)
set trg = CreateTrigger()
call TriggerRegisterUnitEvent(trg, one, EVENT_UNIT_DAMAGED)
call TriggerRegisterUnitEvent(trg, two, EVENT_UNIT_DAMAGED)
call TriggerRegisterUnitEvent(trg, one, EVENT_UNIT_DEATH)
call TriggerRegisterUnitEvent(trg, two, EVENT_UNIT_DEATH)
call TriggerAddCondition(trg, Condition(function Fuse__DeathDamage_Conditions))
call SaveUnitHandle(udg_FuseHashtable, oneId, 0, two)
call SaveUnitHandle(udg_FuseHashtable, twoId, 0, one)
call SaveTriggerHandle(udg_FuseHashtable, oneId, 1, trg)
call SaveTriggerHandle(udg_FuseHashtable, twoId, 1, trg)
if udg_FuseImmune then
call UnitAddType(one, UNIT_TYPE_MAGIC_IMMUNE)
call UnitAddType(two, UNIT_TYPE_MAGIC_IMMUNE)
endif
if StringLength(udg_FuseSfx) > 0 then
set sfx = AddSpecialEffect(udg_FuseSfx, (GetUnitX(one)+GetUnitX(two))/2, (GetUnitY(one)+GetUnitY(two))/2)
call SaveEffectHandle(udg_FuseHashtable, oneId, 2, sfx)
call SaveEffectHandle(udg_FuseHashtable, twoId, 2, sfx)
set sfx = null
endif
// Start the fusion
call IssueImmediateOrder(one, "channel")
call IssueImmediateOrder(two, "channel")
set trg = null
set one = null
set two = null
return false
endfunction
// CHECK IF UNITS ARE STILL MOVING
function Fuse__MoveCheck_Conditions takes nothing returns boolean
local trigger trg = GetTriggeringTrigger()
local integer trgId
local unit one = GetOrderedUnit()
local integer oneId
local unit two = null
local integer twoId
local real angle
local real oneX
local real oneY
local real oneDX
local real oneDY
local real twoX
local real twoY
local real twoDX
local real twoDY
if one == null then
set one = GetDyingUnit()
endif
// Move is interrupted
if one != null then
call FlushChildHashtable(udg_FuseHashtable, GetHandleId(trg))
call DestroyTrigger(trg)
set oneId = GetHandleId(one)
set two = LoadUnitHandle(udg_FuseHashtable, oneId, 0)
call FlushChildHashtable(udg_FuseHashtable, oneId)
call FlushChildHashtable(udg_FuseHashtable, GetHandleId(two))
// Stop other unit
call IssueImmediateOrder(two, "stop")
else
set trgId = GetHandleId(trg)
set one = LoadUnitHandle(udg_FuseHashtable, trgId, 0)
set oneId = GetHandleId(one)
set two = LoadUnitHandle(udg_FuseHashtable, oneId, 0)
// Both units are no longer moving
if GetUnitCurrentOrder(one) != 851986 and GetUnitCurrentOrder(two) != 851986 then
call DestroyTrigger(trg)
call FlushChildHashtable(udg_FuseHashtable, trgId)
set oneX = GetUnitX(one)
set oneY = GetUnitY(one)
set oneDX = LoadReal(udg_FuseHashtable, oneId, 1) - oneX
set oneDY = LoadReal(udg_FuseHashtable, oneId, 2) - oneY
set twoId = GetHandleId(two)
set twoX = GetUnitX(two)
set twoY = GetUnitY(two)
set twoDX = LoadReal(udg_FuseHashtable, twoId, 1) - twoX
set twoDY = LoadReal(udg_FuseHashtable, twoId, 2) - twoY
call FlushChildHashtable(udg_FuseHashtable, oneId)
call FlushChildHashtable(udg_FuseHashtable, twoId)
// Check that units are near target position
if SquareRoot(oneDX*oneDX + oneDY*oneDY) <= 30 and SquareRoot(twoDX*twoDX + twoDY*twoDY) <= 30 then
// Give the units the fusion ability
call UnitAddAbility(one, udg_FuseAbilChan)
call UnitAddAbility(two, udg_FuseAbilChan)
// Make units face eachother
set angle = bj_RADTODEG * Atan2(twoY - oneY, twoX - oneX)
call SetUnitFacingTimed(one, angle, 0.5)
call SetUnitFacingTimed(two, angle+180, 0.5)
// Start fusion after a delay
set trg = CreateTrigger()
set trgId = GetHandleId(trg)
call SaveUnitHandle(udg_FuseHashtable, trgId, 0, one)
call SaveUnitHandle(udg_FuseHashtable, trgId, 1, two)
call TriggerRegisterTimerEvent(trg, 0.5, false)
call TriggerAddCondition(trg, Condition(function Fuse__StartFusion_Conditions))
endif
endif
endif
set one = null
set two = null
set trg = null
return false
endfunction
// START THE PRE-FUSION PROCESS
function Trig_Fuse_Actions takes nothing returns nothing
local group unitsSelected = CreateGroup()
local unit first = null
local unit one = GetSpellAbilityUnit()
local real oneX = GetUnitX(one)
local real oneY = GetUnitY(one)
local integer oneId
local integer oneType = GetUnitTypeId(one)
local unit two = null
local real twoX
local real twoY
local integer twoId
local player owner = GetOwningPlayer(one)
local real distance
local real distanceSmallest = 0
local real x
local real y
local boolean typeFound = false
local trigger trg = null
local real offsetX = 30
local real offsetY = 30
call SyncSelections() // This must be in an Action
call GroupEnumUnitsSelected(unitsSelected, owner, null)
// Find the closest selected unit of the same type
loop
set first = FirstOfGroup(unitsSelected)
exitwhen first == null
if one != first and oneType == GetUnitTypeId(first) then
set typeFound = true
set x = GetUnitX(first)
set y = GetUnitY(first)
set distance = SquareRoot((x-oneX)*(x-oneX) + (y-oneY)*(y-oneY))
if distance <= udg_FuseRange and (two == null or distanceSmallest > distance) then
set distanceSmallest = distance
set two = first
set twoX = x
set twoY = y
endif
endif
call GroupRemoveUnit(unitsSelected, first)
endloop
call DestroyGroup(unitsSelected)
set unitsSelected = null
set first = null
// No valid target found
if two == null then
if typeFound then
call Fuse__ErrorMsg(owner, "Selected " + GetUnitName(one) + " out of range")
else
call Fuse__ErrorMsg(owner, "No " + GetUnitName(one) + " selected")
endif
// Target found
else
if oneX < twoX then
set offsetX = -offsetX
endif
if oneY < twoY then
set offsetY = -offsetY
endif
set x = (oneX + twoX)/2
set y = (oneY + twoY)/2
set oneX = x+offsetX
set oneY = y+offsetY
set twoX = x-offsetX
set twoY = y-offsetY
// Order units to move toward eachother
call IssuePointOrder(one, "move", oneX, oneY)
call IssuePointOrder(two, "move", twoX, twoY)
// Trigger to check is movement is interrupted or finished
set trg = CreateTrigger()
set oneId = GetHandleId(one)
set twoId = GetHandleId(two)
call SaveUnitHandle(udg_FuseHashtable, oneId, 0, two)
call SaveReal(udg_FuseHashtable, oneId, 1, oneX)
call SaveReal(udg_FuseHashtable, oneId, 2, oneY)
call SaveUnitHandle(udg_FuseHashtable, twoId, 0, one)
call SaveReal(udg_FuseHashtable, twoId, 1, twoX)
call SaveReal(udg_FuseHashtable, twoId, 2, twoY)
call SaveUnitHandle(udg_FuseHashtable, GetHandleId(trg), 0, one)
call TriggerRegisterTimerEvent(trg, 0.05, true)
call TriggerRegisterUnitEvent(trg, one, EVENT_UNIT_ISSUED_ORDER)
call TriggerRegisterUnitEvent(trg, one, EVENT_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterUnitEvent(trg, one, EVENT_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterUnitEvent(trg, one, EVENT_UNIT_DEATH)
call TriggerRegisterUnitEvent(trg, two, EVENT_UNIT_ISSUED_ORDER)
call TriggerRegisterUnitEvent(trg, two, EVENT_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterUnitEvent(trg, two, EVENT_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterUnitEvent(trg, two, EVENT_UNIT_DEATH)
call TriggerAddCondition(trg, Condition(function Fuse__MoveCheck_Conditions))
set trg = null
set two = null
endif
set one = null
set owner = null
endfunction
function Trig_Fuse_Filter takes nothing returns boolean
return GetUnitAbilityLevel(GetFilterUnit(), udg_FuseAbil) > 0
endfunction
//===========================================================================
function InitTrig_Fuse takes nothing returns nothing
local integer index = 0
set gg_trg_Fuse = CreateTrigger()
set udg_FuseHashtable = InitHashtable()
loop
call TriggerRegisterPlayerUnitEvent(gg_trg_Fuse, Player(index), EVENT_PLAYER_UNIT_SPELL_FINISH, Filter(function Trig_Fuse_Filter))
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(gg_trg_Fuse, Condition(function Trig_Fuse_Conditions))
call TriggerAddAction(gg_trg_Fuse, function Trig_Fuse_Actions)
endfunction