Step 1 - Make a map.
Step 2 - Copy the map (sms.gz and smp.gz) into a suitable location in the campaign directory.
For this tutorial I'm working on level 3 of the introduction campaign. So I'm going to put the map files into Tales/campaigns/orc/level03/.
Step 3 - Make a copy of level02o_c.sms and level03o_c2.sms (located in Tales/campaigns/orc/), renaming them to level30_c.sms and level03o_c2.sms respectively.
Step 4 - Open up level03o_c2.sms and adjust the title of the mission and the objectives.
In my case I've ended up with:
Code: Select all
title = "III. Sea Preparations"
objectives = {"- Find your ally's base", "- Build a Shipyard", "- Build 5 Destroyers", "- Arthor Literios must not die"}
Step 5 - Open up level03o.smp.gz (using something like 7-Zip) and open level03o.smp (with WordPad or similar).
Add the following line at the end:
Code: Select all
DefineMapSetup("./campaigns/orc/level03o_c.sms")
Step 6 - Open up level03o_c.sms and make sure all the correct files get loaded.
First, you should make sure level03o_c2.sms is loading at the start of the file.
Code: Select all
-- Stratagus Map - Single player campaign
Load("campaigns/orc/level03o_c2.sms")
Briefing(
title,
objectives,
"../campaigns/orc/interface/introscreen1.png",
"campaigns/orc/level03/level03o.txt",
{"campaigns/orc/level02/level03o-intro1.wav"}
)
Code: Select all
Load("campaigns/orc/level03/level03o.sms")
A mission with no triggers should have a section just under Briefing() of:
Code: Select all
Triggers = [[]]
Code: Select all
Triggers = [[
SetDiplomacy(0, "allied", 6)
SetDiplomacy(6, "allied", 0)
SetSharedVision(6, true, 0)
SetSharedVision(0, true, 6)
SetDiplomacy(1, "enemy", 6)
SetDiplomacy(6, "enemy", 1)
]]
Next I'm going to add winning conditions.
Code: Select all
Triggers = [[
SetDiplomacy(0, "allied", 6)
SetDiplomacy(6, "allied", 0)
SetSharedVision(6, true, 0)
SetSharedVision(0, true, 6)
SetDiplomacy(1, "enemy", 6)
SetDiplomacy(6, "enemy", 1)
AddTrigger(
function() return GetPlayerData(GetThisPlayer(), "UnitTypesCount", "unit-human-destroyer") > 4 and
GetPlayerData(GetThisPlayer(), "UnitTypesCount", "unit-human-shipyard") >= 1 end,
function() return ActionVictory() end)
]]
Now I'm going to add some loosing conditions.
Code: Select all
Triggers = [[
SetDiplomacy(0, "allied", 6)
SetDiplomacy(6, "allied", 0)
SetSharedVision(6, true, 0)
SetSharedVision(0, true, 6)
SetDiplomacy(1, "enemy", 6)
SetDiplomacy(6, "enemy", 1)
AddTrigger(
function() return GetPlayerData(GetThisPlayer(), "UnitTypesCount", "unit-human-destroyer") > 4 and
GetPlayerData(GetThisPlayer(), "UnitTypesCount", "unit-human-shipyard") >= 1 end,
function() return ActionVictory() end)
AddTrigger(
function() return GetNumUnitsAt(ThisPlayer.Index, "unit-arthor-literios",
{0, 0}, {128, 128}) < 1 end,
function() return ActionDefeat() end)
AddTrigger(
function() return GetPlayerData(GetThisPlayer(), "TotalNumUnits") == 0 end,
function() return ActionDefeat() end)]]
Step 8 - Add some fancy scripting.
Right now the map is playable, but not winnable. What I'm going to do is have the town hall at the AI's base tranfer to the player. First however I'll deal with those four AI rangers at the start of the map.
Lazy rangers. What I'd love to have happen is for those rangers to lead the way to the allied base. However, currently we don't have the functions needed to make that happen. What I'm going to do is to make my own AI which will make those rangers attack the enemy instead. First, I'll make the AI.
Create a new LUA file in Tales/campaigns/orc/level03/ and call it level03o_ai.lua
Inside insert:
Code: Select all
-- _________ __ __
-- / _____// |_____________ _/ |______ ____ __ __ ______
-- \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
-- / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ \
-- /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
-- \/ \/ \//_____/ \/
-- ______________________ ______________________
-- T H E W A R B E G I N S
-- Stratagus - A free fantasy real time strategy game engine
--
-- level03o_ai.lua - Define the AI.
--
-- (c) Copyright 2012 by Kyran Jackson
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
function AiLevel03()
AiForce(2, {AiShooter(), 4})
AiAttackWithForce(2)
AiSet(AiWorker(), 8)
if ((GetNumUnitsAt(AiPlayer(), "unit-town-hall", {0, 0}, {256, 256}) >= 1) or (GetNumUnitsAt(AiPlayer(), "unit-castle", {0, 0}, {256, 256}) >= 1) or (GetNumUnitsAt(AiPlayer(), "unit-keep", {0, 0}, {256, 256}) >= 1)) then
if (GetNumUnitsAt(AiPlayer(), "unit-human-barracks", {0, 0}, {256, 256}) >= 1) then
if (GetNumUnitsAt(AiPlayer(), "unit-footman", {0, 0}, {256, 256}) >= 4) then
AiForce(3, {AiSoldier(), 12})
if (GetNumUnitsAt(AiPlayer(), "unit-footman", {0, 0}, {256, 256}) >= 8) then
print("attack")
AiAttackWithForce(3)
end
else
AiSet(AiSoldier(), 4)
end
else
AiSet(AiBarracks(), 1)
end
else
AiSet(AiCityCenter(), 1)
end
end
DefineAi("ai_level03", "*", "ai_level03", AiLevel03)
Code: Select all
Load("campaigns/orc/level03/level03o_ai.lua")
Success, the friendly player is now using a custom AI script.
OK, now that we've got that little annoyance out of the way, let's make this mission winnable. I'll open level03o_c.sms back up and have the townhall change to the player when the hero unit stands next to it.
Code: Select all
Triggers = [[
SetDiplomacy(0, "allied", 6)
SetDiplomacy(6, "allied", 0)
SetDiplomacy(1, "enemy", 6)
SetDiplomacy(6, "enemy", 1)
AddTrigger(
function() return GetPlayerData(GetThisPlayer(), "UnitTypesCount", "unit-human-destroyer") > 4 and
GetPlayerData(GetThisPlayer(), "UnitTypesCount", "unit-human-shipyard") >= 1 end,
function() return ActionVictory() end)
AddTrigger(
function() return GetNumUnitsAt(ThisPlayer.Index, "unit-arthor-literios",
{0, 0}, {128, 128}) < 1 end,
function() return ActionDefeat() end)
AddTrigger(
function() return GetPlayerData(GetThisPlayer(), "TotalNumUnits") == 0 end,
function() return ActionDefeat() end)
AddTrigger(
function() return GetNumUnitsAt(ThisPlayer.Index, "unit-arthor-literios",
{17, 29}, {25, 37}) > 0 end,
function() return ChangeUnitsOwner({15, 29}, {25, 37}, 6, 0) end)
]]
Seems one small side effect has come up. When the player takes control of the townhall the AI will build another one. That goes against the lore so I'll remove some functionality from the AI script.
Code: Select all
-- _________ __ __
-- / _____// |_____________ _/ |______ ____ __ __ ______
-- \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
-- / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ \
-- /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
-- \/ \/ \//_____/ \/
-- ______________________ ______________________
-- T H E W A R B E G I N S
-- Stratagus - A free fantasy real time strategy game engine
--
-- level03o_ai.lua - Define the AI.
--
-- (c) Copyright 2012 by Kyran Jackson
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
function AiLevel03()
if (GetNumUnitsAt(AiPlayer(), "unit-ranger", {0, 0}, {256, 256}) >= 4) then
AiForce(2, {AiShooter(), 4})
AiAttackWithForce(2)
end
AiSet(AiWorker(), 8)
if (GetNumUnitsAt(AiPlayer(), "unit-human-barracks", {0, 0}, {256, 256}) >= 1) then
if (GetNumUnitsAt(AiPlayer(), "unit-footman", {0, 0}, {256, 256}) >= 4) then
AiForce(3, {AiSoldier(), 12})
if (GetNumUnitsAt(AiPlayer(), "unit-footman", {0, 0}, {256, 256}) >= 8) then
AiAttackWithForce(3)
end
else
AiSet(AiSoldier(), 4)
end
else
AiSet(AiBarracks(), 1)
end
end
DefineAi("ai_level03", "*", "ai_level03", AiLevel03)
For this mission, the player needs to be able to build a shipyard and destroyers. Open up level03o_c.sms for the final time and fine:
Code: Select all
DefineAllow("unit-human-oil-tanker", "FFFFFFFFFFFFFFFF")
DefineAllow("unit-human-destroyer", "FFFFFFFFFFFFFFFF")
DefineAllow("unit-human-transport", "FFFFFFFFFFFFFFFF")
DefineAllow("unit-human-oil-platform", "FFFFFFFFFFFFFFFF")
DefineAllow("unit-human-shipyard", "FFFFFFFFFFFFFFFF")
Code: Select all
DefineAllow("unit-human-oil-tanker", "AAAAAAAAAAAAAAAA")
DefineAllow("unit-human-destroyer", "AAAAAAAAAAAAAAAA")
DefineAllow("unit-human-transport", "AAAAAAAAAAAAAAAA")
DefineAllow("unit-human-oil-platform", "AAAAAAAAAAAAAAAA")
DefineAllow("unit-human-shipyard", "AAAAAAAAAAAAAAAA")