BF2 Mission scripting tutorial (FAQ)
Posted: Sat Mar 24, 2007 4:31 pm
-----
THIS TUTORIAL IS A WORK IN PROGRESS
-----
Ok let me start with the notice that I'm still figuring this out myself, and I haven't really written any Tutorials before so I'm not the best at it. Furthermore, to keep me from having to type too much and becouse loads of things allready have a great description I have used some text straight from the Doc's. Text with an asterisk(*) is straight out of the Documentation
Learning mission scripting is really a matter of comparing lua scripts in from the campaign wich can be found at 'C:\BF2_ModTools\assets\scripts' and they have a '_c' at the end of their name. For Example 'cor1c_c.lua'; the Jedi Temple mission.
The main problem is that there are many ways to get the same result in scripting and each artist has it's own way of doing things. Therefore you should always compare multiple scripts. I still don't have a clue what some things mean and what they are for, those I will update as soon as I know what they mean. For the moment there will be some empty spots.
You will need:
- a texteditor like notepad. I recommend downloading Notepad ++
- Enough time to learn
- Some basic understanding of some kind of programming language similar to C(C++, PHP or any experience with lua files is highly recomended)
- Some good music to play while learning/scripting, trust me, it makes your modding-life a lot easyer. I recommend the star wars soundtracks, Prodigy and Rage against the machine.
Before you go wild on pasting loads of code in your own Lua, make sure you have a backup. I also recommend that you start with thinking what objectives you want. For example:
- Objective 1; Go to that pile of ruble over there
- Objective 2; Kill those scavaging Jawa's
- Objective 3; Secure the landing pad so the reinforcements can Land
- Objective 4; Destroy That Jawa Sandcrawler
In this Example you want the player to go somewhere, than the player must kill a few designated creatures. After that you want the player to capture a command post, and finally you want the player to destroy an object. Most of these objectives are managed via outside scripts, wich are loaded at the start of your Lua file. In a normal conquest mission, only 'ScriptCB_DoFile("ObjectiveConquest")' and
'ScriptCB_DoFile("setup_teams")' are loaded, but when you have more complex objectives, you'll need more.
All these scripts are located at 'C:\BF2_ModTools\data_@#$\Common\scripts'. These scripts are here so you don't have to exactly write everything again when you start a new map. You can just type ObjectiveGoto and all the text from that file will be automaticly 'read from elsewhere when you munge it. This keeps the mission script short and makes sure that things don't get TOO confusing.
In this Case we need to load these scripts:
after we set this up, we move on to describing the teams:
*"The following line defines the function ScriptPostLoad, which is a function that is run after the game has finished running ScriptInit (more on that below). ScriptPostLoad will contain all your game script, handling everything that actually happens once the level is loaded and play begins. ScriptInit is setup, and making sure everything is loaded, and then ScriptPostLoad actually contains the in-game logic."
The game needs to know what command posts there are, if you want people to be able to spawn and capture other cp's. This is no different from any other Conquest level and should be familiar. If not, stop with this tutorial and practice your basic Modding skills.
If you are modifying a conquest level you will now see this: .
All the Campaign lua's apear to start with THIS:
... or some variation of it. This code makes sure the objectives start AFTER you are spawned. It checks who is spawning, and if It's is a player, it starts a timer wich starts the objectives. And some more things of wich I don't know much right now.
FINALLY we got to the Objectives part. In the normal conquest mode this looks like this:
It says: Conquest means(conquest =) run script 'ObjectiveConquest', make a New one with these properties: this objective is for team Attack, a.k.a. Att and it's for team Defend, a.k.a. DEF. Now display text in the objectives part of the map. for the the attacking team, check the localisation file at 'game.modes.con' and for the defending side check that same file at 'game.modes.con2'. Make sure all these rules are EXACTLY the same when it's played in multiplayer.
But we don't want a plain Conquest map. Those are getting boring, we want the player of the attacking team to go to a specific region. Therefore we replace the previous code with something like THIS:
------------------
THIS WILL BE WHERE THE OTHER OBJECTIVES WILL BE DESCRIBED AT A LATER TIME
------------------
The other side will need objectives too, but to keep it simple for now, let's just keep that at:
somehow you won't be able to play the other team anyway. Probably has something to do with the Campaign Rules.
since the other team is doing conquest we need to tell them wich CP's To capture before they win.
and now it's time to make sure all the Objectives are started:
Well that will do for now. I will continue to update this tutorial. I actually want a large list of all the objectives and how to use them but I'm tired of typing. This tutorial is Still a work in progress. If you spot any mistakes, please tell me.
Good luck for now
THIS TUTORIAL IS A WORK IN PROGRESS
-----
Ok let me start with the notice that I'm still figuring this out myself, and I haven't really written any Tutorials before so I'm not the best at it. Furthermore, to keep me from having to type too much and becouse loads of things allready have a great description I have used some text straight from the Doc's. Text with an asterisk(*) is straight out of the Documentation
Learning mission scripting is really a matter of comparing lua scripts in from the campaign wich can be found at 'C:\BF2_ModTools\assets\scripts' and they have a '_c' at the end of their name. For Example 'cor1c_c.lua'; the Jedi Temple mission.
The main problem is that there are many ways to get the same result in scripting and each artist has it's own way of doing things. Therefore you should always compare multiple scripts. I still don't have a clue what some things mean and what they are for, those I will update as soon as I know what they mean. For the moment there will be some empty spots.
You will need:
- a texteditor like notepad. I recommend downloading Notepad ++
- Enough time to learn
- Some basic understanding of some kind of programming language similar to C(C++, PHP or any experience with lua files is highly recomended)
- Some good music to play while learning/scripting, trust me, it makes your modding-life a lot easyer. I recommend the star wars soundtracks, Prodigy and Rage against the machine.
Before you go wild on pasting loads of code in your own Lua, make sure you have a backup. I also recommend that you start with thinking what objectives you want. For example:
- Objective 1; Go to that pile of ruble over there
- Objective 2; Kill those scavaging Jawa's
- Objective 3; Secure the landing pad so the reinforcements can Land
- Objective 4; Destroy That Jawa Sandcrawler
In this Example you want the player to go somewhere, than the player must kill a few designated creatures. After that you want the player to capture a command post, and finally you want the player to destroy an object. Most of these objectives are managed via outside scripts, wich are loaded at the start of your Lua file. In a normal conquest mission, only 'ScriptCB_DoFile("ObjectiveConquest")' and
'ScriptCB_DoFile("setup_teams")' are loaded, but when you have more complex objectives, you'll need more.
All these scripts are located at 'C:\BF2_ModTools\data_@#$\Common\scripts'. These scripts are here so you don't have to exactly write everything again when you start a new map. You can just type ObjectiveGoto and all the text from that file will be automaticly 'read from elsewhere when you munge it. This keeps the mission script short and makes sure that things don't get TOO confusing.
In this Case we need to load these scripts:
Code: Select all
ScriptCB_DoFile("setup_teams")--*"setup_teams handles the logic for specifying the unit loadout."
ScriptCB_DoFile("ObjectiveConquest")-- This is about capturing CP's
ScriptCB_DoFile("MultiObjectiveContainer")-- I'm not sure what this is for, but it is included in Almost all the Campaign missions
ScriptCB_DoFile("ObjectiveGoto")-- well this speaks for it'selve
ScriptCB_SetGameRules("campaign")
ScriptCB_DoFile("Ambush")-- Jawa's will be ambushing us at the ruble, so we need thisCode: Select all
-- Empire Attacking (attacker is always #1)
local ALL = 2
local IMP = 1
-- These variables do not change
local ATT = 1
local DEF = 2
JawaAmbush = 5
JAM = JawaAmbush*"The following line defines the function ScriptPostLoad, which is a function that is run after the game has finished running ScriptInit (more on that below). ScriptPostLoad will contain all your game script, handling everything that actually happens once the level is loaded and play begins. ScriptInit is setup, and making sure everything is loaded, and then ScriptPostLoad actually contains the in-game logic."
Code: Select all
function ScriptPostLoad()
ScriptCB_SetGameRules("campaign")-- Here you can see a script being used; The script to define the gameRules(of wich I don't really know what they do EXACTLY)
SetAIDifficulty(0, 0, "medium")-- I'd say this influences the dumbness of the A.I. to compensate for difficult maps.
DisableAIAutoBalance()--Help requested on explaining this
The game needs to know what command posts there are, if you want people to be able to spawn and capture other cp's. This is no different from any other Conquest level and should be familiar. If not, stop with this tutorial and practice your basic Modding skills.
Code: Select all
cp1 = CommandPost:New{name = "cp1"}
cp2 = CommandPost:New{name = "cp2"}
cp3 = CommandPost:New{name = "cp3"}
cp4 = CommandPost:New{name = "cp4"}
cp5 = CommandPost:New{name = "cp5"}
Code: Select all
--This sets up the actual objective. This needs to happen after cp's are definedAll the Campaign lua's apear to start with THIS:
Code: Select all
onfirstspawn = OnCharacterSpawn(
function(character)
if IsCharacterHuman(character) then
ReleaseCharacterSpawn(onfirstspawn)
onfirstspawn = nil
objectives_timer = CreateTimer("objectives_timer")
SetTimerValue(objectives_timer, 2)
StartTimer(objectives_timer)
begin_objectives = OnTimerElapse(
function(timer)
StartObjectives ()
ScriptCB_EnableCommandPostVO(0)
end,
objectives_timer
)
end
end
)FINALLY we got to the Objectives part. In the normal conquest mode this looks like this:
Code: Select all
--This sets up the actual objective. This needs to happen after cp's are defined
conquest = ObjectiveConquest:New{teamATT = ATT, teamDEF = DEF,
textATT = "game.modes.con",
textDEF = "game.modes.con2",
multiplayerRules = true}
But we don't want a plain Conquest map. Those are getting boring, we want the player of the attacking team to go to a specific region. Therefore we replace the previous code with something like THIS:
Code: Select all
--objective 1; Go to the pile of ruble... it doesn't really matter what I type here, it's a comment and it won't be processed by the munge thingy anyway. It's just so I know where I am right now.
Objective1 = ObjectiveGoto:New{TeamATT = ATT, --Make a new objective for the attacking team.
text = "level.@#$.objectives.empire.1", popupText = "level.@#$.objectives.empire.1_popup",
--above we tell the game to show the objective we typed in the localisation tool, near the map and in the upperscreen.
regionName = "goto1", mapIcon = "hud_objective_icon_circle", AIGoalWeight = 0}
-- we just told the game to wich region(wich we placed and named in zeroeditor we want the player to go and that the game should indicate this place on the map with a yellow marker. The A.I. Will have no interest in going here(AIGoalWeight = 0)
Objective1.OnStart = function(self)
att_obj1_aigoal = AddAIGoal(ATT, "Deathmatch", 100)
MapAddEntityMarker("goto", "hud_objective_icon", 3.0, 1, "YELLOW", true)
-- here we told the A.I. what to do.
end
Objective1.OnComplete = function(self)
DeleteAIGoal(att_obj1_aigoal)
ShowMessageText("game.objectives.complete")
ShowPopup("level.@#$.objectives.empire.1complete_popup", ATT)
--when the objective is completed, we don't need the A.I. goal anymore, and we want to inform the player that the objective is completed by showing this in the top of the screen and with a popup.
MapRemoveEntityMarker("goto")
-- we don't need that marker anymore so we delete that.
end
--THIS WILL BE WHERE THE OTHER OBJECTIVES WILL BE DESCRIBED AT A LATER TIME
------------------
The other side will need objectives too, but to keep it simple for now, let's just keep that at:
Code: Select all
conquest = ObjectiveConquest:New{teamDEF = DEF,
textDEF = "game.modes.con2",
multiplayerRules = true}
since the other team is doing conquest we need to tell them wich CP's To capture before they win.
Code: Select all
conquest:AddCommandPost(cp1)
conquest:AddCommandPost(cp2)
conquest:AddCommandPost(cp3)
conquest:AddCommandPost(cp4)
conquest:AddCommandPost(cp5)
and now it's time to make sure all the Objectives are started:
Code: Select all
conquest:Start()
EnableSPHeroRules()
end
function StartObjectives()
objectiveSequence = MultiObjectiveContainer:New{delayVictoryTime = 4.0 }
objectiveSequence:AddObjectiveSet(Objective1)
objectiveSequence:Start()
end
Well that will do for now. I will continue to update this tutorial. I actually want a large list of all the objectives and how to use them but I'm tired of typing. This tutorial is Still a work in progress. If you spot any mistakes, please tell me.
Good luck for now