mirror of
https://gitlab.com/the-no-frauds-club/cosmonarchy-bw-release.git
synced 2026-09-21 22:31:45 +00:00
19 September 2026 -- Gauntelet Stage A update
This commit is contained in:
parent
67421c1874
commit
3d8d94764a
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,7 +5,6 @@ logs/
|
||||
**.tmp
|
||||
/*.pcx
|
||||
**.png
|
||||
**.yml
|
||||
|
||||
ddraw.ini
|
||||
BnetLog.txt
|
||||
|
||||
@ -5,6 +5,7 @@ Since December 2022, this changelog shows only past changes.
|
||||
See patchnotes.md for info on the most recent patch!
|
||||
|
||||
# Table of Contents
|
||||
- [4 September 2026](#4-september-2026)
|
||||
- [23 August 2026](#23-august-2026)
|
||||
- [25 July 2026](#25-july-2026)
|
||||
- [18 July 2026](#18-july-2026)
|
||||
@ -120,6 +121,271 @@ See patchnotes.md for info on the most recent patch!
|
||||
- [13 August 2020](#13-august-2020)
|
||||
- [12 August 2020](#12-august-2020)
|
||||
|
||||
# 4 September 2026
|
||||
## Year 4, month 9, patch 1
|
||||
|
||||
## Patch goals
|
||||
- Balance tweaks ahead of Acropolis #5!
|
||||
- Deploy more factional variants for Augustcrap, a Mapcrap event!
|
||||
- Continue technical improvements and bugfixes
|
||||
- Further improve audiovisuals
|
||||
- [Subscribe on ko-fi](https://ko-fi.com/pr0nogoandveeq7) to get a sneak peek of the incoming changes!
|
||||
- Join our communities ([Discord](https://discord.com/invite/s5SKBmY) | [Fluxer](https://fluxer.gg/1rebBmBw)), or get in touch with Pr0nogo via email! pr0nogo@fraudsclub.com
|
||||
|
||||
## Core
|
||||
- **Weapon entries have been extended!**
|
||||
- With much help from DarkenedFantasies (DF) and Jesse, weapon entries are (finally) virtually-unlimited! Say goodbye to broken tooltips and edge case bugs for several Askosi and factional weapons!
|
||||
- *Please report any weapon-based oddities you encounter to us via discord/fluxer or email!*
|
||||
- **Immense improvements have been made to helper and hook wrappers!**
|
||||
- For the less technically-inclined, this means... more stability! Less desyncs! Easier debugging!
|
||||
- *Please report any newfound issues you encounter to us via discord/fluxer or email!*
|
||||
- **The custom trigger system has been deep-cleaned!** (c. Veeq7)
|
||||
- This refactor makes the system easier to use, maintain, and improve upon in the future! But a huge refactor like this might have introduced new issues...
|
||||
- *Please report any newfound issues in campaign and UMS maps to us via discord/fluxer or email!*
|
||||
- **Known issues:** the `wait` crig action does not currently operate
|
||||
- **A new campaign menu has been achieved!** (c. Jesse)
|
||||
- It's so epic... please enjoy!
|
||||
- **Options menu now allows for:** (c. Jesse)
|
||||
- Advisor selection
|
||||
- Player color selection
|
||||
- Validation on save to prevent errors
|
||||
|
||||
## Game Modes
|
||||
- **NEW: Mindshare** (b. BtyB)
|
||||
- Resource pool is shared among allies!
|
||||
- *Caveat: Starting resources are not yet doubled in all cases*
|
||||
- *Caveat: Cancelling units may result in oddities until fixed*
|
||||
|
||||
## Bugfixes
|
||||
- **Stability:**
|
||||
- Arcing projectiles (Phalanx, Aphorist) no longer crash with division by zero when targeting an allied Mimic (r. TheBeaver99)
|
||||
- **Gameplay:**
|
||||
- **Atreus** Binding Plasma can no longer bounce to air units (r. Krankendau)
|
||||
- Mimicry no longer fails to account for weapon factor in many cases (r. shopkeeper dog)
|
||||
- **Egocent**s no longer fail to mimic barrage attacks properly (r. Londier)
|
||||
- Mimicry no longer procs on ability weapons (r. Londier)
|
||||
- **Audiovisual:**
|
||||
- Corrected strings for **Izirokor** tech-enable on **Skibact Scab** and **Tethvith Swamp** (r. Mimika)
|
||||
- Fixed weapon display for **Lobotomy Mine** (r. TheBeaver99)
|
||||
- Corrected armors for **Akreno** and **Abutment** (latter r. TheBeaver99)
|
||||
- Fixed bad shield overlay for **Vulture (Hecaton)** (r. Londier)
|
||||
- Buttons for **Tiangou** and **Cutlass** now show as disabled when no **Scrapyard** is built (r. Pisens)
|
||||
- **Cyclops (Futurist)** now uses its unique shadow and attack sequence instead of the standard variant's (r. lolrsk8s)
|
||||
- Corrected tooltip for **Kagralisk** weapon string (r. Krankendau)
|
||||
|
||||
## Audiovisuals
|
||||
- New models for:
|
||||
- Watchdog (c. Solstice)
|
||||
- Magnetar, Ardent Authority, Argosy (c. DeltaCadimus)
|
||||
- Vorvrokor (c. Baelethal)
|
||||
- Landlock, Radix, Cipher, Function, Proscenium (c. fasswawds)
|
||||
- All new wireframes c. jun3hong!
|
||||
- Resized model for:
|
||||
- Talos, Cyprian
|
||||
- Modified model (mostly shaders) for:
|
||||
- Maverick, Maverick (Futurist), Shaman, Blackguard, Artisan, Pilgrim, Proselyte, Missionary, Vicar, Intendent, Phontis
|
||||
- Zethrokor, Quazilisk, Liiralisk, Hydralisk, Izirokor, Zoryusthaleth (c. Solstice)
|
||||
- Modified weaponfire VFX for Harakan (Golden) (s. Londier)
|
||||
- Added weapon launch offsets for:
|
||||
- Aphorist, Silversoul, Ghostwrit, Phontis, Iconoclast, Crematorium
|
||||
- Modified unit responses for Vorvrokor
|
||||
- New unit responses for Cardinal, Intendent
|
||||
- New error and structure placement SFX for Askosi (c. lolrsk8s)
|
||||
- New weapon SFX for:
|
||||
- Alzurokor (c. lolrsk8s)
|
||||
- Iconoclast, Paraclete
|
||||
- New cast SFX for Paraclete
|
||||
- New training SFX for:
|
||||
- Function, Cosmoscope
|
||||
- New cloaking SFX for damage cloak (e.g. Vestige; c. lolrsk8s)
|
||||
|
||||
## Terran
|
||||
- [Maverick](https://cosmonarchy.com/terran/maverick):
|
||||
- Build time 11 » 12
|
||||
- HP 60 » 75
|
||||
- **Stim Pack:**
|
||||
- HP cost 5 » 10
|
||||
- [Harakan](https://cosmonarchy.com/terran/harakan):
|
||||
- Build time 16 » 14
|
||||
- HP 100 » 120
|
||||
- [Cyprian](https://cosmonarchy.com/terran/cyprian):
|
||||
- Resource costs 75/50 » 100/50
|
||||
- HP 80 » 90
|
||||
- Collision size increased by ~16%
|
||||
- [Heracles](https://cosmonarchy.com/terran/heracles):
|
||||
- HP 200 » 240
|
||||
- [Vulture](https://cosmonarchy.com/terran/vulture):
|
||||
- Resource costs 100/0 » 75/0
|
||||
- HP 120 » 80
|
||||
- [Goliath](https://cosmonarchy.com/terran/goliath):
|
||||
- Mineral cost 175/50 » 150/50
|
||||
- HP 240 » 220
|
||||
- Movement speed 5 » 4.5
|
||||
- [Phalanx](https://cosmonarchy.com/terran/phalanx):
|
||||
- Mineral cost 200/50 » 150/75
|
||||
- [Cataphract](https://cosmonarchy.com/terran/cataphract):
|
||||
- **Longinius Cannons:**
|
||||
- No longer target air units
|
||||
- [Quarry](https://cosmonarchy.com/terran/quarry):
|
||||
- Build time 35 » 45
|
||||
- [Anvil](https://cosmonarchy.com/terran/anvil):
|
||||
- Resource costs 150/150 » 100/150
|
||||
- [Morningstar](https://cosmonarchy.com/terran/morningstar):
|
||||
- Resource costs 100/100 » 50/100
|
||||
- Build time 30 » 25
|
||||
- [Treasury](https://cosmonarchy.com/terran/treasury):
|
||||
- Build time 35 » 45
|
||||
- Can now train **Mason**s while a **Quarry** is constructed.
|
||||
- [Stockade](https://cosmonarchy.com/terran/stockade):
|
||||
- Build time 50 » 45
|
||||
- [Fulcrum](https://cosmonarchy.com/terran/fulcrum):
|
||||
- Resource costs 200/50 » 200/75
|
||||
- Build time 50 » 45
|
||||
|
||||
## Terran factions
|
||||
- [Hotshot](https://cosmonarchy.com/terran/hotshot):
|
||||
- HP 65 » 70
|
||||
- Armor 0 » 1
|
||||
- [Maverick (Futurist)](https://cosmonarchy.com/terran/maverick-futurist):
|
||||
- HP 70 » 75
|
||||
- [Maverick (Upstart](https://cosmonarchy.com/terran/maverick-upstart):
|
||||
- HP 50 » 60
|
||||
- [Harakan (Golden)](https://cosmonarchy.com/terran/harakan-golden):
|
||||
- Build time 16 » 15
|
||||
- [Vulture (Upstart](https://cosmonarchy.com/terran/vulture-upstart):
|
||||
- Resource costs 100/0 » 75/0
|
||||
- HP 120 » 80
|
||||
- **NEW:** [Maverick (Golden)](https://cosmonarchy.com/terran/maverick-golden):
|
||||
- Maverick variant for Golden Republic. Has shields and a fast-firing phase rifle; no Stim Pack.
|
||||
- **NEW:** [Shaman (Upstart](https://cosmonarchy.com/terran/shaman-upstart):
|
||||
- Shaman variant for Upstart Terrans. Stims allies when deployed.
|
||||
- **NEW:** [Morrigan](https://cosmonarchy.com/terran/morrigan):
|
||||
- Eidolon replacement for Upstart Terrans. Has attack cloaking and an area-damage ground-only grenade launcher.
|
||||
|
||||
## Protoss
|
||||
- [Zealot](https://cosmonarchy.com/protoss/zealot):
|
||||
- HP 150 » 160
|
||||
- **Phase Blades:**
|
||||
- Armor penetration 1 » 3
|
||||
- [Atreus](https://cosmonarchy.com/protoss/atreus):
|
||||
- Sight range 9 » 8
|
||||
- Transport weight 4 » 5
|
||||
- **Dauntless Disruption Cannon:**
|
||||
- Weapon damage 12 » 10
|
||||
- Weapon range 5 » 4
|
||||
- [Optecton](https://cosmonarchy.com/protoss/optecton):
|
||||
- Resource costs 500/200 » 500/300
|
||||
- HP 400 » 500
|
||||
- [Unar](https://cosmonarchy.com/protoss/unar):
|
||||
- Resource costs 300/125 » 200/200
|
||||
- Build time 50 » 45
|
||||
- [Architect](https://cosmonarchy.com/protoss/architect):
|
||||
- Resource costs 250/200 » 300/250
|
||||
- Build time 45 » 50
|
||||
- HP 200 » 240
|
||||
- Shields 50 » 40
|
||||
- **Reactive Payload:**
|
||||
- Weapon cooldown 1.33 » 1.25
|
||||
- [Analogue](https://cosmonarchy.com/protoss/analogue):
|
||||
- **Cylindrical Blaster:**
|
||||
- Weapon range 6 » 4
|
||||
- [Gateway](https://cosmonarchy.com/protoss/gateway):
|
||||
- Resource costs 175/0 » 150/0
|
||||
- Build time 50 » 55
|
||||
- [Grand Library](https://cosmonarchy.com/protoss/grand-library):
|
||||
- Resource costs 225/50 » 300/50
|
||||
- [Unitary Union](https://cosmonarchy.com/protoss/unitary-union):
|
||||
- Resource costs 500/250 » 500/300
|
||||
|
||||
## Protoss factions
|
||||
- **NEW:** [Gladius (Order)](https://cosmonarchy.com/protoss/gladius-order):
|
||||
- Order of the Sacred Saber Gladius variant. Has Triumphant Rise (a la Herald / Archon).
|
||||
|
||||
## Zerg
|
||||
- **Reconstitution:**
|
||||
- *Used by Agrileth (new), Vilgorokor*
|
||||
- Carapace Swarm HP 200 » 300
|
||||
- **Miasma:**
|
||||
- No longer spreads on death; **Plague** remains unchanged
|
||||
- *This will be revisited later.*
|
||||
- [Agrileth](https://cosmonarchy.com/zerg/agrileth):
|
||||
- Resource costs 150/50 » 150/75
|
||||
- HP 200 » 140
|
||||
- Armor 2 » 1
|
||||
- **NEW: Reconstitution**
|
||||
- Releases a Carapace Swarm upon taking damage.
|
||||
- [Zethrokor](https://cosmonarchy.com/zerg/zethrokor):
|
||||
- Resource cost 25/0 » 50/0
|
||||
- HP 50 » 60
|
||||
- Movement speed 7.5 » 8.4
|
||||
- **Zethrok Claws:**
|
||||
- Weapon damage 4 » 5
|
||||
- [Vorvrokor](https://cosmonarchy.com/zerg/vorvrokor):
|
||||
- Resource cost 50/0 » 75/0
|
||||
- HP 80 » 90
|
||||
- Armor 1 » 2
|
||||
- Movement speed 9.1 » 9.8
|
||||
- Collision size increased by ~23%
|
||||
- [Liiralisk](https://cosmonarchy.com/zerg/liiralisk):
|
||||
- **Homing Spore:**
|
||||
- Weapon range 7 » 8
|
||||
- [Protathalor](https://cosmonarchy.com/zerg/protathalor):
|
||||
- Resource costs 125/75 » 100/100
|
||||
- Armor 2 » 1
|
||||
- [Izirokor](https://cosmonarchy.com/zerg/izirokor):
|
||||
- Build time 26 » 22
|
||||
- [Bactalisk](https://cosmonarchy.com/zerg/bactalisk):
|
||||
- **Corrosive Acid:**
|
||||
- No longer targets air units
|
||||
- [Zoryusthaleth](https://cosmonarchy.com/zerg/zoryusthaleth):
|
||||
- Resource costs 175/0 » 200/0
|
||||
- Build time 28 » 25
|
||||
- HP 200 » 220
|
||||
- [Lakizilisk](https://cosmonarchy.com/zerg/lakizilisk):
|
||||
- Resource costs 75/75 » 100/75
|
||||
- Build time 30 » 28
|
||||
- HP 140 » 150
|
||||
- **Subterranean Spines:**
|
||||
- Weapon damage 12 » 15
|
||||
- Weapon cooldown 1.63 » 1.75
|
||||
- [Vilgorokor](https://cosmonarchy.com/zerg/vilgorokor):
|
||||
- Resource costs 220/75 » 200/50
|
||||
- HP 280 » 200
|
||||
|
||||
## Askosi
|
||||
- **Shared Designs:**
|
||||
- Team building from **Pilgrim**s and **Constituent**s now increases build rate by 25% per worker, from 20%
|
||||
- **Ash Heap:**
|
||||
- Now consumes corpses
|
||||
- **Power Overload:**
|
||||
- *Used by Grandstand, Rove (new), Intendent*
|
||||
- No longer deals damage over time to armored targets
|
||||
- Now steals armor, to a cap of 4
|
||||
- [Cardinal](https://cosmonarchy.com/askosi/cardinal):
|
||||
- Resource costs 75/25 » 100/25
|
||||
- [Rove](https://cosmonarchy.com/askosi/rove):
|
||||
- **Elre Scaleshot:**
|
||||
- Weapon damage 8 » 4
|
||||
- Armor penetration 2 » 0
|
||||
- Weapon range 5 » 3
|
||||
- Weapon factor 1 » 3
|
||||
- Now fires in a shotgun pattern (e.g. **Hotshot**, **Siren**)
|
||||
- **Impact Dissipation** removed
|
||||
- **NEW: Power Overload**
|
||||
- [Tortare](https://cosmonarchy.com/askosi/tortare):
|
||||
- **Deathrattle Assembly:**
|
||||
- Now grants 2 armor when deployed
|
||||
- [Radix](https://cosmonarchy.com/askosi/radix):
|
||||
- Resource costs 100/0 » 125/0
|
||||
- [Function](https://cosmonarchy.com/askosi/function):
|
||||
- Resource costs 125/25 » 150/25
|
||||
|
||||
## Askosi factions
|
||||
- **NEW: Sons of Ash**
|
||||
- Conqueror clergy, set to burn the dead wood.
|
||||
- **NEW:** [Scralia](https://cosmonarchy.com/askosi/scralia)
|
||||
- Intendent replacement for Sons of Ash. Short-range assault craft with Booming Blast and Ash Heap.
|
||||
|
||||
# 23 August 2026
|
||||
## Year 4, month 8, patch 1
|
||||
|
||||
|
||||
Binary file not shown.
@ -720,15 +720,15 @@ Shaman (Upstart, Adrenaline)
|
||||
Ammo Crate
|
||||
Medkit
|
||||
Battery Cell
|
||||
Extended Flingy #514
|
||||
Extended Flingy #515
|
||||
Extended Flingy #516
|
||||
Extended Flingy #517
|
||||
Extended Flingy #518
|
||||
Extended Flingy #519
|
||||
Extended Flingy #520
|
||||
Extended Flingy #521
|
||||
Extended Flingy #522
|
||||
Okrimnilisk Spore
|
||||
Raynor (Maverick)
|
||||
Cyprian (Hecaton)
|
||||
Memphis (Tank Mode)
|
||||
Memphis (Flak Mode)
|
||||
Memphis Turret (Tank Mode)
|
||||
Memphis Turret (Flak Mode)
|
||||
Fragmentary Shells (with damage)
|
||||
Floor Flame Trap
|
||||
Extended Flingy #523
|
||||
Extended Flingy #524
|
||||
Extended Flingy #525
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -2488,22 +2488,22 @@ Battery Cell Shadow (Carried)
|
||||
Flamethrower (Blue)
|
||||
Watchdog Engine
|
||||
Watchdog Engine Idle
|
||||
Extended Image #1488
|
||||
Extended Image #1489
|
||||
Extended Image #1490
|
||||
Extended Image #1491
|
||||
Extended Image #1492
|
||||
Extended Image #1493
|
||||
Extended Image #1494
|
||||
Extended Image #1495
|
||||
Extended Image #1496
|
||||
Extended Image #1497
|
||||
Extended Image #1498
|
||||
Extended Image #1499
|
||||
Extended Image #1500
|
||||
Extended Image #1501
|
||||
Extended Image #1502
|
||||
Extended Image #1503
|
||||
Okrimnilisk Spore
|
||||
Spore Hit (White)
|
||||
Spore Trail (White)
|
||||
Raynor (Maverick)
|
||||
Raynor (Maverick) Shadow
|
||||
Raynor (Maverick) Remains
|
||||
Cyprian (Hecaton)
|
||||
Cyprian (Hecaton) Shadow
|
||||
Memphis (Tank Mode)
|
||||
Memphis Turret (Tank Mode)
|
||||
Memphis (Tank Mode) Shadow
|
||||
Memphis (Flak Mode)
|
||||
Memphis Turret (Flak Mode)
|
||||
Fragmentary Shells (with damage)
|
||||
Floor Flame Trap
|
||||
Floor Flame Trap Turret
|
||||
Extended Image #1504
|
||||
Extended Image #1505
|
||||
Extended Image #1506
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -310,30 +310,30 @@ Prophet 2
|
||||
Bloodsummon Advisor
|
||||
Vestige
|
||||
Rozirokor
|
||||
Extended Portrait #203
|
||||
Extended Portrait #204
|
||||
Extended Portrait #205
|
||||
Extended Portrait #206
|
||||
Extended Portrait #207
|
||||
Extended Portrait #208
|
||||
Extended Portrait #209
|
||||
Extended Portrait #210
|
||||
Extended Portrait #211
|
||||
Extended Portrait #212
|
||||
Extended Portrait #213
|
||||
Extended Portrait #214
|
||||
Extended Portrait #215
|
||||
Extended Portrait #216
|
||||
Extended Portrait #217
|
||||
Extended Portrait #218
|
||||
Extended Portrait #219
|
||||
Extended Portrait #220
|
||||
Extended Portrait #221
|
||||
Extended Portrait #222
|
||||
Extended Portrait #223
|
||||
Extended Portrait #224
|
||||
Extended Portrait #225
|
||||
Extended Portrait #226
|
||||
Vespene Node
|
||||
Ajax
|
||||
Alzurokor
|
||||
Arquebus
|
||||
Azanthrokor
|
||||
Broadside
|
||||
Cutlass
|
||||
Cyprian (Hecaton)
|
||||
Garvrokor
|
||||
Goremast
|
||||
Morrigan
|
||||
Quadriga
|
||||
Serathiel
|
||||
Shaman (Upstart)
|
||||
Sovrokor
|
||||
Tartarus Mine
|
||||
Valkyrie (Hecaton)
|
||||
Vulture (Hecaton)
|
||||
Vulture (Upstart)
|
||||
Eidolon (Golden)
|
||||
Dredge
|
||||
Ixodid
|
||||
Camazotz
|
||||
Cannibal
|
||||
Extended Portrait #227
|
||||
Extended Portrait #228
|
||||
Extended Portrait #229
|
||||
|
||||
@ -4391,21 +4391,21 @@ Intendent Under Attack 01
|
||||
Intendent Under Attack 02
|
||||
Intendent Under Attack 03
|
||||
Intendent Under Attack 04
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Pit Door Open 01
|
||||
Pit Door Open 02
|
||||
Pit Door Close 01
|
||||
Pit Door Close 02
|
||||
Upper Door Open 01
|
||||
Upper Door Open 02
|
||||
Upper Door Close 01
|
||||
Upper Door Close 02
|
||||
Memphis Weaponfire 01
|
||||
Memphis Weaponfire 02
|
||||
Memphis Weaponfire 03
|
||||
Memphis Weaponhit 2 01
|
||||
Memphis Weaponhit 2 02
|
||||
Memphis Weaponhit 2 03
|
||||
Memphis Weaponhit 2 04
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
Extended Sound #1
|
||||
|
||||
@ -4390,4 +4390,19 @@ cm\a\intendent\agg-04.wav
|
||||
cm\a\intendent\hlp-01.wav
|
||||
cm\a\intendent\hlp-02.wav
|
||||
cm\a\intendent\hlp-03.wav
|
||||
cm\a\intendent\hlp-04.wav
|
||||
cm\a\intendent\hlp-04.wav
|
||||
cm\n\doors\pit-open-01.wav
|
||||
cm\n\doors\pit-open-02.wav
|
||||
cm\n\doors\pit-close-01.wav
|
||||
cm\n\doors\pit-close-02.wav
|
||||
cm\n\doors\upper-open-01.wav
|
||||
cm\n\doors\upper-open-02.wav
|
||||
cm\n\doors\upper-close-01.wav
|
||||
cm\n\doors\upper-close-02.wav
|
||||
cm\f-t\memphis\wf-01.wav
|
||||
cm\f-t\memphis\wf-02.wav
|
||||
cm\f-t\memphis\wf-03.wav
|
||||
cm\f-t\memphis\wh-2-01.wav
|
||||
cm\f-t\memphis\wh-2-02.wav
|
||||
cm\f-t\memphis\wh-2-03.wav
|
||||
cm\f-t\memphis\wh-2-04.wav
|
||||
Binary file not shown.
@ -1193,18 +1193,18 @@ Ammo Crate
|
||||
Medkit
|
||||
Battery Cell
|
||||
Flamethrower (Blue)
|
||||
Extended Sprite #679
|
||||
Extended Sprite #680
|
||||
Extended Sprite #681
|
||||
Extended Sprite #682
|
||||
Extended Sprite #683
|
||||
Extended Sprite #684
|
||||
Extended Sprite #685
|
||||
Extended Sprite #686
|
||||
Extended Sprite #687
|
||||
Extended Sprite #688
|
||||
Extended Sprite #689
|
||||
Extended Sprite #690
|
||||
Okrimnilisk Spore
|
||||
Spore Hit (White)
|
||||
Spore Trail (White)
|
||||
Raynor (Maverick)
|
||||
Raynor (Maverick) Remains
|
||||
Cyprian (Hecaton)
|
||||
Memphis (Tank Mode)
|
||||
Memphis (Flak Mode)
|
||||
Memphis Turret (Tank Mode)
|
||||
Memphis Turret (Flak Mode)
|
||||
Fragmentary Shells (with damage)
|
||||
Floor Flame Trap
|
||||
Extended Sprite #691
|
||||
Extended Sprite #692
|
||||
Extended Sprite #693
|
||||
|
||||
Binary file not shown.
@ -201,17 +201,17 @@ Terran Captaincy
|
||||
Terran Scrapyard
|
||||
Protoss Crucible
|
||||
Carapace Swarm
|
||||
Terran Nanite Assembly
|
||||
Floor Missile Trap
|
||||
Zerg Kalkiir Lake
|
||||
Left Upper Level Door
|
||||
Right Upper Level Door
|
||||
Left Pit Door
|
||||
Right Pit Door
|
||||
Terran Sentinel
|
||||
Terran Tarasque (Nydus)
|
||||
Terran Anticthon
|
||||
Zerg Kethraj Keep
|
||||
Terran Atelier
|
||||
Floor Gun Trap
|
||||
Wall Missile Trap (Left)
|
||||
Wall Flame Trap (Left)
|
||||
Wall Missile Trap (Right)
|
||||
Wall Flame Trap (Right)
|
||||
Start Location
|
||||
Terran Treasury
|
||||
Zerg Larvosk Cesiant
|
||||
@ -258,10 +258,10 @@ Terran Matador (Tank Mode)
|
||||
Terran Future Station
|
||||
Zerg Zarcavrokor
|
||||
Terran Cestus
|
||||
Terran Aerie (unused)
|
||||
Terran Pegasus (unused)
|
||||
Terran Sentinel
|
||||
Terran Nanite Assembly
|
||||
Terran Hippogriff
|
||||
Terran Oberon (unused)
|
||||
Terran Tarasque (Nydus)
|
||||
Terran Aion
|
||||
Protoss Herald
|
||||
Protoss Epigraph
|
||||
@ -287,7 +287,7 @@ Terran Dilettante
|
||||
Terran Sevenstep
|
||||
Terran Hypnagogue
|
||||
Terran Parthenon
|
||||
Terran Armistice
|
||||
Terran Anticthon
|
||||
Terran Pythean
|
||||
Zerg Ogroszaleth
|
||||
Zerg Spirtith Cesiant
|
||||
@ -301,7 +301,7 @@ Terran Throneroom
|
||||
Terran Emperor
|
||||
Terran Jester
|
||||
Zerg Agrileth
|
||||
unused
|
||||
Zerg Kethraj Keep
|
||||
Protoss Sequestered Icon
|
||||
Protoss Unitary Union
|
||||
Protoss Servitor
|
||||
@ -547,7 +547,7 @@ Askosi Zylode
|
||||
Askosi Astrolabe
|
||||
Terran Serathiel (Hecaton)
|
||||
Zerg Malkothrokor
|
||||
unused
|
||||
Zerg Kalkiir Lake
|
||||
Askosi Panoply
|
||||
Askosi Aphorist
|
||||
Askosi Doronin
|
||||
@ -611,8 +611,8 @@ Forerunner Athla
|
||||
Forerunner Vicere
|
||||
Forerunner Machinamentum
|
||||
Big Infested Kerrigan
|
||||
Raynor Vulture
|
||||
Duke Minotaur
|
||||
Raynor (Vulture)
|
||||
Duke (Minotaur)
|
||||
Askosi Scralia
|
||||
Zerg Rozirokor (Imicren)
|
||||
Bloodsummon Thrombocyte
|
||||
@ -637,23 +637,23 @@ Ammo Crate
|
||||
Medkit
|
||||
Battery Cell
|
||||
Forerunner Buildings
|
||||
Extended Unit #412
|
||||
Extended Unit #413
|
||||
Extended Unit #414
|
||||
Extended Unit #415
|
||||
Extended Unit #416
|
||||
Extended Unit #417
|
||||
Extended Unit #418
|
||||
Extended Unit #419
|
||||
Extended Unit #420
|
||||
Extended Unit #421
|
||||
Extended Unit #422
|
||||
Extended Unit #423
|
||||
Extended Unit #424
|
||||
Extended Unit #425
|
||||
Extended Unit #426
|
||||
Extended Unit #427
|
||||
Extended Unit #428
|
||||
Terran Eveningstar
|
||||
Raynor (Maverick)
|
||||
Terran Cyprian (Hecaton)
|
||||
Terran Memphis (Tank)
|
||||
Terran Memphis (Tank, Turret)
|
||||
Terran Memphis (Flak)
|
||||
Terran Memphis (Flak, Turret)
|
||||
Forerunner Processus
|
||||
Forerunner Aestuarius
|
||||
Forerunner Corcillum
|
||||
Floor Flame Trap
|
||||
Forerunner Bastilius
|
||||
Forerunner Molaris
|
||||
Forerunner Insignis
|
||||
Forerunner Incaendium
|
||||
Forerunner Ossum
|
||||
Forerunner Voluntatis
|
||||
Extended Unit #429
|
||||
Extended Unit #430
|
||||
Extended Unit #431
|
||||
|
||||
Binary file not shown.
@ -29,7 +29,7 @@ Arclite Shock Cannon (Phalanx, Siege)
|
||||
Monstrous Maw (Zoryusthaleth)
|
||||
Longbolt Missiles (Watchdog)
|
||||
Yamato Cannon (Magnetar ability)
|
||||
Nuclear Missile
|
||||
Nuclear Payload (Morningstar)
|
||||
Lobotomy Grenade (Goska)
|
||||
Psi Assault (Tassadar)
|
||||
Irradiate (Seraph ability)
|
||||
@ -307,14 +307,14 @@ Epitaph Grenade Launcher (Morrigan)
|
||||
Scalpel Cannon (Shaman Upstart)
|
||||
Reactive Blaster (Manifold Starbound)
|
||||
Plasmathrower (Harakan Golden)
|
||||
Extended Weapon #180
|
||||
Extended Weapon #181
|
||||
Extended Weapon #182
|
||||
Extended Weapon #183
|
||||
Extended Weapon #184
|
||||
Extended Weapon #185
|
||||
Extended Weapon #186
|
||||
Extended Weapon #187
|
||||
High-Tonnage Payload (Eveningstar)
|
||||
Gauss Launcher (Raynor Maverick)
|
||||
Boreal Railguns (Cyprian Hecaton)
|
||||
Twinstrike Cannons (Memphis)
|
||||
Twinflak Cannons (Memphis)
|
||||
Hellfire Missile Pack (Missile Trap)
|
||||
Vigil Autocannon (Gun Trap)
|
||||
Flamethrower (Flame Trap)
|
||||
Extended Weapon #188
|
||||
Extended Weapon #189
|
||||
Extended Weapon #190
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
56
mpq/game/huds.yml
Normal file
56
mpq/game/huds.yml
Normal file
@ -0,0 +1,56 @@
|
||||
huds:
|
||||
Neutral: # for replays
|
||||
image: game\nconsole.pcx
|
||||
hud_overlay: game\nconover.pcx
|
||||
progressbar_empty: game\tpbrempt.pcx
|
||||
progressbar_full: game\tpbrfull.pcx
|
||||
mineral_icon: 1
|
||||
gas_icon: 1
|
||||
supply_icon: 1
|
||||
command_buttons: unit\cmdbtns\tcmdbtns.grp
|
||||
command_buttons_bin: rez\statbtnn.bin
|
||||
chat_textbox_bounds: [] # currently defined by a bin file
|
||||
Terran:
|
||||
image: game\tconsole.pcx
|
||||
hud_overlay: game\tconover.pcx
|
||||
progressbar_empty: game\tpbrempt.pcx
|
||||
progressbar_full: game\tpbrfull.pcx
|
||||
mineral_icon: 1
|
||||
gas_icon: 1
|
||||
supply_icon: 1
|
||||
command_buttons: unit\cmdbtns\tcmdbtns.grp
|
||||
command_buttons_bin: rez\statbtnt.bin
|
||||
chat_textbox_bounds: [] # currently defined by a bin file
|
||||
Protoss:
|
||||
image: game\pconsole.pcx
|
||||
hud_overlay: game\pconover.pcx
|
||||
progressbar_empty: game\ppbrempt.pcx
|
||||
progressbar_full: game\ppbrfull.pcx
|
||||
mineral_icon: 2
|
||||
gas_icon: 2
|
||||
supply_icon: 2
|
||||
command_buttons: unit\cmdbtns\pcmdbtns.grp
|
||||
command_buttons_bin: rez\statbtnp.bin
|
||||
chat_textbox_bounds: [] # currently defined by a bin file
|
||||
Zerg:
|
||||
image: game\zconsole.pcx
|
||||
hud_overlay: game\zconover.pcx
|
||||
progressbar_empty: game\zpbrempt.pcx
|
||||
progressbar_full: game\zpbrfull.pcx
|
||||
mineral_icon: 0
|
||||
gas_icon: 0
|
||||
supply_icon: 0
|
||||
command_buttons: unit\cmdbtns\zcmdbtns.grp
|
||||
command_buttons_bin: rez\statbtnz.bin
|
||||
chat_textbox_bounds: [] # currently defined by a bin file
|
||||
Askosi:
|
||||
image: game\aconsole.pcx
|
||||
hud_overlay: game\aconover.pcx
|
||||
progressbar_empty: game\apbrempt.pcx
|
||||
progressbar_full: game\apbrfull.pcx
|
||||
mineral_icon: 3
|
||||
gas_icon: 3
|
||||
supply_icon: 3
|
||||
command_buttons: unit\cmdbtns\acmdbtns.grp
|
||||
command_buttons_bin: rez\statbtna.bin
|
||||
chat_textbox_bounds: [] # currently defined by a bin file
|
||||
Binary file not shown.
BIN
mpq/game/logo_80.pcx
Normal file
BIN
mpq/game/logo_80.pcx
Normal file
Binary file not shown.
BIN
mpq/game/logo_banner.pcx
Normal file
BIN
mpq/game/logo_banner.pcx
Normal file
Binary file not shown.
1
mpq/lua/.gitignore
vendored
Normal file
1
mpq/lua/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.luarc.json
|
||||
3
mpq/lua/AGENTS.md
Normal file
3
mpq/lua/AGENTS.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Resources
|
||||
- Load local Lua API reference from `.luarc.json`
|
||||
- Fetch Cosmonarchy tech tree from `https://cosmonarchy.com/export/all.json`
|
||||
1
mpq/lua/CLAUDE.md
Normal file
1
mpq/lua/CLAUDE.md
Normal file
@ -0,0 +1 @@
|
||||
@AGENTS.md
|
||||
151
mpq/lua/examples/basic_ai.lua
Normal file
151
mpq/lua/examples/basic_ai.lua
Normal file
@ -0,0 +1,151 @@
|
||||
-- Setup main variables
|
||||
local player = Player()
|
||||
if player.type ~= PlayerType.Computer then
|
||||
return
|
||||
end
|
||||
local ai = AI()
|
||||
local config = PlayerVars().ai_config or {}
|
||||
|
||||
local main_town = ai:start_town()
|
||||
|
||||
-- Neat way to organize stuff is to use a table
|
||||
local brain = {
|
||||
saw_air_units = false,
|
||||
}
|
||||
|
||||
---@param town Town
|
||||
local function flyer_watch(town)
|
||||
wait_until(function() return brain.saw_air_units end)
|
||||
for i = 1, 5 do
|
||||
town:build(i, UnitId.TerranWatchdog, 70-i)
|
||||
wait(secs(30 + 5 * i))
|
||||
end
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
local function build_main_town(town)
|
||||
town:build(20, UnitId.TerranMason, 90)
|
||||
wait(secs(30))
|
||||
town:build(1, UnitId.TerranStockade, 100)
|
||||
wait(secs(90))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
wait(secs(5))
|
||||
town:build(3, UnitId.TerranStockade, 70)
|
||||
wait(mins(1))
|
||||
town:multirun(flyer_watch)
|
||||
town:build(4, UnitId.TerranStockade, 70)
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
local function build_expo(town)
|
||||
cprint(TextColor.Orange, "Expanding:")
|
||||
print(town)
|
||||
town:build(1, UnitId.TerranMinistry, 90)
|
||||
town:wait_build(1, UnitId.TerranMinistry)
|
||||
town:transfer_workers(4)
|
||||
town:build(20, UnitId.TerranMason, 85)
|
||||
town:wait_build(10, UnitId.TerranMason)
|
||||
town:multirun(flyer_watch)
|
||||
town:build(1, UnitId.TerranStockade, 80)
|
||||
wait(secs(30))
|
||||
town:build(2, UnitId.TerranStockade, 70)
|
||||
-- TODO: town:build_at(UnitId.TerranStockage, Point(69, 69), 90)
|
||||
-- TODO: town:new_guard(...)
|
||||
end
|
||||
|
||||
local function expand_loop()
|
||||
wait(secs(90))
|
||||
while true do
|
||||
local town = ai:expand()
|
||||
town:multirun(build_expo) -- town:multirun manages script lifetime based on town alive state
|
||||
if town.is_alive then
|
||||
wait(math.random(mins(3), mins(4)))
|
||||
else
|
||||
wait(math.random(secs(30), mins(1))) -- if town didn't create we wait for shorter
|
||||
end
|
||||
|
||||
-- NOTE: if we didn't need the town.is_alive check we can use nice shorthand:
|
||||
-- ai:expand:multirun(build_expo)
|
||||
end
|
||||
end
|
||||
|
||||
local function attack_waves()
|
||||
main_town:wait_build(1, UnitId.TerranStockade)
|
||||
while true do
|
||||
-- Classic attack wave with counts
|
||||
--[[
|
||||
local attack = ai:new_attack()
|
||||
attack.from = Point(3800, 500)
|
||||
if Time.elapsed <= mins(5) then
|
||||
attack:add(5 + (Time.elapsed // mins(2)), UnitId.TerranMaverick)
|
||||
else
|
||||
attack:add(4 + (Time.elapsed // mins(4)), UnitId.TerranMaverick)
|
||||
attack:add(2 + (Time.elapsed // mins(4)), UnitId.TerranHarakan)
|
||||
end
|
||||
]]
|
||||
|
||||
-- Composing attack wave from power value
|
||||
local attack_budget = player:unit_count(UnitId.TerranMason) * 50
|
||||
+ (player.minerals + player.gas) // 2
|
||||
local attack = ai:new_attack(attack_budget)
|
||||
attack.budget = attack_budget
|
||||
attack.timeout = 120
|
||||
-- attack.from = Point(3800, 500)
|
||||
if player:unit_count(UnitId.TerranStockade) > 0 then
|
||||
attack:compose(config.pref_maverick or 1, UnitId.TerranMaverick)
|
||||
attack:compose(config.pref_harakan or 1, UnitId.TerranHarakan)
|
||||
attack:compose(config.pref_cyprian or 1, UnitId.TerranCyprian)
|
||||
end
|
||||
|
||||
cprint(TextColor.Red, "Sending attack:")
|
||||
print(attack)
|
||||
attack:send()
|
||||
wait(math.random(secs(5), secs(15)))
|
||||
end
|
||||
end
|
||||
|
||||
local function dump_defenses()
|
||||
cprint(TextColor.Yellow3, "Defenses:")
|
||||
print("build.gg:", ai.defense.build.gg)
|
||||
print("use.gg:", ai.defense.use.gg)
|
||||
print("build.ag:", ai.defense.build.ag)
|
||||
print("use.ag:", ai.defense.use.ag)
|
||||
print("build.ga:", ai.defense.build.ga)
|
||||
print("use.ga:", ai.defense.use.ga)
|
||||
print("build.aa:", ai.defense.build.aa)
|
||||
print("use.aa:", ai.defense.use.aa)
|
||||
end
|
||||
|
||||
---@param unit_id UnitId
|
||||
---@param cond fun(): boolean
|
||||
local function defense_watch_impl(unit_id, cond)
|
||||
while true do
|
||||
wait_until(cond, secs(1))
|
||||
ai.defense:auto_set(unit_id)
|
||||
-- dump_defenses()
|
||||
wait_while(cond, secs(1))
|
||||
ai.defense:auto_remove(unit_id)
|
||||
-- dump_defenses()
|
||||
end
|
||||
end
|
||||
|
||||
---@param factory_id UnitId
|
||||
---@param unit_id UnitId
|
||||
local function defense_watch(factory_id, unit_id)
|
||||
defense_watch_impl(unit_id, function()
|
||||
return player:unit_count(factory_id) > 0
|
||||
end)
|
||||
end
|
||||
|
||||
-- Run all the functions
|
||||
|
||||
-- Special kind of multirun, this script will die when town dies
|
||||
-- Equivalent to `multirun(function(town) town:auto_kill() ... end, town)`
|
||||
main_town:multirun(build_main_town)
|
||||
multirun(expand_loop)
|
||||
multirun(attack_waves)
|
||||
multirun(defense_watch, UnitId.TerranStockade, UnitId.TerranMaverick)
|
||||
multirun(defense_watch, UnitId.TerranStockade, UnitId.TerranHarakan)
|
||||
|
||||
wait(mins(8))
|
||||
brain.saw_air_units = true -- let's pretend, since we don't have api for detecting units yet
|
||||
3
mpq/lua/examples/start_melee_ai.lua
Normal file
3
mpq/lua/examples/start_melee_ai.lua
Normal file
@ -0,0 +1,3 @@
|
||||
require "melee.melee_ai"
|
||||
|
||||
MeleeAI(Personalities.Terran.Raider.EightRax):run()
|
||||
6
mpq/lua/examples/start_melee_ai_customized.lua
Normal file
6
mpq/lua/examples/start_melee_ai_customized.lua
Normal file
@ -0,0 +1,6 @@
|
||||
require "melee.melee_ai"
|
||||
|
||||
local eight_rax_harakan = deepcopy(Personalities.Terran.Raider.EightRax)
|
||||
eight_rax_harakan.unit_composition[UnitId.TerranHarakan] = 3
|
||||
|
||||
MeleeAI(eight_rax_harakan):run()
|
||||
13
mpq/lua/melee/askosi/basic.lua
Normal file
13
mpq/lua/melee/askosi/basic.lua
Normal file
@ -0,0 +1,13 @@
|
||||
local Basic = {}
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_ground(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 4, UnitId.AskosiGrandstand, 70, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_air(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 4, UnitId.AskosiGrandstand, 80, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
return Basic
|
||||
40
mpq/lua/melee/askosi/temp/temp_default.lua
Normal file
40
mpq/lua/melee/askosi/temp/temp_default.lua
Normal file
@ -0,0 +1,40 @@
|
||||
local Basic = require "melee.askosi.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Temp Default",
|
||||
unit_composition = {
|
||||
-- ground
|
||||
[UnitId.AskosiMissionary] = 1,
|
||||
[UnitId.AskosiCardinal] = 1,
|
||||
[UnitId.AskosiRove] = 1,
|
||||
[UnitId.AskosiObject] = 1,
|
||||
[UnitId.AskosiScepter] = 1,
|
||||
[UnitId.AskosiIntendent] = 1,
|
||||
-- air
|
||||
[UnitId.AskosiHelion] = 1,
|
||||
[UnitId.AskosiEmissary] = 1,
|
||||
[UnitId.AskosiInkblot] = 1,
|
||||
[UnitId.AskosiTirade] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.AskosiRadix, 100, true)
|
||||
town:build(1, UnitId.AskosiFunction, 100, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.AskosiCosmoscope, 90, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:start_expanding()
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:build(1, UnitId.AskosiRadix, 70, true)
|
||||
town:build(1, UnitId.AskosiFunction, 70, true)
|
||||
town:build(1, UnitId.AskosiCosmoscope, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
20
mpq/lua/melee/deepcopy.lua
Normal file
20
mpq/lua/melee/deepcopy.lua
Normal file
@ -0,0 +1,20 @@
|
||||
---@param original any
|
||||
---@param seen? table
|
||||
---@return any
|
||||
function deepcopy(original, seen)
|
||||
if type(original) ~= "table" then
|
||||
return original
|
||||
end
|
||||
|
||||
seen = seen or {}
|
||||
if seen[original] then
|
||||
return seen[original]
|
||||
end
|
||||
|
||||
local copy = {}
|
||||
seen[original] = copy
|
||||
for key, value in pairs(original) do
|
||||
copy[deepcopy(key, seen)] = deepcopy(value, seen)
|
||||
end
|
||||
return setmetatable(copy, deepcopy(getmetatable(original), seen))
|
||||
end
|
||||
366
mpq/lua/melee/melee_ai.lua
Normal file
366
mpq/lua/melee/melee_ai.lua
Normal file
@ -0,0 +1,366 @@
|
||||
require "melee.deepcopy"
|
||||
require "melee.personalities"
|
||||
|
||||
---@alias BuildOrder fun(melee_ai: MeleeAI, town: Town)
|
||||
|
||||
---@class AIPersonality
|
||||
---@field name string
|
||||
---@field unit_composition table<UnitId, number>
|
||||
---@field main_build_order BuildOrder
|
||||
---@field expansion_build_order BuildOrder
|
||||
---@field build_anti_ground_defenses BuildOrder
|
||||
---@field build_anti_air_defenses BuildOrder
|
||||
---@field expand_rate? number Default is 3 minutes 30 seconds
|
||||
---@field expand_wait_after_fail? number Default is 30 seconds
|
||||
---@field attack_wave_budget_scaling? number Default is 1.0
|
||||
---@field attack_wave_cost_bias? number Default derived from AI:new_attack()
|
||||
|
||||
---@class TownState
|
||||
---@field started_anti_ground_defenses boolean
|
||||
---@field started_anti_air_defenses boolean
|
||||
|
||||
---@overload fun(personality?: AIPersonality, player?: Player): MeleeAI
|
||||
---@class MeleeAI
|
||||
---@field debugging {enabled: boolean, last_tick: number, last_script_id: number}
|
||||
---@field player Player
|
||||
---@field personality AIPersonality
|
||||
---@field ai AI
|
||||
---@field main_town Town
|
||||
---@field towns table<Town, TownState>
|
||||
---@field started_expanding boolean
|
||||
---@field started_attacking boolean
|
||||
---@field seen_air_threats boolean
|
||||
MeleeAI = {}
|
||||
MeleeAI.__index = MeleeAI
|
||||
|
||||
setmetatable(MeleeAI, {
|
||||
__call = function(cls, ...)
|
||||
return cls.new(...)
|
||||
end,
|
||||
})
|
||||
|
||||
---@param personality? AIPersonality
|
||||
---@param player? Player
|
||||
---@return MeleeAI melee_ai
|
||||
function MeleeAI.new(personality, player)
|
||||
local self = setmetatable({}, MeleeAI)
|
||||
self.player = player or Player()
|
||||
if self.player.type ~= PlayerType.Computer then
|
||||
return self
|
||||
end
|
||||
self.debugging = {
|
||||
enabled = PlayerVars(self.player).ai_debug or false,
|
||||
last_tick = -1,
|
||||
last_script_id = -1,
|
||||
}
|
||||
self.personality = personality or Personalities.pick_random(player)
|
||||
self.ai = AI(self.player.id)
|
||||
self.main_town = self.ai:start_town()
|
||||
self.towns = {
|
||||
[self.main_town] = {
|
||||
started_anti_ground_defenses = false,
|
||||
started_anti_air_defenses = false,
|
||||
},
|
||||
}
|
||||
self.started_expanding = false
|
||||
self.started_attacking = false
|
||||
self.seen_air_threats = true -- TODO: detect dynamically or after timeout
|
||||
-- TODO: maybe have a dynamic unit loss threshold check that triggers a stronger defense response
|
||||
|
||||
self:cdebug(TextColor.White, "Starting AI with personality: " .. self.personality.name)
|
||||
return self
|
||||
end
|
||||
|
||||
function MeleeAI:debug_header()
|
||||
if self.debugging.last_tick ~= Time.elapsed or self.debugging.last_script_id ~= Script.id then
|
||||
self.debugging.last_tick = Time.elapsed
|
||||
self.debugging.last_script_id = Script.id
|
||||
print()
|
||||
cprint(TextColor.Yellow3, "-- " .. tostring(self.player.name) .. " (P" .. tostring(self.player.id) .. "):\n")
|
||||
end
|
||||
end
|
||||
|
||||
function MeleeAI:debug(...)
|
||||
if self.debugging.enabled then
|
||||
self:debug_header()
|
||||
print(...)
|
||||
end
|
||||
end
|
||||
|
||||
function MeleeAI:cdebug(color, ...)
|
||||
if self.debugging.enabled then
|
||||
self:debug_header()
|
||||
cprint(color, ...)
|
||||
end
|
||||
end
|
||||
|
||||
---@protected
|
||||
---@return table<UnitId, number>
|
||||
function MeleeAI:get_final_unit_composition()
|
||||
local unit_composition = {}
|
||||
for unit_id, preference in pairs(self.personality.unit_composition) do
|
||||
unit_composition[unit_id] = preference
|
||||
end
|
||||
return unit_composition
|
||||
end
|
||||
|
||||
function MeleeAI:run()
|
||||
if not self.ai then
|
||||
return
|
||||
end
|
||||
for unit_id, preference in pairs(self:get_final_unit_composition()) do
|
||||
if preference > 0 then
|
||||
multirun(function()
|
||||
wait_until(function() return self.player:can_make(unit_id) end, secs(1))
|
||||
self:cdebug(TextColor.Teal, "Added " .. UnitId.name(unit_id) .. " to defense")
|
||||
self.ai.defense:auto_set(unit_id)
|
||||
wait_while(function() return self.player:can_make(unit_id) end, secs(1))
|
||||
self:cdebug(TextColor.Teal, "Added " .. UnitId.name(unit_id) .. " to defense")
|
||||
self.ai.defense:auto_remove(unit_id)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
self.main_town:multirun(function(main_town)
|
||||
self.personality.main_build_order(self, main_town)
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_expanding()
|
||||
if self.started_expanding then
|
||||
return
|
||||
end
|
||||
self.started_expanding = true
|
||||
multirun(function()
|
||||
while true do
|
||||
local town = self.ai:expand()
|
||||
self:cdebug(TextColor.Green, "Expanding:")
|
||||
self:debug(town)
|
||||
if town.is_alive then
|
||||
self.towns[town] = {
|
||||
started_anti_ground_defenses = false,
|
||||
started_anti_air_defenses = false,
|
||||
}
|
||||
town:multirun(function()
|
||||
self.personality.expansion_build_order(self, town)
|
||||
end)
|
||||
wait(self.personality.expand_rate or (mins(3) + secs(30)))
|
||||
else
|
||||
wait(self.personality.expand_wait_after_fail or secs(30))
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_attacking()
|
||||
if self.started_attacking then
|
||||
return
|
||||
end
|
||||
self.started_attacking = true
|
||||
multirun(function()
|
||||
while true do
|
||||
local budget = self:town_count() * 500 +
|
||||
self.player:unit_count(self:default_worker()) * 50 +
|
||||
(self.ai.minerals + self.ai.gas) / 2
|
||||
budget = budget * (self.personality.attack_wave_budget_scaling or 1.0)
|
||||
|
||||
local attack = self.ai:new_attack(budget, self.personality.attack_wave_cost_bias or nil)
|
||||
for unit_id, preference in pairs(self:get_final_unit_composition()) do
|
||||
if preference > 0 and self.player:can_make(unit_id) then
|
||||
attack:compose(preference, unit_id)
|
||||
end
|
||||
end
|
||||
|
||||
self:cdebug(TextColor.Orange, "Sending attack:")
|
||||
self:debug(attack)
|
||||
attack:send()
|
||||
wait(secs(5))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_anti_ground_defenses(town)
|
||||
if self.personality.build_anti_ground_defenses == nil then
|
||||
return
|
||||
end
|
||||
if self.towns[town].started_anti_ground_defenses then
|
||||
return
|
||||
end
|
||||
self.towns[town].started_anti_ground_defenses = true
|
||||
|
||||
multirun(function()
|
||||
self.personality.build_anti_ground_defenses(self, town)
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_anti_air_defenses(town)
|
||||
if self.personality.build_anti_air_defenses == nil then
|
||||
return
|
||||
end
|
||||
if self.towns[town].started_anti_air_defenses then
|
||||
return
|
||||
end
|
||||
self.towns[town].started_anti_air_defenses = true
|
||||
|
||||
multirun(function()
|
||||
wait_until(function() return self.seen_air_threats end, secs(1))
|
||||
self.personality.build_anti_air_defenses(self, town)
|
||||
end)
|
||||
end
|
||||
|
||||
---@return UnitId worker_unit_id
|
||||
function MeleeAI:default_worker()
|
||||
local race = self.player.race
|
||||
if race == RaceId.Terran then
|
||||
return UnitId.TerranMason
|
||||
elseif race == RaceId.Zerg then
|
||||
return UnitId.ZergDroleth
|
||||
elseif race == RaceId.Protoss then
|
||||
return UnitId.ProtossScribe
|
||||
elseif race == RaceId.Askosi then
|
||||
return UnitId.AskosiPilgrim
|
||||
end
|
||||
error("Race " .. tostring(race) .. " has no default worker set")
|
||||
end
|
||||
|
||||
---@return UnitId town_building_unit_id
|
||||
function MeleeAI:default_town_building()
|
||||
local race = self.player.race
|
||||
if race == RaceId.Terran then
|
||||
return UnitId.TerranMinistry
|
||||
elseif race == RaceId.Zerg then
|
||||
return UnitId.ZergHachirosk
|
||||
elseif race == RaceId.Protoss then
|
||||
return UnitId.ProtossNexus
|
||||
elseif race == RaceId.Askosi then
|
||||
return UnitId.AskosiLandlock
|
||||
end
|
||||
error("Race " .. tostring(race) .. " has no default town set")
|
||||
end
|
||||
|
||||
---@param unit_id UnitId
|
||||
---@return boolean
|
||||
function MeleeAI:can_make(unit_id)
|
||||
return self.player:can_make(unit_id)
|
||||
end
|
||||
|
||||
---@return number
|
||||
function MeleeAI:worker_count(town)
|
||||
return town:unit_count(self:default_worker(), true)
|
||||
end
|
||||
|
||||
---@return number
|
||||
function MeleeAI:total_worker_count()
|
||||
return self.player:unit_count(self:default_worker(), true)
|
||||
end
|
||||
|
||||
---@return number
|
||||
function MeleeAI:town_count()
|
||||
local count = 0
|
||||
for town, _ in pairs(self.towns) do
|
||||
if town.is_alive and town:unit_count(self:default_town_building(), true) > 0 then
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
---@param duration integer
|
||||
function MeleeAI:dynamic_wait(duration)
|
||||
local elapsed = 0
|
||||
while elapsed < duration do
|
||||
local chunk = math.min(secs(2), duration - elapsed)
|
||||
local resources = self.ai.minerals + self.ai.gas
|
||||
local resource_scale = math.max(0, math.min(1, (1100 - resources) / 600))
|
||||
local scaled_chunk = math.floor(chunk * resource_scale)
|
||||
if scaled_chunk > 0 then
|
||||
wait(scaled_chunk)
|
||||
end
|
||||
elapsed = elapsed + chunk
|
||||
end
|
||||
end
|
||||
|
||||
---@param unit_id UnitId
|
||||
function MeleeAI:wait_can_make(unit_id)
|
||||
wait_until(function()
|
||||
return self.player:can_make(unit_id)
|
||||
end, secs(1))
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
---@param count number
|
||||
function MeleeAI:wait_worker_count(town, count)
|
||||
wait_until(function()
|
||||
return self:worker_count(town) >= count
|
||||
end, secs(1))
|
||||
end
|
||||
|
||||
---@param count number
|
||||
function MeleeAI:wait_total_worker_count(count)
|
||||
wait_until(function()
|
||||
return self:total_worker_count() >= count
|
||||
end, secs(1))
|
||||
end
|
||||
|
||||
---@param count number
|
||||
function MeleeAI:wait_town_count(count)
|
||||
wait_until(function()
|
||||
return self:town_count() >= count
|
||||
end, secs(1))
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
---@param ... BuildOrder
|
||||
function MeleeAI:pick_random(town, ...)
|
||||
local builds = {...}
|
||||
builds[math.random(#builds)](self, town)
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
function MeleeAI:build_main(town)
|
||||
town:build(1, self:default_town_building(), 120)
|
||||
town:build(town.max_workers, self:default_worker(), 100)
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
---@param wait_for_workers boolean
|
||||
function MeleeAI:build_expansion(town, wait_for_workers)
|
||||
town:build(1, self:default_town_building(), 120)
|
||||
town:wait_build(1, self:default_town_building())
|
||||
town:build(town.max_workers, self:default_worker(), 100)
|
||||
town:transfer_workers(8)
|
||||
if wait_for_workers then
|
||||
town:wait_build(10, self:default_worker())
|
||||
end
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
---@param count integer
|
||||
---@param unit_id UnitId
|
||||
---@param priority integer
|
||||
---@param wait? integer
|
||||
function MeleeAI:build_and_wait(town, count, unit_id, priority, wait)
|
||||
town:build(count, unit_id, priority)
|
||||
town:wait_build(count, unit_id, false)
|
||||
if wait then
|
||||
self:dynamic_wait(wait)
|
||||
end
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
---@param start integer
|
||||
---@param end_ integer
|
||||
---@param unit_id UnitId
|
||||
---@param priority integer
|
||||
---@param priority_decrease integer
|
||||
---@param wait integer
|
||||
---@param wait_increase integer
|
||||
function MeleeAI:build_sequence(town, start, end_, unit_id, priority, priority_decrease, wait, wait_increase)
|
||||
for i = start, end_ do
|
||||
town:build(i, unit_id, priority - priority_decrease * (i - 1))
|
||||
town:wait_build(i, unit_id, false)
|
||||
if wait and i ~= end_ then
|
||||
self:dynamic_wait(wait + wait_increase * (i - 1))
|
||||
end
|
||||
end
|
||||
end
|
||||
150
mpq/lua/melee/personalities.lua
Normal file
150
mpq/lua/melee/personalities.lua
Normal file
@ -0,0 +1,150 @@
|
||||
---@class Personalities
|
||||
Personalities = {
|
||||
Terran = {
|
||||
General = {
|
||||
TwoFulcrumMech = require "melee.terran.general.two_fulcrum_mech",
|
||||
EarlyRiser = require "melee.terran.general.early_riser",
|
||||
TheCube = require "melee.terran.general.the_cube",
|
||||
DoublingUp = require "melee.terran.general.doubling_up",
|
||||
MechIntoAir = require "melee.terran.general.mech_into_air",
|
||||
Observant = require "melee.terran.general.observant",
|
||||
},
|
||||
Raider = {
|
||||
EightRax = require "melee.terran.raider.eight_rax",
|
||||
ThreeRaxBio = require "melee.terran.raider.three_rax_bio",
|
||||
FastAnvil = require "melee.terran.raider.fast_anvil",
|
||||
FourRaxPressure = require "melee.terran.raider.four_rax_pressure",
|
||||
Uprising = require "melee.terran.raider.uprising",
|
||||
HolyAckmeds = require "melee.terran.raider.holy_ackmeds",
|
||||
},
|
||||
Armor = {
|
||||
TankPush = require "melee.terran.armor.tank_push",
|
||||
FeFiveFulc = require "melee.terran.armor.fe_five_fulc",
|
||||
TwoFulcVulture = require "melee.terran.armor.two_fulc_vulture",
|
||||
WalkerPower = require "melee.terran.armor.walker_power",
|
||||
IronCrusade = require "melee.terran.armor.iron_crusade",
|
||||
DavidAndGoliath = require "melee.terran.armor.david_and_goliath",
|
||||
},
|
||||
Orbital = {
|
||||
RapidStarpads = require "melee.terran.orbital.rapid_starpads",
|
||||
TheDon = require "melee.terran.orbital.the_don",
|
||||
WraithBio = require "melee.terran.orbital.wraith_bio",
|
||||
Hotdrop = require "melee.terran.orbital.hotdrop",
|
||||
SuddenStarport = require "melee.terran.orbital.sudden_starport",
|
||||
AcesHigh = require "melee.terran.orbital.aces_high",
|
||||
},
|
||||
},
|
||||
Protoss = {
|
||||
General = {
|
||||
LunaticLegion = require "melee.protoss.general.lunatic_legion",
|
||||
StridentStriders = require "melee.protoss.general.strident_striders",
|
||||
Worship = require "melee.protoss.general.worship",
|
||||
RoboticsFe = require "melee.protoss.general.robotics_fe",
|
||||
TheSwordsmiths = require "melee.protoss.general.the_swordsmiths",
|
||||
Matriarchy = require "melee.protoss.general.matriarchy",
|
||||
},
|
||||
Templar = {
|
||||
ThreeGateStrider = require "melee.protoss.templar.three_gate_strider",
|
||||
SuffocatingShadow = require "melee.protoss.templar.suffocating_shadow",
|
||||
Legion = require "melee.protoss.templar.legion",
|
||||
Initiates = require "melee.protoss.templar.initiates",
|
||||
Martyrdom = require "melee.protoss.templar.martyrdom",
|
||||
LegionsHeralds = require "melee.protoss.templar.legions_heralds",
|
||||
},
|
||||
Ranger = {
|
||||
TwoGateStrider = require "melee.protoss.ranger.two_gate_strider",
|
||||
EmissarySquared = require "melee.protoss.ranger.emissary_squared",
|
||||
OneGateAuthority = require "melee.protoss.ranger.one_gate_authority",
|
||||
LatticeExpo = require "melee.protoss.ranger.lattice_expo",
|
||||
SimulantSwarm = require "melee.protoss.ranger.simulant_swarm",
|
||||
TheRegistry = require "melee.protoss.ranger.the_registry",
|
||||
},
|
||||
Skylord = {
|
||||
SolarEscort = require "melee.protoss.skylord.solar_escort",
|
||||
DeadlyOmen = require "melee.protoss.skylord.deadly_omen",
|
||||
TwoGatePanoptus = require "melee.protoss.skylord.two_gate_panoptus",
|
||||
Exalted = require "melee.protoss.skylord.exalted",
|
||||
SorrowFleet = require "melee.protoss.skylord.sorrow_fleet",
|
||||
ShipsAndSwords = require "melee.protoss.skylord.ships_and_swords",
|
||||
},
|
||||
},
|
||||
Zerg = {
|
||||
General = {
|
||||
SleepingGiant = require "melee.zerg.general.sleeping_giant",
|
||||
ShriekingSwarm = require "melee.zerg.general.shrieking_swarm",
|
||||
Subjugation = require "melee.zerg.general.subjugation",
|
||||
BeforeTheStorm = require "melee.zerg.general.before_the_storm",
|
||||
TimeAfterTime = require "melee.zerg.general.time_after_time",
|
||||
ConstrainedCoil = require "melee.zerg.general.constrained_coil",
|
||||
},
|
||||
Swarm = {
|
||||
ThreeBaseFlood = require "melee.zerg.swarm.three_base_flood",
|
||||
ThreeBaseUltrav = require "melee.zerg.swarm.three_base_ultrav",
|
||||
InstantQuazeth = require "melee.zerg.swarm.instant_quazeth",
|
||||
ThreeBaseOthstol = require "melee.zerg.swarm.three_base_othstol",
|
||||
GatesOfHell = require "melee.zerg.swarm.gates_of_hell",
|
||||
PrimitivePressure = require "melee.zerg.swarm.primitive_pressure",
|
||||
},
|
||||
Assault = {
|
||||
ThreeBaseHydrith = require "melee.zerg.assault.three_base_hydrith",
|
||||
TwoBaseZorkiz = require "melee.zerg.assault.two_base_zorkiz",
|
||||
TwoBaseHydrithQuazeth = require "melee.zerg.assault.two_base_hydrith_quazeth",
|
||||
TwoBaseAlkag = require "melee.zerg.assault.two_base_alkag",
|
||||
Potency = require "melee.zerg.assault.potency",
|
||||
EarthenTides = require "melee.zerg.assault.earthen_tides",
|
||||
},
|
||||
Sunblot = {
|
||||
BigAndLittle = require "melee.zerg.sunblot.big_and_little",
|
||||
TheTriad = require "melee.zerg.sunblot.the_triad",
|
||||
SkitteringDuo = require "melee.zerg.sunblot.skittering_duo",
|
||||
EarlyBirds = require "melee.zerg.sunblot.early_birds",
|
||||
FlyingFeint = require "melee.zerg.sunblot.flying_feint",
|
||||
DescendingHorizon = require "melee.zerg.sunblot.descending_horizon",
|
||||
},
|
||||
},
|
||||
Askosi = {
|
||||
Temp = {
|
||||
Default = require "melee.askosi.temp.temp_default",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
---@class RacePersonalities
|
||||
|
||||
---@param race RaceId
|
||||
---@return RacePersonalities
|
||||
local function by_race(race)
|
||||
if race == RaceId.Terran then
|
||||
return Personalities.Terran
|
||||
elseif race == RaceId.Zerg then
|
||||
return Personalities.Zerg
|
||||
elseif race == RaceId.Protoss then
|
||||
return Personalities.Protoss
|
||||
elseif race == RaceId.Askosi then
|
||||
return Personalities.Askosi
|
||||
end
|
||||
error("Race " .. tostring(race) .. " is not a valid AI race")
|
||||
end
|
||||
|
||||
---@param dict table
|
||||
---@return AIPersonality
|
||||
local function pick_random(dict)
|
||||
local keys = {}
|
||||
for key, _ in pairs(dict) do
|
||||
table.insert(keys, key)
|
||||
end
|
||||
local random_key = keys[math.random(#keys)]
|
||||
return dict[random_key]
|
||||
end
|
||||
|
||||
---@param player? Player
|
||||
---@return AIPersonality
|
||||
function Personalities.pick_random(player)
|
||||
player = player or Player()
|
||||
local race = by_race(player.race)
|
||||
local category = pick_random(race)
|
||||
local personality = pick_random(category)
|
||||
return personality
|
||||
end
|
||||
|
||||
return Personalities
|
||||
13
mpq/lua/melee/protoss/basic.lua
Normal file
13
mpq/lua/melee/protoss/basic.lua
Normal file
@ -0,0 +1,13 @@
|
||||
local Basic = {}
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_ground(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 4, UnitId.ProtossWarden, 70, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_air(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 3, UnitId.ProtossMatrix, 80, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
return Basic
|
||||
72
mpq/lua/melee/protoss/general/lunatic_legion.lua
Normal file
72
mpq/lua/melee/protoss/general/lunatic_legion.lua
Normal file
@ -0,0 +1,72 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Lunatic Legion",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossAurora] = 1,
|
||||
[UnitId.ProtossMagister] = 1,
|
||||
[UnitId.ProtossDidact] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(3, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- production for the Legionnaire + Simulacrum army + Stargate / Argosy fleet & Synthetic Synod
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 82, true)
|
||||
town:build(1, UnitId.ProtossEmbassy, 80, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossArgosy, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
67
mpq/lua/melee/protoss/general/matriarchy.lua
Normal file
67
mpq/lua/melee/protoss/general/matriarchy.lua
Normal file
@ -0,0 +1,67 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Matriarchy",
|
||||
unit_composition = {
|
||||
-- signature units (Prostration Stage / Synthetic Synod)
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossAmaranth] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEmpress] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossMindTyrant] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
-- tier4
|
||||
town:build(2, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- production for the Zealot / Amaranth / Vassal army + Synthetic Synod & Prostration Stage tech
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 82, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
63
mpq/lua/melee/protoss/general/robotics_fe.lua
Normal file
63
mpq/lua/melee/protoss/general/robotics_fe.lua
Normal file
@ -0,0 +1,63 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Robotics FE",
|
||||
unit_composition = {
|
||||
-- signature units (Ardent Authority x2)
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossServitor] = 1,
|
||||
[UnitId.ProtossPositron] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossClarion] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(20))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- production for the Ardent Authority core (Servitor / Positron / Accantor / Clarion) + Zealot / Vassal
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 82, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 72, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
58
mpq/lua/melee/protoss/general/strident_striders.lua
Normal file
58
mpq/lua/melee/protoss/general/strident_striders.lua
Normal file
@ -0,0 +1,58 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Strident Striders",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossDracadin] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(45))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- production for the Dracadin striders (+ Atreus / Pariah / Analogue) + Synthetic Synod tech
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 82, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
70
mpq/lua/melee/protoss/general/the_swordsmiths.lua
Normal file
70
mpq/lua/melee/protoss/general/the_swordsmiths.lua
Normal file
@ -0,0 +1,70 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: The Swordsmiths",
|
||||
unit_composition = {
|
||||
-- signature units (Ardent Authority x2)
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossManifold] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossServitor] = 1,
|
||||
[UnitId.ProtossPositron] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossClarion] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
town:wait_build(1, UnitId.ProtossGateway)
|
||||
town:wait_build(1, UnitId.ProtossLattice)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- production for the Zealot + Manifold + Ardent Authority core + Synthetic Synod tech
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 82, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 72, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
68
mpq/lua/melee/protoss/general/worship.lua
Normal file
68
mpq/lua/melee/protoss/general/worship.lua
Normal file
@ -0,0 +1,68 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Worship",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossAmaranth] = 2,
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossGolem] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- production for the Amaranth + Simulacrum army + Synthetic Synod & Prostration Stage tech
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 82, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
68
mpq/lua/melee/protoss/ranger/emissary_squared.lua
Normal file
68
mpq/lua/melee/protoss/ranger/emissary_squared.lua
Normal file
@ -0,0 +1,68 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Ranger: Emissary Squared",
|
||||
unit_composition = {
|
||||
-- signature units (Synthetic Synod)
|
||||
[UnitId.ProtossAnalogue] = 2,
|
||||
[UnitId.ProtossDemiurge] = 2,
|
||||
[UnitId.ProtossEmpress] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossVassal] = 1,
|
||||
[UnitId.ProtossGolem] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossLattice, 70)
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Lattice / Gateway army + Synthetic Synod & Prostration Stage tech
|
||||
town:build(1, UnitId.ProtossLattice, 85, true)
|
||||
town:build(1, UnitId.ProtossGateway, 82, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
60
mpq/lua/melee/protoss/ranger/lattice_expo.lua
Normal file
60
mpq/lua/melee/protoss/ranger/lattice_expo.lua
Normal file
@ -0,0 +1,60 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Ranger: Lattice Expo",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(3, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Lattice / Gateway army + Synthetic Synod & Prostration Stage tech
|
||||
town:build(1, UnitId.ProtossLattice, 85, true)
|
||||
town:build(1, UnitId.ProtossGateway, 82, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
73
mpq/lua/melee/protoss/ranger/one_gate_authority.lua
Normal file
73
mpq/lua/melee/protoss/ranger/one_gate_authority.lua
Normal file
@ -0,0 +1,73 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Ranger: 1 Gate Authority",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossManifold] = 2,
|
||||
-- filler units (Prostration Stage)
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossPotentate] = 1,
|
||||
[UnitId.ProtossSycophant] = 1,
|
||||
[UnitId.ProtossMindTyrant] = 1,
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(4, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ProtossArdentAuthority, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Manifold + Prostration Stage army (+ Accantor / Analogue)
|
||||
town:build(1, UnitId.ProtossLattice, 85, true)
|
||||
town:build(1, UnitId.ProtossGateway, 82, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
67
mpq/lua/melee/protoss/ranger/simulant_swarm.lua
Normal file
67
mpq/lua/melee/protoss/ranger/simulant_swarm.lua
Normal file
@ -0,0 +1,67 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Ranger: Simulant Swarm",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(5, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Simulacrum swarm + Synthetic Synod & Prostration Stage tech
|
||||
town:build(1, UnitId.ProtossLattice, 85, true)
|
||||
town:build(1, UnitId.ProtossGateway, 82, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
60
mpq/lua/melee/protoss/ranger/the_registry.lua
Normal file
60
mpq/lua/melee/protoss/ranger/the_registry.lua
Normal file
@ -0,0 +1,60 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Ranger: The Registry",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossManifold] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(4, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Manifold registry army + Synthetic Synod & Prostration Stage tech
|
||||
town:build(1, UnitId.ProtossLattice, 85, true)
|
||||
town:build(1, UnitId.ProtossGateway, 82, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
65
mpq/lua/melee/protoss/ranger/two_gate_strider.lua
Normal file
65
mpq/lua/melee/protoss/ranger/two_gate_strider.lua
Normal file
@ -0,0 +1,65 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Ranger: 2 Gate Strider",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossDracadin] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(5, UnitId.ProtossGateway, 70)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Vassal + Dracadin striders + Synthetic Synod & Prostration Stage tech
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 82, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
71
mpq/lua/melee/protoss/skylord/deadly_omen.lua
Normal file
71
mpq/lua/melee/protoss/skylord/deadly_omen.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Skylord: Deadly Omen",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossExemplar] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossStarSovereign] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossStargate, 90)
|
||||
town:wait_build(1, UnitId.ProtossStargate)
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(5, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Zealot + Vassal + Panoptus army (-> Argosy -> Monument of Sin) + Pariah tech
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
town:build(1, UnitId.ProtossEmbassy, 78, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 68, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossArgosy, 55, true)
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
73
mpq/lua/melee/protoss/skylord/exalted.lua
Normal file
73
mpq/lua/melee/protoss/skylord/exalted.lua
Normal file
@ -0,0 +1,73 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Skylord: Exalted",
|
||||
unit_composition = {
|
||||
-- signature units (Monument of Sin)
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossStarSovereign] = 2,
|
||||
[UnitId.ProtossAnthelion] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossExemplar] = 1,
|
||||
[UnitId.ProtossDidact] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
town:build(1, UnitId.ProtossWarden, 79)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossWarden, 79)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
town:wait_build(1, UnitId.ProtossArgosy, false)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossCrucible, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the exalted capital fleet (Star Sovereign / Anthelion / Didact) + Crucible
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
town:build(1, UnitId.ProtossEmbassy, 78, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossArgosy, 55, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossCrucible, 50, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
67
mpq/lua/melee/protoss/skylord/ships_and_swords.lua
Normal file
67
mpq/lua/melee/protoss/skylord/ships_and_swords.lua
Normal file
@ -0,0 +1,67 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Skylord: Ships and Swords",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossAurora] = 1.5,
|
||||
[UnitId.ProtossMagister] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.ProtossGladius] = 1,
|
||||
[UnitId.ProtossStarSovereign] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(3, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Stargate + Argosy fleet (Aurora / Magister / Gladius) -> Monument of Sin
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
town:build(1, UnitId.ProtossEmbassy, 78, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossArgosy, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
63
mpq/lua/melee/protoss/skylord/solar_escort.lua
Normal file
63
mpq/lua/melee/protoss/skylord/solar_escort.lua
Normal file
@ -0,0 +1,63 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Skylord: Solar Escort",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossSolarion] = 2,
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossGladius] = 1,
|
||||
[UnitId.ProtossEmpyrean] = 1,
|
||||
[UnitId.ProtossStarSovereign] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(3, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Solarion + Vassal escort (Stargate -> Argosy -> Monument of Sin) + Gateway
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
town:build(1, UnitId.ProtossEmbassy, 78, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossArgosy, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
63
mpq/lua/melee/protoss/skylord/sorrow_fleet.lua
Normal file
63
mpq/lua/melee/protoss/skylord/sorrow_fleet.lua
Normal file
@ -0,0 +1,63 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Skylord: Sorrow Fleet",
|
||||
unit_composition = {
|
||||
-- signature units (Monument of Sin)
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossStarSovereign] = 2,
|
||||
[UnitId.ProtossAnthelion] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossGladius] = 1,
|
||||
[UnitId.ProtossEmpyrean] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(2, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(45))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Monument of Sin fleet (Star Sovereign / Anthelion) + Stargate / Argosy
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
town:build(1, UnitId.ProtossEmbassy, 78, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossArgosy, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
62
mpq/lua/melee/protoss/skylord/two_gate_panoptus.lua
Normal file
62
mpq/lua/melee/protoss/skylord/two_gate_panoptus.lua
Normal file
@ -0,0 +1,62 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Skylord: 2 Gate Panoptus",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossPanoptus] = 3,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossHierophant] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossStarSovereign] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(mins(1) + secs(35))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Panoptus + Vassal army (-> Argosy -> Monument of Sin) + Hierophant / Pariah tech
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
town:build(1, UnitId.ProtossEmbassy, 78, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 68, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossArgosy, 55, true)
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
66
mpq/lua/melee/protoss/templar/initiates.lua
Normal file
66
mpq/lua/melee/protoss/templar/initiates.lua
Normal file
@ -0,0 +1,66 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Templar: Initiates",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossCantavis] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossArchon] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
town:wait_build(2, UnitId.ProtossGateway)
|
||||
melee_ai:dynamic_wait(secs(10))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Zealot core (+ Cantavis / Accantor / Archon / Pariah)
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
68
mpq/lua/melee/protoss/templar/legion.lua
Normal file
68
mpq/lua/melee/protoss/templar/legion.lua
Normal file
@ -0,0 +1,68 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Templar: Legion",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossArchon] = 1,
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
town:build(3, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(5, UnitId.ProtossGateway, 90)
|
||||
town:build(4, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(6, UnitId.ProtossGateway, 90)
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(9, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Legionnaire core (Gateway -> Grand Library -> Ancestral Archives)
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
64
mpq/lua/melee/protoss/templar/legions_heralds.lua
Normal file
64
mpq/lua/melee/protoss/templar/legions_heralds.lua
Normal file
@ -0,0 +1,64 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Templar: Legion's Heralds",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossHerald] = 1,
|
||||
[UnitId.ProtossPatriarch] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(40) + mins(1))
|
||||
town:build(5, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(9, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(55))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Legionnaire + Herald / Patriarch core (Gateway -> Grand Library -> Ancestral Archives)
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
67
mpq/lua/melee/protoss/templar/martyrdom.lua
Normal file
67
mpq/lua/melee/protoss/templar/martyrdom.lua
Normal file
@ -0,0 +1,67 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Templar: Martyrdom",
|
||||
unit_composition = {
|
||||
-- signature units (Ancestral Archives x4)
|
||||
[UnitId.ProtossArchon] = 2,
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossMindTyrant] = 1,
|
||||
[UnitId.ProtossOptecton] = 1,
|
||||
[UnitId.ProtossPatriarch] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(2) + secs(30))
|
||||
-- tier2
|
||||
town:build(4, UnitId.ProtossPylon, 40)
|
||||
town:build(2, UnitId.ProtossRogueGallery, 70)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossCrucible, 50)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(2, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(2, UnitId.ProtossAncestralArchives, false)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Ancestral Archives martyrs (Archon / Optecton / Patriarch + Legionnaire)
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossCrucible, 50, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
59
mpq/lua/melee/protoss/templar/suffocating_shadow.lua
Normal file
59
mpq/lua/melee/protoss/templar/suffocating_shadow.lua
Normal file
@ -0,0 +1,59 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Templar: Suffocating Shadow",
|
||||
unit_composition = {
|
||||
-- signature units (Rogue Gallery)
|
||||
[UnitId.ProtossVagrant] = 2,
|
||||
[UnitId.ProtossCabalist] = 2,
|
||||
[UnitId.ProtossCharlatan] = 2,
|
||||
[UnitId.ProtossBarghest] = 2,
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossArchon] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossRogueGallery, 70)
|
||||
town:build(2, UnitId.ProtossRogueGallery, 70)
|
||||
melee_ai:dynamic_wait(secs(30) + secs(40))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Rogue Gallery shadow army (Vagrant / Cabalist / Charlatan / Barghest + Zealot)
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossRogueGallery, 75, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
60
mpq/lua/melee/protoss/templar/three_gate_strider.lua
Normal file
60
mpq/lua/melee/protoss/templar/three_gate_strider.lua
Normal file
@ -0,0 +1,60 @@
|
||||
local Basic = require "melee.protoss.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Templar: 3 Gate Strider",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
[UnitId.ProtossArchon] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 40)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(5, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier4
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Legionnaire striders (+ Accantor / Dracadin / Archon / Pariah)
|
||||
town:build(1, UnitId.ProtossGateway, 85, true)
|
||||
town:build(1, UnitId.ProtossLattice, 80, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 55, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
97
mpq/lua/melee/terran/armor/david_and_goliath.lua
Normal file
97
mpq/lua/melee/terran/armor/david_and_goliath.lua
Normal file
@ -0,0 +1,97 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Armor: David and Goliath",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranGoliath] = 3,
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMatadorTankMode] = 1,
|
||||
[UnitId.TerranPhalanxTankMode] = 1,
|
||||
[UnitId.TerranWraith] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
town:wait_build(2, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 89)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(5, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranPalladium, 89)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(5, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Goliath / Maverick army (+ Matador / Phalanx / Wraith / Cuirass)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
town:build(1, UnitId.TerranPalladium, 68, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStarpad, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
80
mpq/lua/melee/terran/armor/fe_five_fulc.lua
Normal file
80
mpq/lua/melee/terran/armor/fe_five_fulc.lua
Normal file
@ -0,0 +1,80 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Armor: FE 5Fulc",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranVulture] = 2,
|
||||
[UnitId.TerranBlackjack] = 2,
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
[UnitId.TerranAzazel] = 1,
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
-- tier2 (starport/commandment)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranCommandment, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
melee_ai:dynamic_wait(secs(70) + secs(25))
|
||||
town:build(5, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(15))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Vulture / Blackjack / Phalanx army (+ Azazel / Seraph / Cuirass)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
town:build(1, UnitId.TerranPalladium, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranCommandment, 65, true)
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
78
mpq/lua/melee/terran/armor/iron_crusade.lua
Normal file
78
mpq/lua/melee/terran/armor/iron_crusade.lua
Normal file
@ -0,0 +1,78 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Armor: Iron Crusade",
|
||||
unit_composition = {
|
||||
-- signature units (Iron Foundry x4 is the real investment of this build)
|
||||
[UnitId.TerranPaladin] = 3,
|
||||
[UnitId.TerranCuirassTankMode] = 2,
|
||||
[UnitId.TerranPazuzu] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranVulture] = 1,
|
||||
[UnitId.TerranWraith] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:wait_build(3, UnitId.TerranFulcrum, false)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranMantle, 69, true)
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranIronFoundry, 50)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranIronFoundry, 50)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(3, UnitId.TerranIronFoundry, 50)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(4, UnitId.TerranIronFoundry, 50)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Iron Foundry crusade (Paladin / Cuirass / Pazuzu + Vulture / Wraith / Ramesses)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStarpad, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
84
mpq/lua/melee/terran/armor/tank_push.lua
Normal file
84
mpq/lua/melee/terran/armor/tank_push.lua
Normal file
@ -0,0 +1,84 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Armor: Tank Push",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMatadorTankMode] = 2,
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1,
|
||||
-- filler units
|
||||
[UnitId.TerranCyprian] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranMadrigalImperiosoMode] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranScrapyard, 90)
|
||||
town:multirun(function(town)
|
||||
melee_ai:dynamic_wait(secs(18))
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 89)
|
||||
town:wait_build(4, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranPalladium, 89)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranScrapyard, false)
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.TerranStockade, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Matador / Phalanx tank push (+ Cleric / Ramesses / Cuirass)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
town:build(1, UnitId.TerranPalladium, 68, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
57
mpq/lua/melee/terran/armor/two_fulc_vulture.lua
Normal file
57
mpq/lua/melee/terran/armor/two_fulc_vulture.lua
Normal file
@ -0,0 +1,57 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Armor: 2Fulc Vulture",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranVulture] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
-- tier2/tier3
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Vulture-heavy mech (+ Maverick / Cyclops / Ramesses / Cuirass)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
70
mpq/lua/melee/terran/armor/walker_power.lua
Normal file
70
mpq/lua/melee/terran/armor/walker_power.lua
Normal file
@ -0,0 +1,70 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Armor: Walker Power",
|
||||
unit_composition = {
|
||||
-- signature units (walkers)
|
||||
[UnitId.TerranGoliath] = 3,
|
||||
[UnitId.TerranCyclops] = 2,
|
||||
[UnitId.TerranBlackjack] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranPhalanxTankMode] = 1,
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(10))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
-- tier2/tier3
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Goliath / Cyclops / Blackjack walkers (+ Phalanx / Ramesses / Cuirass)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
town:build(1, UnitId.TerranPalladium, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
13
mpq/lua/melee/terran/basic.lua
Normal file
13
mpq/lua/melee/terran/basic.lua
Normal file
@ -0,0 +1,13 @@
|
||||
local Basic = {}
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_ground(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 2, UnitId.TerranAnchor, 70, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_air(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 4, UnitId.TerranWatchdog, 80, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
return Basic
|
||||
84
mpq/lua/melee/terran/general/doubling_up.lua
Normal file
84
mpq/lua/melee/terran/general/doubling_up.lua
Normal file
@ -0,0 +1,84 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Doubling Up",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
[UnitId.TerranGoliath] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranShamanSupportMode] = 1,
|
||||
-- filler units
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 89)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Maverick + Goliath doubles (+ Shaman / Cyclops / Blackjack / Cuirass)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
65
mpq/lua/melee/terran/general/early_riser.lua
Normal file
65
mpq/lua/melee/terran/general/early_riser.lua
Normal file
@ -0,0 +1,65 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Early Riser",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1,
|
||||
-- filler units
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
[UnitId.TerranRamesses] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
-- tier2/tier3
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Maverick + Cleric core (+ Cyclops / Ramesses / Cuirass)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
107
mpq/lua/melee/terran/general/mech_into_air.lua
Normal file
107
mpq/lua/melee/terran/general/mech_into_air.lua
Normal file
@ -0,0 +1,107 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Mech into Air",
|
||||
unit_composition = {
|
||||
-- signature units (the mech-into-air transition)
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
[UnitId.TerranMinotaur] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMatadorTankMode] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
[UnitId.TerranHippogriff] = 1,
|
||||
[UnitId.TerranPhobos] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 69)
|
||||
town:build(1, UnitId.TerranQuarry, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(4, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
town:wait_build(5, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(6, UnitId.TerranFulcrum)
|
||||
town:build(4, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(3, UnitId.TerranStarport)
|
||||
town:build(3, UnitId.TerranRotary, 69)
|
||||
town:wait_build(4, UnitId.TerranStarport)
|
||||
town:build(4, UnitId.TerranRotary, 69)
|
||||
town:wait_build(5, UnitId.TerranStarport)
|
||||
town:build(5, UnitId.TerranRotary, 69)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:wait_build(6, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranCommandment, 69)
|
||||
town:wait_build(7, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranCommandment, 69)
|
||||
town:wait_build(8, UnitId.TerranStarport)
|
||||
town:build(3, UnitId.TerranCommandment, 69)
|
||||
town:build(2, UnitId.TerranNaniteAssembly, 69)
|
||||
town:wait_build(1, UnitId.TerranNaniteAssembly)
|
||||
town:build(1, UnitId.TerranHadron, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 70)
|
||||
melee_ai:dynamic_wait(secs(15) + mins(1) + secs(15))
|
||||
town:build(6, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(4, UnitId.TerranStarport, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(8, UnitId.TerranStarport, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the mech-to-air transition (Phalanx / Matador -> Minotaur / Seraph / Hippogriff)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
town:build(1, UnitId.TerranPalladium, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:build(1, UnitId.TerranCommandment, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
town:build(1, UnitId.TerranHadron, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
73
mpq/lua/melee/terran/general/observant.lua
Normal file
73
mpq/lua/melee/terran/general/observant.lua
Normal file
@ -0,0 +1,73 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Observant",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranCyprian] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranCentaur] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranCommandment, 69)
|
||||
town:wait_build(1, UnitId.TerranCommandment)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(5) + secs(35))
|
||||
town:build(1, UnitId.TerranStarpad, 70)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(25) + secs(50))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:build(3, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Cyprian core + Blackjack / Seraph / Centaur
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranCommandment, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
69
mpq/lua/melee/terran/general/the_cube.lua
Normal file
69
mpq/lua/melee/terran/general/the_cube.lua
Normal file
@ -0,0 +1,69 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: The Cube",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranVulture] = 1,
|
||||
[UnitId.TerranPhalanxTankMode] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranCentaur] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40) + secs(25) + secs(50))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Maverick core + Vulture / Phalanx / Salamander / Centaur
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranPalladium, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
71
mpq/lua/melee/terran/general/two_fulcrum_mech.lua
Normal file
71
mpq/lua/melee/terran/general/two_fulcrum_mech.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: 2 Fulcrum Mech",
|
||||
unit_composition = {
|
||||
-- signature units (Mantle x2)
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
[UnitId.TerranRamesses] = 2,
|
||||
[UnitId.TerranDurendal] = 2,
|
||||
[UnitId.TerranCataphract] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranMadrigalImperiosoMode] = 1,
|
||||
[UnitId.TerranCuirassTankMode] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(4, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40) + secs(40))
|
||||
town:build(2, UnitId.TerranMantle, 70)
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Mantle walkers (Ramesses / Durendal / Cataphract) + Phalanx / Blackjack / Cuirass
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
town:build(1, UnitId.TerranPalladium, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranMantle, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranIronFoundry, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
72
mpq/lua/melee/terran/orbital/aces_high.lua
Normal file
72
mpq/lua/melee/terran/orbital/aces_high.lua
Normal file
@ -0,0 +1,72 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Orbital: Aces High",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranVulture] = 3,
|
||||
[UnitId.TerranWraith] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranCentaur] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranScrapyard, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
-- tier2/tier3
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Vulture + Wraith aces (+ Blackjack / Cyclops / Salamander / Centaur)
|
||||
town:build(1, UnitId.TerranFulcrum, 70, true)
|
||||
town:build(1, UnitId.TerranScrapyard, 68, true)
|
||||
town:build(1, UnitId.TerranStarpad, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
78
mpq/lua/melee/terran/orbital/hotdrop.lua
Normal file
78
mpq/lua/melee/terran/orbital/hotdrop.lua
Normal file
@ -0,0 +1,78 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Orbital: Hotdrop",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranHarakan] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranWraith] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranCentaur] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:build(2, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(3, UnitId.TerranStarpad)
|
||||
town:wait_build(2, UnitId.TerranStockade, false)
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.TerranCovenant, 69)
|
||||
town:wait_build(1, UnitId.TerranCovenant)
|
||||
town:build(1, UnitId.TerranAnvil, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Harakan drop force + Wraith / Salamander / Centaur support
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranStarpad, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
75
mpq/lua/melee/terran/orbital/rapid_starpads.lua
Normal file
75
mpq/lua/melee/terran/orbital/rapid_starpads.lua
Normal file
@ -0,0 +1,75 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Orbital: 2 Starpad Wraith",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranWraith] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranAzazel] = 1,
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
[UnitId.TerranCentaur] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 110)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(2, UnitId.TerranStarpad)
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(5))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
town:build(3, UnitId.TerranStarport, 70)
|
||||
town:wait_build(3, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranCommandment, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Wraith fleet + Salamander / Azazel / Seraph gunships
|
||||
town:build(1, UnitId.TerranStarpad, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:build(1, UnitId.TerranCommandment, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
78
mpq/lua/melee/terran/orbital/sudden_starport.lua
Normal file
78
mpq/lua/melee/terran/orbital/sudden_starport.lua
Normal file
@ -0,0 +1,78 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Orbital: Sudden Starport",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
[UnitId.TerranSundog] = 2,
|
||||
[UnitId.TerranSalamander] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.TerranCentaur] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport, false)
|
||||
town:build(4, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
town:wait_build(3, UnitId.TerranStarport)
|
||||
town:build(3, UnitId.TerranRotary, 69)
|
||||
town:wait_build(4, UnitId.TerranStarport)
|
||||
town:build(4, UnitId.TerranRotary, 69)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Maverick + Sundog / Salamander army (+ Cleric / Centaur)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
56
mpq/lua/melee/terran/orbital/the_don.lua
Normal file
56
mpq/lua/melee/terran/orbital/the_don.lua
Normal file
@ -0,0 +1,56 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Orbital: The Don",
|
||||
unit_composition = {
|
||||
-- signature units (Nanite Assembly x3)
|
||||
[UnitId.TerranMinotaur] = 2,
|
||||
[UnitId.TerranCentaur] = 2,
|
||||
[UnitId.TerranMagnetar] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranGorgon] = 1,
|
||||
[UnitId.TerranWraith] = 0.5,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(2, UnitId.TerranNaniteAssembly, 50)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranNaniteAssembly, 50)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Nanite Assembly capital fleet (+ Gorgon / Wraith)
|
||||
town:build(1, UnitId.TerranStarpad, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
65
mpq/lua/melee/terran/orbital/wraith_bio.lua
Normal file
65
mpq/lua/melee/terran/orbital/wraith_bio.lua
Normal file
@ -0,0 +1,65 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Orbital: Wraith Bio",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 3,
|
||||
[UnitId.TerranWraith] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranValkyrie] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranCentaur] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
-- tier2/tier3
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Maverick + Wraith bio-air army (+ Valkyrie / Salamander / Centaur)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranStarpad, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranNaniteAssembly, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
72
mpq/lua/melee/terran/raider/eight_rax.lua
Normal file
72
mpq/lua/melee/terran/raider/eight_rax.lua
Normal file
@ -0,0 +1,72 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Raider: 8Rax",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranMaverick] = 3,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.TerranHarakan] = 1,
|
||||
[UnitId.TerranCyprian] = 1,
|
||||
[UnitId.TerranMadcap] = 1,
|
||||
[UnitId.TerranDilettante] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:build_and_wait(town, 1, UnitId.TerranStockade, 110, secs(15))
|
||||
melee_ai:build_sequence(town, 2, 6, UnitId.TerranStockade, 110, 0, secs(15), 0)
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(6, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1 scale-up
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:build_and_wait(town, 8, UnitId.TerranStockade, 90, secs(50))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 69)
|
||||
town:wait_build(3, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 69)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranCovenant, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
|
||||
-- production for the Maverick-heavy raid (+ Cleric / Madcap / Dilettante)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranCaptaincy, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranApothecary, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
77
mpq/lua/melee/terran/raider/fast_anvil.lua
Normal file
77
mpq/lua/melee/terran/raider/fast_anvil.lua
Normal file
@ -0,0 +1,77 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Raider: Fast Anvil",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranCyprian] = 2,
|
||||
[UnitId.TerranEidolon] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
[UnitId.TerranMadcap] = 1,
|
||||
[UnitId.TerranDilettante] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 89)
|
||||
town:wait_build(1, UnitId.TerranCovenant, false)
|
||||
town:build(1, UnitId.TerranAnvil, 89)
|
||||
town:wait_build(3, UnitId.TerranStockade)
|
||||
town:wait_build(1, UnitId.TerranAnvil, false)
|
||||
town:build(2, UnitId.TerranCovenant, 89)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(3, UnitId.TerranCovenant, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.TerranStockade, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Cyprian + Eidolon anvil raid (+ Madcap / Dilettante)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranCovenant, 68, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranAnvil, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranCaptaincy, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranApothecary, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
71
mpq/lua/melee/terran/raider/four_rax_pressure.lua
Normal file
71
mpq/lua/melee/terran/raider/four_rax_pressure.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Raider: 4Rax Pressure",
|
||||
unit_composition = {
|
||||
-- healers
|
||||
[UnitId.TerranShamanSupportMode] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranSavantEntropyGauntlets] = 1,
|
||||
[UnitId.TerranCyprian] = 1,
|
||||
[UnitId.TerranMadcap] = 1,
|
||||
[UnitId.TerranDilettante] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 89)
|
||||
town:wait_build(3, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 89)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranCovenant, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
-- tier2/tier3
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Shaman + Savant support raid (+ Cyprian / Madcap / Dilettante)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
town:build(1, UnitId.TerranCovenant, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranCaptaincy, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranApothecary, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
70
mpq/lua/melee/terran/raider/holy_ackmeds.lua
Normal file
70
mpq/lua/melee/terran/raider/holy_ackmeds.lua
Normal file
@ -0,0 +1,70 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Raider: Holy Ackmeds!",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranHarakan] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranSundog] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranDilettante] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(4, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Harakan raid + Sundog / Salamander gunships
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranStarport, 65, true)
|
||||
town:build(1, UnitId.TerranRotary, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranApothecary, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
65
mpq/lua/melee/terran/raider/three_rax_bio.lua
Normal file
65
mpq/lua/melee/terran/raider/three_rax_bio.lua
Normal file
@ -0,0 +1,65 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Raider: 3Rax Maverick & Cleric",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 3,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranEidolon] = 1,
|
||||
[UnitId.TerranMadcap] = 1,
|
||||
[UnitId.TerranDilettante] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(10))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Maverick + Cleric bio raid (+ Eidolon / Madcap / Dilettante)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
town:build(1, UnitId.TerranCovenant, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranCaptaincy, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranApothecary, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
67
mpq/lua/melee/terran/raider/uprising.lua
Normal file
67
mpq/lua/melee/terran/raider/uprising.lua
Normal file
@ -0,0 +1,67 @@
|
||||
local Basic = require "melee.terran.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Raider: Uprising",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranCyprian] = 3,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.TerranEidolon] = 1,
|
||||
[UnitId.TerranMadcap] = 1,
|
||||
[UnitId.TerranDilettante] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:wait_build(2, UnitId.TerranVestry)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
-- tier2/tier3
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
-- production for the Cyprian-heavy raid (+ Cleric / Eidolon / Madcap / Dilettante)
|
||||
town:build(1, UnitId.TerranStockade, 70, true)
|
||||
town:build(1, UnitId.TerranVestry, 68, true)
|
||||
town:build(1, UnitId.TerranCovenant, 68, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranCaptaincy, 65, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:build(1, UnitId.TerranApothecary, 65, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.4,
|
||||
}
|
||||
104
mpq/lua/melee/zerg/assault/earthen_tides.lua
Normal file
104
mpq/lua/melee/zerg/assault/earthen_tides.lua
Normal file
@ -0,0 +1,104 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Assault: Earthen Tides",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergIzirokor] = 2,
|
||||
[UnitId.ZergLakizilisk] = 2,
|
||||
[UnitId.ZergProtathalor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergKeskathalor] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergHydrithDen, 110, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(5))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Earthen Tides army (Izirokor / Lakizilisk / Protathalor)
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
104
mpq/lua/melee/zerg/assault/potency.lua
Normal file
104
mpq/lua/melee/zerg/assault/potency.lua
Normal file
@ -0,0 +1,104 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Assault: Potency",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZoryusthaleth] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
[UnitId.ZergKalkalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergKagralisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergEvigrilisk] = 1,
|
||||
[UnitId.ZergAlmaksalisk] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergHydrithDen, 110, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergAlkagIteth, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the broad Potency army (Zorkiz / Hydra / Kalkiir / Alkag / Mutath)
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
town:build(1, UnitId.ZergAlkagIteth, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
89
mpq/lua/melee/zerg/assault/three_base_hydrith.lua
Normal file
89
mpq/lua/melee/zerg/assault/three_base_hydrith.lua
Normal file
@ -0,0 +1,89 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Assault: 3 Base Hydrith",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergHydralisk] = 3,
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Hydralisk / Zethrokor / Ultrokor assault army
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
81
mpq/lua/melee/zerg/assault/two_base_alkag.lua
Normal file
81
mpq/lua/melee/zerg/assault/two_base_alkag.lua
Normal file
@ -0,0 +1,81 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Assault: 2 Base Alkag",
|
||||
unit_composition = {
|
||||
-- signature units (Alkag Iteth)
|
||||
[UnitId.ZergKagralisk] = 2,
|
||||
[UnitId.ZergEvigrilisk] = 2,
|
||||
[UnitId.ZergAlmaksalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 90, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergAlkagIteth, 90, true)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 90, true)
|
||||
end)
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
-- tier2
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Alkag Iteth army (Kagralisk / Evigrilisk / Almaksalisk)
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergAlkagIteth, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
81
mpq/lua/melee/zerg/assault/two_base_hydrith_quazeth.lua
Normal file
81
mpq/lua/melee/zerg/assault/two_base_hydrith_quazeth.lua
Normal file
@ -0,0 +1,81 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Assault: 2 Base Hydrith-Quazeth",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergHydralisk] = 3,
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergQuazilisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Hydralisk / Zethrokor / Ultrokor / Vornath army
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
80
mpq/lua/melee/zerg/assault/two_base_zorkiz.lua
Normal file
80
mpq/lua/melee/zerg/assault/two_base_zorkiz.lua
Normal file
@ -0,0 +1,80 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "Assault: 2 Base Hydrith-Zorkiz",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergHydralisk] = 3,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
[UnitId.ZergZoryusthaleth] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergIzirokor] = 1,
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier2
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Hydralisk / Ultrokor / Zoryusthaleth assault army
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.6,
|
||||
}
|
||||
17
mpq/lua/melee/zerg/basic.lua
Normal file
17
mpq/lua/melee/zerg/basic.lua
Normal file
@ -0,0 +1,17 @@
|
||||
local Basic = {}
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_ground(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 3, UnitId.ZergSurkithCesiant, 80, 5, secs(25), secs(5))
|
||||
melee_ai:wait_can_make(UnitId.ZergSkortrithCesiant)
|
||||
melee_ai:build_sequence(town, 1, 3, UnitId.ZergSkortrithCesiant, 80, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
---@type BuildOrder
|
||||
function Basic.build_anti_air(melee_ai, town)
|
||||
melee_ai:build_sequence(town, 1, 3, UnitId.ZergSpraithCesiant, 80, 5, secs(25), secs(5))
|
||||
melee_ai:wait_can_make(UnitId.ZergSpirtithCesiant)
|
||||
melee_ai:build_sequence(town, 1, 3, UnitId.ZergSpirtithCesiant, 80, 5, secs(25), secs(5))
|
||||
end
|
||||
|
||||
return Basic
|
||||
96
mpq/lua/melee/zerg/general/before_the_storm.lua
Normal file
96
mpq/lua/melee/zerg/general/before_the_storm.lua
Normal file
@ -0,0 +1,96 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Before the Storm",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergKalkalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool, false)
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergDroleth, 100)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(2) + secs(30))
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Zethrokor / Kalkalisk army + Mutalisk / Geszithalor
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
86
mpq/lua/melee/zerg/general/constrained_coil.lua
Normal file
86
mpq/lua/melee/zerg/general/constrained_coil.lua
Normal file
@ -0,0 +1,86 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Constrained Coil",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergKalkalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool, false)
|
||||
melee_ai:start_expanding()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergDroleth, 100)
|
||||
melee_ai:dynamic_wait(secs(1))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(35))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the constrained Zethrokor / Kalkalisk army
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
95
mpq/lua/melee/zerg/general/shrieking_swarm.lua
Normal file
95
mpq/lua/melee/zerg/general/shrieking_swarm.lua
Normal file
@ -0,0 +1,95 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Shrieking Swarm",
|
||||
unit_composition = {
|
||||
-- signature units (Vornath Pond)
|
||||
[UnitId.ZergVorvrokor] = 2,
|
||||
[UnitId.ZergNathrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergUltrokor] = 1,
|
||||
[UnitId.ZergHydralisk] = 1,
|
||||
[UnitId.ZergLakizilisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Vornath-centric army (+ Ultrokor / Hydralisk / Zorkiz)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
107
mpq/lua/melee/zerg/general/sleeping_giant.lua
Normal file
107
mpq/lua/melee/zerg/general/sleeping_giant.lua
Normal file
@ -0,0 +1,107 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Sleeping Giant",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(15, UnitId.ZergDroleth)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(45))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- tier3
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Zethrokor / Ultrokor / Hydralisk army
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
100
mpq/lua/melee/zerg/general/subjugation.lua
Normal file
100
mpq/lua/melee/zerg/general/subjugation.lua
Normal file
@ -0,0 +1,100 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Subjugation",
|
||||
unit_composition = {
|
||||
-- signature units (Skibact Scab)
|
||||
[UnitId.ZergSkithrokor] = 2,
|
||||
[UnitId.ZergBactalisk] = 2,
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKeskathalor] = 1,
|
||||
[UnitId.ZergHydralisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergVithrilisk] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergDroleth, 100)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
-- tier2
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Skibact / Zethrokor army + Keskathalor tech
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
94
mpq/lua/melee/zerg/general/time_after_time.lua
Normal file
94
mpq/lua/melee/zerg/general/time_after_time.lua
Normal file
@ -0,0 +1,94 @@
|
||||
local Basic = require "melee.zerg.basic"
|
||||
|
||||
---@type AIPersonality
|
||||
return {
|
||||
name = "General: Time After Time",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergSkithrokor] = 2,
|
||||
[UnitId.ZergLakizilisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergLiiralisk] = 1,
|
||||
[UnitId.ZergCikralisk] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = function(melee_ai, town)
|
||||
melee_ai:build_main(town)
|
||||
-- opener
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
-- tier1
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
-- tier2
|
||||
town:multirun(function(town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
-- tier3
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
-- saturated production
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end,
|
||||
expansion_build_order = function(melee_ai, town)
|
||||
melee_ai:build_expansion(town, true)
|
||||
town:multirun(function(town)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
-- production for the Zethrokor / Skithrokor / Lakizilisk army
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
end,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = 0.5,
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user