To make your own AOD level, you need the following stuff in your level:
Markers
For each path:
Spawn marker -- Spawn location
Spawn direction marker -- Spawn direction
Path or target marker -- AI will either follow a path or move to the given target
For each sneak attack:
Spawn marker -- Spawn location
Spawn direction marker -- Spawn direction
Entry point marker -- AI will move towards this marker when spawned
For each failure position
Failure marker -- Players will fail if AI reaches this point (20m range)
Also create a marker that has all enemy bases within its range
Enemy base marker -- All buildings will be destroyed on level start
Groups
Path sector entity group -- Group that holds all sectors that contain the route for the AI
Level code
import("ScarUtil.scar")
-- SETUP ------------------------------------------------
SETUP = {
["WAVE_DEFAULT_INTERVAL"] = 10, -- default interval between waves
["START_TIME"] = 30, -- time before first wave moves in
["BOMB_FRIENDLY_SQUADS_ABILITY"] = "il-2_bombing_run_sp", -- ability to use when bombing friendly squads on route sector
["BOMB_FRIENDLY_ENTITIES_ABILITY"] = "il-2_bombing_run_sp", -- ability to use when bombing friendly entities on route sector
["HURT_FRIENDLY_SQUADS_SOUND"] = "speech/mp/soviet/cn2/events/pinned/sb_cn2_pin_gengen_lt_s", -- bsc file linking to sounds that should be played when units are getting damage on route sector
["BOMB_FRIENDLY_SQUADS_SOUND"] = "speech/mp/aef/ech/events/warning/ab_ech_wrn_astgen_lt_s", -- bsc file linking to sounds that should be played when units on route sector are about to get bombed
["INVULNERABLE_PLANES"] = {"il-2_sturmovik_rocket_sp_squad", "paratroopers_plane_paras"}, -- list of planes that should be invulnerable (default = empty list)
["AI_PATHS"] = { -- paths for the AI opponent (should have either 'path', 'target' or 'entry_point')
-- 'real' spawns - AI squad spawns at spawn_position and either follows a path or moves to a target
[1] = {
["spawn_position"] = "AOD_spawn_1", -- spawn position (should be the name of an existing marker)
["spawn_direction"] = "AOD_spawn_direction_1", -- spawn direction (should be the name of an existing marker)
["path"] = "AOD_path_1" -- path to follow when spawned (should be the name of an existing marker)
},
[2] = {
["spawn_position"] = "AOD_spawn_2", -- spawn position (should be the name of an existing marker)
["spawn_direction"] = "AOD_spawn_direction_2", -- spawn direction (should be the name of an existing marker)
["target"] = "AOD_target_2" -- target to move to (should be the name of an existing marker)
},
-- sneak attacks - AI squad spawns at spawn_position and moves to entry_point (can spawn outside the map, and make an entry at the given location)
[3] = {
["spawn_position"] = "AOD_sneak_1", -- spawn position (should be the name of an existing marker)
["spawn_direction"] = "AOD_sneak_direction_1", -- spawn direction (should be the name of an existing marker)
["entry_point"] = "AOD_sneak_entry_point_1" -- target to move to (should be the name of an existing marker)
}
},
["AI_FAIL_POSITIONS"] = { -- markers to trigger fail condition (range is 20m)
[1] = "AOD_dest_fail"
},
["DIFFICULTY"] = { -- difficulty settings { easy, normal, hard, hardest }
["starting_resources"] = {
["manpower"] = {2000, 1500, 1200, 1000}, -- starting manpower
["fuel"] = {300, 200, 100, 80}, -- starting fuel
["ammo"] = {800, 600, 300, 200}, -- starting ammo
["command"] = {20, 10, 5, 0} -- starting command points
},
["resource_multipliers"] = {
["manpower"] = {1.6, 1.4, 1.2, 1.0}, -- manpower multiplier
["fuel"] = {1.5, 1.4, 1.2, 1.0}, -- fuel multiplier
["ammo"] = {1.5, 1.4, 1.2, 1.0}, -- ammo multiplier
["upkeep"] = {0.4, 0.5, 0.6, 0.7} -- upkeep multiplier
},
["wave"] = {
["autofire"] = {false, true, true, true}, -- autofire for AI squads (do they fire while moving)
["armor"] = {0.9, 1.0, 1.1, 1.2}, -- armor for AI squads
["speed"] = {0.9, 0.9, 1.0, 1.1}, -- speed for AI squads
["veterancy"] = {0, 0, 1, 2}, -- veterancy for AI squads
["received_suppression"] = {0.75, 0.25, 0, 0}, -- received suppression for AI squads (0 means not able to be suppressed)
},
["hurt_units_on_route"] = { -- settings for hurting units that are moving or standing still on the route
["time_without_damage"] = {3, 2, 1, 1}, -- time to allow player squads to pass through the sector
["time_till_max_damage"] = {5, 4, 3, 3}, -- buildup time until unit gets max damage per second
["max_damage_per_second"] = {0.1, 0.1, 0.15, 0.2} -- max damage per second (percentage)
},
["popcap"] = {250, 225, 200, 150}, -- max popcap for players
["sight"] = {1.5, 1.3, 1.0, 0.8}, -- sight multiplier for players
["experience"] = {1.0, 0.8, 0.7, 0.6}, -- experience multiplier for players
["units_allowed_to_pass"] = {11, 4, 0, 0} -- units that are allowed to reach the end of the level (objective not shown when setting to 0)
},
["WAVE_SETUP"] = { -- setup of the waves
[1] = { -- always start with wave 1 and increment by 1 until the last wave
["units"] = { -- list of unit types to spawn
[1] = {
["type"] = "assault_officer_squad_mp", -- squad blueprint
["amount"] = 1, -- amount of squads to spawn (default = 1)
["interval"] = 2, -- time between squads (default = 2)
["spawns"] = {1}, -- spawnpoints (from AI_PATHS) (default = all 'real' spawnpoints)
["slots"] = {"grenadier_mg42_lmg_moving_mp"}, -- items to give to free slots
["upgrades"] = {"pioneer_minesweeper_mp"} -- updates to give to squads
},
[2] = {
["type"] = "kubelwagen_squad_mp", -- squad blueprint
["amount"] = 1, -- amount of squads to spawn (default = 1)
["interval"] = 2, -- time between squads (default = 2)
["spawns"] = {4, 5, 6}, -- spawnpoints (from AI_PATHS) (default = all 'real' spawnpoints)
["delay"] = 5.5 -- delay before spawning (when not using "wait_for_wave", this will count from the start of the wave) (default = 0)
},
[3] = {
["type"] = "assault_officer_squad_mp", -- squad blueprint
["amount"] = 1, -- amount of squads to spawn (default = 1)
["interval"] = 2, -- time between squads (default = 2)
["spawns"] = {4, 5, 6}, -- spawnpoints (from AI_PATHS) (default = all 'real' spawnpoints)
["delay"] = 5.5, -- delay before spawning (since "wait_for_wave", this delay will be after the specified wave has been spawned) (default = 0)
["wait_for_wave"] = 2 -- wait before spawning until speficied wave has been spawned (can be a number or "previous", which will link to the previous wave. When the wave doesn't exist, it's ignored)
},
[4] = {
["type"] = "kubelwagen_squad_mp", -- squad blueprint
["amount"] = 1, -- amount of squads to spawn (default = 1)
["interval"] = 2, -- time between squads (default = 2)
["spawns"] = {4, 5, 6} -- spawnpoints (from AI_PATHS) (default = all 'real' spawnpoints)
} -- since there is no delay and no wait_for_wave, this part of the wave will be spawned after part 3
},
["wait_until_everybody_dead"] = true, -- start next wave countdown when this wave is dead (default = false)
["delay_after_wave"] = 60.0, -- delay after this wave until next wave starts (default = WAVE_DEFAULT_INTERVAL)
["hurt_moving_friendly_squads_on_route"] = false, -- do damage to moving player squads on route sector (default = false)
["hurt_friendly_squads_on_route"] = false, -- do damage to idle player squads on route sector (default = false)
["bomb_friendly_squads_on_route"] = false, -- bomb player squads on route sector (default = false)
["bomb_friendly_entities_on_route"] = false, -- bomb player entities on route sector (mines, bunkers, etc) (default = false)
["kill_friendly_entities_on_route"] = false, -- instantly kill player entities on route sector (default = false)
["sound_on_spawn"] = "speech/sp/theater_of_war/t03/11040387", --Plays a sound at the start of the wave (default = none)
["message_when_starting"] = { -- show a message when this wave starts
["title"] = "Secure the area and destroy the capitacommunilist army!", -- title of the message (default = empty)
["desc1"] = "Allies are holding this vital point to secure a safe passage of their main army.", -- first line of the message (default = empty)
["desc2"] = "Prepare yourself to retake this position and ambush the main army!", -- second line of the message (default = empty)
["fadein"] = 1.0, -- fade in time (default = 0.5)
["fadeout"] = 1.0, -- fade out time (default = 0.5)
["lifetime"] = 5.0 -- lifetime of the message (default = 2.0)
}
["event_when_starting"] = { -- events when wave starts (possible types are: 'markers', 'bomb_friendly_squads', 'paradrop_near_random_objective', 'spawn_in_random_building')
[1] = {
["blueprint"] = "off_map_artillery_percise_fast", -- blueprint of the event (AbilityBlueprint)
["type"] = "markers", -- type of the event ('markers' spawns the provided ability at the given locations, can be artillery or bombing strike for example)
["locations"] = -- list of locations
{
[0] = {
["position"] = "AOD_event_1", -- location position (should be the name of an existing marker)
["direction"] = "AOD_event_dir1", -- location direction (should be the name of an existing marker)
}, -- no delay specified, will be spawned at the beginning of the wave
[1] = {
["position"] = "AOD_event_2", -- location position (should be the name of an existing marker)
["direction"] = "AOD_event_dir2", -- location direction (should be the name of an existing marker)
["delay"] = 5 -- delay after the start of the wave (default = 0)
}
}
},
[2] = {
["blueprint"] = "b4_203mm_barrage_mp", -- blueprint of the event (AbilityBlueprint)
["type"] = "bomb_friendly_squads" -- type of the event ('bomb_friendly_squads' bombs all player units on the route sector)
},
[3] = {
["blueprint"] = "paratroopers_paradrop", -- blueprint of the event (AbilityBlueprint)
["type"] = "paradrop_near_random_objective", -- type of the event ('paradrop_near_random_objective' does a paradrop on a random player sector)
["delay"] = 3 -- delay after the start of the wave (default = 0)
},
[4] = {
["blueprint"] = "partisans_lmg_mp", -- blueprint of the event (SquadBlueprint)
["type"] = "spawn_in_random_building" -- type of the event ('spawn_in_random_building' spawns a squad in a random available building on the map)
}
}
},
[2] = {
["units"] = {
[1] = {
["type"] = "ostruppen_squad_mp",
["amount"] = 3,
["interval"] = 2,
["spawns"] = {1, 2, 3},
["upgrades"] = {"grenadier_mg42_lmg_mp", "grenadier_mg42_lmg_mp", "grenadier_mg42_lmg_mp"}
},
[2] = {
["type"] = "kubelwagen_squad_mp",
["amount"] = 1,
["interval"] = 2,
["spawns"] = {4, 5, 6}
}
},
["wait_until_everybody_dead"] = true,
["delay_after_wave"] = 60.0,
["event_when_starting"] = {
[1] = {
["blueprint"] = "b4_203mm_barrage_mp",
["type"] = "bomb_friendly_squads"
}
},
["message_when_starting"] = {
["title"] = "Kubelwagens incoming!",
["fadein"] = 1.0,
["fadeout"] = 1.0,
["lifetime"] = 5.0
}
}
}
}
-- init
function OnInit()
-- Initialize the map, send the setup variables to the mod script
AOD_Setup(SETUP)
AOD_OnOnit()
end
function ShowWelcomeMessage()
-- Gets triggered when game starts
local messageTitle = Util_CreateLocString("player count: " .. (PLAYER_COUNT - 1))
local messageBody1 = Util_CreateLocString("by Niels Stoelinga and Kees Fluitman")
local messageBody2 = Util_CreateLocString("Prevent the enemy from reaching the other end of the map!")
Game_SubTextFade(messageTitle, messageBody1, messageBody2, 0.5, 4.0, 1.5)
end
function OnFaultyInit()
-- Gets triggered when the proper victory condition mod hasn't been selected
local messageTitle = LOC("ERROR")
messageTitle[1] = "ERROR"
local messageBody1 = LOC("Make sure that you are running this level with the official Art of Defence mod enabled")
messageBody1[1] = "Make sure that you are running this level with the official Art of Defence mod enabled"
local messageBody2 = LOC("")
messageBody2[1] = ""
Game_SubTextFade(messageTitle, messageBody1, messageBody2, 0.5, 20.0, 1.5)
end
if pcall(function() import("winconditions/aod.scar") end) then
Scar_AddInit(OnInit)
else
Scar_AddInit(OnFaultyInit)
end