//----------------------------------------------------------------------
//----------------------------------------------------------------------
// C O M B O S Y S T E M
// Made by: Nyuu
// Version: 1.5
//
// What system does:
// - This system will count the combo that a unit attack
// enemies. Affected only when a unit attack without using spell.
//
// How to use:
// - To start counting combo from a unit, use this function:
// function UnitComboAdd takes unit whichUnit,real Scale,real ComboDisableTimer returns nothing
// => whichUnit - Which unit you want to count
// => Scale - Scaling size of the unit (Make the height more accurate)
// => ComboDisableTimer - Timer of the combo, if the unit stop attacking the enemies,
// Combo will be destroyed and reset to 0.
// - To start counting combo from a unit, use this function (Ex):
// function UnitComboAddEx takes unit whichUnit,real Scale,real ComboDisableTimer,real whichHeight,string decorateLeft,string decorateRight,string textCombo returns nothing
// => whichUnit - Which unit you want to count
// => Scale - Scaling size of the unit (Make the height more accurate)
// => ComboDisableTimer - Timer of the combo, if the unit stop attacking the enemies,
// Combo will be destroyed and reset to 0.
// => whichHeight: Your height value
// => decorateLeft: Your decorate left text
// => decorateRogjt: Your decorate right text
// => textCombo: Your text combo text
// - To stop counting combo from a unit, use this function:
// function UnitComboRemove takes unit whichUnit returns nothing
// => whichUnit - Which unit you want to remove from this system
// - To get combo count of a unit, use this function:
// function GetUnitComboCount takes unit whichUnit returns integer
// => whichUnit - Which unit you want to get combo count
// - To change scale value from a unit, use this function:
// function SetTextComboScale takes unit whichUnit,real whichScale returns nothing
// => whichUnit - Which unit you want to change
// => whichScale - Your scale value
// - To change height value from a unit, use this function:
// function SetTextComboheighttakes unit whichUnit,real whichHeight returns nothing
// => whichUnit - Which unit you want to change
// => whichHeight - Your height value
// - To change text decorate left from a unit, use this function:
// function SetTextComboDecorateLeft takes unit whichUnit,string whichText returns nothing
// => whichUnit - Which unit you want to change
// => whichText - Your text
// - To change text decorate right from a unit, use this function:
// function SetTextComboDecorateRight takes unit whichUnit,string whichText returns nothing
// => whichUnit - Which unit you want to change
// => whichText - Your text
// - To change text combo from a unit, use this function:
// function SetTextComboText takes unit whichUnit,string whichText returns nothing
// => whichUnit - Which unit you want to change
// => whichText - Your text
// - To register unit combo event, use this function:
// function TriggerRegisterUnitComboEvent takes unit whichUnit,integer whichCombo,trigger whichTrigger returns nothing
// => whichUnit - Which unit you want to register
// => whichCombo - Which combo you want to register
// => whichTrigger - Which trigger you want to register
// - To register unit any combo event, use this function:
// function TriggerRegisterUnitAnyComboEvent takes unit whichUnit,trigger whichTrigger returns nothing
// => whichUnit - Which unit you want to register
// => whichTrigger - Which trigger you want to register
// - To remove any event combo event, use this function:
// function RemoveTriggerComboEvent takes unit whihUnit, trigger whichTrigger returns nothing
// => whichTrigger - Which trigger you want to remove
// => whichUnit - Which unit you want to remove the triger event
//
// How to import:
// - Copy Combo system code and play with the configuration below.
// - Go to Variables panel (Ctrl + B) copy variable System_ComboUnit, System_ComboCount and all the variables of GDD
// - Be sure "Automatically create unknown variables while pasting trigger data" is
// enabled in the World Editor general preferences.
//
// Credit:
// - Weep - Damage Detection System - [url]http://www.hiveworkshop.com/forums/spells-569/gui-friendly-damage-detection-v1-2-1-a-149098/?prev=search%3DDamage%2520Detection%26d%3Dlist%26r%3D20[/url]
//----------------------------------------------------------------------
//----------------------------------------------------------------------
library ComboSystem
private module Init
static method onInit takes nothing returns nothing
call Init()
endmethod
endmodule
globals
//----------------------------------------------------------------
// SYSTEM CONFIGURABLE
//System period
private constant real PERIODIC = .0312500
//Default size of the text tag
private constant real TEXT_TAG_SIZE = 10.
//Limited size of the text tag when it increasing
private constant real TEXT_TAG_SIZE_LIMIT = 20.
//Text tag size increase per period
private constant real SIZE_INCREASE = 2.
//Text tag size decrease per period
private constant real SIZE_DECREASE = 3.
//Height default of the text tag
private constant real HEIGHT_DEFAULT = 150.
//
private constant real TEXT_CENTER = -65.
//Text tag color decrease per period
private constant integer TEXT_COLOR_DECREASE= 12
private constant string COMBO_TEXT = "Combo - "
private constant string DECORATE_TEXT_LEFT = "=>"
private constant string DECORATE_TEXT_RIGHT = "<="
//----------------------------------------------------------------
//----------------------------------------------------------------
// NON - CONFIGURABLE //
/*-*/private integer Index = 0 /*-*/
/*-*/private integer Counter = 0 /*-*/
/*-*/private integer EventCount = 0 /*-*/
/*-*/private integer DataIndex /*-*/
/*-*/private integer array StructIndex /*-*/
/*-*/private integer array ComboCount /*-*/
/*-*/private integer array Color /*-*/
/*-*/private integer array ComboCounter /*-*/
/*-*/private real array SizeValue /*-*/
/*-*/private real array ScaleValue /*-*/
/*-*/private real array ComboTime /*-*/
/*-*/private real array ComboTimeCounter /*-*/
/*-*/private real array Height /*-*/
/*-*/private real array HeightSetting /*-*/
/*-*/private trigger array EventTrigger /*-*/
/*-*/private player array ComboPlayer /*-*/
/*-*/private unit array ComboUnit /*-*/
/*-*/private unit array EventUnit /*-*/
/*-*/private boolean array SizeBlock /*-*/
/*-*/private boolean array AttackDetector /*-*/
/*-*/private texttag array TextTag /*-*/
/*-*/private string array Value /*-*/
/*-*/private string array DecorateLeft /*-*/
/*-*/private string array DecorateRight /*-*/
/*-*/private string array ComboText /*-*/
/*-*/private hashtable ComboHashtable /*-*/
/*-*/private constant timer TIMER = CreateTimer() /*-*/
/*-*/private constant location LOC = Location(0.,0.) /*-*/
//----------------------------------------------------------------
endglobals
private function eventConditions takes integer whichCombo returns nothing
set udg_System_ComboUnit = EventUnit[DataIndex]
set udg_System_ComboCount = whichCombo
if ComboCounter[DataIndex] == whichCombo or ComboCounter[DataIndex] == -1 then
call TriggerExecute(EventTrigger[DataIndex])
endif
endfunction
private function CheckEventCombo takes integer key,integer whichCombo,integer id returns nothing
set DataIndex=LoadInteger(ComboHashtable,key,id)
call eventConditions(whichCombo)
endfunction
private function DoesUnitExist takes integer id returns boolean
set DataIndex=LoadInteger(ComboHashtable,0,id)
return DataIndex != 0
endfunction
private function removeKey takes boolean isAny,integer handleId1,integer handleId2 returns nothing
local integer key
if isAny then
set key=1
else
set key=2
endif
call RemoveSavedInteger(ComboHashtable,key,handleId1)
if DataIndex!=EventCount then
call SaveInteger(ComboHashtable,key,handleId2,DataIndex)
endif
endfunction
function RemoveTriggerComboEvent takes unit whichUnit, trigger whichTrigger returns nothing
local integer id = GetHandleId(whichUnit)
if DoesUnitExist(id) then
set DataIndex=LoadInteger(ComboHashtable,1,id)
if EventTrigger[DataIndex] != whichTrigger then
set DataIndex=LoadInteger(ComboHashtable,2,id)
if EventTrigger[DataIndex]!=whichTrigger then
debug call BJDebugMsg("This trigger doesn't exist in the system.")
return
endif
endif
set EventUnit[DataIndex] = EventUnit[EventCount]
set EventUnit[EventCount] = null
set EventTrigger[DataIndex] = EventTrigger[EventCount]
set EventTrigger[EventCount] = null
set ComboCounter[DataIndex] = ComboCounter[EventCount]
call removeKey(ComboCounter[DataIndex]!=-1,id,GetHandleId(EventUnit[DataIndex]))
set EventCount = EventCount - 1
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
endfunction
private function TriggerRegisterComboEventHelper takes unit whichUnit, integer whichCombo, trigger whichTrigger, integer hashIndex returns nothing
local integer id = GetHandleId(whichUnit)
if DoesUnitExist(id) then
set EventCount = EventCount + 1
call SaveInteger(ComboHashtable,hashIndex,id,EventCount)
set EventTrigger[EventCount] = whichTrigger
set EventUnit[EventCount] = whichUnit
set ComboCounter[EventCount] = whichCombo
else
debug call BJDebugMsg("This unit doesn't exists in the system.")
endif
endfunction
function TriggerRegisterComboEvent takes unit whichUnit,integer whichCombo,trigger whichTrigger returns nothing
if whichCombo > 0 then
call TriggerRegisterComboEventHelper(whichUnit, whichCombo, whichTrigger, 1)
else
debug call BJDebugMsg("Combo = "+I2S(whichCombo)+" ?????, what kind of your combo 0.0..")
endif
endfunction
function TriggerRegisterAnyComboEvent takes unit whichUnit,trigger whichTrigger returns nothing
call TriggerRegisterComboEventHelper(whichUnit,-1,whichTrigger, 2)
endfunction
function GetUnitComboCount takes unit whichUnit returns integer
if DoesUnitExist(GetHandleId(whichUnit)) then
return ComboCount[DataIndex]
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
return 0
endfunction
function UnitAddComboEx takes unit whichUnit,real Scale,real ComboDisableTimer,real whichHeight,string decorateLeft,string decorateRight,string comboText returns nothing
local integer id = GetHandleId(whichUnit)
if not DoesUnitExist(id) then
set Index = Index + 1
call SaveInteger(ComboHashtable,0,id,Index)
set ComboUnit[Index] = whichUnit
set ComboCount[Index] = 0
set ScaleValue[Index] = Scale
set ComboTime[Index] = ComboDisableTimer
set StructIndex[Index] = Index
set DecorateLeft[Index] = decorateLeft
set DecorateRight[Index] = decorateRight
set ComboText[Index] = comboText
set HeightSetting[Index] = whichHeight
set ComboPlayer[Index] = GetOwningPlayer(ComboUnit[Index])
set TextTag[Index] = CreateTextTag()
call MoveLocation(LOC,GetUnitX(ComboUnit[Index]),GetUnitY(ComboUnit[Index]))
call SetTextTagPosUnit(TextTag[Index],ComboUnit[Index],GetUnitFlyHeight(ComboUnit[Index])+GetLocationZ(LOC))
call SetTextTagText(TextTag[Index],null,TEXT_TAG_SIZE)
call SetTextTagColor(TextTag[Index],255,255,255,255)
call SetTextTagSuspended(TextTag[Index],true)
call SetTextTagPermanent(TextTag[Index],false)
else
debug call BJDebugMsg("This unit already exist in the system.")
endif
endfunction
function UnitComboAdd takes unit whichUnit, real Scale, real ComboDisableTimer returns nothing
call UnitAddComboEx(whichUnit, Scale, ComboDisableTimer, HEIGHT_DEFAULT, /*
*/ DECORATE_TEXT_LEFT, DECORATE_TEXT_RIGHT, COMBO_TEXT)
endfunction
function UnitComboRemove takes unit whichUnit returns nothing
local integer id = GetHandleId(whichUnit)
if DoesUnitExist(id) then
set ComboUnit[DataIndex] = ComboUnit[Index]
set ComboCount[DataIndex] = ComboCount[Index]
set ScaleValue[DataIndex] = ScaleValue[Index]
set ComboTime[DataIndex] = ComboTime[Index]
set DecorateLeft[DataIndex] = DecorateLeft[Index]
set DecorateRight[DataIndex] = DecorateRight[Index]
set ComboText[DataIndex] = ComboText[Index]
set HeightSetting[DataIndex] = HeightSetting[Index]
set ScaleValue[DataIndex] = ScaleValue[Index]
set ComboPlayer[DataIndex] = ComboPlayer[Index]
call DestroyTextTag(TextTag[DataIndex])
set TextTag[DataIndex] = TextTag[Index]
set StructIndex[DataIndex] = StructIndex[Index]
set StructIndex[Index] = 0
set TextTag[Index] = null
set ComboUnit[Index] = null
call RemoveSavedInteger(ComboHashtable,0,id)
if DataIndex!=Index then
call SaveInteger(ComboHashtable,0,GetHandleId(ComboUnit[DataIndex]),DataIndex)
endif
set Index = Index - 1
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
endfunction
function SetTextComboHeight takes unit whichUnit,real whichHeight returns nothing
if DoesUnitExist(GetHandleId(whichUnit)) then
set HeightSetting[DataIndex] = whichHeight
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
endfunction
function SetTextComboText takes unit whichUnit,string whichText returns nothing
if DoesUnitExist(GetHandleId(whichUnit)) then
set ComboText[DataIndex] = whichText
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
endfunction
function SetTextComboDecorateLeft takes unit whichUnit,string whichText returns nothing
if DoesUnitExist(GetHandleId(whichUnit)) then
set DecorateLeft[DataIndex] = whichText
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
endfunction
function SetTextComboDecorateRight takes unit whichUnit,string whichText returns nothing
if DoesUnitExist(GetHandleId(whichUnit)) then
set DecorateRight[DataIndex] = whichText
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
endfunction
function SetTextComboScale takes unit whichUnit,real whichScale returns nothing
if DoesUnitExist(GetHandleId(whichUnit)) then
set ScaleValue[DataIndex] = whichScale
else
debug call BJDebugMsg("This unit doesn't exist in the system.")
endif
endfunction
private struct ComboSystem extends array
static method textTag takes string whichString,integer Indexx,real Scale returns nothing
local thistype this = Indexx
call SetTextTagText(TextTag[this],whichString,TEXT_TAG_SIZE)
call SetTextTagVisibility(TextTag[this], GetLocalPlayer() == ComboPlayer[this])
set ComboTimeCounter[this] = ComboTime[this]
set SizeValue[this] = TEXT_TAG_SIZE
set SizeBlock[this] = false
set Value[this] = whichString
set Color[this] = 255
set Height[this] = HeightSetting[this]*ScaleValue[this]
call SetTextTagColor(TextTag[this],255,255,255,255)
set Counter = Counter + 1
if Counter == 1 then
call TimerStart(TIMER,PERIODIC,true,function thistype.onPeriodic)
endif
endmethod
static method damageDetection takes nothing returns boolean
if IsUnitEnemy(udg_GDD_DamageSource,GetOwningPlayer(udg_GDD_DamagedUnit)) then
if DoesUnitExist(GetHandleId(udg_GDD_DamageSource)) then
if AttackDetector[DataIndex] then
set ComboCount[DataIndex] = ComboCount[DataIndex] + 1
call textTag(DecorateLeft[DataIndex]+ComboText[DataIndex]+I2S(ComboCount[DataIndex])+DecorateRight[DataIndex],DataIndex,ScaleValue[DataIndex])
call CheckEventCombo(1,ComboCount[DataIndex],GetHandleId(ComboUnit[DataIndex]))
call CheckEventCombo(2,ComboCount[DataIndex],GetHandleId(ComboUnit[DataIndex]))
endif
endif
endif
return false
endmethod
private static real cos= TEXT_CENTER * Cos(.0174533)
private static real sin= TEXT_CENTER * Sin(.0174533)
static method onPeriodic takes nothing returns nothing
local integer i = 1
local thistype this
local real x
local real y
loop
exitwhen i > Index
set this = StructIndex[i]
if GetUnitTypeId(ComboUnit[this]) != 0 then
if not SizeBlock[this] then
set SizeValue[this] = SizeValue[this] + SIZE_INCREASE
set SizeBlock[this] = SizeValue[this] >= TEXT_TAG_SIZE_LIMIT
else
if SizeValue[this] > TEXT_TAG_SIZE then
set SizeValue[this] = SizeValue[this] - SIZE_DECREASE
endif
endif
set x = GetUnitX(ComboUnit[this])+cos
set y = GetUnitY(ComboUnit[this])+sin
call MoveLocation(LOC,x,y)
call SetTextTagColor(TextTag[this],255,255,255,Color[this])
call SetTextTagText(TextTag[this],Value[this],SizeValue[this]*0.0023)
call SetTextTagPos(TextTag[this],x,y,GetUnitFlyHeight(ComboUnit[this])+GetLocationZ(LOC)+Height[this])
if ComboTimeCounter[this] > 0. and not IsUnitType(ComboUnit[this],UNIT_TYPE_DEAD) then
set ComboTimeCounter[this] = ComboTimeCounter[this] - PERIODIC
else
if Color[this] > 0 then
set Color[this] = Color[this] - TEXT_COLOR_DECREASE
set SizeValue[this] = SizeValue[this] + SIZE_INCREASE
else
set ComboCount[this] = 0
call SetTextTagVisibility(TextTag[this],false)
set Counter = Counter - 1
if Counter == 0 then
call PauseTimer(TIMER)
endif
endif
endif
else
call UnitComboRemove(ComboUnit[this])
set Counter = Counter - 1
if Counter == 0 then
call PauseTimer(TIMER)
endif
endif
set i = i + 1
endloop
endmethod
static method attackDetection takes nothing returns boolean
if DoesUnitExist(GetHandleId(GetAttacker())) then
set AttackDetector[DataIndex] = true
endif
return false
endmethod
static method spellDetection takes nothing returns boolean
if DoesUnitExist(GetHandleId(GetTriggerUnit())) then
set AttackDetector[DataIndex] = false
endif
return false
endmethod
static method Init takes nothing returns nothing
local trigger damageTrigger = CreateTrigger()
local trigger attackTrigger = CreateTrigger()
local trigger spellTrigger = CreateTrigger()
local integer i = 0
set ComboHashtable=InitHashtable()
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(attackTrigger,Player(i),EVENT_PLAYER_UNIT_ATTACKED,null)
call TriggerRegisterPlayerUnitEvent(spellTrigger,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,null)
set i = i + 1
endloop
call TriggerRegisterVariableEvent(damageTrigger, "udg_GDD_Event", EQUAL, 0 )
call TriggerAddCondition(damageTrigger,function thistype.damageDetection)
call TriggerAddCondition(attackTrigger,function thistype.attackDetection)
call TriggerAddCondition(spellTrigger,function thistype.spellDetection)
set damageTrigger = null
set attackTrigger = null
set spellTrigger = null
endmethod
implement Init
endstruct
endlibrary