- Setup a leaderboard to keep track of a players tributes and fame
- Create melee units for the players participating
- Have player and computer share vision
- Transfer ownership of units to the respective computer when tributes are given, and update the leaderboard
- Update the leaderboard when tributes die by removing their value from the tributes
- Update fame based on current tribute score at regular intervals
- Have player and computer pair share upgrades
- Have player and computer pair share supplies
Perhaps here I should include a generic disclaimer: The methods used below to accomplish the tasks mentioned above are simply the ones I tried. They are in no way the best or most efficient, I cannot even guaranty that they work (although I hope they do). Any suggestions on how to improve them, or constructive feedback as to why one way may be better than another is appreciated, just please don't complain that it sucks...because you've been warned!
Leaderboard, Melee, and Relations
I'll start with the leaderboard. I suspect there are fancy ways to use dialogues to add parts to the UI and make a very smart looking leaderboard, but I will start by using the built in functions. First, Initialization:
- Leaderboard - Create a leaderboard with 3 columns and 7 rows, with the name "Tribute Army Value", and using (100%, 100%, 100%) color.
I think I'd like to change it later to be the actual number of people playing to limit its size, but for now let's just get it up and working. Now I'll name my leaderboard for future use:
- Variable - Set Leaderboard = (Last created leaderboard)
Where Leaderboard is a variable:
- Leaderboard = No Leaderboard <Leaderboard>
Now that Leaderboard has been assigned the value of the last created leaderboard, I can name the columns:
- Leaderboard - Set (Last created leaderboard) item text at column 1 and row Header to "Player"
- Leaderboard - Set (Last created leaderboard) item text at column 2 and row Header to "Tributes"
- Leaderboard - Set (Last created leaderboard) item text at column 3 and row Header to "Favor"
Now to set up the rows of the leaderboard. To do this, I'll simply iterate through the number of possible players, and catch the ones with status Playing. Once I've determined that they are playing, I'll name and color the row accordingly. Once the leaderboard is set up, I'll give the player melee units so they can begin training tributes. Finally, I set the relationship between the player and the computer 8 players larger. This is where the limit of 7 players comes in, as player 16 is not usable. Here is the code:
General - For each integer i from 1 to 7 with increment 1, do (Actions)
Actions
General - If (Conditions) then do (Actions) else do (Actions)
If
(Status of player i) == Playing
Then
Leaderboard - Set Leaderboard item text at column 1 and row i to (Name of player i)
Leaderboard - Set (Last created leaderboard) item text color at column 1 and row i to (Color((Current player i color)))
Leaderboard - Set (Last created leaderboard) item text at column 2 and row i to "0"
Leaderboard - Set (Last created leaderboard) item text at column 3 and row i to "0"
Melee - Create (Race of player i) melee starting units for player i at (Start location of player i)
Player - Make player i and player {i+8} treat each other as Ally With Shared Vision And Pushable
Else
Giving Tributes
The idea behind tributes is relatively simple. Since I am looking to make a macro-only game mode, any and all micro should be done by the computer. Micro is done through the interaction of one player with another, so all player-player interactions are to be controlled by the computer AI. Essentially the players simply train heroes to fight in their name, without any orders from the player. As for the victory conditions, the invisible spectators enjoy watching combat, and will look to the players with the largest army competing. The metric for army size will be the sum of minerals and gas costs of all units participating. Therefore, there are two main things which must happen when giving tributes:
- The resource cost of the tributed unit must be added to the players score
- Control of the unit must be set to the computer player and the unit must attempt to hold the center region
The first is simple. It will be done with the use of an array:
- Tribute Army Value = 0 <Integer[9]>
Give Tribute
Events
Unit - Any Unit Enters (Region named "ComputerControl")
Local Variables
owner = (Owner of (Triggering unit)) <Integer>
With the actions accomplishing the above two tasks. The first task is accomplished with:
- Variable - Modify Tribute Army Value[owner]: + (Sum - Minerals, Vespene cost of (Unit type of (Triggering unit)))
- Leaderboard - Set Leaderboard item text at column 2 and row owner to (Text(Tribute Army Value[(Triggering player)]))
- Leaderboard - Sort Leaderboard by column 2, in Descending order, with priority 1
- Unit - Change ownership of (Triggering unit) to player {owner+8} and Retain Color
- Unit - Share Vision of (Triggering unit) with Player owner
- AI - Add (Triggering unit) to the next attack wave for player {owner+8}
- AI - Set the target for player {owner+8} attack (or defense) waves to be the region Hill with replace behavior Replace Never.
- AI - Send the attack wave from player {owner+8} to attack in 0 seconds and Don't Wait
Tribute Dies
The death of a tribute is pretty straight forward. First, set the trigger for when a unit dies, with the condition that the owner of that unit is a computer player. Then, remove the points that unit gives from the players tributes score, and we are done! It looks something like this:
Tribute Dies
Events
Unit - Any Unit dies
Local Variables
owner = {(Owner of (Triggering unit))-8} <Integer>
Conditions
(Owner of (Triggering unit)) >= 9
Actions
Variable - Modify Tribute Army Value[owner]: - (Sum - Minerals, Vespene cost of (Unit type of (Triggering unit)))
Leaderboard - Set Leaderboard item text at column 2 and row owner to (Text(Tribute Army Value[owner]))
Tribute Dies
Events
Unit - Any Unit dies
Local Variables
owner = {(Owner of (Triggering unit))-8} <Integer>
Conditions
(Owner of (Triggering unit)) >= 9
Actions
Variable - Modify Tribute Army Value[owner]: - (Sum - Minerals, Vespene cost of (Unit type of (Triggering unit)))
Leaderboard - Set Leaderboard item text at column 2 and row owner to (Text(Tribute Army Value[owner]))
Fame
Now that the very basic mechanics are in place, and the tribute score is properly generated, we can look at the metric for victory: Fame. The idea here is to have some number which gives an overview of how often a player has been the 'King of the Hill'. I suppose traditionally it would be the person who is in control of the top most point of the hill, but here we will take a more continuous approach and look at who has the greatest army in the hill region. That is where the tribute score comes in. My idea is rather simple: determine what fraction of the total score is controlled by a given player, and move their Fame score in that direction. I imagine the movement would be large if the two scores differ greatly, and smaller if the two scores are similar. Therefore, Fame will be a floating number from 0 to 1, and will be displayed on the leaderboard as a percent. Before I discuss the trigger, here are a few necessary variables:
- Aggregate Rate = 0.001 <Real>
- Aggregate Value = 0.0 <Real[9]>
The Aggregate Rate is multiplied into the difference between the current ratio and the Aggregate Value (Fame). The trigger that manages Fame is as follows (with some comments thrown in there):
iterate
Events
Timer - Every 1.0 seconds of Game Time
Local Variables
total = 0 <Integer>
Percent = 0.0 <Real>
Conditions
That is the setup. Now for the actions, we need to do a few things. First: determine the total army value on the hill:
Actions
General - Pick each integer from 1 to 7, and do (Actions)
Actions
General - If (Conditions) then do (Actions) else do (Actions)
If
Tribute Army Value[(Picked integer)] > 0
Then
Variable - Modify total: + Tribute Army Value[(Picked integer)]
Else
Now that we have the total determined, we can determine the Percent of the total each player has, and modify their Aggregate Value (Fame) accordingly (note the condition used to eliminate any divide by zero errors):
General - Pick each integer from 1 to 7, and do (Actions)
Actions
General - If (Conditions) then do (Actions) else do (Actions)
If
(Status of player (Picked integer)) == Playing
Then
General - If (Conditions) then do (Actions) else do (Actions)
If
(Tribute Army Value[(Picked integer)] + Aggregate Value[(Picked integer)]) != 0
Then
Variable - Set Percent = {(Real(Tribute Army Value[(Picked integer)]))/(Real(total))}
Variable - Modify Aggregate Value[(Picked integer)]: + {(Percent-Aggregate Value[(Picked integer)])/(Percent+Aggregate Value[(Picked integer)])*Aggregate Rate}
Else
Leaderboard - Set Leaderboard item text at column 2 and row (Picked integer) to (Text(Tribute Army Value[(Picked integer)]))
Leaderboard - Set Leaderboard item text at column 3 and row (Picked integer) to (Text(Aggregate Value[(Picked integer)]) with Percent decimal places (Do Not use delimiters, precision limits: 0 to 0))
Else
One more thing we can stick in this trigger is a notification of a player dropping from the game. Note that none of their units are set to be destroyed, they must be defeated on the hill. However, the above trigger which changes the Fate value does not calculate for dropped players. In that way, a record of their Fame when they dropped is preserved.
General - If (Conditions) then do (Actions) else do (Actions)
If
(Status of player (Picked integer)) == Left The Game
Then
Leaderboard - Set Leaderboard item text at column 1 and row (Picked integer) to "Dropped..."
Else
I have one more trigger for calculating Fame, and that is a slow increase of the Aggregate Rate. This is to help prevent games from going on indefinitely. This looks like:
Aggregate Rate Increase
Events
Timer - Every 150.0 seconds of Game Time
Local Variables
Conditions
Actions
Variable - Modify Aggregate Rate: + 0.001
The balancing of the Fate will probably take some time, to make sure games are long enough that players can have come-from-behind victories, but not so long as to lose appeal. The trigger which generates the victory condition itself will still need to be made, but for testing purposes I have neglected to write it (when I play solo, the game will be over before it begins).
Learning to Share
The final part is setting up the sharing between the player and the computer. There are two things which need to be shared:
- Upgrades
- Supplies
The upgrades are simple, and accomplished with the following trigger:
Upgrade
Events
Unit - Any Unit research progress is Completed
Local Variables
Conditions
Actions
Tech Tree - Set (Triggering progress upgrade) upgrade level to ((Triggering progress upgrade) count for player (Triggering player), counting Complete) for player {(Triggering player)+8}
As for supplies, I spent a good amount of time looking for an equally simple approach. I was unsuccessful, and forced to come up with a more complicated approach. I will share this approach in the next post!


