Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
THE DAMAGE ENGINE IN THIS MAP IS NOT MINE!
Credits for that go to Bribe.
This is a simple system that awards gold to all units involved in a kill ( all units that dealt damage ) based on the percentage damage they dealt in the last 20 seconds to the killed unit. Like this:
My hero is attacking and enemy hero, when my ally appears and nukes him, thus getting the killing blow.
While i was attacking my enemy, i managed to get him down to 10% health, so that my total damage percentage was 90%. My ally just dealt 10% damage.
The enemy hero's level was 5 and the hero gold modifier is 2 so that the total gold awarded is 5*2=10.
My hero, who dealt 90% of the damage, will get 90% of the gold ( 9 gold ).
My ally, who tried to kill-steal me, got just 10% of the gold ( 1 gold ).
This system also supports dice-rolling for additional bounty reward, similar to the system used in blizzard's object editor.
If you used the past version of this system ( v1.0 ), be sure to delete all "Bounty_" variables, because those are no longer needed.
Hope you enjoy!
Full GUI, leakless and ( i think ) lagless.
Triggs:
Color Init
Events
Map initialization
Conditions
Actions
Set PlayerColors[1] = |cffff0303
Set PlayerColors[2] = |cff0042ff
Set PlayerColors[3] = |cff1ce6b9
Set PlayerColors[4] = |cff540081
Set PlayerColors[5] = |cfffffc01
Set PlayerColors[6] = |cfffeba0e
Set PlayerColors[7] = |cff20c000
Set PlayerColors[8] = |cffe55bb0
Set PlayerColors[9] = |cff959697
Set PlayerColors[10] = |cff7ebff1
Set PlayerColors[11] = |cff106246
Set PlayerColors[12] = |cff4e2a04
AwardGoldConfig
Events
Map initialization
Conditions
Actions
-------- How much gold is granted per killed unit level. --------
Set AwardGold_LevelMultiplier = 10
-------- How much extra gold is awarded if killed unit is a hero ( multiplier ). --------
Set AwardGold_HeroMultiplier = 3
-------- How much time does it take for damage instances to be reset. --------
Set AwardGold_ResetTimer = 20
-------- Dice amount is the quantity of dice rolled when a unit dies. A bigger number of dice makes to that extreme values ( Min. and Max.) become more unlikely and mid values become more common. This value multiplies DiceSides --------
Set AwardGold_DiceAmount = 2
-------- Dice Sides is the value range that can be obtained when rolling a dice. This value multiplies creature level, so that Maximum gold awarded is 50% certain and 50% random when this var is == to 1. --------
Set AwardGold_DiceSides = 1.50
AwardGoldStore
Events
Game - DamageEvent becomes Equal to 1.00
Conditions
((Owner of DamageEventSource) is an ally of (Owner of DamageEventTarget)) Equal to False
Actions
Set AwardGold_HasChecker = False
For each (Integer AwardGold_LoopInteger) from 1 to AwardGold_Index, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
DamageEventTarget Equal to AwardGold_Target[AwardGold_LoopInteger]
DamageEventSource Equal to AwardGold_Source[AwardGold_LoopInteger]
Then - Actions
Set AwardGold_HasChecker = True
Set AwardGold_Amount[AwardGold_LoopInteger] = (AwardGold_Amount[AwardGold_LoopInteger] + DamageEventAmount)
Set AwardGold_Period[AwardGold_LoopInteger] = AwardGold_ResetTimer
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
AwardGold_HasChecker Equal to False
Then - Actions
Set AwardGold_Index = (AwardGold_Index + 1)
Set AwardGold_Target[AwardGold_Index] = DamageEventTarget
Set AwardGold_Source[AwardGold_Index] = DamageEventSource
Set AwardGold_Amount[AwardGold_Index] = DamageEventAmount
Set AwardGold_Period[AwardGold_Index] = AwardGold_ResetTimer
Game - Display to (All players) the text: New damage instance!
Else - Actions
Game - Display to (All players) the text: ((Name of DamageEventSource) + ( dealt + ((String(DamageEventAmount, 0, 0)) + ( damage to + ((Name of DamageEventTarget) + .)))))
AwardGoldLoop
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
For each (Integer AwardGold_LoopInteger) from 1 to AwardGold_Index, do (Actions)
Loop - Actions
Set AwardGold_Period[AwardGold_LoopInteger] = (AwardGold_Period[AwardGold_LoopInteger] - 1)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
AwardGold_Period[AwardGold_LoopInteger] Equal to 0
Then - Actions
Set AwardGold_Target[AwardGold_LoopInteger] = AwardGold_Target[AwardGold_Index]
Set AwardGold_Source[AwardGold_LoopInteger] = AwardGold_Source[AwardGold_Index]
Set AwardGold_Amount[AwardGold_LoopInteger] = AwardGold_Amount[AwardGold_Index]
Set AwardGold_Period[AwardGold_LoopInteger] = AwardGold_Period[AwardGold_Index]
Set AwardGold_Index = (AwardGold_Index - 1)
Set AwardGold_LoopInteger = (AwardGold_LoopInteger - 1)
Game - Display to (All players) the text: Damage instance res...
Else - Actions
AwardGoldDeath
Events
Unit - A unit Dies
Conditions
Actions
Set AwardGold_KilledUnit = (Triggering unit)
Set AwardGold_KilledLevel = (Level of AwardGold_KilledUnit)
Set AwardGold_NumAwarded = 0
Set AwardGold_DmgCap = 0.00
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(AwardGold_KilledUnit is A Hero) Equal to True
Then - Actions
Set AwardGold_KilledLevel = (AwardGold_KilledLevel x AwardGold_HeroMultiplier)
Else - Actions
Set AwardGold_GoldGranted = (AwardGold_KilledLevel x AwardGold_LevelMultiplier)
For each (Integer AwardGold_LoopInteger) from 1 to AwardGold_DiceAmount, do (Actions)
Loop - Actions
Set AwardGold_DiceValue = (Integer(((Random real number between 1.00 and (Real(AwardGold_KilledLevel))) x AwardGold_DiceSides)))
Set AwardGold_GoldGranted = (AwardGold_GoldGranted + AwardGold_DiceValue)
Game - Display to (All players) the text: (Dice Roll: + (String(AwardGold_DiceValue)))
For each (Integer AwardGold_LoopInteger) from 1 to AwardGold_Index, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
AwardGold_Target[AwardGold_LoopInteger] Equal to AwardGold_KilledUnit
AwardGold_Source[AwardGold_LoopInteger] Not equal to AwardGold_KilledUnit
Then - Actions
Set AwardGold_NumAwarded = (AwardGold_NumAwarded + 1)
Set AwardGold_DmgCap = (AwardGold_DmgCap + AwardGold_Amount[AwardGold_LoopInteger])
Set AwardGold_IndivUnit[AwardGold_NumAwarded] = AwardGold_Source[AwardGold_LoopInteger]
Set AwardGold_IndivDamage[AwardGold_NumAwarded] = AwardGold_Amount[AwardGold_LoopInteger]
-------- Reset --------
Set AwardGold_Target[AwardGold_LoopInteger] = AwardGold_Target[AwardGold_Index]
Set AwardGold_Source[AwardGold_LoopInteger] = AwardGold_Source[AwardGold_Index]
Set AwardGold_Amount[AwardGold_LoopInteger] = AwardGold_Amount[AwardGold_Index]
Set AwardGold_Period[AwardGold_LoopInteger] = AwardGold_Period[AwardGold_Index]
Set AwardGold_Index = (AwardGold_Index - 1)
Set AwardGold_LoopInteger = (AwardGold_LoopInteger - 1)
Game - Display to (All players) the text: Damage instance res...
Else - Actions
For each (Integer AwardGold_LoopInteger) from 1 to AwardGold_NumAwarded, do (Actions)
Loop - Actions
Set AwardGold_IndivInteger = AwardGold_NumAwarded
For each (Integer AwardGold_LoopInteger2) from 1 to AwardGold_NumAwarded, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
AwardGold_IndivDamage[AwardGold_LoopInteger] Greater than AwardGold_IndivDamage[AwardGold_LoopInteger2]
Then - Actions
Set AwardGold_IndivInteger = (AwardGold_IndivInteger - 1)
Else - Actions
Set AwardGold_IndivOrder[AwardGold_IndivInteger] = AwardGold_LoopInteger
Game - Display to (All players) the text: (((PlayerColors[(Player number of (Owner of AwardGold_KilledUnit))] + (Name of (Owner of AwardGold_KilledUnit))) + |r) + ('s unit has died granting a total of + ((String(AwardGold_GoldGranted)) + gold. Stats:)))
For each (Integer AwardGold_LoopInteger) from 1 to AwardGold_NumAwarded, do (Actions)
Loop - Actions
Set AwardGold_IndivGold = (Integer(((AwardGold_IndivDamage[AwardGold_IndivOrder[AwardGold_LoopInteger]] / AwardGold_DmgCap) x (Real(AwardGold_GoldGranted)))))
Player - Add AwardGold_IndivGold to (Owner of AwardGold_Source[AwardGold_LoopInteger]) Current gold
Special Effect - Create a special effect attached to the overhead of AwardGold_IndivUnit[AwardGold_IndivOrder[AwardGold_LoopInteger]] using UI\Feedback\GoldCredit\GoldCredit.mdl
Special Effect - Destroy (Last created special effect)
Floating Text - Create floating text that reads (String(AwardGold_IndivGold)) above AwardGold_IndivUnit[AwardGold_IndivOrder[AwardGold_LoopInteger]] with Z offset 0.00, using font size 12.00, color (100.00%, 100.00%, 0.00%), and 0.00% transparency
Set AwardGold_Text = (Last created floating text)
Floating Text - Set the velocity of AwardGold_Text to 70.00 towards 110.00 degrees
Floating Text - Change AwardGold_Text: Disable permanence
Floating Text - Change the fading age of AwardGold_Text to 0.60 seconds
Floating Text - Change the lifespan of AwardGold_Text to 1.00 seconds
Game - Display to (All players) the text: (((PlayerColors[(Player number of (Owner of AwardGold_IndivUnit[AwardGold_IndivOrder[AwardGold_LoopInteger]]))] + (Name of (Owner of AwardGold_IndivUnit[AwardGold_IndivOrder[AwardGold_LoopInteger]]))) + |r) + ('s + ((Name of AwardGold_IndivUnit[AwardGold_Ind
v1.2a - Major update, many changes:
- A hashtable array is no longer used in this system, making it much faster and reliable
- Added config file, which allows for many changes in the system.
- Added random gold ( Dice Gold ) method that grants extra random gold with each kill.
- Added player colored units that can be used for testing the system's color array.
- All used variables changed names: from "Bounty_" to "AwardGold_".
v1.0 - Uploaded.
esdo - Creator of the system ( me! )
Bribe - Creator of the damage engine, a requirement for this system to work.
12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.
18:24, 9th Jul 2014
PurgeandFire: Review:
http://www.hiveworkshop.com/forums/2554140-post30.html
I see absolutely no way of reworking this to remove hashtable arrays - I would need a whole new system.
One possibility I had to chose from when creating this was using some method of double indexing, but i thought this was better. I've read somewhere that hashtables are 2x slower that indexing, but I didn't think that would matter when all my system do is some simple math.
You can only have 255 hashtables in your map so once 256 total hashtables are created this system will break.
Hashtables are also 4 to 8 times slower and they get slower with more info added.
Basic method of doing this with only one hashtable is to make it with an indexing hashtable method.
Basically you store everything you can in arrays and use the hashtable to load a key / index to which array you are storing the stuff for that unit.
Give me a few minutes and I will update this with a good description of how to do something like what you are trying to achieve.
Basic method of doing this with only one hashtable is to make it with an indexing hashtable method.
Basically you store everything you can in arrays and use the hashtable to load a key / index to which array you are storing the stuff for that unit.
Hashtable will be called HASHTABLE
So for example unit 1 (attacking unit) attacks unit 2(damaged unit). To make it easy handle id of unit 1 is 1000 and for unit 2 it is 2000. The index counter will be called hashIndexCount
Then you store info like this.
hashIndexCount = (hashIndexCount + 1)
Save hashIndexCount as 0 of 1000 in HASHTABLE
// The above will store the index identifier in the hashtable.
// Next we store the unit that is doing the attacking into the hashtable.
// So we need a max integer to determine how many units have attacked that unit. Call it NumOfUnitsThatAttacked[]. It is also an array.
// we also need a temp boolean.
Set TempBoolean = true
Loop For each tempInt from 0 to NumOfUnitsThatAttacked[ hashIndexCount]
// This is to check if that unit has attacked before.
// To store the units that attacked before we need an integer array. I'll call it AttackingUnitIDs
If 2000 == AttackingUnitIDs[ tempInt] // If this is true then the unit is already in there and you need to increase the amount of damage it did.
then
increase damage with damage that was done.
Set TempBoolean = false
else
// After the loop we check the boolean.
If TempBoolean == true
then
// create new instance for the attacking unit.
// First we increase the counter that keeps count of how many units have attacked that one unit.
NumOfUnitsThatAttacked[ hashIndexCount] = (NumOfUnitsThatAttacked[ hashIndexCount] + 1)
// Then we store the new unit with all info needed into arrays that deal with the units damage.
Set damage.
The above is just the basics.
To do counters efficiently add an integer array or a real array your choice. ( I prefer real arrays). Name it TimeAttackResets. ( Your 20 second time )
First you need a trigger that runs every .03 seconds Every .03 seconds add it to a GameTime real variable.
In the ITE where you check for the units id type you need to check if the GameTime is greater than TimeAttackResets is. If it is then you remove that unit since his delay between attacks time will be to long.
You then de-index that unit. If you need a better explanation on how to do integer timers then I can try to explain it better.
I'm having a hard time understanding this - could you explain it better?
Is it that you are suggesting to keep track of each damage instance? Like if unit A attacks unit B, index ++. If unit A attacks C, Index ++. That way the maximum num. of instances would be 8192 ( or something like that ).
Anyway - wouldn't it be FAR easier to do this in vJass? I think I'm gonna give it a try.
I'm having a hard time understanding this - could you explain it better?
Is it that you are suggesting to keep track of each damage instance? Like if unit A attacks unit B, index ++. If unit A attacks C, Index ++. That way the maximum num. of instances would be 8192 ( or something like that ).
Anyway - wouldn't it be FAR easier to do this in vJass? I think I'm gonna give it a try.
Okay, so, what I would need to do is create one damage instance ( like a registry, something that increases the Max Index ) every time a unit is attacked, similarly to when the Index of a MUI ability is increased when some unit casts it?
Problem is that there would be a cap at 8192 attacks. Right?
Okay, so, what I would need to do is create one damage instance ( like a registry, something that increases the Max Index ) every time a unit is attacked, similarly to when the Index of a MUI ability is increased when some unit casts it?
Problem is that there would be a cap at 8192 attacks. Right?
What I said above creates a struct to be used. Structs are simple an integer array.
The this.unit is the same as unit[ this]
So if this = 1 it would be the same as unit[ 1]
Structs in Vjass use this same method. It is just better syntax in vJass. Also the indexing they use is a little better than indexed arrays. They also have a way to stop crashes since it simply doesn't let you create a new struct if you cannot.
I posted before the spell description was updated.
I'll check out the system when I can.
Edit:
This should use a hashtable for lookup purposes. It is very slow looking through all of the instances. This will eventually hit the op-limit.
The method I provided to you above will never hit op-limit. Only limit it can hit is the 8192 limit but that means that there has to be 8192 units being attacked before it breaks. It also does not need the loop trigger.
It only needs three triggers. The config trigger. A trigger that fires when unit is damaged. And a trigger that fires when unit dies.
If you need help making the system I described above feel free to ask. I will help. If not I may make the system when I can.
The problem with the way you have written is the lookup for when the unit dies to see who gets the bounty for killing that unit. You would have to search through everything to see which units get bounty.
You've improved it quite a bit since you first submitted it. Nice job!
I really like the idea and the implementation.
You should add an option of whether to display the floating text (a boolean configurable).
Remove the "Game - Display" messages, such as "New Damage Instance!". If you want to keep the one telling the bounty received, that is fine, but make it a configurable of whether to display it.
There could be some improvement by using a hashtable. As deathismyfriend said, looping through all the damage instances is pretty heavy. By using a hashtable, you could store each damage instance under the keys of the source and target. That way, you can just load their index from the hashtable rather than looping through all the instances.
Here is your current implementation:
AwardGoldStore
Events
Game - DamageEvent becomes Equal to 1.00
Conditions
((Owner of DamageEventSource) is an ally of (Owner of DamageEventTarget)) Equal to False
Actions
Set AwardGold_HasChecker = False
For each (Integer AwardGold_LoopInteger) from 1 to AwardGold_Index, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
DamageEventTarget Equal to AwardGold_Target[AwardGold_LoopInteger]
DamageEventSource Equal to AwardGold_Source[AwardGold_LoopInteger]
Then - Actions
Set AwardGold_HasChecker = True
Set AwardGold_Amount[AwardGold_LoopInteger] = (AwardGold_Amount[AwardGold_LoopInteger] + DamageEventAmount)
Set AwardGold_Period[AwardGold_LoopInteger] = AwardGold_ResetTimer
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
AwardGold_HasChecker Equal to False
Then - Actions
Set AwardGold_Index = (AwardGold_Index + 1)
Set AwardGold_Target[AwardGold_Index] = DamageEventTarget
Set AwardGold_Source[AwardGold_Index] = DamageEventSource
Set AwardGold_Amount[AwardGold_Index] = DamageEventAmount
Set AwardGold_Period[AwardGold_Index] = AwardGold_ResetTimer
Game - Display to (All players) the text: New damage instance!
Else - Actions
Game - Display to (All players) the text: ((Name of DamageEventSource) + ( dealt + ((String(DamageEventAmount, 0, 0)) + ( damage to + ((Name of DamageEventTarget) + .)))))
With a hashtable, it could look something like this:
AwardGoldStore
Events
Game - DamageEvent becomes Equal to 1.00
Conditions
((Owner of DamageEventSource) is an ally of (Owner of DamageEventTarget)) Equal to False
Actions
Set AwardGold_HasChecker = False
Set AwardGold_LoopInteger = (Load (Key DamageEventTarget) of (Key DamageEventSource) in AwardGold_Hash)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(AwardGold_LoopInteger) Not Equal to 0
Then - Actions
Set AwardGold_HasChecker = True
Set AwardGold_Amount[AwardGold_LoopInteger] = (AwardGold_Amount[AwardGold_LoopInteger] + DamageEventAmount)
Set AwardGold_Period[AwardGold_LoopInteger] = AwardGold_ResetTimer
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
AwardGold_HasChecker Equal to False
Then - Actions
Set AwardGold_Index = (AwardGold_Index + 1)
Set AwardGold_Target[AwardGold_Index] = DamageEventTarget
Set AwardGold_Source[AwardGold_Index] = DamageEventSource
Set AwardGold_Amount[AwardGold_Index] = DamageEventAmount
Set AwardGold_Period[AwardGold_Index] = AwardGold_ResetTimer
Hashtable - Save AwardGold_Index as (Key DamageEventTarget) of (Key DamageEventSource) in AwardGold_Hash
Game - Display to (All players) the text: New damage instance!
Else - Actions
Game - Display to (All players) the text: ((Name of DamageEventSource) + ( dealt + ((String(DamageEventAmount, 0, 0)) + ( damage to + ((Name of DamageEventTarget) + .)))))
And that would be a lot more efficient. That was freehand, so it might not work/be exact, but that should paint a basic picture of what it would look like. Of course, when you decrease AwardGold_Index, you would also remove the data from the hashtable. It would require a bit of work, but it would really help make this a solid system.
Otherwise, nice job. Just make a few updates and it should be approvable. The last update (about the hashtable) isn't required, but it could bump up the rating, and I highly recommend it.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.