• 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!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Trigger] Random passive bonus system

Level 7
Joined
Feb 22, 2009
Messages
260
These are the passives. I call them Titan's gift in general.

What I am planning to do is creating a system where each trained unit will receive 1 random combat Titan's gift, 1 random defense Titan's gift and 1 random utility Titan's gift.

This system of gifts is applied to a custom melee map so any and every player can benefit from this system as long as they play as Human. The gift system is supposed to replace the attack and armour upgrade.

There are 3 upgrades that affects the probability of obtain a gift as well as the level of said gift.

These 3 upgrades are Gift of War, Gift of Protection and Gift of Fortune which correspond to Titan's gift of Combat, Defense and Utility.


  • Titan Gift setup
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • Set GiftCombat[1] = Frost Attack (Titan - Combat)
      • Set GiftCombat[2] = Feedback (Titan - Combat)
      • Set GiftCombat[3] = Liquid Fire (Titan - Combat)
      • Set GiftCombat[4] = Haste (Titan - Combat)
      • Set GiftCombat[5] = Titan Strength (Titan - Combat)
      • Set GiftCombat[6] = Improved Range (Titan - Combat)
      • Set GiftCombat[7] = Anti Air (Titan - Combat)
      • -------- =================== --------
      • Set GiftDef[1] = Arrow Block (Titan - Defense)
      • Set GiftDef[2] = Reincarnation (Titan - Defense)
      • Set GiftDef[3] = Spell Guard (Titan - Defense)
      • Set GiftDef[4] = Spiked Shell (Titan - Defense)
      • Set GiftDef[5] = Titan Protection (Titan - Defense)
      • -------- =================== --------
      • Set GiftUtility[1] = Ensnare (Autocast) (Titan - Utility)
      • Set GiftUtility[2] = Liquid Fire (Titan - Combat)
      • Set GiftUtility[3] = Pillage (Titan - Utility)
      • Set GiftUtility[4] = Vigor (Titan - Utility)
      • Set GiftUtility[5] = Titan Reactor (Titan - Utility)
At lv0 or no upgrade at all, the unit has no chance of receiving a gift.
At lv 1, trained units has 40% chance of receiving a gift of corresponding type.
Lv2, trained units has 60% chance of receiving a gift of corresponding type. Said gift has a 25% of being lv2 instead of lv 1.
Lv3, trained units has 80% chance of receiving a gift of corresponding type. Said gift has a 35% of being lv2 and 25% of being lv 3.



To illustrate, if a player has Gift of War researched to lv3 and Gift of Fortune researched to lv1, a footman for example has 80% of receiving a combat passive (can be Frost Attack or Feedback, etc.) and 40% of receiving an Utility passive (Ensnare or Liquid of Fire, etc.). Because the player has Gift of War lv3, the combat passive (said Feedback for example) has 35% of being lv2 and 25% of being lv3.


Of course, I also want certain passive can only be given to certain types of unit. For example, The Improved Range and Anti air Combat passive should only be considered when the trained unit is a range unit like Riflemen. Meanwhile, only melee units like Knight and Footman should be allowed to randomise Orb effect passive like Feedback and Frost Attack. Meanwhile, only spellcasters (or units with mana) should be able to receive Titan Reactor (a passive that increases mana and mana regen).


How do I create a dynamic system like this?
 
Level 29
Joined
Sep 26, 2009
Messages
2,595
I believe this would be easier to do/understand in jass or lua, since you can create your own functions and structs there. In GUI this may be a bit more of a headache to do.

Let's start with the last thing you wrote:
Of course, I also want certain passive can only be given to certain types of unit. For example, The Improved Range and Anti air Combat passive should only be considered when the trained unit is a range unit like Riflemen
I think for this to work you will need to manually specify which unit type is melee, which is caster and which is ranged. One way would be to use something like hashtable where key is the unit's type and value is a constant that would tell you which of the three types it is. Another way would be to use hidden abilities that serve to categorize them. So you would create an ability (i.e. using Channel ability that is now shown in UI) called 'Ranged Unit' and give this ability to all units you consider ranged.

I don't think there is better way to determine unit's category, because other solutions (like just checking attack type) may be limiting. Let's take as an example the Spellbreaker unit - what kind of unit is it? One cannot really say if it is ranged or melee, since it uses projectiles but at medium range. It also has enough HP/armor to combat on front lines. It also has mana and spells like a spell caster.

---
Next, from what I understand, all three categories of the boons (combat, defense, utility) use same system, right? So for example all three have that 40/60/80% chance depending on their respective tech levels.

What you can do here is create a GUI trigger that does not have any event/condition as you will be running "manually" that trigger from other triggers using "Trigger - Run Trigger" action. This trigger would be used to determine what level of boon should newly trained unit get.

Inputs (global variables) used by this trigger would be:
  • tech/research to check (Gift of War/Protection/Fortune)
  • player whose tech will be checked/owner of that newly trained unit
Output (global variable) would be integer representing the level of boon to give that unit.
To determine chance for each level of boon, you can do the following:
  • get the level of tech for player. I'll refer to that level as "tech_lvl"
  • set boon_lvl (the output variable) to zero.
  • calculate chance for boon of level 1/2/3 to occur
  • pick random integer number between 1 and 100, compare if picked number is <= boon chance
  • if yes, set boon_lvl to appropriate value.

You could do this using various If/Else statements, but you can also leverage integer arithmetic to do this. Here is pseudo code for calculating chance for each boon level:
JASS:
set tech_lvl = level of tech for player
set boon_lvl = 0 //the default state if no boon procc'd

set boon_chances[1] = ((tech_lvl + 2) / 3) * (40 + (tech_lvl - 1) * 20) // calculates 40/60/80% chance for lvl 1 boon
set boon_chances[2] = (tech_lvl / 2) * (25 + 10 * (tech_lvl / 3))       // calculates 0/25/35% chance for lvl 2 boon
set boon_chances[3] = (tech_lvl / 3) * 25                               // calculates 0/0/25% chance for lvl 3 boon

for int x from 1 to 3:
   if (random_integer between 1 and 100) <= boon_chances[x] then:
       set boon_lvl = x
The above is easily achievable in GUI, I am just writing this without WE right now, so pseudo code will have to be enough :D
The trick is using integer arithmetic which is used in various ways to have one member of the multiplication be zero unless specified tech_lvl was researched.

This trigger would have to be called 3 times - once for each tech (Gift of War/Protection/Fortuned). After each run of the trigger you would need to check if value of boon_lvl is greater than zero - if so, you need to give unit a boon from the specified category and set its level to match the boon_lvl value.

---
Finally, you also wrote that boons can be applied only to certain type of unit. At the start of this post, I wrote about how you should use for example abilities to determine unit's category type (ranged, melee, magic). Once you know the type, the issue is how to determine which subset of boons can be applied to the unit.
I think the most straightforward way to do this is to organize boons by their category. For example like this:
  • -------- these are for melee only --------
  • Set GiftCombat[1] = Frost Attack (Titan - Combat)
  • Set GiftCombat[2] = Feedback (Titan - Combat)
  • Set GiftCombat[3] = Liquid Fire (Titan - Combat)
  • Set GiftCombat[4] = Haste (Titan - Combat)
  • -------- these are for range only --------
  • Set GiftCombat[5] = Titan Strength (Titan - Combat)
  • Set GiftCombat[6] = Improved Range (Titan - Combat)
  • -------- these are for magic only --------
  • Set GiftCombat[7] = Anti Air (Titan - Combat)
All of these are GiftCombat, but now we can say that indices 1-4 are for melee, 5-6 are for ranged and 7-7 are for casters.
I would then store these min/max indices in hashtable, using unit's category as key.
Then you could use pseudo code below to pick random boon for a unit's category:
JASS:
set unitCategory = however you would determine the category ranged/melee/caster
set min = load 0 of unitCategory from hashtable
set max = load 1 of unitCategory from hashtable
set pickedIndex = random_integer between min and max
set combatAbil = GiftCombat[pickedIndex]
Instead of 0 and 1 as subkeys, you could use string keys like "CombatMin" and CombatMax", "DefMin", "DefMax", "UtilMin", "UtilMax"

A GUI trigger would look something like this:
JASS:
Events
   Unit has been trained
Conditions
Actions
   Set player = (Triggering player)
   Set unitCategory = (however you determine if melee/ranged/caster)
   --- ---------------------- ---
   Set tech = Gift of War
   Trigger - Run Trigger "Determine boon level"
   if (boon_lvl > 0)
      Set keyMin = "CombatMin"
      Set keyMax = "CombatMax"
      Trigger - Run Trigger "Add boon ability"
  --- ---------------------- ---
   Set tech = Gift of Protection
   Trigger - Run Trigger "Determine boon level"
   if (boon_lvl > 0)
      Set keyMin = "DefMin"
      Set keyMax = "DefMax"
      Trigger - Run Trigger "Add boon ability"
  --- ---------------------- ---
   Set tech = Gift of Fortune
   Trigger - Run Trigger "Determine boon level"
   if (boon_lvl > 0)
      Set keyMin = "UtilMin"
      Set keyMax = "UtilMax"
      Trigger - Run Trigger "Add boon ability"
The two other triggers called in this pseudo code ("Determine boon level" and "Add boon ability") would be GUI triggers that do what I described earlier in the post.
 
Level 7
Joined
Feb 22, 2009
Messages
260
I believe this would be easier to do/understand in jass or lua, since you can create your own functions and structs there. In GUI this may be a bit more of a headache to do.

Let's start with the last thing you wrote:

I think for this to work you will need to manually specify which unit type is melee, which is caster and which is ranged. One way would be to use something like hashtable where key is the unit's type and value is a constant that would tell you which of the three types it is. Another way would be to use hidden abilities that serve to categorize them. So you would create an ability (i.e. using Channel ability that is now shown in UI) called 'Ranged Unit' and give this ability to all units you consider ranged.

I don't think there is better way to determine unit's category, because other solutions (like just checking attack type) may be limiting. Let's take as an example the Spellbreaker unit - what kind of unit is it? One cannot really say if it is ranged or melee, since it uses projectiles but at medium range. It also has enough HP/armor to combat on front lines. It also has mana and spells like a spell caster.

---
Next, from what I understand, all three categories of the boons (combat, defense, utility) use same system, right? So for example all three have that 40/60/80% chance depending on their respective tech levels.

What you can do here is create a GUI trigger that does not have any event/condition as you will be running "manually" that trigger from other triggers using "Trigger - Run Trigger" action. This trigger would be used to determine what level of boon should newly trained unit get.

Inputs (global variables) used by this trigger would be:
  • tech/research to check (Gift of War/Protection/Fortune)
  • player whose tech will be checked/owner of that newly trained unit
Output (global variable) would be integer representing the level of boon to give that unit.
To determine chance for each level of boon, you can do the following:
  • get the level of tech for player. I'll refer to that level as "tech_lvl"
  • set boon_lvl (the output variable) to zero.
  • calculate chance for boon of level 1/2/3 to occur
  • pick random integer number between 1 and 100, compare if picked number is <= boon chance
  • if yes, set boon_lvl to appropriate value.

You could do this using various If/Else statements, but you can also leverage integer arithmetic to do this. Here is pseudo code for calculating chance for each boon level:
JASS:
set tech_lvl = level of tech for player
set boon_lvl = 0 //the default state if no boon procc'd

set boon_chances[1] = ((tech_lvl + 2) / 3) * (40 + (tech_lvl - 1) * 20) // calculates 40/60/80% chance for lvl 1 boon
set boon_chances[2] = (tech_lvl / 2) * (25 + 10 * (tech_lvl / 3))       // calculates 0/25/35% chance for lvl 2 boon
set boon_chances[3] = (tech_lvl / 3) * 25                               // calculates 0/0/25% chance for lvl 3 boon

for int x from 1 to 3:
   if (random_integer between 1 and 100) <= boon_chances[x] then:
       set boon_lvl = x
The above is easily achievable in GUI, I am just writing this without WE right now, so pseudo code will have to be enough :D
The trick is using integer arithmetic which is used in various ways to have one member of the multiplication be zero unless specified tech_lvl was researched.

This trigger would have to be called 3 times - once for each tech (Gift of War/Protection/Fortuned). After each run of the trigger you would need to check if value of boon_lvl is greater than zero - if so, you need to give unit a boon from the specified category and set its level to match the boon_lvl value.

---
Finally, you also wrote that boons can be applied only to certain type of unit. At the start of this post, I wrote about how you should use for example abilities to determine unit's category type (ranged, melee, magic). Once you know the type, the issue is how to determine which subset of boons can be applied to the unit.
I think the most straightforward way to do this is to organize boons by their category. For example like this:
  • -------- these are for melee only --------
  • Set GiftCombat[1] = Frost Attack (Titan - Combat)
  • Set GiftCombat[2] = Feedback (Titan - Combat)
  • Set GiftCombat[3] = Liquid Fire (Titan - Combat)
  • Set GiftCombat[4] = Haste (Titan - Combat)
  • -------- these are for range only --------
  • Set GiftCombat[5] = Titan Strength (Titan - Combat)
  • Set GiftCombat[6] = Improved Range (Titan - Combat)
  • -------- these are for magic only --------
  • Set GiftCombat[7] = Anti Air (Titan - Combat)
All of these are GiftCombat, but now we can say that indices 1-4 are for melee, 5-6 are for ranged and 7-7 are for casters.
I would then store these min/max indices in hashtable, using unit's category as key.
Then you could use pseudo code below to pick random boon for a unit's category:
JASS:
set unitCategory = however you would determine the category ranged/melee/caster
set min = load 0 of unitCategory from hashtable
set max = load 1 of unitCategory from hashtable
set pickedIndex = random_integer between min and max
set combatAbil = GiftCombat[pickedIndex]
Instead of 0 and 1 as subkeys, you could use string keys like "CombatMin" and CombatMax", "DefMin", "DefMax", "UtilMin", "UtilMax"

A GUI trigger would look something like this:
JASS:
Events
   Unit has been trained
Conditions
Actions
   Set player = (Triggering player)
   Set unitCategory = (however you determine if melee/ranged/caster)
   --- ---------------------- ---
   Set tech = Gift of War
   Trigger - Run Trigger "Determine boon level"
   if (boon_lvl > 0)
      Set keyMin = "CombatMin"
      Set keyMax = "CombatMax"
      Trigger - Run Trigger "Add boon ability"
  --- ---------------------- ---
   Set tech = Gift of Protection
   Trigger - Run Trigger "Determine boon level"
   if (boon_lvl > 0)
      Set keyMin = "DefMin"
      Set keyMax = "DefMax"
      Trigger - Run Trigger "Add boon ability"
  --- ---------------------- ---
   Set tech = Gift of Fortune
   Trigger - Run Trigger "Determine boon level"
   if (boon_lvl > 0)
      Set keyMin = "UtilMin"
      Set keyMax = "UtilMax"
      Trigger - Run Trigger "Add boon ability"
The two other triggers called in this pseudo code ("Determine boon level" and "Add boon ability") would be GUI triggers that do what I described earlier in the post.
Is there any risk of a bug happening when 9 footmen are trained at the same time?
 
Top