GFreak45
I didnt slap you, i high 5'd your face.
- Reaction score
- 130
Ok... so this is so you guys can tell me what you think about this system...
I made it so that a friend can check the regen on his heroes, so i made it so that it would be somewhat GUI friendly, but it should work fine for anyone's needs
please tell me what you would do different, and how i should improve it.
I made it so that a friend can check the regen on his heroes, so i made it so that it would be somewhat GUI friendly, but it should work fine for anyone's needs
please tell me what you would do different, and how i should improve it.
JASS:
/*GHD - v1.1 - by GFreak45
Gui-Friendly Healing/Regen Detection
Requires: Any unit indexer that assigns custom values to units.
Recommended:
Aids: <a href="http://www.thehelper.net/forums/showthread.php/130752-Advanced-Indexing-Data-Storage?highlight=advanced+indexing+data+storage" class="link link--internal">http://www.thehelper.net/forums/sho...rage?highlight=advanced+indexing+data+storage</a>
Implementation:
Create a new trigger in the editor, rename it GHD, and convert it to custom text. Then delete what is inside and paste this there. Then you will need to register the unit's you wish to record, but it is recommended that you only record heroes and limited non-heroes, as this system can become very slow and cost inefficient if you register every unit. You will also need to create the following global variables:
* GHDUnit (unit)
* GHDLifeEvent (real)
* GHDManaEvent (real)
* GHDLifeAmmount (real)
* GHDManaAmmount (real)
* GHDLifePos (boolean)
* GHDManaPos (boolean)
Before anyone rages, yes the idea of this came from Weep's GDD. This system checks units at an interval, and under the right circumstances will register their health and or mana, compare it with their health/mana at the previous interval, and come to a conclusion determining the unit's regen, and whether or not the unit has taken any kind of healing or damaging effects in the most recent refresh interval. This CAN detect life change type-damage (setting a unit's health lower than it is via triggers or by using a negative value in a healing ability).
function calls/GUI Uses and variables/constants:
functions:
call GHDRegisterUnit(what unit) - registered the indicated unit for use with the system recording all units results in a drastic speed/efficiency/accuracy (with regen) drop
call GHDRemoveUnit(what unit) - un-registers a unit to be checked at every interval, this should be used only when a (non-hero) unit decays or is removed completely from the game or when the player would like to stop recording a specific unit
call GHDRefreshUnit(what unit) - completely erases the saved information on a unit's regen and allows it to be overwritten, this is important because if a unit gains items/abilities/levels all at once and now their base regen is large enough it will not register any healing/damage
function GetUnitRegenLife takes unit whichunit returns real - returns the life regen for the unit, it must have already been registered for a bit and not recently been refreshed in order to return a proper regen, otherwise, it will return null
function GetUnitRegenMana takes unit whichunit returns real - returns the mana regen for the unit, it must have already been registered for a bit and not recently been refreshed in order to return a proper regen, otherwise, it will return null
GUI Use:
GUI users must register the units that they wish to record still, but this can be done by setting the unit to a variable and using: Custom Script: call GHDRegisterUnit(udg_VariableName) This is simply something i cant change at the moment, but i will update the system with the option to use Auto-Registration for heroes. The following variables will need to be created in order to use the system properly for GUI users. Also, if you would like to use a unit's saved regen, just use: Custom Script: set udg_RealVariable = GetUnitRegenLife(udg_UnitVariable) or Custom Script: set udg_RealVariable = GetUnitRegenMana(udg_UnitVariable)
GUI Variables:
GHDUnit (unit variable) - this is the unit that had some kind of change, only use this in instant triggers or save it to another variable to use it in waits, it is not MUI
GHDLifeEvent (real variable) - this is used as the event for a unit gains life, using the game event: Game - GHDLifeEvent becomes equal to 0.00, you can easily detect when a unit recieves some kind of healing
GHDLifeAmmount (real variable) - this is the ammount of healing the unit took. This is Not MUI and will be changed shortly after use if another unit takes healing, make sure to use this in instant triggers or save it in a variable
GHDLifePos (boolean variable) - if this is true, the change in health was a positive change; ie: (healing), if it is false, the change was a negative change; ie: Unit - Set life of Unit equal to life of Unit - 100, or using a healing ability with a negative healed value
GHDManaEvent (real variable) - this is used as the event for a unit has a change in mana, like the life event use: Event: Game - GHDManaEvent becomes equal to 0.00
GHDManaAmmount (real variable) - also like the health variable, but used for a change in mana
GHDManaPos (boolean variable) - also like the boolean for life, if this is true the unit gained some kind of mana, maybe through a potion, if it is false, the unit lost mana (casts or mana burn)
Constants:
MaxInstanceAmmount - This is the maximum ammount of saved instances of un-interupted healing that is saved for each unit with this system. This indirectly correlates with the ammount of units that the system can have registered. The higher the instance ammount, the lower the unit ammount but the more accurate the system is.
RefreshTime - This is the interval at which the system refreshes and checks each unit to see if they recieved any type of healing, and the interval at which it registers regeneration
GapMax - this is the max deviation between the health that the unit had for the last refresh interval + its regen over the interval and its current health; ie: 50.0 means that health changes larger than 50% of the current saved regen will not be registered as regen and instead healing
Special thanks to:
Grags - idea for the system
Weep - although we havent talked... ever, i loved your GDD system
thehelper.net - for teaching me all i know about GUI and Jass
Additional Notes/Change Log:
If anyone has any questions as far as how to implement this you can pm me on thehelper.net
*/
library GHD initializer GHDTrigger requires optional AIDS, optional UnitIndexer//or any other unit indexer that
//assigns a custom value to units that enter the map, they MUST assign a value to the unit
//and you should add the requirement here between requires and optional
globals
private constant integer MaxInstanceAmmount = 81//this is the ammount of saved instances of
//eligible life/mana regen, the ammount of units save-able is equal 8190/this. Default is 100
//units, 8 = 1000 units, 819 = 10
private constant real RefreshTime = 1.0//the interval in seconds it takes while
//one of the registered units is under their max health and does not take
//damage, pick up an item, gain a level, cast an ability, or be the target
//of an ability cast in order to register that as regen
private constant real GapMax = 50.0//the % deviation from the units current regen that is
//alloud to be registered, if the unit is past this it took some sort of healing.
private group GHDGroup//do not change this.
endglobals
struct GHDStats extends array
real GHDLastLife
real GHDRegenLife
integer GHDRegisterCountLife = 0
boolean GHDChangeLife = true
boolean GHDClearLife = false
trigger GHDTrigLife
real GHDTimeLife
real GHDRegisteredLife
real array GHDListLife[MaxInstanceAmmount+1]
integer GHDListOrderLife
real GHDLastMana
real GHDRegenMana
integer GHDRegisterCountMana = 0
boolean GHDChangeMana = true
boolean GHDClearMana = false
trigger GHDTrigMana
real GHDTimeMana
real GHDRegisteredMana
real array GHDListMana[MaxInstanceAmmount + 1]
integer GHDListOrderMana
static method register takes unit u returns thistype
local thistype this = GetUnitUserData(u)
return this
endmethod
static method remove takes unit u returns nothing
local integer i = GetUnitUserData(u)
local integer l = 1
set GHDStats<i>.GHDLastLife = null
set GHDStats<i>.GHDRegenLife = null
set GHDStats<i>.GHDRegisterCountLife = 1
set GHDStats<i>.GHDChangeLife = true
set GHDStats<i>.GHDClearLife = false
set GHDStats<i>.GHDTimeLife = 0.0
call DestroyTrigger(GHDStats<i>.GHDTrigLife)
loop
exitwhen l == MaxInstanceAmmount + 1
set GHDStats<i>.GHDListLife[l] = null
set l = l + 1
endloop
set l = 1
set GHDStats<i>.GHDLastMana = null
set GHDStats<i>.GHDRegenMana = null
set GHDStats<i>.GHDRegisterCountMana = 1
set GHDStats<i>.GHDChangeMana = true
set GHDStats<i>.GHDClearMana = false
set GHDStats<i>.GHDTimeMana = 0.0
call DestroyTrigger(i.GHDTrigMana)
loop
exitwhen l == MaxInstanceAmmount + 1
set GHDStats<i>.GHDListMana[l] = null
set l = l + 1
endloop
endmethod
endstruct
function GHDDamageActions takes nothing returns nothing
local integer i = GetUnitUserData(GetTriggerUnit())
set i.GHDLastLife = i.GHDLastLife - GetEventDamage()
set i.GHDChangeMana = false
endfunction
//======================================================================================================
//Here we have the register unit function, this can be used via: call GHDRegisterUnit(unit)
//The system only checks the units that have been registered. All this function does is add the unit to
//GHDGroup (the group that contains all registered units), creates any triggers used to determine
//eligibility, and preps the unit to be checked for health/mana changes
function GHDRegisterUnit takes unit u returns nothing
local integer l = 0
local GHDStats i = null
local group g = GHDGroup
local code c = function GHDLifeActions
loop
exitwhen (FirstOfGroup(g) == null)
set l = l + 1
call GroupRemoveUnit(g, FirstOfGroup(g))
endloop
if (i < R2I(8190 / I2R(MaxInstanceAmmount))) then
call GroupAddUnit(GHDGroup, u)
set i = GHDStats.register
set i.GHDTrigLife = CreateTrigger()
set i.GHDTrigMana = CreateTrigger()
call GHDLifeEvents(i)
call GHDManaEvents(i)
call TriggerAddCondition(i.GHDTrigLife, Filter(c))
set c = function GHDManaActions
call TriggerAddAction(i.GHDTrigMana, Filter(c))
else
call BJDebugMsg("ERROR: You have too many units registered for mana/health regen and alteration detection.")
endif
set c = null
call DestroyGroup(g)
endfunction
//======================================================================================================
//you can use this function to refresh the unit's regen, this will erase the current saved data, but
//allow the unit to begin re-freshing it's regen anew, without previous data corrupting the accuracy or
//stopping new values from being registered.
function GHDRefreshUnit takes unit u returns nothing
local integer i = GetUnitUserData(u)
local integer a = 1
loop
exitwhen a > MaxInstanceAmmount
set GHDStats<i>.GHDListLife[a] = 0
set GHDStats<i>.GHDListMana[a] = 0
set a = a + 1
endloop
set GHDStats<i>.GHDListOrderLife = 1
set GHDStats<i>.GHDListOrderMana = 1
set GHDStats<i>.GHDRegenLife = null
set GHDStats<i>.GHDRegenMana = null
set GHDStats<i>.GHDTimeLife = 0.0
set GHDStats<i>.GHDTimeMana = 0.0
set GHDStats<i>.GHDRegisteredLife = 0.0
set GHDStats<i>.GHDRegisteredMana = 0.0
endfunction
//======================================================================================================
//you can use these functions to get unit's regen, if you try to get a unit that has recently been
//registered and has not gotten the chance to regenerate yet, or has not been registered at all, then
//this will return: null
function GetUnitRegenLife takes unit whichunit returns real
if (IsUnitInGroup(whichunit, GHDGroup)) then
if (GetUnitUserData(whichunit).GHDRegenLife != 0.0) then
return GetUnitUserData(whichunit).GHDRegenLife
else
return null
endif
endif
return null
endfunction
function GetUnitRegenMana takes unit whichunit returns real
if (IsUnitInGroup(whichunit, GHDGroup)) then
if (GetUnitUserData(whichunit).GHDRegenMana != 0.0) then
return GetUnitUserData(whichunit).GHDRegenMana
else
return null
endif
endif
return null
endfunction
//======================================================================================================
//here we can unregister or remove units from the system, this is so that you can register other units
//so you dont hit the max ammount of registered units, and so that you can remove decaying/removed units
//from the system
function GHDRemoveUnit takes unit u returns nothing
local integer i = GetUnitUserData(u)
call GHDStats.remove
call GroupRemoveUnit(GHDGroup, u)
endfunction
//======================================================================================================
//here are the actions for the core trigger to the system, this is what occurs at every refresh interval
//it checks each unit that has been registered for mana/healing checking and compares whether the unit
//is eligible for it's mana/health to be registered, if not it sets the unit to be eligible and
//continues on to the other units, this way the next interval will be eligible if the unit has not done
//anything that would make them not eligible
private function GHDActions takes nothing returns nothing
local group g = GHDGroup
local unit u = null
local real r = 0.0
loop
exitwhen (FirstOfGroup(g) = null)
set u = FirstOfGroup(g)
set r = ((GetUnitState(u, UNIT_STATE_LIFE) - GHDStats[GetUnitUserData(u)].GHDLastLife)/RefreshTime)
if (GHDStats[GetUnitUserData(u)].GHDChangeLife = true) then
if (GHDStats[GetUnitUserData(u)].GHDRegenLife != null) then
if (r <= (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime * (1.0 + (GapMax/100.0)))
if (r >= (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime * (1.0 - (GapMax/100.0)))
set GHDStats[GetUnitUserData(u)].GHDRegisteredLife = GHDStats[GetUnitUserData(u)].GHDRegisteredLife + r
if (GHDStats[GetUnitUserData(u)].GHDRegisterCountLife < MaxInstanceAmmount) then
set GHDStats[GetUnitUserData(u)].GHDTimeLife = GHDStats[GetUnitUserData(u)].GHDTimeLife + RefreshTime
set GHDStats[GetUnitUserData(u)].GHDRegisterCountLife = GHDStats[GetUnitUserData(u)].GHDRegisterCountLife + 1
set GHDStats[GetUnitUserData(u)].GHDRegenLife = (GHDStats[GetUnitUserData(u)].GHDRegisteredLife / GHDStats[GetUnitUserData(u)].GHDTimeLife)
set GHDStats[GetUnitUserData(u)].GHDListLife[GHDStats[GetUnitUserData(u)].GHDRegisterCountLife] = r
else
if (GHDStats[GetUnitUserData(u)].GHDListOrderLife < MaxInstanceAmmount)
set GHDStats[GetUnitUserData(u)].GHDListOrderLife = GHDStats[GetUnitUserData(u)].GHDListOrderLife + 1
else
set GHDStats[GetUnitUserData(u)].GHDListOrderLife = 1
endif
set GHDStats[GetUnitUserData(u)].GHDRegenLife = (GHDStats[GetUnitUserData(u)].GHDRegisteredLife / GHDStats[GetUnitUserData(u)].GHDTimeLife)
set GHDStats[GetUnitUserData(u)].GHDRegisteredLife = GHDStats[GetUnitUserData(u)].GHDRegisteredLife - GHDStats[GetUnitUserData(u)].GHDListLife[GHDStats[GetUnitUserData(u)].GHDListOrderLife]
set GHDStats[GetUnitUserData(u)].GHDListLife[GHDStats[GetUnitUserData(u)].GHDListOrderLife] = r
endif
else
set udg_GHDUnit = u
set udg_GHDLifeAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime)
set udg_GHDLifePos = false
set udg_GHDLifeEvent = 0.0
set udg_GHDLifeEvent = 1.0
endif
else
set udg_GHDUnit = u
set udg_GHDLifeAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime)
set udg_GHDLifePos = true
set udg_GHDLifeEvent = 0.0
set udg_GHDLifeEvent = 1.0
endif
else
set GHDStats[GetUnitUserData(u)].GHDRegisteredLife = GHDStats[GetUnitUserData(u)].GHDRegisteredLife + r
set GHDStats[GetUnitUserData(u)].GHDRegisterCountLife = 1
set GHDStats[GetUnitUserData(u)].GHDTimeLife = GHDStats[GetUnitUserData(u)].GHDTimeLife + RefreshTime
set GHDStats[GetUnitUserData(u)].GHDRegenLife = (GHDStats[GetUnitUserData(u)].GHDRegisteredLife / GHDStats[GetUnitUserData(u)].GHDTimeLife)
set GHDStats[GetUnitUserData(u)].GHDListLife[GHDStats[GetUnitUserData(u)].GHDRegisterCountLife] = r
endif
else
if (GHDStats[GetUnitUserData(u)].GHDRegenLife != null) then
if (r >= (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime * (1.0 + (GapMax/100.0)))
set udg_GHDUnit = u
set udg_GHDLifeAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime)
set udg_GHDLifePos = true
set udg_GHDLifeEvent = 0.0
set udg_GHDLifeEvent = 1.0
elseif (r <= (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime * (1.0 - (GapMax/100.0)))
set udg_GHDUnit = u
set udg_GHDLifeAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime)
set udg_GHDLifePos = false
set udg_GHDLifeEvent = 0.0
set udg_GHDLifeEvent = 1.0
endif
endif
set GHDStats[GetUnitUserData(u)].GHDChangeLife = true)
endif
//here is where the life check ends and the mana check starts
set r = ((GetUnitState(u, UNIT_STATE_MANA) - GHDStats[GetUnitUserData(u)].GHDLastMana)/RefreshTime)
if (GHDStats[GetUnitUserData(u)].GHDChangeMana = true) then
if (GHDStats[GetUnitUserData(u)].GHDRegenMana != null) then
if (r <= (GHDStats[GetUnitUserData(u)].GHDRegenMana * RefreshTime * (1.0 + (GapMax/100.0)))
if (r >= (GHDStats[GetUnitUserData(u)].GHDRegenMana * RefreshTime * (1.0 - (GapMax/100.0)))
set GHDStats[GetUnitUserData(u)].GHDRegisteredMana = GHDStats[GetUnitUserData(u)].GHDRegisteredMana + r
if (GHDStats[GetUnitUserData(u)].GHDRegisterCountMana < MaxInstanceAmmount) then
set GHDStats[GetUnitUserData(u)].GHDTimeMana = GHDStats[GetUnitUserData(u)].GHDTimeMana + RefreshTime
set GHDStats[GetUnitUserData(u)].GHDRegisterCountMana = GHDStats[GetUnitUserData(u)].GHDRegisterCountMana + 1
set GHDStats[GetUnitUserData(u)].GHDRegenMana = (GHDStats[GetUnitUserData(u)].GHDRegisteredMana / GHDStats[GetUnitUserData(u)].GHDTimeMana)
set GHDStats[GetUnitUserData(u)].GHDListMana[GHDStats[GetUnitUserData(u)].GHDRegisterCountMana] = r
else
if (GHDStats[GetUnitUserData(u)].GHDListOrderMana < MaxInstanceAmmount)
set GHDStats[GetUnitUserData(u)].GHDListOrderMana = GHDStats[GetUnitUserData(u)].GHDListOrderMana + 1
else
set GHDStats[GetUnitUserData(u)].GHDListOrderMana = 1
endif
set GHDStats[GetUnitUserData(u)].GHDRegenMana = (GHDStats[GetUnitUserData(u)].GHDRegisteredMana / GHDStats[GetUnitUserData(u)].GHDTimeMana)
set GHDStats[GetUnitUserData(u)].GHDRegisteredMana = GHDStats[GetUnitUserData(u)].GHDRegisteredMana - GHDStats[GetUnitUserData(u)].GHDListMana[GHDStats[GetUnitUserData(u)].GHDListOrderMana]
set GHDStats[GetUnitUserData(u)].GHDListMana[GHDStats[GetUnitUserData(u)].GHDListOrderMana] = r
endif
else
set udg_GHDUnit = u
set udg_GHDManaAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime)
set udg_GHDManaPos = true
set udg_GHDManaEvent = 0.0
set udg_GHDManaEvent = 1.0
endif
set udg_GHDUnit = u
set udg_GHDManaAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenLife * RefreshTime)
set udg_GHDManaPos = true
set udg_GHDManaEvent = 0.0
set udg_GHDManaEvent = 1.0
endif
else
set GHDStats[GetUnitUserData(u)].GHDRegisteredMana = GHDStats[GetUnitUserData(u)].GHDRegisteredMana + r
set GHDStats[GetUnitUserData(u)].GHDRegisterCountMana = 1
set GHDStats[GetUnitUserData(u)].GHDTimeMana = GHDStats[GetUnitUserData(u)].GHDTimeMana + RefreshTime
set GHDStats[GetUnitUserData(u)].GHDRegenMana = (GHDStats[GetUnitUserData(u)].GHDRegisteredMana / GHDStats[GetUnitUserData(u)].GHDTimeMana)
set GHDStats[GetUnitUserData(u)].GHDListMana[GHDStats[GetUnitUserData(u)].GHDRegisterCountMana] = r
endif
else
if (GHDStats[GetUnitUserData(u)].GHDRegenMana != null) then
if (r >= (GHDStats[GetUnitUserData(u)].GHDRegenMana * RefreshTime * (1.0 + (GapMax/100.0)))
set udg_GHDUnit = u
set udg_GHDManaAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenMana * RefreshTime)
set udg_GHDManaPos = true
set udg_GHDManaEvent = 0.0
set udg_GHDManaEvent = 1.0
elseif (r <= (GHDStats[GetUnitUserData(u)].GHDRegenMana * RefreshTime * (1.0 - (GapMax/100.0)))
set udg_GHDUnit = u
set udg_GHDManaAmmount = r - (GHDStats[GetUnitUserData(u)].GHDRegenMana * RefreshTime)
set udg_GHDManaPos = false
set udg_GHDManaEvent = 0.0
set udg_GHDManaEvent = 1.0
endif
endif
set GHDStats[GetUnitUserData(u)].GHDChangeMana = true
endif
set GetUnitUserData.GHDLastLife = GetUnitState(u, UNIT_STATE_LIFE)
set GetUnitUserData.GHDLastMana = GetUnitState(u, UNIT_STATE_MANA)
call GroupRemoveUnit(g, u)
endloop
set u = null
call DestroyGroup(g)
endfunction
//======================================================================================================
//Mana Cancellation occurs when a unit casts an ability or is the target of an ability, this is so that
//whenever a unit uses mana or has a chance to be a target of a mana burn type ability, they do not
//register mana on the upcoming refresh
private function GHDManaCancellation takes nothing returns nothing
if (IsUnitInGroup(GetTriggerUnit(), GHDGroup)) then
set GetUnitUserData(GetTriggerUnit()).GHDChangeMana = false
endif
if (IsUnitInGroup(GetSpellTargetUnit(), GHDGroup)) then
set GetUnitUserData(GetSpellTargetUnit().GHDChangeMana = false
endif
endfunction
//======================================================================================================
//In this we create the core triggers and create actions using conditions saved as code... relatively
//simple
private function GHDTrigger takes nothing returns nothing
local trigger t = CreateTrigger()
local code c = function GHDActions
call TriggerRegisterTimerEvent(t, RefreshTime, true)
call TriggerAddCondition(t, Filter(c))
set c = function GHDManaCancellation
set t = CreateTrigger()
call TriggerRegisterUnitEvent(t, null, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Filter(c))
set c = null
set t = null
endfunction
endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>