• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

Bloodstone (DotA) GUI v1.4

Description:
I made this spell on request of yrogerg.
This is based on the item Bloodstone from DotA.

Item Description:
- Kills the owner on activation.
- Gains a charge each time an enemy hero dies within 1675 range. Each charge grants 1 mana regeneration per second. If the bearer dies, 500 + 30 health per charge is restored to all allies within a 1675 radius, while the Bloodstone loses a third of its charges. A bloodmark is then placed where the bearer died, granting vision over a 1800 radius and allowing the bearer to gain nearby experience while dead.

How to install:
Copy or create a bloodstone item.
Copy or create all custom abilities from the test map.
Copy or create all global variables used in the test map.
Copy all triggers from the Bloodstone category into your map.
Copy all triggers from the Game Time System (GTS) into your map.
Copy the functions from the header file into your map.
Set the bloodstone variable to the item boodstone.

Triggers:
  • Bloodstone Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Bloodstone = Bloodstone
      • Set Bloodstone_Dummy_Hero = Dummy Hero
      • Set Bloodstone_Param_Heal_Base = 500.00
      • Set Bloodstone_Param_Heal_Increase = 30.00
      • Set Bloodstone_Param_Heal_Radius = 1675.00
      • Set Bloodstone_Param_Stack_Radius = 1675.00
      • Set Bloodstone_Param_Stack_Lose = 0.67
      • Set Bloodstone_Param_Visual_Radius = 1800.00
      • Set Bloodstone_Param_Mana_Gain = 1.00
  • Bloodstone Death Effect
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • -------- ------------------------------------ --------
      • -------- Local Variables --------
      • -------- ------------------------------------ --------
      • Custom script: local unit udg_TempUnit
      • Custom script: local unit udg_TempUnit2
      • Custom script: local fogmodifier udg_TempVisibilityModifier
      • Custom script: local effect udg_TempSpecialEffect
      • Custom script: local integer udg_TempInteger2
      • -------- ------------------------------------ --------
      • -------- A hero dies in range of an enemy hero with bloodstone --------
      • -------- ------------------------------------ --------
      • Set TempUnit = (Triggering unit)
      • Set TempPlayer = (Owner of TempUnit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (TempUnit is A Hero) Equal to True
        • Then - Actions
          • Set TempLocation = (Position of TempUnit)
          • Set TempUnitGroup = (Units within Bloodstone_Param_Stack_Radius of TempLocation)
          • Custom script: call RemoveLocation(udg_TempLocation)
          • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
            • Loop - Actions
              • Set TempUnit2 = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (TempUnit2 is alive) Equal to True
                  • (TempUnit2 belongs to an enemy of TempPlayer) Equal to True
                  • (TempUnit2 has an item of type Bloodstone) Equal to True
                • Then - Actions
                  • For each (Integer TempInteger) from 1 to 6, do (Actions)
                    • Loop - Actions
                      • Set TempItem = (Item carried by TempUnit2 in slot TempInteger)
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Item-type of TempItem) Equal to Bloodstone
                        • Then - Actions
                          • Item - Set charges remaining in TempItem to ((Charges remaining in TempItem) + 1)
                        • Else - Actions
                • Else - Actions
          • Custom script: call DestroyGroup(udg_TempUnitGroup)
          • Custom script: set udg_TempUnit2 = null
        • Else - Actions
      • -------- ------------------------------------ --------
      • -------- Condition for bloodstone effect --------
      • -------- ------------------------------------ --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (TempUnit has an item of type Bloodstone) Equal to False
        • Then - Actions
          • Custom script: set udg_TempUnit = null
          • Skip remaining actions
        • Else - Actions
      • -------- ------------------------------------ --------
      • -------- Heal Allies --------
      • -------- ------------------------------------ --------
      • Set TempItem = (Item carried by TempUnit of type Bloodstone)
      • Set TempInteger = (Charges remaining in TempItem)
      • Set TempReal = (Bloodstone_Param_Heal_Base + (Bloodstone_Param_Heal_Increase x (Real(TempInteger))))
      • Set TempLocation = (Position of TempUnit)
      • Special Effect - Create a special effect at TempLocation using Abilities\Spells\NightElf\Tranquility\Tranquility.mdl
      • Set TempSpecialEffect = (Last created special effect)
      • Set TempUnitGroup = (Units within Bloodstone_Param_Heal_Radius of TempLocation)
      • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit2 = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit2 is alive) Equal to True
              • (TempUnit2 is A structure) Equal to False
              • (TempUnit2 belongs to an ally of TempPlayer) Equal to True
            • Then - Actions
              • Unit - Set life of TempUnit2 to ((Life of TempUnit2) + TempReal)
            • Else - Actions
      • Custom script: call DestroyGroup(udg_TempUnitGroup)
      • -------- ------------------------------------ --------
      • -------- Remove Charges --------
      • -------- ------------------------------------ --------
      • For each (Integer TempInteger) from 1 to 6, do (Actions)
        • Loop - Actions
          • Set TempItem = (Item carried by TempUnit in slot TempInteger)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Item-type of TempItem) Equal to Bloodstone
            • Then - Actions
              • Set TempReal = ((Real((Charges remaining in TempItem))) x Bloodstone_Param_Stack_Lose)
              • Item - Set charges remaining in TempItem to (Integer(TempReal))
            • Else - Actions
      • -------- ------------------------------------ --------
      • -------- Add Vision --------
      • -------- ------------------------------------ --------
      • Set TempLocation = (Position of TempUnit)
      • Visibility - Create an initially Enabled visibility modifier for TempPlayer emitting Visibility from TempLocation to a radius of Bloodstone_Param_Visual_Radius
      • Set TempVisibilityModifier = (Last created visibility modifier)
      • -------- ------------------------------------ --------
      • -------- Keep Track Of Experience --------
      • -------- ------------------------------------ --------
      • Unit - Create 1 Bloodstone_Dummy_Hero for TempPlayer at TempLocation facing (Facing of TempUnit) degrees
      • Set TempUnit2 = (Last created unit)
      • Hero - Set TempUnit2 experience to (Hero experience of TempUnit), Hide level-up graphics
      • Unit - Make TempUnit2 Invulnerable
      • Custom script: call RemoveLocation(udg_TempLocation)
      • -------- ------------------------------------ --------
      • -------- Remove Heal Special Effect --------
      • -------- ------------------------------------ --------
      • Wait 3.67 game-time seconds
      • Special Effect - Destroy TempSpecialEffect
      • -------- ------------------------------------ --------
      • -------- Wait until hero revives --------
      • -------- ------------------------------------ --------
      • Custom script: loop
      • Custom script: exitwhen GetWidgetLife(udg_TempUnit) > 0
      • Custom script: call TriggerSleepAction(1)
      • Custom script: endloop
      • -------- ------------------------------------ --------
      • -------- Remove Vision --------
      • -------- ------------------------------------ --------
      • Visibility - Disable TempVisibilityModifier
      • Visibility - Destroy TempVisibilityModifier
      • -------- ------------------------------------ --------
      • -------- Add Experience --------
      • -------- ------------------------------------ --------
      • Set TempInteger = (Hero experience of TempUnit2)
      • Hero - Add TempInteger experience to TempUnit, Show level-up graphics
      • Unit - Remove TempUnit2 from the game
      • Custom script: set udg_TempUnit = null
      • Custom script: set udg_TempUnit2 = null
      • Custom script: set udg_TempVisibilityModifier = null
      • Custom script: set udg_TempSpecialEffect = null
  • Bloodstone Activation
    • Events
      • Unit - A unit Uses an item
    • Conditions
      • (Item-type of (Item being manipulated)) Equal to Bloodstone
    • Actions
      • Set TempItem = (Item being manipulated)
      • Item - Set charges remaining in TempItem to ((Charges remaining in TempItem) + 1)
      • Unit - Kill (Triggering unit)
  • Bloodstone Acquire Item
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Item-type of (Item being manipulated)) Equal to Bloodstone
    • Actions
      • Set TempUnit = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (TempUnit is in BloodstoneUnitGroup) Equal to False
        • Then - Actions
          • Unit Group - Add TempUnit to BloodstoneUnitGroup
          • Trigger - Turn on Bloodstone Mana Regeneration <gen>
        • Else - Actions
      • For each (Integer TempInteger) from 1 to 6, do (Actions)
        • Loop - Actions
          • Set TempItem = (Item carried by TempUnit in slot TempInteger)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempItem Not equal to (Item being manipulated)
              • (Item-type of TempItem) Equal to Bloodstone
            • Then - Actions
              • Item - Set charges remaining in (Item being manipulated) to (Charges remaining in TempItem)
              • Skip remaining actions
            • Else - Actions
  • Bloodstone Lose Item
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • (Item-type of (Item being manipulated)) Equal to Bloodstone
    • Actions
      • Set TempUnit = (Triggering unit)
      • Set TempItem = (Item being manipulated)
      • For each (Integer TempInteger) from 1 to 6, do (Actions)
        • Loop - Actions
          • Set TempItem2 = (Item carried by TempUnit in slot TempInteger)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempItem2 Not equal to TempItem
              • (Item-type of TempItem2) Equal to Bloodstone
            • Then - Actions
              • Skip remaining actions
            • Else - Actions
      • Unit Group - Remove TempUnit from BloodstoneUnitGroup
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in BloodstoneUnitGroup) Equal to 0
        • Then - Actions
          • Trigger - Turn off Bloodstone Mana Regeneration <gen>
        • Else - Actions
  • Bloodstone Mana Regeneration
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in BloodstoneUnitGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Picked unit)
          • Set TempInteger = (Charges remaining in (Item carried by TempUnit of type Bloodstone))
          • Set TempReal = ((Real(TempInteger)) x Bloodstone_Param_Mana_Gain)
          • Unit - Set mana of TempUnit to ((Mana of TempUnit) + TempReal)
fpPDEMs.png

j1imFuw.jpg

D0VsUSd.png


Changelog:
- 1.4 - 03/03/2015 - Fixed the drop item bug and minor performance improvements.
- 1.3 - 01/03/2015 - Added parameters and reset normal Wait timer.
- 1.2 - 04/02/2015 - Update on review of IcemanBo.
Merged the two "A unit dies" triggers to one.
Fixed a bug where units would not be removed from the mana regeneration group.
Made a variable for the ex-hardcoded dummy hero.
Replaced Wait gametime with a custom wait timer which is more accurate and uses a global timer.
A little code optimization.
- 1.1 - Now sets the dummy unit's experience to the experience of the owner of bloodstone.
This is required for level-dependant experience reduction.
- 1.0 - Uploaded this spell on the Hive.

Keywords:
DotA, Bloodstone.
Contents

Just another Warcraft III map (Map)

Reviews
IcemanBo: -date: 3rd March 2015 -submission: Bloodstone (DotA) GUI v1.4 http://www.hiveworkshop.com/forums/spells-569/bloodstone-dota-gui-v1-4-a-261704/index2.html#post2660263 02:26, 3th Feb 2015 IcemanBo...
Nice locals technique.
This line though;
  • Set TempUnitGroup = (Units within 1675.00 of TempLocation matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True) and (((Matching unit) has an item of type Bloodstone) Equal to True))))
please store the picked unit into a variable in the loop, then reference that unit in an ITE with these conditions. That way it's more readable and is more efficient with less calls.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
@Daffa the Mage
The wait annoys you?
There are 2 waits in this trigger. One of them being the duration of how long the visual effect is shown.
The second one is a 1 second check to tell when the hero is revived.
The first one is visual only and therefor has no reason to be changed into a timer.
The other one does have a behavior difference but I would rather have a 1 second delay between the revive of the hero and the stuff that it should do than making an array of stuff or hashtable to save the hero and get its id by the handle of the timer.
There is no way you could do anything in that <1 second.

@Mythic
I actually was annoyed by the pick every unit but now that I think of it.
It has no actual difference between those two :) (Except for the visual and editable stuff.)
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Not trying to be a prick but game-time waits leak a reference:
JASS:
function PolledWait takes real duration returns nothing
   @local timer t@
    local real  timeRemaining

    if (duration > 0) then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            exitwhen timeRemaining <= 0

            // If we have a bit of time left, skip past 10% of the remaining
            // duration instead of checking every interval, to minimize the
            // polling on long waits.
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
        call DestroyTimer(t)
    endif
endfunction
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Not trying to be a prick but game-time waits leak a reference:
JASS:
function PolledWait takes real duration returns nothing
   @local timer t@
    local real  timeRemaining

    if (duration > 0) then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            exitwhen timeRemaining <= 0

            // If we have a bit of time left, skip past 10% of the remaining
            // duration instead of checking every interval, to minimize the
            // polling on long waits.
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
        call DestroyTimer(t)
    endif
endfunction

In that case I will put a nice function in the header that does exacly the same except for the leak... would you be satisfied then?

JASS:
function CustomWait takes real duration returns nothing
    local timer t
    local real  timeRemaining

    set t = CreateTimer()
    call TimerStart(t, duration, false, null)
    loop
        set timeRemaining = TimerGetRemaining(t)
        exitwhen timeRemaining <= 0

        if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
            call TriggerSleepAction(0.5 * timeRemaining)
        else
            call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
        endif
    endloop
    call PauseTimer(t)
    call DestroyTimer(t)
    set t = null
endfunction
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
There is no need to satisfy me, I just pointed it out. Also, only mods can decide if that's acceptable or not.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
There is no need to satisfy me, I just pointed it out.
In that case I will use the standard wait timer.

Also, only mods can decide if that's acceptable or not.
I never said that you had to approve did I?

But for real, if a non-moderator can give proper/true/helpfull and clear feedback and suggestions, then it is equally appreciated as the feedback from a moderator.

Ofcourse I want to remove the pending and let my resources be approved but every feedback or suggestion helps to achieve that ain't I right?

EDIT: As I just took a better look at the wait function, I would not even create a new timer. I would make a timer at the start of the game that runs for one hour and get the (3600 - remaining time + 3600 * number of times that it ran out.) to get the game time instead.
With that, I reduce the amount of timers used in my custom polledwaits from (one for every polledwait) to ONE!
Next to that... Who doesn't want to be able to get the current gametime? There could be many stuff that would improve by using that variable.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
I never said that you had to approve did I?
Nor did I imply that, I was clarifying that only a mod can answer that question you asked.

EDIT: As I just took a better look at the wait function, I would not even create a new timer. I would make a timer at the start of the game that runs for one hour and get the (3600 - remaining time + 3600 * number of times that it ran out.) to get the game time instead.
With that, I reduce the amount of timers used in my custom polledwaits from (one for every polledwait) to ONE!
Next to that... Who doesn't want to be able to get the current gametime? There could be many stuff that would improve by using that variable.
People often use timers and its callback for that since it has better precision than sleeps.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
I am aware of the inaccurate use of timers, it is clearly visible when you see the code of the PolledWait and I assume that TriggerSleepAction works almost the same.

But as I said before:
If there is no effect on behavior or data (which only leaves visual effect), like in the first wait timer, the prefect accuracy is not required.
For the second one there are two options:
1. Use a TriggerSleepAction and suffer from a <1 second delay.
2. Create a timer and save the hero and timer in an array (with indexer) or in a hashtable and retrieve them once the timer runs out.

I chose the first because the stuff that has to be made is too much to achieve such a small thing. I mean who can do something within less than one second to actually make any difference? You get the picture.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
I am aware of the inaccurate use of timers, it is clearly visible when you see the code of the PolledWait and I assume that TriggerSleepAction works almost the same
They do since PolledWait also uses sleep calls.
 
Make more configurable. Like effect, range, specific values, etc.

onDeath -> "remove charges": You make two operations to calculate the correct charge. Just make "Chrages*0.66".

When you keep track of experience, do not hardcode the unit type.

We might talk about the wait loop some later.
Also, you use "Wait 3,62 seconds". Im curious of where this strange value come from.
By the way, waits are not that accurate. It does not make much sense to make such precice values. (though it's nothing bad to trying be accurate^^)

Why do you increase charges onAcivation?

In trigger "Aquire Item" loop from 1-6, not 0-6. Also you do not need the "And - All Conditions" block.
The only scenario an "And -All Conditions" block is useful may be in combination with an "Or - Any Condition" block.

Your "lose item" will never remove the unit from ManaRegeneration.
1) You use the "Add to group" function.
2) The boolean check will never match. It doesn't work like this. Find an other way.

The trigger condition in "Add charge":
Just PickAllUnitsInRange, and make the filter yourself by using If/Then/Else inside the enumeration function.
Currently the line is very lond and just unreadable. It would be better like mentioned.

Both death triggers could be combined into one. We try to practice the DRY principle: "Don't repeat yourself."

I have no idea about this dota related stuff, but for a fan it might be useful.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
We might talk about the wait loop some later.
Also, you use "Wait 3,62 seconds". Im curious of where this strange value come from.
By the way, waits are not that accurate. It does not make much sense to make such precice values. (though it's nothing bad to trying be accurate^^)

Yea the second wait timer is made because I don't want to limit the user to the blizzard revive system... Because AoS maps almost never use the regular revive.

The first wait timer is a little more interesting indeed.
As soon as I get home, I will place the wait timer test map in my latest post in this thread.
I will also change the regular wait timer with my Game Time Wait...
Just a bit optimization of wait timers.

Why do you increase charges onAcivation?
I activate an item... It removes a charge... I add a charge.
Good enough?
I cannot add a charge when the hero dies because if he died on a natural way he would gain a free stack!


I have no idea about this dota related stuff, but for a fan it might be useful.
In fact, I never played the original dota :D
It was on request for a fan.

Make more configurable. Like effect, range, specific values, etc.

onDeath -> "remove charges": You make two operations to calculate the correct charge. Just make "Chrages*0.66".

When you keep track of experience, do not hardcode the unit type.

In trigger "Aquire Item" loop from 1-6, not 0-6. Also you do not need the "And - All Conditions" block.
The only scenario an "And -All Conditions" block is useful may be in combination with an "Or - Any Condition" block.

Your "lose item" will never remove the unit from ManaRegeneration.
1) You use the "Add to group" function.
2) The boolean check will never match. It doesn't work like this. Find an other way.

The trigger condition in "Add charge":
Just PickAllUnitsInRange, and make the filter yourself by using If/Then/Else inside the enumeration function.
Currently the line is very lond and just unreadable. It would be better like mentioned.

Both death triggers could be combined into one. We try to practice the DRY principle: "Don't repeat yourself."
Will do.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Sounds plausible.
Sounds more like a feature... but then a glitch.
When you have 9 stacks for example.
When you die regulary you have 9 - (9*0.66(=3)) = 6 stacks.
When you activate the item (you use a stack), you will have 9 - 1 = 8 stacks.
Then you die and you will have 8 - (8*0.66(=3)) = 5 stacks.
That is a glitch... I don't like glitches enough.

Hm, PolledWait() does not null the timer after removed, in the implemented function.
That is true...

Here is my version of PolledWait(). It is more accurate but can be shorter than the requested duration.
You get (ussually) a maximum difference between -0.075 and +0.075.
The real difference is mostly 0 or +/-0.025.
It cannot be used below 1 second though. But I would never tell someone to use wait timers or custom waits for those duration just because of how "TriggerSleepAction()" works.

It also does not make a timer for each wait. Instead it uses one global timer which is the gametime. It is very easy code:
JASS:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Header File
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function GetGameTime takes nothing returns real
    return 3600*udg_GTS_Hours + TimerGetElapsed(udg_GTS_Timer)
endfunction

function GameTimeWait takes real duration returns nothing
    local real starttime = GetGameTime()
    local real endtime = GetGameTime() + duration
    local real remainingtime
    local real timerfactor
    
    if (duration > 0) then
        loop
            if GetGameSpeed() == MAP_SPEED_SLOWEST then
                set remainingtime = endtime - GetGameTime() - 0.045
            elseif GetGameSpeed() == MAP_SPEED_SLOW then
                set remainingtime = endtime - GetGameTime() - 0.035
            elseif GetGameSpeed() == MAP_SPEED_NORMAL then
                set remainingtime = endtime - GetGameTime() - 0.075
            elseif GetGameSpeed() == MAP_SPEED_FAST then
                //Untested yet
                set remainingtime = endtime - GetGameTime()
            elseif GetGameSpeed() == MAP_SPEED_FASTEST then
                //Untested yet
                set remainingtime = endtime - GetGameTime()
            endif
            
            exitwhen remainingtime <= 0
            if remainingtime > 1 then
                call TriggerSleepAction(0.5 * remainingtime)
            endif
            call TriggerSleepAction(0.05 * remainingtime)
        endloop
    endif
    set udg_TempReal = GetGameTime() - starttime
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Trig_GTS_System
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function GTS_Add_Hour takes nothing returns nothing
    set udg_GTS_Hours = udg_GTS_Hours + 1
endfunction

function InitTrig_GTS_System takes nothing returns nothing
    set udg_GTS_Timer = CreateTimer()
    call TimerStart(udg_GTS_Timer, 3600, true, function GTS_Add_Hour)
endfunction

It is that simple. I am too lazy to do the FAST and FASTEST part because if I want those two I need to make triggers to set the game speed to those values.
When using + and - you switch between SLOWEST, SLOW and NORMAL.

EDIT:
Sorry about the range and stuff but those things are only used once.
I don't like having a lot of global variables that I never use.
Because the effects are GUI, I do not have to change them. And many people can read the effect data without a problem.
So I don't really see the point of having 10 extra variables if everyone already is able to change it. Sorry if you feel offended.

-----------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------

Update 1.2

I just released version 1.2

Here are the changes:
  • Merged the two "A unit dies" triggers to one.
  • Fixed a bug where units would not be removed from the mana regeneration group.
  • Made a variable for the ex-hardcoded dummy hero.
  • Replaced Wait gametime with a custom wait timer which is more accurate and uses a global timer.
  • A little code optimization.
 

Attachments

  • Game Time System 0.7b.w3x
    17.2 KB · Views: 139
Last edited:
Okay. Then please read my older review again. Some points still needs to be changed. (config part, and the lose item thing were points I mentioned again for example)

EDIT:
Sorry about the range and stuff but those things are only used once.
I don't like having a lot of global variables that I never use.
Because the effects are GUI, I do not have to change them. And many people can read the effect data without a problem.
So I don't really see the point of having 10 extra variables if everyone already is able to change it. Sorry if you feel offended.
This was the point against range variable etc? If yes, it is better user has one config part where he can change all things he need.
Some users are not pro in coding, and it's confusing and frustrating for them to go through code and find/change values by themselves.
A good thing is when user do not even needs to have a look in your code, but only in the (short) config part.
I don't felt offended or anything similar, don't worry bro.

And frankly, I'm very skeptical with your approach of custom wait. :s
Me personaly would just prefer the normal GUI "wait" function in here.

"Wait until hero revives"
exit loop if hero is alive or unit type id == 0. (means hero was removed)
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Okay. Then please read my older review again. Some points still needs to be changed. (config part, and the lose item thing were points I mentioned again for example)
Except for these two:
Make more configurable. Like effect, range, specific values, etc.
(Mentioned)

onDeath -> "remove charges": You make two operations to calculate the correct charge. Just make "Chrages*0.66".
(Fixed)

When you keep track of experience, do not hardcode the unit type.
(Mentioned)

We might talk about the wait loop some later.
Also, you use "Wait 3,62 seconds". Im curious of where this strange value come from.
By the way, waits are not that accurate. It does not make much sense to make such precice values. (though it's nothing bad to trying be accurate^^)
(Because I can)

Why do you increase charges onAcivation?
(Because it is required)

In trigger "Aquire Item" loop from 1-6, not 0-6. Also you do not need the "And - All Conditions" block.
The only scenario an "And -All Conditions" block is useful may be in combination with an "Or - Any Condition" block.
(Fixed)

Your "lose item" will never remove the unit from ManaRegeneration.
1) You use the "Add to group" function.
2) The boolean check will never match. It doesn't work like this. Find an other way.
(Fixed)

The trigger condition in "Add charge":
Just PickAllUnitsInRange, and make the filter yourself by using If/Then/Else inside the enumeration function.
Currently the line is very lond and just unreadable. It would be better like mentioned.
(Fixed)

Both death triggers could be combined into one. We try to practice the DRY principle: "Don't repeat yourself."
(Fixed)

I have no idea about this dota related stuff, but for a fan it might be useful.
(So I think you wanted me to fix this :p)

And frankly, I'm very skeptical with your approach of custom wait. :s
Me personaly would just prefer the normal GUI "wait" function in here.
Yea who the hell needs improved accuracy and leak fixes :p
Just doing the best I can.
I will replace it with Leakless wait so at least the leak will be fixed.

This was the point against range variable etc? If yes, it is better user has one config part where he can change all things he need.
Some users are not pro in coding, and it's confusing and frustrating for them to go through code and find/change values by themselves.
A good thing is when user do not even needs to have a look in your code, but only in the (short) config part.
I don't felt offended or anything similar, don't worry bro.

"Wait until hero revives"
exit loop if hero is alive or unit type id == 0. (means hero was removed)
Will do.

-----------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------

Update 1.3

I just released version 1.3

Here are the changes:
  • Removed the Gametime System and reset the custom timer to the normal Wait timer.
  • Made a parameter for every effect variable.
 
Last edited:
Hey, with the config it looks some nicer to me. :)

  • The drop item bug needs to be fixed. Unit won't get removed properly from group when losing the item.
  • Store "PickedUnit" into a temporary unit variable. It is used more often. (death trigger)
  • onDeath directly make a trigger condition if TriggeringUnit has the item.
  • exitwhen GetUnitState(udg_TempUnit, UNIT_STATE_LIFE) > 0
    ->
    exitwhen GetWidgetLife(udg_TempUnit) > 0
    ^It is faster.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Update 1.4

I just released version 1.4

Here are the changes:
  • Fixed the bug where the mana regeneration would never be removed from the unit... even though he would not regenerate any mana though.
  • Added minor performance improvements.

@Icemanbo
You really have to make up your mind man.
First you say that I should put triggers with the same event together and now you want me to split them up again. -_-
If you take a good look at the on-death trigger, you see that the first action is not applied on units with bloodstone, the second actions is.
So I cannot put the bloodstone check in the conditions because that would remove the first action completely.
Or I have to split those in two triggers... what I changed in 1.2.
 
Yes, you're right. DyingUnit might not have the item. :)

  • Set TempUnit = (Triggering unit)
^This could be done immediatly on top of trigger, and only once.

  • Unit - Set life of (Picked unit) to ((Leben of TempUnit2) + TempReal)
You forgot here to replace "PickedUnit" here with the varible.

Good, the item bug has been fixed. :)

The TriggerSleepAction loop is not a perfect solution,
but it works here and simplifies it a lot for you.
So it's fine for me here.

I would prefer a custom counter over using the "IsGroupEmpty" function.

In my eyes it's a very specified spell, but might be useful.

Approved.
 
Top