How to detect a duration of Stats gain skills?

DarkBELL

New Member
Reaction score
1
I'm trying to make a skills that mess with stats

The skills is whenever the Caster takes damage each 19 HP he lost is replace with 1 Str point

Leveling the skills put more duration into the Bonus Str gain

so at level 4 the Bonus Str gained from this skill will stays with the caster for 60 seconds

No trigger has actually been written yet, But I have figure out the Bonus Attribute part
it probably something like:

-Damage Detection System

-Detect Damage

-(Damage Detect)/(19) = Number of Str you Get

------

But I really can't thinks of how to do the duration part, like how to specifically detects which Bonus Str Point has already exceed it's duration
 

KaerfNomekop

Swim, fishies. Swim through the veil of steel.
Reaction score
612
Make dummy units with expiration timers. When a dummy dies, subtract 1 Strength from the Hero.
 

KaerfNomekop

Swim, fishies. Swim through the veil of steel.
Reaction score
612
I'm not sure, I guess it should. Even if it doesn't, you can have a dummy HERO to track stats, then set your actual Hero's current stats to those of the dummy Hero.
 

DarkBELL

New Member
Reaction score
1
It's not always a 1 Str Gain, It's 1 Str for every 19 Damage taken

Now, This is my attempt

Trigger:
  • Chimera Shift 1
    • Events
      • Game - GDD_Event becomes Equal to 0.00
    • Conditions
      • (Level of Chimera Shift (True) for GDD_DamagedUnit) Greater than 0
      • GDD_Damage Greater than or equal to 19.00
    • Actions
      • Set ChimeraShift_Caster = GDD_DamagedUnit
      • Set ChimeraShift_StrFactor[ChimeraShift_Timer_Amount] = ((Integer(GDD_Damage)) / 19)
      • Hero - Modify Strength of ChimeraShift_Caster: Add ChimeraShift_StrFactor[ChimeraShift_Timer_Amount]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Chimera Shift for ChimeraShift_Caster) Equal to 1
        • Then - Actions
          • Set ChimeraShift_Timer[ChimeraShift_Timer_Amount] = 15
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Chimera Shift for ChimeraShift_Caster) Equal to 2
        • Then - Actions
          • Set ChimeraShift_Timer[ChimeraShift_Timer_Amount] = 30
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Chimera Shift for ChimeraShift_Caster) Equal to 3
        • Then - Actions
          • Set ChimeraShift_Timer[ChimeraShift_Timer_Amount] = 45
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Chimera Shift for ChimeraShift_Caster) Equal to 4
        • Then - Actions
          • Set ChimeraShift_Timer[ChimeraShift_Timer_Amount] = 60
        • Else - Actions
      • Set ChimeraShift_Timer_Amount = (ChimeraShift_Timer_Amount + 1)



Trigger:
  • Chimera Shift 2
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ChimeraShift_Timer_Amount Greater than 0
        • Then - Actions
          • For each (Integer ChimeraShift_Integer) from 1 to ChimeraShift_Timer_Amount, do (Actions)
            • Loop - Actions
              • Set ChimeraShift_Timer[ChimeraShift_Timer_Amount] = (ChimeraShift_Timer[ChimeraShift_Timer_Amount] - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ChimeraShift_Timer[ChimeraShift_Timer_Amount] Equal to 0
                • Then - Actions
                  • Hero - Modify Strength of ChimeraShift_Caster: Subtract ChimeraShift_StrFactor[ChimeraShift_Timer_Amount]
                  • Set ChimeraShift_Timer_Amount = (ChimeraShift_Timer_Amount - 1)
                • Else - Actions
        • Else - Actions
          • Do nothing



It fails though no Bonus Strength is gain at all, so I test a few things with it

-I thinks maybe the ChimeraShift_StrFactor is lower than 1, So I just change it to have the skill add 10 Str whenever I was attack by a damage more than 19, But still, No strength is gain
-I thinks there is problem with my duration system, so I try disabling the trigger "Chimera Shift 2" (The one that takes away Str), but no Still No Strength is gains

So, I think thats there is something wrong with the Damage detection system and that somehow, it didn't registered my unit being attacked as GDD_DamagedUnit

Can anyone please help me with this OTL
 

Cookie!

Member
Reaction score
0
Here's my two cents. Make several items based off Item Strength Bonus, with their bonuses set to +1, +2, +4, +8, +16, +32 and so on. Then, make a trigger that runs periodically, and have it assign (total hitpoints - current hitpoints) to a variable (this is hitpoints left). Divide this value by 19, and you'll have the strength bonus you need to give your Hero. Now, pick the item that has the highest strength bonus that is lower than the strength bonus you require (I do hope that made sense), and add the ability to your Hero. Subtract this from your variable, and repeat till the variable becomes zero.

This is called the bitflagging technique, by the way.

If you use the exact method I've outlined here, however, the bonus will not be time dependent; rather, it will change dynamically with the Hero's current hitpoints.

Hope this helped :).
 

KaerfNomekop

Swim, fishies. Swim through the veil of steel.
Reaction score
612
If only there was an Attribute Bonus aura. This would be much easier.
 

Cookie!

Member
Reaction score
0
Oh! I only just understood what you're trying to do :eek:. I'll outline you a method.

What we need is an array of integers, to store damage taken over time. The number of integers in this array depends on how often you want your strength bonus to refresh. For this example, I'll consider once every second.

My array contains 60 integers, which, multiplied by 1 second refresh time gives 60 seconds buff time.

Now, every time my unit takes damage, I add the damage taken to the last element of the array, which represents damage taken during the current second.

I have another trigger that fires once every second, and shifts all the elements of the array back by one index and stores the total in another variable; that is:

Trigger:
  • Actions
    • Set Total_Damage = 0
    • For each (Integer A) from 0 to 58, do (Actions)
      • Loop - Actions
        • Set Damage_Array[(Integer A)] = Damage_Array[((Integer A) + 1)]
        • Set Total_Damage = (Total_Damage + Damage_Array[(Integer A)])
    • Damage_Array[59] = 0


After the loop, you divide total damage by 19, remove all Item Strength Bonus (the custom ones, which you've made), and use the bitflagging technique to add the new strength bonus.

Now, whenever a unit takes damage, you add the damage taken to Damage_Array[59], which, if you remember, stores the damage taken in the current second.

Further, as far as different levels giving different buff durations goes, just add damage taken from the damage detection trigger to a different index of the array; for instance, for a 15 second buff, you would add damage taken to Damage_Array[14], instead of Damage_Array[59].

Hopefully, that made sense :p.

Oh, and I'd stay away from modifying Hero attributes via triggers unless I intended them to be permanent... they tend to get messy.

If you're still having trouble, just leave a post saying so, and I'll make you a skeleton trigger :D.
 

Cookie!

Member
Reaction score
0
Ah, well, I went ahead and made you a trigger. Two triggers, actually :p.

Trigger:
  • Untitled Trigger 001
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Set Total_Damage = 0
      • For each (Integer A) from 0 to 58, do (Actions)
        • Loop - Actions
          • Set Damage_Array[(Integer A)] = Damage_Array[((Integer A) + 1)]
          • Set Total_Damage = (Total_Damage + Damage_Array[(Integer A)])
      • Set Damage_Array[59] = 0
      • Set New_Bonus = (Total_Damage / 19)
      • Hero - Modify Strength of Chimera_Shift_Caster: Subtract Old_Bonus
      • Hero - Modify Strength of Chimera_Shift_Caster: Add New_Bonus
      • Set Old_Bonus = New_Bonus


Trigger:
  • Untitled Trigger 002
    • Events
      • Game - GDD_Event becomes Equal to 0.00
    • Conditions
      • (Level of Chimera Shift (True) for GDD_DamagedUnit) Greater than 0
    • Actions
      • Set Chimera_Shift_Caster = GDD_DamagedUnit
      • If ((Level of Chimera Shift for GDD_DamagedUnit) Equal to 1) then do (Set DamageArray[14] = (DamageArray[14] + (Integer(GDD_Damage)))) else do (Do nothing)
      • If ((Level of Chimera Shift for GDD_DamagedUnit) Equal to 2) then do (Set DamageArray[29] = (DamageArray[29] + (Integer(GDD_Damage)))) else do (Do nothing)
      • If ((Level of Chimera Shift for GDD_DamagedUnit) Equal to 3) then do (Set DamageArray[44] = (DamageArray[44] + (Integer(GDD_Damage)))) else do (Do nothing)
      • If ((Level of Chimera Shift for GDD_DamagedUnit) Equal to 4) then do (Set DamageArray[59] = (DamageArray[59] + (Integer(GDD_Damage)))) else do (Do nothing)


These should work outright, but I'd recommend using an item-bonus based system, instead of doing "Hero - Modify Strength"

What's happening here is that you're storing all the damage you've taken over the past minute, and changing your strength bonus accordingly.

The issue you had with the timing of the individual bonuses is now gone, because instead of detecting every damage event, calculating and granting the bonus, and storing it for future deletion, you now store the damage done, and calculate bonus on total damage done. Since the array that stores damage shifts back one index every second, damage that was done more than 60 seconds ago is automatically deleted from the system.

Pretty clever, actually :D.
 

Bogrim

y hello thar
Reaction score
154
That's... really making the trigger a lot more complex than it needs to be, Cookie. I don't think you know GDD that well.

Trigger:
  • Strength Expiration
    • Events
      • Game - GDD_Event becomes Equal to 0.00
    • Conditions
      • (Level of Your Ability for (Triggering unit)) Greater than 0
      • GDD_Damage Greater than 0.00
    • Actions
      • Custom script: local integer i
      • Set real_DamageCount = (real_DamageCount + GDD_Damage)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • real_DamageCount Greater than or equal to 19.00
        • Then - Actions
          • Set Temp_Integer = ((Integer(GDD_Damage)) / 19)
          • Set real_DamageCount = (real_DamageCount - (19.00 x (Real(Temp_Integer))))
          • Hero - Modify Strength of (Triggering unit): Add Temp_Integer
          • Custom script: set i = udg_Temp_Integer
          • Wait (15.00 x (Real((Level of Your Ability for (Triggering unit))))) seconds
          • Custom script: set udg_Temp_Integer = i
          • Hero - Modify Strength of (Triggering unit): Subtract Temp_Integer
        • Else - Actions


In this trigger you save the damage taken by the unit. Then whenever it hits the 19 damage threshold, the trigger adds the corresponding amount of strength, saves the value as a local integer, then waits out the timer and then subtracts the strength again.

What you need for this trigger is 1 temporary integer variable (you normally have a set of temporary variables for all your triggers, like "TempUnit" and "TempGroup") and 1 specific real variable to store the damage in.

If you need the trigger to be MUI, you can use an indexer and make the real an array or use a hashtable to save the real value. If you only have 1 hero with this ability, don't worry about it.
 

Cookie!

Member
Reaction score
0
That's... really making the trigger a lot more complex than it needs to be, Cookie. I don't think you know GDD that well.

I'm not sure why I need to know GDD to make a trigger... GDD simply handles the generic damage taken event; the spell trigger itself is pure logic.
 

Bogrim

y hello thar
Reaction score
154
I'm not sure why I need to know GDD to make a trigger... GDD simply handles the generic damage taken event; the spell trigger itself is pure logic.

For one thing, you used GDD_DamagedUnit when it's the same as Triggering Unit, only it's a global variable instead of the local variable that saves the local instance data through wait periods. The difference here is that you create an additional unnecessary periodic trigger that only serves to reduce the game's performance as the trigger runs even when the unit isn't damaged and between intervals where no damage is taken. As GDD is a damage detection system, you can detect the exact moment the unit takes damage and with a timer (or just a less accurate wait) set the precise time the trigger needs to subtract the added values instead of running a constant frequent check.
 

Cookie!

Member
Reaction score
0
The difference here is that you create an additional unnecessary periodic trigger that only serves to reduce the game's performance as the trigger runs even when the unit isn't damaged and between intervals where no damage is taken.

Does your method not do the exact same thing? Sure, it's far more economical when no damage is being taken, but consider a situation where you're taking hits from 6 different units, once every second. You're essentially creating 360 integers to store the bonuses you granted, while I'm still using my constant 60 integers...
 

GFreak45

I didnt slap you, i high 5'd your face.
Reaction score
130
This DOES work, and heres what i have with a map included, it can be copied but if u copy the ability, variables, and triggers in that order... but now looking back if bogrims system works it would probably take up less cpu usage/memory

Made a custom ability from critical strike, set tooltips, max lvl to 4, crit chance to 0, and crit multiplier to 0

then put this in triggers

Detect Initial Units
Events
Map initialization
Conditions
Actions
Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
Loop - Actions
Trigger - Add to Unit Takes Damage <gen> the event (Unit - (Picked unit) Takes damage)

Detect New Units
Events
Unit - A unit enters (Playable map area)
Conditions
Actions
Trigger - Add to Unit Takes Damage <gen> the event (Unit - (Triggering unit) Takes damage)

Unit Takes Damage
Events
Conditions
(Level of Chimaera Shift for (Triggering unit)) Greater than 0
(Damage taken) Greater than or equal to 19.00
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Chimaera_Shift_Timer[(Player number of (Owner of (Triggering unit)))] Equal to 0
Then - Actions
Set Hero_Stats = (Strength of (Triggering unit) (Exclude bonuses))
Else - Actions
Hero - Modify Strength of (Triggering unit): Add (Integer((((Damage taken) / 19.00) - (((Damage taken) mod 19.00) / 19.00))))
Set Chimaera_Shift_Timer[(Player number of (Owner of (Triggering unit)))] = ((Level of Chimaera Shift for (Triggering unit)) x 15)

Chimaera Shift Duration
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
Player Group - Pick every player in (All players) and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Chimaera_Shift_Timer[(Player number of (Picked player))] Greater than 0
Then - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Chimaera_Shift_Timer[(Player number of (Picked player))] Equal to 1
Then - Actions
Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Owner of (Picked unit)) Equal to (Picked player)
((Picked unit) is A Hero) Equal to True
Then - Actions
Set Unit_Life = (Percentage life of (Picked unit))
Hero - Modify Strength of (Picked unit): Set to Hero_Stats
Unit - Set life of (Triggering unit) to Unit_Life%
Else - Actions
Else - Actions
Set Chimaera_Shift_Timer[(Player number of (Picked player))] = (Chimaera_Shift_Timer[(Player number of (Picked player))] - 1)
Else - Actions

Unit Dies with Chimaera Shift
Events
Unit - A unit Dies
Conditions
(Level of Chimaera Shift for (Triggering unit)) Greater than 0
Actions
Trigger - Add to Revive with Chimaera Strike Stats corrected <gen> the event (Unit - (Dying unit) Finishes reviving)

Revive with Chimaera Strike Stats corrected
Events
Conditions
Chimaera_Shift_Timer[(Player number of (Owner of (Reviving Hero)))] Equal to 0
Actions
Hero - Modify Strength of (Reviving Hero): Set to Hero_Stats

Adjust Stats if level
Events
Unit - A unit Gains a level
Conditions
Chimaera_Shift_Timer[(Player number of (Owner of (Triggering unit)))] Greater than 0
(Level of Chimaera Shift for (Triggering unit)) Greater than 0
Actions
Set Hero_Stats = (Hero_Stats + [your heroes strength gain/level])

this should correct the heroes stats if the hero dies or levels while under the effect of the spell
 

Attachments

  • Help Map for Chimaera Shift.w3x
    19.6 KB · Views: 249

GFreak45

I didnt slap you, i high 5'd your face.
Reaction score
130
the problem i saw with the posts up there is that attributes are integers (whole value) where as any time u divide a number by another number u are more than likely going to get a number that either isnt real (continuing forever) or a real value that is between integers, my triggers subtract that extra over shoot of the nearest whole number... like if a unit takes 20 damage instead of dividing it by 19 and getting 1.0526... continuing forever... it subtracts that 0.0526 continuing number from the whole number so that it can be added to stats, otherwise it wont add it to the units strength propperly :)
 

Bogrim

y hello thar
Reaction score
154
Does your method not do the exact same thing? Sure, it's far more economical when no damage is being taken, but consider a situation where you're taking hits from 6 different units, once every second. You're essentially creating 360 integers to store the bonuses you granted, while I'm still using my constant 60 integers...
This would be a valid concern if we are talking about a unit that can take such large amounts of damage, but most likely the damage in your example would mean the hero dies since 60*19 = 1140 damage taken, making it the absolute peak in the trigger and assuming all the damage taken are constant small hits while hero units usually die from larger hits. Furthermore, in your trigger it's not a peak but a limit.

This isn't a contest between triggers though. The idea here is that the more triggers and more variables you have to use to achieve the same result, the worse your efficiency becomes. As a map creator, you would want to consider efficiency for the smoothest performance. However, both triggers work and get the job done and it's a clever method you though of and you could implement it just fine. I only thought it was odd that you were using GDD_DamagedUnit over Triggering Unit, and that it would be beneficial for you to understand how local variables work for more effective trigger work.

where as any time u divide a number by another number u are more than likely going to get a number that either isnt real (continuing forever)
That's simply not how the Warcraft 3 engine works. Though real numbers are far larger than they appear in the trigger editor, there is still a cap on the number of decimals. Using a real variable to store damage simply adds accuracy, it does not affect performance.
 

GFreak45

I didnt slap you, i high 5'd your face.
Reaction score
130
then is there even a use for the action: Math - mod? and the real variable to store damage was still used, but after divided by 19 it was changed into an integer to provide stat bonus accuracy...
 

Cookie!

Member
Reaction score
0
This isn't a contest between triggers though. The idea here is that the more triggers and more variables you have to use to achieve the same result, the worse your efficiency becomes. As a map creator, you would want to consider efficiency for the smoothest performance. However, both triggers work and get the job done and it's a clever method you though of and you could implement it just fine. I only thought it was odd that you were using GDD_DamagedUnit over Triggering Unit, and that it would be beneficial for you to understand how local variables work for more effective trigger work.

I do apologize if I sounded a bit impolite... Of course, it's not a contest :p.
 

DarkBELL

New Member
Reaction score
1
Oh, guys, Thanks a lot for the help

Now, I just need to check all the resources you gave me

Thank you very much guys, I'm gonna cry
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top