Repository navigation
Game logic
How Legion TD 2 computes the numbers it shows or pays and the choices it makes for players, as
of game version 26.10. The power score and the MVP score come from MvpScore in Natives.dll;
the other rules come from the map's rules in server_triggers.dll and the map's data files.
ProLeak's local server plays each of them as described here. The values the
game keeps in its code rather than its data files are read from game version
26.10a by tools/GameTables.
Contents
- Power score
- Shutdown bounty
- Leak gold
- Target choice
- Purchase queues
- Recommended value
- MVP score
- Auto Power send
- Proc chances
- Mastermind draws
- Announcements
- Sudden death
The power score drives the scoreboard's stack rank, the shutdown bounty and the team gold split. The game takes it at the start of a wave and again as its rewards are given.
PowerScore = NetWorth + PowerScoreValueOffset
- IncomeGainedThisWave
+ 1.25 * (Mythium + MythiumSentForNextWave)
+ IncomeMultiplier
+ ExtraPowerScore + ExtraPowerScoreFromMastermind + ExtraPowerScoreFromFighters
+ ExtraPowerScoreOnWave[wave]
+ 25 # wave 1 only
+ 0.08 * Gold # wave 2 only
+ PlaystyleBias
+ ClassicIncomeBias-
NetWorthis the value of the player's fighters, plus gold in hand, gold spent on workers andExtraNetWorth. -
IncomeGainedThisWaveis the income now, less the income the player had as the last wave spawned. It is 0 on wave 1 and during sudden death. -
MythiumSentForNextWaveis the mythium already sent to the next wave (on wave 21, the mythium sent during wave 21's battle phase). -
IncomeMultiplierweighs the income held as the last wave spawned (I) by the waves left to earn it, withwthe wave number:I * (3.49 + 1.38 * (1 - e^(0.06 * (w + 1)))) # 1v1 I * (3.49 + 0.403 * (1 - e^(0.108 * (w + 1)))) # 4v4 full I * (3.49 + 0.8 * (1 - e^(0.08 * (w + 1)))) # otherwise
"4v4 full" means all eight seats are playing; a 2v2 or an uneven game takes the last line.
-
PlaystyleBiascovers the Mastermind playstyles whose income changes at wave 10. Withvthe wave number (plus one while the wave's rewards are being given), up tov= 11, mapped linearly fromv= 2 tov= 11 and held at both ends:Playstyle At v = 2 At v = 11 Castle +15 +150 Cartel -13 -130 Champion -4 -42 -
ClassicIncomeBiastakes off the matchmaking income bonus (B), only whileIncomeMultiplieris above 0.kis 2 in classic special mode 9 and 0 otherwise:-((3.49 + 0.403 * (1 - e^(0.108 * (w + 1)))) * B + B * (w - k))
The factor that weighs I in IncomeMultiplier, by wave (orange 1v1, blue 4v4 full, green
otherwise):
%%{init: {"themeVariables": {"xyChart": {"plotColorPalette": "#e6b44c, #4c9be6, #6cc24a"}}}}%%
xychart-beta
x-axis "Wave" [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
y-axis "Factor" -0.5 --> 3.5
line [3.31, 3.12, 2.89, 2.64, 2.36, 2.03, 1.67, 1.27, 0.81, 0.29, -0.30]
line [3.39, 3.27, 3.12, 2.94, 2.71, 2.42, 2.07, 1.62, 1.08, 0.40, -0.44]
line [3.35, 3.19, 3.00, 2.77, 2.51, 2.20, 1.84, 1.41, 0.91, 0.33, -0.36]
When a player's lane leaks, the other team is paid that player's shutdown bounty, at most once per player per wave. A player has a bounty only when their team is ahead.
The bounty of a player p on a wave, from the power scores of that wave:
flowchart TD
A[Power scores of the wave] --> B[Average of each team]
B --> C{Higher average}
C -- ahead --> D["Pot: |avgLeft - avgRight| / 5.75 * players"]
C -- behind --> X[No bounty]
D --> E["Weight: max(0, PowerScore - avgBehind)"]
E --> F[Pot times the share of the weights, down to 25]
-
Average the power scores of the playing players of each team (seats 1 to 4, 5 to 8). The team whose average is higher (left on a tie) is ahead; the other team's players have no bounty. Neither team has any when a team has nobody playing, in co-op games and on wave 1.
-
The ahead team's pot is
|avgLeft - avgRight| / 5.75times its number of playing players. -
Each player of the ahead team weighs
max(0, PowerScore - avgBehind), whereavgBehindis the other team's average. If the weights add up to 0, nobody has a bounty. -
pgets the pot times their share of the weights, rounded down to a multiple of 25:bounty = 25 * floor(pot * weight[p] / sum(weights) / 25)
Paying it, each player of the other team receives
round(bounty * receivingTeamSize * TeamGoldMultiplier(receiver))The team gold multiplier splits team gold by power score. It is taken again each time a wave
finishes spawning (0.25 until the first one). On the classic map a team of 3 takes 0.33 each, a
team of 2 takes 0.5 each and a player alone takes 1. A team of 4 uses
s = clamp(lowestPowerScore / sumOfTeamPowerScores, 0.1, 1):
| Player | Classic map | 2v2 map |
|---|---|---|
| Richest | 5/3 * s - 1/6 |
5 * s - 2 |
| Poorest | 1.5 - 5 * s |
3 - 5 * s |
| Others | 5/3 * s - 1/6 |
1 |
On the classic map the richest and poorest shares meet at 0.25 as the team evens out (orange richest, blue poorest):
%%{init: {"themeVariables": {"xyChart": {"plotColorPalette": "#e6b44c, #4c9be6"}}}}%%
xychart-beta
x-axis "s" [0.10, 0.13, 0.16, 0.19, 0.22, 0.25]
y-axis "Share" 0 --> 1
line [0.00, 0.05, 0.10, 0.15, 0.20, 0.25]
line [1.00, 0.85, 0.70, 0.55, 0.40, 0.25]
On the 2v2 map, s is clamped from 0.4 instead of 0.1, and a player alone takes 1. Where two
players tie, the first one checked takes the richest or poorest share.
The attacker of the player shut down earns a shutdown factor of paid / 1.1^(wave - 1), where
paid is the total gold the other team received. The MVP score uses the sum of these factors
without the last wave's.
When a lane leaks, each of its wave units still alive pays out in its own way as it dies. The wave's row in the map data sets the shares:
| Wave | Leaker's share back | The same, one against one | Catch | Hourglass |
|---|---|---|---|---|
| 1 | 0.75 | 0.90 | 0.10 | 0.20 |
| 5 | 0.66 | 0.76 | 0.10 | 0.34 |
| 10 | 0.18 | 0.36 | 0.10 | 0.94 |
| 11 | 0.05 | 0.25 | 0.10 | 1.12 |
| 15 | 0.05 | 0.05 | 0.10 | 2.04 |
| 21 | 0.05 | 0.05 | 0.10 | 4.02 |
The fields are goldbountyleakleakerpercent, leakpercent1v1, goldbountyleakkillpercent
and goldbountyleakhgpercent, and every wave has its own values; the table shows some.
%%{init: {"themeVariables": {"xyChart": {"plotColorPalette": "#e6b44c"}}}}%%
xychart-beta
title "Hourglass share by wave"
x-axis "Wave" [1, 5, 10, 11, 15, 21]
y-axis "Share of the bounty" 0 --> 4.5
bar [0.20, 0.34, 0.94, 1.12, 2.04, 4.02]
Where the bounty of a leaked unit goes as it dies:
flowchart LR
U["Leaked unit dies (bounty B)"] --> H["Other team: round(B * hourglass)"]
U --> L["Leaker: round(B * share)"]
U --> K{Killed by}
K -- a unit --> KU["Killer: B * catch"]
K -- a king --> KK["King's team: round(0.10 * B)"]
As a leaked unit with bounty B dies:
-
The other team shares the hourglass gold,
round(B * hourglass)(half of that one against one). Each of its players takes the gold times their team gold multiplier (see Shutdown bounty) times a weight, rounded. The leaker's attacker takes at least 1.Teams Leaker's attacker Others 4 against 4 2.68 0.44 3 against 3 1.98 0.51 2 against 2 1.34 0.66 Any other 1 1 -
The leaker gets
round(B * share)back. A player whose worker score is below the game's average gets more:share = min(1, leakerShare + 2.5 * (1 - w)) # when w < 1
wis the player's worker score over the average of every player's. The worker score is the power score, plus 50 for each worker, plusExtraNetWorth, taken with the power scores. -
The unit's killer earns its bounty times the catch share. When a king kills it,
round(0.10 * B)goes to the king's team instead: each player takes it times their team gold multiplier and the "Others" weight above, and the leaker's share back is added to the leaker's part.
Waves 10 and 20 hold a boss with a fixed part C of its bounty (goldbountybossconstfactor: 25
and 50). With L the boss's share of life left as it leaked, the hourglass gold and the share
back use C + L * (B - C) in place of B.
A unit looks for a target every 0.5 seconds among the enemies within 1.2 times its radius plus its acquisition range, and keeps its target in between. Each candidate gets a score, and the lowest wins. A game mode can replace the choice.
A king (or any other building) scores a target by the hits it needs to kill it:
score = (100 * hits + 100 * life / maxLife) / threat
+ 1000 + distance^2 # out of range onlyhits is ceil(life / attack), with the king's upgrades in its attack. With Giant Slayer each
hit counts attack + 0.24 * lifeLeft. threat is the target's effectivethreat; a merged
mercenary of Giga Mercs counts once for each mercenary it stands for.
Any other unit adds these terms:
| Term | Value |
|---|---|
| Dead target | 100000 |
| Out of range | 10000 + 10 * distance |
| Health | 10000 for a target out of range or unhurt. Otherwise, for a wave unit or a mercenary, 10000 - 2 * missing / typeLife; for a fighter, 9000 - 5000 * missing / typeLife. |
| Distance to the cave | Wave units and mercenaries only, for a target in range: how far the target's fighter (or the fighter that summoned it) stands from the top of its lane, up to 20. A Great Boar or Red Eyes counts 14 further, a Sea Serpent or Deepcoiler 6.5 nearer. |
| Back of the send | For a mercenary target in range whose spawnbias is 0.75 or more: 5 up to wave 3, falling to 0 at wave 8. |
| Tie break | For a target in range: 0.01 * distance when the two units touch (less than 1.05 apart beyond both radii), otherwise 10 * distance. A Sea Serpent or Deepcoiler target counts at least 60. |
missing is the type's base life less the target's life now. A fighter therefore goes for the
most hurt enemy in range. A wave unit weighs a fighter's distance to the top of the lane (up to
20) against ten times its own distance to that fighter.
A shift-click, or a click without enough mythium or gold, queues a mercenary, a worker or a king upgrade. The server tries the queues when the resources change, at these moments only:
- Mercenaries: in the build phase, when mythium rises past a multiple of 20. The dearest type goes first, and the queue stops at the first one it cannot pay for.
- King upgrades: in the build phase, when mythium changes and is 20 or more. The dearest goes first, as many as mythium pays for.
- Workers: when gold crosses a multiple of 50, either way. One of each queued kind is trained, the dearest first, as gold allows.
A mythium gain that ends between 410 and 3000 (both left out) tries neither mercenaries nor king upgrades. As the wave spawns, the mercenary queue sends what mythium pays for (the dearest first, passing over any it cannot pay for), the king upgrades are tried once more, and both queues empty. The worker queue stays from one wave to the next.
After each wave's rewards, and at the end of each sudden death wave, the server sets each player's extra recommended value. The HUD adds it to the next wave's own recommended value. It is what the player's attacker can send next:
extra = 1.5 * (M + T * r * 0.1 * W) + 0.1 * G-
Mis the attacker's mythium plus the mythium they already sent for the next wave (in sudden death also their waiting mercenaries). A player without an attacker uses the other team's average, and a player alone their own. -
Tis the next wave's build time in seconds, andrandWthe attacker's mythium gather rate (1 by default) and workers.Gis the attacker's gold. - Around waves 11 to 13 the legion spells' extra values are added, and from wave 20 the growth of
sudden death:
R * (1.1^g - 1), rounded, withRthe wave's recommended value andgthe number of sudden deaths on the 2v2 map, or twice that plus 2 on the classic map. - After wave 10 a bot's extra is at most
25 * wave.
The result is rounded to tens. Allies see the new values at once, and enemies as the mercenaries warp to the lanes.
Each team's MVP is the player with the highest MVP score at the end of the game. The score is truncated to a whole number:
MvpScore = 1.0 * WavesSavedFactor(you)
+ 1.0 * WavesSavedFactor(your attacker)
+ 1.0 * MythiumSpentOnKingUpgrades
- 5.0 * LeakPercentValue(you)
+ 5.0 * LeakPercentValue(the player you send to)
+ 3.0 * LeakCaughtPercentValue(you)
+ 4.0 * ShutdownGoldEarnedFactor(you)
- 4.0 * ShutdownGoldEarnedFactor(your attacker)
+ SpreadTheWealthThe code also lists the end value, total mythium, leak values and the power score, each weighed
0. In classic special mode 11 the weights become 0.2 * TotalMythium, -5 * LeakPercentValue,
3 * LeakCaughtPercentValue and -4 * ShutdownGoldEarnedFactor(your attacker), plus the Spread
the Wealth term.
-
WavesSavedFactor(N)adds, over waveskfrom 1 toN, the mythium the player kept unsent as wavek's mercenaries warped to the lanes, weighed by how early that was:WavesSavedFactor(N) = sum(MythiumKept[k] * 1.17^(21 - k) / 7 for k in 1..N)
-
LeakPercentValueadds, for each wave a player's lane leaked, the share of the wave's bounty still alive when the lane fell, as a percentage. An enemy counts its bounty less the part its lost life already paid. The wave's bounty leaves out mercenaries; a wave with no bounty uses its hit points instead. -
LeakCaughtPercentValueadds, for each leaked enemy a player kills, the bounty that kill catches as a percentage of the leaking player's wave bounty. -
SpreadTheWealthis5 * wave + 15if the player took the Spread the Wealth spell, and the same amount taken off if their cross partner did.
The Auto Power choice of the send menu spends the player's mythium (20 or more) as each wave's rewards come, and again as the wave spawns, after which the choice goes back to saving. Past wave 1, the send at the spawn happens only when Auto Power sent at that wave's rewards, or a powerful mercenary is already sent or queued.
It spends in steps of the Snail's cost. Each step picks the mercenary with the best score among those the player can buy, with at most 8 of one type for the wave:
- 10, less 0.02 for each place the mercenary takes in the wave's preference list (
mercprefin its row); 8 for a mercenary not in the list. - Plus
(cost / 20 - min(20, mythium / 20)) / 4, so a dearer mercenary scores higher. - Less 0.4 for each of the same type already sent, from wave 10.
- Less 0.5 (20 from wave 10) when the send would leave 20 to 39 mythium.
- Plus the fit with the defending build, from its fighters' values by attack type, armor type
and role (damage, tank, area damage, scaling, healing), each as a share of the build's value:
- The mercenary's attack against the build's armors, and the build's attacks against the
mercenary's armor: the average damage multiplier away from 1, weighted by the
mercenary's role (tank, melee or ranged, from its
spawnbias). - From wave 8, melee and ranged mercenaries gain against a build with little damage, tanks against one with much. Tanks gain 1.5 on the ranged waves (8, 11, 15, 19).
- Area damage over 15% of the build favors Safety Mole, Honey Bear and Hermit (less on waves 6, 10, 13, 18 and 20) and ranged mercenaries; below it Honey Bear and Hermit lose 1.5.
- Scaling over 30% favors melee and ranged mercenaries, and Pack Leader by 2.
- The mercenary's attack against the build's armors, and the build's attacks against the
mercenary's armor: the average damage multiplier away from 1, weighted by the
mercenary's role (tank, melee or ranged, from its
- Plus the game's own preferences for single mercenaries:
| Mercenary | Bonus |
|---|---|
| Powerful mercenaries (below) | 8 |
| Giant Snail | 20 |
| Robo, with 59 mythium or less, up to wave 3 | 0.5 (in place of the powerful bonus) |
| Brute, with 60 to 79 mythium | 3.5 |
| Ogre, up to wave 10 | 2.5 |
| Imp, on wave 7 | -1 |
| Shaman | 50 on wave 21, 15 on wave 20, 3 on waves 15 and 18, -2 otherwise |
| Witch, from wave 10 | 1.5 * n |
| Mimic, before wave 17 | 5 * n |
| Four Eyes, from wave 10 |
1.5 * (1 - n), plus 12 times the healing share |
| Centaur | 1.5 times the melee share |
| Ghost Knight | 2 times the build's damage per second over its value |
| Siege Ram | 1.5 times the ranged share |
n is the build's fighter count over 30, at most 1. Safety Mole and Pack Leader lose 2.5 when
the other is already sent, and a second support mercenary (Safety Mole, Pack Leader, Hermit,
Shaman) of a type scores 0.
The powerful mercenaries are Brute, Centaur, Four Eyes, Ghost Knight, Hermit, Honey Bear, Imp, Kraken, Mimic, Needler, Ogre, Pack Leader, Robo, Safety Mole, Shaman, Siege Ram and Witch.
An ability that procs on a chance rolls 1 to 100 against the chance in whole percent: 15.9%
procs on rolls up to 15. Bash, Evasion and Shadowbreeder use a pseudo random roll instead. It
starts at a small chance C and adds C after each miss, back to C after a proc, so procs
come at the stated rate but more evenly:
| Stated chance | C |
|---|---|
| 5% or less | 0.2% |
| 10% | 1.47% |
| 15% | 3.22% |
| 20% | 5.57% |
| 25% | 8.47% |
%%{init: {"themeVariables": {"xyChart": {"plotColorPalette": "#e6b44c"}}}}%%
xychart-beta
title "Pseudo random step C by stated chance"
x-axis "Stated chance (%)" [5, 10, 15, 20, 25]
y-axis "C (%)" 0 --> 10
bar [0.2, 1.47, 3.22, 5.57, 8.47]
Above 5%, C is the value whose average proc rate equals the stated chance. The 26.10 rows of
some of these abilities count hits instead (every so many attacks), with no roll.
A Mastermind offer holds 11 fighters from every legion, drawn in this order:
flowchart LR
G[Guaranteed fighters] --> R[3 damage dealers, 3 tanks]
R --> P[One per missing roll group]
P --> W[The rest by roll weight]
W --> S[Sorted by gold cost]
- The guaranteed fighters (a Lock In).
- Three damage dealers of different attack types and three tanks of different armor types, no more than two of one tier. A type is picked as likely as the number of fighters that have it.
- One fighter for each roll group the offer still lacks, the groups taken in random order:
tier 1, arcane, fortified or natural, swift or natural, magic, pierce, impact, tier 6, tier 4
or 5, tier 2 and tier 3. The groups are the
mm_groupsflags of the fighters' rows. - The rest by roll weight: each fighter holds
mm_roll_weighttickets, drawn without return. Past three tier 6 fighters, tier 6 holds none.
The offer is shown sorted by gold cost. A reroll keeps six fighters and draws five more, at most one of tier 1.
Within each step a fighter is picked as likely as its pick weight against the others' 1. Step 2 picks the damage dealers and tanks by the role weights instead. Pick weights:
| Fighter | Weight |
|---|---|
| Antler | 0.4 |
| Bazooka | 0.7 |
| Chained Fist | 0.5 |
| Fire Lord | 0.65 |
| Gargoyle | 0.35 |
| Goblin Copter | 0.8 |
| Golden Buckler | 0.05 |
| Grarl | 0.35 |
| Holy Avenger | 0.0001 |
| Pirate Skeleton | 0.0001 |
| Pollywog | 0.3 |
| Proton | 0.1 |
| Radiant Halo | 0.1 |
| Seedling | 0.5 |
| Slime Larva | 0.2 |
| Warg | 0.25 |
| Yozora | 0.55 |
Role weights:
| Fighter | Weight |
|---|---|
| Bazooka | 1 |
| Priestess Of The Abyss | 1 |
| Proton | 1 |
| Radiant Halo | 1 |
| Seedling | 1 |
Some rules leave fighters out of a whole draw by chance:
| Fighters | Chance to be left out | When |
|---|---|---|
| Seedling | 50% | on the 2v2 map, for Fiesta |
| Seedling, Eggsack and Dwarf Banker | 75% | on the classic map |
| Crab Warlock | 88% | under 2000 Elo |
Aristocrat's offer holds a second tier 2 and a second tier 6 check. Swarm's starts with its tier 1 fighters, then draws without tier 1, one damage dealer and one tank, with its own groups and no pick weights.
The game announces swings of the spectators' win chance across the screen:
- Game changer and Power play: as the scoreboard refreshes before a wave's rewards, from wave 4, when the west's chance moved by 0.25 or more since the last refresh. Game changer when the favourite changed, Power play otherwise.
-
Not even close: 0.3 seconds after a side clears its enemies, when its king is low and was
hurt this wave (with
leftandtakenin percent,left * 20 - taken < 30andtaken > 0.1). Once a wave.
One announcement shows every 2.5 seconds at most. The sandbox's -wave command stops them for
the rest of the game.
After wave 21 the game plays wave 21 again, as sudden death; the HUD shows wave 21 plus the number of sudden deaths. Players earn no income. Each sudden death gives every wave unit one more Indomitable stack (more attack speed and less damage taken) and shows it 5% larger. The recommended value grows as described in Recommended value; as a sudden death wave ends, the mythium sent for it stops counting toward it.
At the end of the fourteenth sudden death, 30 Dire Toads appear at the west king's waypoint, whatever the teams.
stateDiagram-v2
direction LR
Wave21: Wave 21
SD: Sudden death n (wave 21 again, n Indomitable stacks)
Toads: 30 Dire Toads at the west king
Wave21 --> SD: no king fell
SD --> SD: n + 1
SD --> Toads: end of n = 14
Using ProLeak
Features
Tutorial
- Your first plugin
- Plugin basics
- Handling events
- Plugin settings
- User interface
- Players, units and game data
- Purchases, signals and pings
- Chat, camera, input and more
- Cosmetics
- Game modes
- Game updates
- Publishing plugins
Reference