diff --git a/OpenRA.sln b/OpenRA.sln index 6e52afbaf6..0c5f771be1 100644 --- a/OpenRA.sln +++ b/OpenRA.sln @@ -46,6 +46,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tiberian Dawn Lua scripts", mods\cnc\maps\nod06c\nod06c.lua = mods\cnc\maps\nod06c\nod06c.lua mods\cnc\maps\nod07a\nod07a-AI.lua = mods\cnc\maps\nod07a\nod07a-AI.lua mods\cnc\maps\nod07a\nod07a.lua = mods\cnc\maps\nod07a\nod07a.lua + mods\cnc\maps\nod07a\nod07a-AI.lua = mods\cnc\maps\nod07b\nod07b-AI.lua + mods\cnc\maps\nod07a\nod07a.lua = mods\cnc\maps\nod07b\nod07b.lua mods\cnc\maps\funpark01\scj01ea.lua = mods\cnc\maps\funpark01\scj01ea.lua mods\cnc\maps\shellmap\shellmap.lua = mods\cnc\maps\shellmap\shellmap.lua EndProjectSection diff --git a/mods/cnc/maps/nod07b/map.bin b/mods/cnc/maps/nod07b/map.bin new file mode 100644 index 0000000000..062be90c6a Binary files /dev/null and b/mods/cnc/maps/nod07b/map.bin differ diff --git a/mods/cnc/maps/nod07b/map.png b/mods/cnc/maps/nod07b/map.png new file mode 100644 index 0000000000..a08b442bcc Binary files /dev/null and b/mods/cnc/maps/nod07b/map.png differ diff --git a/mods/cnc/maps/nod07b/map.yaml b/mods/cnc/maps/nod07b/map.yaml new file mode 100644 index 0000000000..e0aa0c5c63 --- /dev/null +++ b/mods/cnc/maps/nod07b/map.yaml @@ -0,0 +1,956 @@ +MapFormat: 11 + +RequiresMod: cnc + +Title: Sick And Dying (b) + +Author: Westwood Studios + +Tileset: DESERT + +MapSize: 64,64 + +Bounds: 5,5,54,54 + +Visibility: MissionSelector + +Categories: Campaign + +LockPreview: True + +Players: + PlayerReference@GDI: + Name: GDI + Faction: gdi + Color: F5D378 + Allies: Civilians + Enemies: Nod + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Faction: gdi + PlayerReference@Civilians: + Name: Civilians + NonCombatant: True + Faction: gdi + Allies: GDI + Enemies: Nod + PlayerReference@Nod: + Name: Nod + Faction: nod + AllowBots: False + Playable: True + Required: True + LockFaction: True + LockColor: True + Color: FE1100 + LockSpawn: True + LockTeam: True + Enemies: GDI, Civilians + +Actors: + Actor0: brik + Location: 49,49 + Owner: GDI + Actor1: brik + Location: 48,49 + Owner: GDI + Actor2: brik + Location: 47,49 + Owner: GDI + Actor3: brik + Location: 46,49 + Owner: GDI + Actor4: brik + Location: 45,49 + Owner: GDI + Actor5: brik + Location: 44,49 + Owner: GDI + Actor6: brik + Location: 43,49 + Owner: GDI + Actor7: brik + Location: 42,49 + Owner: GDI + Actor8: brik + Location: 41,49 + Owner: GDI + Actor9: brik + Location: 49,48 + Owner: GDI + Actor10: brik + Location: 41,48 + Owner: GDI + Actor11: brik + Location: 58,47 + Owner: GDI + Actor12: brik + Location: 57,47 + Owner: GDI + Actor13: brik + Location: 56,47 + Owner: GDI + Actor14: brik + Location: 55,47 + Owner: GDI + Actor15: brik + Location: 54,47 + Owner: GDI + Actor16: brik + Location: 49,47 + Owner: GDI + Actor17: brik + Location: 48,47 + Owner: GDI + Actor18: brik + Location: 42,47 + Owner: GDI + Actor19: brik + Location: 41,47 + Owner: GDI + Actor20: brik + Location: 58,46 + Owner: GDI + Actor21: brik + Location: 55,46 + Owner: GDI + Actor22: brik + Location: 54,46 + Owner: GDI + Actor23: brik + Location: 49,46 + Owner: GDI + Actor24: brik + Location: 48,46 + Owner: GDI + Actor25: brik + Location: 42,46 + Owner: GDI + Actor26: brik + Location: 41,46 + Owner: GDI + Actor27: brik + Location: 58,45 + Owner: GDI + Actor28: brik + Location: 58,44 + Owner: GDI + Actor29: brik + Location: 58,43 + Owner: GDI + Actor30: brik + Location: 58,42 + Owner: GDI + Actor31: brik + Location: 42,42 + Owner: GDI + Actor32: brik + Location: 41,42 + Owner: GDI + Actor33: brik + Location: 58,41 + Owner: GDI + Actor34: brik + Location: 42,41 + Owner: GDI + Actor35: brik + Location: 41,41 + Owner: GDI + Actor36: brik + Location: 58,40 + Owner: GDI + Actor37: brik + Location: 41,40 + Owner: GDI + Actor38: brik + Location: 58,39 + Owner: GDI + Actor39: brik + Location: 41,39 + Owner: GDI + Actor40: brik + Location: 58,38 + Owner: GDI + Actor41: brik + Location: 41,38 + Owner: GDI + Actor42: brik + Location: 58,37 + Owner: GDI + Actor43: brik + Location: 41,37 + Owner: GDI + Actor44: brik + Location: 58,36 + Owner: GDI + Actor45: brik + Location: 48,36 + Owner: GDI + Actor46: brik + Location: 47,36 + Owner: GDI + Actor47: brik + Location: 44,36 + Owner: GDI + Actor48: brik + Location: 43,36 + Owner: GDI + Actor49: brik + Location: 41,36 + Owner: GDI + Actor50: brik + Location: 58,35 + Owner: GDI + Actor51: brik + Location: 57,35 + Owner: GDI + Actor52: brik + Location: 56,35 + Owner: GDI + Actor53: brik + Location: 55,35 + Owner: GDI + Actor54: brik + Location: 54,35 + Owner: GDI + Actor55: brik + Location: 53,35 + Owner: GDI + Actor56: brik + Location: 52,35 + Owner: GDI + Actor57: brik + Location: 51,35 + Owner: GDI + Actor58: brik + Location: 50,35 + Owner: GDI + Actor59: brik + Location: 49,35 + Owner: GDI + Actor60: brik + Location: 48,35 + Owner: GDI + Actor61: brik + Location: 47,35 + Owner: GDI + Actor62: brik + Location: 44,35 + Owner: GDI + Actor63: brik + Location: 43,35 + Owner: GDI + Actor64: brik + Location: 42,35 + Owner: GDI + Actor65: brik + Location: 41,35 + Owner: GDI + Actor66: cycl + Location: 53,21 + Owner: Civilians + Actor67: cycl + Location: 52,21 + Owner: Civilians + Actor68: cycl + Location: 51,21 + Owner: Civilians + Actor69: cycl + Location: 50,21 + Owner: Civilians + Actor70: cycl + Location: 49,21 + Owner: Civilians + Actor71: cycl + Location: 48,21 + Owner: Civilians + Actor72: cycl + Location: 47,21 + Owner: Civilians + Actor73: cycl + Location: 53,20 + Owner: Civilians + Actor74: cycl + Location: 51,20 + Owner: Civilians + Actor75: cycl + Location: 49,20 + Owner: Civilians + Actor76: cycl + Location: 47,20 + Owner: Civilians + Actor77: cycl + Location: 47,19 + Owner: Civilians + Actor78: cycl + Location: 53,18 + Owner: Civilians + Actor79: cycl + Location: 51,18 + Owner: Civilians + Actor80: cycl + Location: 49,18 + Owner: Civilians + Actor81: cycl + Location: 47,18 + Owner: Civilians + Actor82: cycl + Location: 53,17 + Owner: Civilians + Actor83: cycl + Location: 52,17 + Owner: Civilians + Actor84: cycl + Location: 51,17 + Owner: Civilians + Actor85: cycl + Location: 50,17 + Owner: Civilians + Actor86: cycl + Location: 49,17 + Owner: Civilians + Actor87: cycl + Location: 48,17 + Owner: Civilians + Actor88: cycl + Location: 47,17 + Owner: Civilians + Actor89: t18 + Location: 47,33 + Owner: Neutral + Actor90: t08 + Location: 44,34 + Owner: Neutral + Actor91: t08 + Location: 45,54 + Owner: Neutral + Actor92: t08 + Location: 32,54 + Owner: Neutral + Actor93: t18 + Location: 30,53 + Owner: Neutral + Actor94: t18 + Location: 17,51 + Owner: Neutral + Actor95: t08 + Location: 45,30 + Owner: Neutral + Actor96: t08 + Location: 41,28 + Owner: Neutral + Actor97: t18 + Location: 39,27 + Owner: Neutral + Actor98: t18 + Location: 40,22 + Owner: Neutral + Actor99: t18 + Location: 49,47 + Owner: Neutral + Actor100: t18 + Location: 37,41 + Owner: Neutral + Actor101: t18 + Location: 8,49 + Owner: Neutral + Actor102: t18 + Location: 23,37 + Owner: Neutral + Actor103: t08 + Location: 11,20 + Owner: Neutral + Actor104: t08 + Location: 9,28 + Owner: Neutral + Actor105: t08 + Location: 8,36 + Owner: Neutral + Actor106: t08 + Location: 24,28 + Owner: Neutral + Actor107: t08 + Location: 27,26 + Owner: Neutral + Actor108: t08 + Location: 23,27 + Owner: Neutral + Actor109: t08 + Location: 26,16 + Owner: Neutral + Actor110: t08 + Location: 20,18 + Owner: Neutral + Actor111: t08 + Location: 33,10 + Owner: Neutral + Actor112: t08 + Location: 37,17 + Owner: Neutral + Actor113: rock1 + Location: 37,15 + Owner: Neutral + Actor114: t18 + Location: 54,30 + Owner: Neutral + Actor115: t18 + Location: 57,27 + Owner: Neutral + Actor116: t08 + Location: 55,27 + Owner: Neutral + Actor117: t18 + Location: 48,25 + Owner: Neutral + Actor134: v24 + Location: 30,5 + Owner: Civilians + Health: 22 + Actor135: v27 + Location: 43,25 + Owner: Civilians + Health: 99 + Actor136: v24 + Location: 41,24 + Owner: Civilians + Health: 99 + Actor137: v24 + Location: 43,26 + Owner: Civilians + Health: 99 + Actor138: v27 + Location: 42,27 + Owner: Civilians + Health: 99 + Actor139: v27 + Location: 41,27 + Owner: Civilians + Health: 99 + Actor140: v27 + Location: 40,27 + Owner: Civilians + Health: 99 + Actor141: v27 + Location: 39,25 + Owner: Civilians + Health: 99 + Actor142: v26 + Location: 36,23 + Owner: Civilians + Health: 99 + Actor143: v25 + Location: 40,20 + Owner: Civilians + Health: 99 + Actor144: v21 + Location: 47,24 + Owner: Civilians + Health: 99 + Actor145: v20 + Location: 42,29 + Owner: Civilians + Health: 99 + Actor146: v22 + Location: 45,28 + Owner: Civilians + Health: 99 + Actor147: v23 + Location: 40,23 + Owner: Civilians + Health: 99 + Actor148: v26 + Location: 47,27 + Owner: Civilians + Health: 99 + Actor149: v28 + Location: 47,23 + Owner: Civilians + Health: 99 + Actor150: v28 + Location: 48,23 + Owner: Civilians + Health: 99 + Actor151: v28 + Location: 49,23 + Owner: Civilians + Health: 99 + Actor152: v29 + Location: 52,23 + Owner: Civilians + Health: 99 + Actor153: v30 + Location: 50,25 + Owner: Civilians + Health: 99 + Actor154: v31 + Location: 56,23 + Owner: Civilians + Health: 99 + Actor155: v32 + Location: 55,24 + Owner: Civilians + Health: 99 + Actor156: v33 + Location: 57,25 + Owner: Civilians + Health: 99 + Actor157: v34 + Location: 58,26 + Owner: Civilians + Health: 99 + Actor158: v35 + Location: 57,27 + Owner: Civilians + Health: 99 + Actor159: v36 + Location: 56,26 + Owner: Civilians + Health: 99 + Actor160: v29 + Location: 49,27 + Owner: Civilians + Health: 99 + Actor161: v29 + Location: 50,27 + Owner: Civilians + Health: 99 + Actor162: arco + Location: 45,20 + Owner: Civilians + Health: 98 + Actor163: v19 + Location: 48,18 + Owner: Neutral + Health: 99 + Actor164: v19 + Location: 52,18 + Owner: Neutral + Health: 99 + Actor165: v19 + Location: 50,20 + Owner: Neutral + Health: 99 + Actor166: v19 + Location: 50,18 + Owner: Neutral + Health: 99 + Actor167: v19 + Location: 48,20 + Owner: Neutral + Health: 99 + Actor168: v19 + Location: 52,20 + Owner: Neutral + Health: 99 + Actor169: v30 + Location: 43,23 + Owner: Civilians + Health: 99 + Actor171: hosp + Location: 55,28 + Owner: Civilians + Actor172: mtnk + Location: 51,40 + Owner: GDI + Actor173: jeep + Location: 17,31 + Owner: GDI + Facing: 224 + Actor174: mtnk + Location: 21,36 + Owner: GDI + Facing: 224 + Actor175: mtnk + Location: 42,52 + Owner: GDI + Facing: 160 + Actor176: jeep + Location: 14,26 + Owner: GDI + Facing: 32 + Actor177: mtnk + Location: 50,47 + Owner: GDI + Facing: 96 + Actor188: mtnk + Location: 51,53 + Owner: GDI + Facing: 160 + Actor189: mtnk + Location: 24,26 + Owner: GDI + Facing: 224 + Actor190: mtnk + Location: 29,36 + Owner: GDI + Facing: 128 + Actor191: mtnk + Location: 27,36 + Owner: GDI + Facing: 128 + Actor192: jeep + Location: 8,38 + Owner: GDI + Health: 97 + Actor193: jeep + Location: 8,29 + Owner: GDI + Actor195: e2 + Location: 56,42 + Owner: GDI + SubCell: 4 + Actor196: e2 + Location: 57,42 + Owner: GDI + SubCell: 0 + Actor197: e2 + Location: 57,46 + Owner: GDI + SubCell: 1 + Actor198: e2 + Location: 51,35 + Owner: GDI + SubCell: 4 + Actor199: e2 + Location: 43,40 + Owner: GDI + SubCell: 1 + Actor200: e1 + Location: 42,40 + Owner: GDI + SubCell: 0 + Actor201: e1 + Location: 44,39 + Owner: GDI + SubCell: 4 + Actor202: e1 + Location: 56,46 + Owner: GDI + SubCell: 1 + Actor203: e1 + Location: 43,41 + Owner: GDI + SubCell: 2 + Actor204: e2 + Location: 24,56 + Owner: GDI + SubCell: 3 + Actor205: e2 + Location: 24,57 + Owner: GDI + SubCell: 1 + Actor206: e1 + Location: 14,48 + Owner: GDI + SubCell: 0 + Actor207: e1 + Location: 14,48 + Owner: GDI + SubCell: 2 + Actor208: e1 + Location: 15,48 + Owner: GDI + SubCell: 3 + Actor209: e3 + Location: 10,28 + Owner: GDI + SubCell: 3 + Actor210: e3 + Location: 5,31 + Owner: GDI + SubCell: 2 + Actor211: e3 + Location: 13,40 + Owner: GDI + Health: 83 + Facing: 224 + SubCell: 4 + Actor212: e3 + Location: 13,42 + Owner: GDI + Facing: 192 + SubCell: 4 + Actor213: e2 + Location: 11,37 + Owner: GDI + SubCell: 4 + Actor214: e2 + Location: 7,30 + Owner: GDI + SubCell: 2 + Actor221: c1 + Location: 35,24 + Owner: Civilians + Health: 19 + SubCell: 0 + Actor222: c2 + Location: 40,24 + Owner: Civilians + Facing: 160 + SubCell: 2 + Actor223: c3 + Location: 36,25 + Owner: Civilians + Facing: 224 + SubCell: 2 + Actor224: c4 + Location: 41,26 + Owner: Civilians + Facing: 64 + SubCell: 3 + Actor225: c5 + Location: 44,25 + Owner: Civilians + SubCell: 1 + Actor226: c6 + Location: 42,28 + Owner: Civilians + Facing: 64 + SubCell: 2 + Actor227: c7 + Location: 38,26 + Owner: Civilians + Health: 19 + Facing: 224 + SubCell: 0 + Actor228: c8 + Location: 40,26 + Owner: Civilians + Facing: 32 + SubCell: 3 + Actor229: c9 + Location: 36,22 + Owner: Civilians + Facing: 64 + SubCell: 2 + Actor230: c1 + Location: 44,24 + Owner: Civilians + Health: 19 + Facing: 64 + SubCell: 2 + Actor231: c2 + Location: 36,26 + Owner: Civilians + Facing: 64 + SubCell: 1 + Actor232: c3 + Location: 51,26 + Owner: Civilians + Facing: 128 + SubCell: 2 + Actor233: c4 + Location: 55,23 + Owner: Civilians + Facing: 32 + SubCell: 3 + Actor234: c5 + Location: 57,26 + Owner: Civilians + Facing: 160 + SubCell: 1 + Actor235: c6 + Location: 48,26 + Owner: Civilians + Facing: 64 + SubCell: 3 + Actor236: c7 + Location: 42,22 + Owner: Civilians + Facing: 160 + SubCell: 2 + Actor237: c8 + Location: 46,30 + Owner: Civilians + Health: 19 + Facing: 128 + SubCell: 1 + Actor238: c9 + Location: 39,29 + Owner: Civilians + Health: 19 + SubCell: 3 + Actor239: e2 + Location: 13,40 + Owner: GDI + SubCell: 4 + Actor240: e2 + Location: 9,37 + Owner: GDI + Health: 87 + SubCell: 4 + Actor241: e2 + Location: 13,39 + Owner: GDI + SubCell: 3 + Actor242: e2 + Location: 15,55 + Owner: GDI + SubCell: 1 + Actor243: e2 + Location: 16,55 + Owner: GDI + SubCell: 0 + Actor244: e1 + Location: 13,53 + Owner: GDI + SubCell: 0 + Actor245: e1 + Location: 14,54 + Owner: GDI + SubCell: 1 + Actor246: e1 + Location: 15,53 + Owner: GDI + SubCell: 1 + Actor247: e2 + Location: 30,29 + Owner: GDI + SubCell: 4 + Actor248: e2 + Location: 29,27 + Owner: GDI + SubCell: 3 + waypoint27: waypoint + Location: 32,32 + Owner: Neutral + waypoint26: waypoint + Location: 5,5 + Owner: Neutral + waypoint15: waypoint + Location: 57,52 + Owner: Neutral + waypoint14: waypoint + Location: 6,16 + Owner: Neutral + waypoint13: waypoint + Location: 28,28 + Owner: Neutral + waypoint12: waypoint + Location: 34,35 + Owner: Neutral + waypoint11: waypoint + Location: 8,43 + Owner: Neutral + waypoint10: waypoint + Location: 15,56 + Owner: Neutral + waypoint9: waypoint + Location: 26,54 + Owner: Neutral + waypoint8: waypoint + Location: 16,21 + Owner: Neutral + waypoint7: waypoint + Location: 6,22 + Owner: Neutral + waypoint6: waypoint + Location: 6,30 + Owner: Neutral + waypoint5: waypoint + Location: 11,30 + Owner: Neutral + waypoint4: waypoint + Location: 20,35 + Owner: Neutral + waypoint3: waypoint + Location: 29,48 + Owner: Neutral + waypoint2: waypoint + Location: 36,48 + Owner: Neutral + waypoint1: waypoint + Location: 36,45 + Owner: Neutral + waypoint0: waypoint + Location: 46,43 + Owner: Neutral + GDIBuilding1: gtwr + Location: 40,42 + Owner: GDI + GDIBuilding2: gtwr + Location: 49,50 + Owner: GDI + GDIBuilding3: gtwr + Location: 54,48 + Owner: GDI + GDIBuilding4: nuke + Location: 57,29 + Owner: GDI + GDIBuilding5: gtwr + Location: 40,46 + Owner: GDI + GDIBuilding6: silo + Location: 44,45 + Owner: GDI + GDIBuilding7: silo + Location: 46,45 + Owner: GDI + GDIBuilding8: silo + Location: 46,47 + Owner: GDI + GDIBuilding9: silo + Location: 44,47 + Owner: GDI + GDICYard: fact + Location: 55,43 + Owner: GDI + GDIHarvester: harv + Location: 46,38 + Owner: GDI + GDIHQ: hq + Location: 42,36 + Owner: GDI + GDINuke1: nuke + Location: 52,36 + Owner: GDI + GDINuke2: nuke + Location: 54,36 + Owner: GDI + GDINuke3: nuke + Location: 56,36 + Owner: GDI + GDIProc: proc + Location: 49,36 + Owner: GDI + FreeActor: False + GDIPyle: pyle + Location: 52,39 + Owner: GDI + GDIWeap: weap + Location: 55,38 + Owner: GDI + ReinforcementsBikesRally: waypoint + Owner: Neutral + Location: 8,11 + ReinforcementsBuggyRally: waypoint + Owner: Neutral + Location: 12,11 + ReinforcementsGDISpawn: waypoint + Owner: Neutral + Location: 39,5 + ReinforcementsGunnersRally: waypoint + Owner: Neutral + Location: 8,9 + ReinforcementsMCVRally: waypoint + Owner: Neutral + Location: 10,10 + ReinforcementsRocketsRally: waypoint + Owner: Neutral + Location: 12,9 + ReinforcementsTanksRally: waypoint + Owner: Neutral + Location: 10,8 + ReinforcementsSpawnCenter: waypoint + Owner: Neutral + Location: 10,5 + ReinforcementsSpawnLeft: waypoint + Owner: Neutral + Location: 8,5 + ReinforcementsSpawnRight: waypoint + Owner: Neutral + Location: 12,5 + +Rules: cnc|rules/campaign-maprules.yaml, cnc|rules/campaign-tooltips.yaml, cnc|rules/campaign-palettes.yaml, rules.yaml diff --git a/mods/cnc/maps/nod07b/nod07b-AI.lua b/mods/cnc/maps/nod07b/nod07b-AI.lua new file mode 100644 index 0000000000..24504bdfc3 --- /dev/null +++ b/mods/cnc/maps/nod07b/nod07b-AI.lua @@ -0,0 +1,193 @@ +AttackPaths = { { AttackPath1 }, { AttackPath2 } } +GDIBase = { GDICYard, GDIPyle, GDIWeap, GDIHQ, GDIProc, GDINuke1, GDINuke2, GDINuke3, GDIBuilding1, GDIBuilding2, GDIBuilding3, GDIBuilding4, GDIBuilding5, GDIBuilding6, GDIBuilding7, GDIBuilding8, GDIBuilding9 } +InfantryAttackGroup = { } +InfantryGroupSize = 4 +InfantryProductionCooldown = DateTime.Minutes(3) +InfantryProductionTypes = { "e1", "e1", "e2" } +HarvesterProductionType = { "harv" } +VehicleAttackGroup = { } +VehicleGroupSize = 4 +VehicleProductionCooldown = DateTime.Minutes(4) +VehicleProductionTypes = { "jeep", "jeep", "mtnk", "mtnk", "mtnk" } +StartingCash = 4000 + +BaseProc = { type = "proc", pos = CPos.New(49, 36), cost = 1500, exists = true } +BaseNuke1 = { type = "nuke", pos = CPos.New(52, 36), cost = 500, exists = true } +BaseNuke2 = { type = "nuke", pos = CPos.New(54, 36), cost = 500, exists = true } +BaseNuke3 = { type = "nuke", pos = CPos.New(56, 36), cost = 500, exists = true } +InfantryProduction = { type = "pyle", pos = CPos.New(52, 39), cost = 500, exists = true } +VehicleProduction = { type = "weap", pos = CPos.New(55, 38), cost = 2000, exists = true } + +BaseBuildings = { BaseProc, BaseNuke1, BaseNuke2, BaseNuke3, InfantryProduction, VehicleProduction } + +BuildBase = function(cyard) + Utils.Do(BaseBuildings, function(building) + if not building.exists and not cyardIsBuilding then + BuildBuilding(building, cyard) + return + end + end) + Trigger.AfterDelay(DateTime.Seconds(10), function() BuildBase(cyard) end) +end + +BuildBuilding = function(building, cyard) + cyardIsBuilding = true + + Trigger.AfterDelay(Actor.BuildTime(building.type), function() + cyardIsBuilding = false + + if cyard.IsDead or cyard.Owner ~= enemy then + return + end + + local actor = Actor.Create(building.type, true, { Owner = enemy, Location = building.pos }) + enemy.Cash = enemy.Cash - building.cost + + building.exists = true + + if actor.Type == 'pyle' or actor.Type == 'hand' then + Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(actor) end) + elseif actor.Type == 'weap' or actor.Type == 'afld' then + Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(actor) end) + end + + Trigger.OnKilled(actor, function() building.exists = false end) + + Trigger.OnDamaged(actor, function(building) + if building.Owner == enemy and building.Health < building.MaxHealth * 3/4 then + building.StartBuildingRepairs() + end + end) + + Trigger.AfterDelay(DateTime.Seconds(10), function() BuildBase(cyard) end) + end) +end + +CheckForHarvester = function() + local harv = enemy.GetActorsByType("harv") + return #harv > 0 +end + +IdleHunt = function(unit) + if not unit.IsDead then + Trigger.OnIdle(unit, unit.Hunt) + end +end + +IdlingUnits = function(enemy) + local lazyUnits = enemy.GetGroundAttackers() + + Utils.Do(lazyUnits, function(unit) + IdleHunt(unit) + end) +end + +ProduceHarvester = function(building) + if not buildingHarvester then + buildingHarvester = true + building.Build(HarvesterProductionType, function() + buildingHarvester = false + end) + end +end + +ProduceInfantry = function(building) + if building.IsDead then + return + elseif not CheckForHarvester() then + Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end) + end + + local delay = Utils.RandomInteger(DateTime.Seconds(3), DateTime.Seconds(9)) + local toBuild = { Utils.Random(InfantryProductionTypes) } + local Path = Utils.Random(AttackPaths) + building.Build(toBuild, function(unit) + InfantryAttackGroup[#InfantryAttackGroup + 1] = unit[1] + + if #InfantryAttackGroup >= InfantryGroupSize then + SendUnits(InfantryAttackGroup, Path) + InfantryAttackGroup = { } + Trigger.AfterDelay(InfantryProductionCooldown, function() ProduceInfantry(building) end) + else + Trigger.AfterDelay(delay, function() ProduceInfantry(building) end) + end + end) + +end + +ProduceVehicle = function(building) + if building.IsDead then + return + elseif not CheckForHarvester() then + ProduceHarvester(building) + Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(building) end) + end + + local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17)) + local toBuild = { Utils.Random(VehicleProductionTypes) } + local Path = Utils.Random(AttackPaths) + building.Build(toBuild, function(unit) + VehicleAttackGroup[#VehicleAttackGroup + 1] = unit[1] + + if #VehicleAttackGroup >= VehicleGroupSize then + SendUnits(VehicleAttackGroup, Path) + VehicleAttackGroup = { } + Trigger.AfterDelay(VehicleProductionCooldown, function() ProduceVehicle(building) end) + else + Trigger.AfterDelay(delay, function() ProduceVehicle(building) end) + end + end) +end + +SendUnits = function(units, waypoints) + Utils.Do(units, function(unit) + if not unit.IsDead then + Utils.Do(waypoints, function(waypoint) + unit.AttackMove(waypoint.Location) + end) + IdleHunt(unit) + end + end) +end + +StartAI = function(cyard) + Utils.Do(Map.NamedActors, function(actor) + if actor.Owner == enemy and actor.HasProperty("StartBuildingRepairs") then + Trigger.OnDamaged(actor, function(building) + if building.Owner == enemy and building.Health < 3/4 * building.MaxHealth then + building.StartBuildingRepairs() + end + end) + end + end) + enemy.Cash = StartingCash + BuildBase(cyard) +end + +Trigger.OnAllKilledOrCaptured(GDIBase, function() + IdlingUnits(enemy) +end) + +Trigger.OnKilled(GDIProc, function(building) + BaseProc.exists = false +end) + +Trigger.OnKilled(GDINuke1, function(building) + BaseNuke1.exists = false +end) + +Trigger.OnKilled(GDINuke2, function(building) + BaseNuke2.exists = false +end) + +Trigger.OnKilled(GDINuke3, function(building) + BaseNuke3.exists = false +end) + +Trigger.OnKilled(GDIPyle, function(building) + InfantryProduction.exists = false +end) + +Trigger.OnKilled(GDIWeap, function(building) + VehicleProduction.exists = false +end) diff --git a/mods/cnc/maps/nod07b/nod07b.lua b/mods/cnc/maps/nod07b/nod07b.lua new file mode 100644 index 0000000000..65e754f28a --- /dev/null +++ b/mods/cnc/maps/nod07b/nod07b.lua @@ -0,0 +1,265 @@ +WaypointGroup1 = { waypoint0, waypoint15 } +WaypointGroup2 = { waypoint0, waypoint1, waypoint2, waypoint3, waypoint4, waypoint5, waypoint8 } +WaypointGroup3 = { waypoint0, waypoint1, waypoint2, waypoint3, waypoint9, waypoint10, waypoint11, waypoint6, waypoint7 } +WaypointGroup4 = { waypoint9, waypoint10, waypoint11, waypoint6, waypoint7, waypoint14 } + +GDI1 = { units = { ['e2'] = 2, ['e6'] = 1 }, waypoints = WaypointGroup4, delay = 40 } +GDI2 = { units = { ['e1'] = 1, ['e2'] = 1}, waypoints = WaypointGroup3, delay = 40 } +GDI3 = { units = { ['e2'] = 1, ['e3'] = 1, ['jeep'] = 1 }, waypoints = WaypointGroup2, delay = 40 } +GDI4 = { units = { ['mtnk'] = 1 }, waypoints = WaypointGroup3, delay = 40 } +GDI5 = { units = { ['e1'] = 1, ['e2'] = 2 }, waypoints = WaypointGroup2, delay = 40 } +GDI6 = { units = { ['e2'] = 2, ['e2'] = 3 }, waypoints = WaypointGroup1, delay = 40 } +Auto1 = { units = { ['e1'] = 3, ['e2'] = 2 }, waypoints = WaypointGroup3, delay = 40 } +Auto2 = { units = { ['e1'] = 1, ['e2'] = 2 }, waypoints = WaypointGroup2, delay = 40 } +Auto3 = { units = { ['e1'] = 1, ['e3'] = 2 }, waypoints = WaypointGroup2, delay = 40 } +Auto4 = { units = { ['e2'] = 2, ['e3'] = 2 }, waypoints = WaypointGroup3, delay = 40 } +Auto5 = { units = { ['jeep'] = 1 }, waypoints = WaypointGroup2, delay = 50 } +Auto6 = { units = { ['jeep'] = 1 }, waypoints = WaypointGroup3, delay = 40 } +Auto7 = { units = { ['mtnk'] = 1 }, waypoints = WaypointGroup2, delay = 50 } +Auto8 = { units = { ['mtnk'] = 1 }, waypoints = WaypointGroup3, delay = 30 } + +AirstrikeDelay = DateTime.Minutes(2) + DateTime.Seconds(10) + +AutoAttackWaves = { Auto1, Auto2, Auto3, Auto4, Auto5, Auto6, Auto7, Auto8 } +WhitelistedStructures = { 'afld', 'hand', 'hq', 'nuke', 'silo', 'proc', 'sam' } + +NodUnitsTanks = { 'ltnk', 'ltnk', 'ltnk' } +NodUnitsBikes = { 'bike', 'bike', 'bike' } +NodUnitsBuggys = { 'bggy', 'bggy', 'bggy' } +NodUnitsRockets = { 'e3', 'e3', 'e3' } +NodUnitsGunners = { 'e1', 'e1', 'e1' } + +Atk1 = { CPos.New(11, 43), CPos.New(10, 43), CPos.New(9, 43), CPos.New(8, 43), CPos.New(7, 43), CPos.New(6, 43), CPos.New(5, 43), CPos.New(11, 42), CPos.New(10, 42), CPos.New(9, 42), CPos.New(8, 42), CPos.New(7, 42), CPos.New(6, 42), CPos.New(5, 42), CPos.New(23, 38), CPos.New(22, 38), CPos.New(21, 38), CPos.New(20, 38), CPos.New(19, 38), CPos.New(24, 37), CPos.New(23, 37), CPos.New(22, 37), CPos.New(21, 37), CPos.New(20, 37), CPos.New(19, 37) } +Atk2 = { CPos.New(16, 52), CPos.New(15, 52), CPos.New(14, 52), CPos.New(13, 52), CPos.New(12, 52), CPos.New(11, 52), CPos.New(10, 52), CPos.New(9, 52), CPos.New(8, 52), CPos.New(16, 51), CPos.New(15, 51), CPos.New(14, 51), CPos.New(13, 51), CPos.New(12, 51), CPos.New(11, 51), CPos.New(10, 51), CPos.New(9, 51), CPos.New(8, 51), CPos.New(31, 44), CPos.New(30, 44), CPos.New(29, 44), CPos.New(28, 44), CPos.New(27, 44), CPos.New(26, 44), CPos.New(25, 44), CPos.New(24, 44), CPos.New(23, 44), CPos.New(22, 44), CPos.New(21, 44), CPos.New(31, 43), CPos.New(30, 43), CPos.New(29, 43), CPos.New(28, 43), CPos.New(27, 43), CPos.New(26, 43), CPos.New(25, 43), CPos.New(24, 43), CPos.New(23, 43), CPos.New(22, 43), CPos.New(21, 43) } +Atk3 = { CPos.New(53, 58), CPos.New(52, 58), CPos.New(51, 58), CPos.New(53, 57), CPos.New(52, 57), CPos.New(51, 57), CPos.New(53, 56), CPos.New(52, 56), CPos.New(51, 56), CPos.New(53, 55), CPos.New(52, 55), CPos.New(51, 55) } +Atk4 = { CPos.New(54, 47), CPos.New(53, 47), CPos.New(52, 47), CPos.New(51, 47), CPos.New(43, 47), CPos.New(54, 46), CPos.New(53, 46), CPos.New(52, 46), CPos.New(51, 46), CPos.New(50, 46), CPos.New(43, 46), CPos.New(42, 46), CPos.New(41, 46), CPos.New(43, 45), CPos.New(42, 45), CPos.New(41, 45), CPos.New(43, 44), CPos.New(42, 44), CPos.New(41, 44), CPos.New(43, 43), CPos.New(42, 43), CPos.New(41, 43), CPos.New(43, 42) } + +CaptureStructures = function(actor) + for i = 1, #WhitelistedStructures do + structures = player.GetActorsByType(WhitelistedStructures[i]) + if #structures > 0 then + if not actor.IsDead and not structures[1].IsDead then + actor.Capture(structures[1]) + return + end + end + end +end + +CheckForSams = function() + local sams = player.GetActorsByType("sam") + return #sams >= 3 +end + +searches = 0 +getAirstrikeTarget = function() + local list = player.GetGroundAttackers() + + if #list == 0 then + return + end + + local target = list[DateTime.GameTime % #list + 1].CenterPosition + + local sams = Map.ActorsInCircle(target, WDist.New(8 * 1024), function(actor) + return actor.Type == "sam" end) + + if #sams == 0 then + searches = 0 + return target + elseif searches < 6 then + searches = searches + 1 + return getAirstrikeTarget() + else + searches = 0 + return nil + end +end + +GetCargo = function(team) + cargo = { } + for type, count in pairs(team.units) do + for i = 1, count, 1 do + cargo[#cargo + 1] = type + end + end + return cargo +end + +InsertNodUnits = function() + Media.PlaySpeechNotification(player, "Reinforce") + Reinforcements.Reinforce(player, NodUnitsBikes, { ReinforcementsSpawnLeft.Location, ReinforcementsBikesRally.Location }, 1) + Reinforcements.Reinforce(player, NodUnitsBuggys, { ReinforcementsSpawnRight.Location, ReinforcementsBuggyRally.Location }, 50) + Reinforcements.Reinforce(player, NodUnitsGunners, { ReinforcementsSpawnLeft.Location, ReinforcementsGunnersRally.Location }, 50) + Reinforcements.Reinforce(player, NodUnitsRockets, { ReinforcementsSpawnRight.Location, ReinforcementsRocketsRally.Location }, 50) + Trigger.AfterDelay(DateTime.Seconds(6), function() + Reinforcements.Reinforce(player, { 'mcv' }, { ReinforcementsSpawnCenter.Location, ReinforcementsMCVRally.Location }) + Reinforcements.Reinforce(player, NodUnitsTanks, { ReinforcementsSpawnCenter.Location, ReinforcementsTanksRally.Location }, 50) + end) +end + +SendAttackWave = function(team) + for type, amount in pairs(team.units) do + count = 0 + actors = enemy.GetActorsByType(type) + Utils.Do(actors, function(actor) + if actor.IsIdle and count < amount then + SetAttackWaypoints(actor, team.waypoints) + if actor.Type == "e6" then + CaptureStructures(actor) + else + IdleHunt(actor) + end + count = count + 1 + end + end) + end +end + +SetAttackWaypoints = function(actor, waypoints) + if not actor.IsDead then + Utils.Do(waypoints, function(waypoint) + actor.AttackMove(waypoint.Location) + end) + end +end + +SendGDIAirstrike = function(hq, delay) + if not hq.IsDead and hq.Owner == enemy then + local target = getAirstrikeTarget() + + if target then + hq.SendAirstrike(target, false, Facing.NorthEast + 4) + Trigger.AfterDelay(delay, function() SendGDIAirstrike(hq, delay) end) + else + Trigger.AfterDelay(delay/4, function() SendGDIAirstrike(hq, delay) end) + end + end +end + +SendWaves = function(counter, Waves) + if counter <= #Waves then + team = Waves[counter] + SendAttackWave(team) + Trigger.AfterDelay(DateTime.Seconds(team.delay), function() SendWaves(counter + 1, Waves) end) + end +end + +SendReinforcementsWave = function(team) + Reinforcements.ReinforceWithTransport(enemy, "apc", GetCargo(team), { ReinforcementsGDISpawn.Location, waypoint12.Location}, nil, function(transport, passengers) + SetReinforcementsWaypoints(transport, team.waypoints) + transport.UnloadPassengers() + Trigger.OnPassengerExited(transport, function(_, passenger) + Utils.Do(passengers, function(actor) + if actor.Type == "e6" then + CaptureStructures(actor) + else + IdleHunt(actor) + end + end) + if not transport.HasPassengers then + IdleHunt(transport) + end + end) + end) +end + +SetReinforcementsWaypoints = function(actor, waypoints) + if not actor.IsDead then + Utils.Do(waypoints, function(waypoint) + actor.Move(waypoint.Location) + end) + IdleHunt(actor) + end +end + +StartWaves = function() + SendWaves(1, AutoAttackWaves) +end + + + +Trigger.OnEnteredFootprint(Atk1, function(a, id) + if not atk1Trigger and a.Owner == player then + atk1Trigger = true + SendAttackWave(GDI5) + end +end) + +Trigger.OnEnteredFootprint(Atk2, function(a, id) + if not atk2Trigger and a.Owner == player then + atk2Trigger = true + SendAttackWave(GDI4) + end +end) + +Trigger.OnEnteredFootprint(Atk3, function(a, id) + if not atk3Trigger and a.Owner == player then + atk3Trigger = true + SendAttackWave(GDI6) + end +end) + +Trigger.OnEnteredFootprint(Atk4, function(a, id) + if not atk4Trigger and a.Owner == player then + atk4Trigger = true + SendReinforcementsWave(GDI1) + end +end) + +WorldLoaded = function() + player = Player.GetPlayer("Nod") + enemy = Player.GetPlayer("GDI") + Camera.Position = waypoint26.CenterPosition + + InsertNodUnits() + StartAI(GDICYard) + + Trigger.AfterDelay(DateTime.Seconds(10), function() SendAttackWave(GDI2) end) + Trigger.AfterDelay(DateTime.Seconds(55), function() SendAttackWave(GDI2) end) + Trigger.AfterDelay(DateTime.Seconds(85), function() SendAttackWave(GDI3) end) + + Trigger.AfterDelay(AirstrikeDelay, function() SendGDIAirstrike(GDIHQ, AirstrikeDelay) end) + Trigger.AfterDelay(DateTime.Minutes(2), function() ProduceInfantry(GDIPyle) end) + Trigger.AfterDelay(DateTime.Minutes(3), function() ProduceVehicle(GDIWeap) end) + + Trigger.OnPlayerDiscovered(player, StartWaves) + + Trigger.OnObjectiveAdded(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") + end) + + Trigger.OnObjectiveCompleted(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") + end) + + Trigger.OnObjectiveFailed(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") + end) + + Trigger.OnPlayerWon(player, function() + Media.PlaySpeechNotification(player, "Win") + end) + + Trigger.OnPlayerLost(player, function() + Media.PlaySpeechNotification(player, "Lose") + end) + + NodObjective1 = player.AddPrimaryObjective("Eliminate all GDI forces in the area.") + NodObjective2 = player.AddSecondaryObjective("Build 3 SAMs to fend off the GDI bombers.") + GDIObjective = enemy.AddPrimaryObjective("Eliminate all Nod forces in the area.") +end + +Tick = function() + if DateTime.GameTime > 2 and player.HasNoRequiredUnits() then + enemy.MarkCompletedObjective(GDIObjective) + end + + if DateTime.GameTime > 2 and enemy.HasNoRequiredUnits() then + player.MarkCompletedObjective(NodObjective1) + end + + if not player.IsObjectiveCompleted(NodObjective2) and CheckForSams() then + player.MarkCompletedObjective(NodObjective2) + end +end diff --git a/mods/cnc/maps/nod07b/rules.yaml b/mods/cnc/maps/nod07b/rules.yaml new file mode 100644 index 0000000000..7e21a872c9 --- /dev/null +++ b/mods/cnc/maps/nod07b/rules.yaml @@ -0,0 +1,127 @@ +World: + LuaScript: + Scripts: nod07b.lua, nod07b-AI.lua + MusicPlaylist: + StartingMusic: linefire + VictoryMusic: nod_win1 + MissionData: + Briefing: The Brotherhood has located a huge field of Tiberium in the area.\n\nThe nearby village has laid claim to the field.\n\nEliminate the villagers, as to prevent any infection of our own workers.\n\nGDI forces are reported to be minimal, so elimination of them is of secondary importance. + BriefingVideo: nod7a.vqa + StartVideo: tankgo.vqa + LossVideo: visor.vqa + SmudgeLayer@CRATER: + InitialSmudges: + cr1 9,12 0 + +Player: + PlayerResources: + DefaultCash: 4000 + +^Bridge: + DamageMultiplier@INVULNERABLE: + Modifier: 0 + +CYCL: + Buildable: + Prerequisites: ~disabled + +NUK2: + Buildable: + Prerequisites: ~disabled + +HPAD: + Buildable: + Prerequisites: ~disabled + +BRIK: + Buildable: + Prerequisites: ~disabled + +EYE: + Buildable: + Prerequisites: ~disabled + +GUN: + Buildable: + Prerequisites: ~disabled + +OBLI: + Buildable: + Prerequisites: ~disabled + +TMPL: + Buildable: + Prerequisites: ~disabled + +E2: + Buildable: + Prerequisites: ~pyle + +E5: + Buildable: + Prerequisites: ~disabled + +HARV: + Harvester: + SearchFromOrderRadius: 45 + +MTNK: + Buildable: + Prerequisites: ~weap + +HTNK: + Buildable: + Prerequisites: ~disabled + +RMBO: + Buildable: + Prerequisites: ~disabled + +MCV: + Buildable: + Prerequisites: ~disabled + +FTNK: + Buildable: + Prerequisites: ~disabled + +MLRS: + Buildable: + Prerequisites: ~disabled + +MSAM: + Buildable: + Prerequisites: ~disabled + +ATWR: + Buildable: + Prerequisites: ~disabled + +HELI: + Buildable: + Prerequisites: ~disabled + +STNK: + Buildable: + Prerequisites: ~disabled + +ARTY: + Buildable: + Prerequisites: ~disabled + +FIX: + Buildable: + Prerequisites: ~disabled + +SBAG: + Buildable: + Queue: Defence.GDI, Defence.Nod + +GTWR: + Buildable: + Queue: Defence.GDI + +HQ: + AirstrikePower: + Prerequisites: gdi + SquadSize: 1 diff --git a/mods/cnc/missions.yaml b/mods/cnc/missions.yaml index 0512dc9117..a285280e22 100644 --- a/mods/cnc/missions.yaml +++ b/mods/cnc/missions.yaml @@ -22,6 +22,7 @@ Nod Campaign: ./mods/cnc/maps/nod06b ./mods/cnc/maps/nod06c ./mods/cnc/maps/nod07a + ./mods/cnc/maps/nod07b Funpark Campaign: ./mods/cnc/maps/funpark01