[Tutorial] Mission Scripting

In this forum you will find and post information regarding the modding of Star Wars Battlefront 2. DO NOT POST MOD IDEAS/REQUESTS.

Moderator: Moderators

Post Reply
User avatar
CT108
Rebel Sergeant
Rebel Sergeant
Posts: 186
Joined: Mon Aug 22, 2016 6:20 am
Projects :: None
Games I'm Playing :: CS2
xbox live or psn: Captain CT108
Location: Xanadu

[Tutorial] Mission Scripting

Post by CT108 »

Hey guys !

I've been looking for a mission scripting tutorial a few months ago but found nothing, excepted some little things here and here, but there's not a 'true' tutorial about the mission scripting.

I apologize if there's another complete tutorial on gametoast that I missed. Also, I've found some parts of code on discussions on GT but I don't remember where, so I'll make credits when I'll find where I've got the code.

That being said let's start !

WHAT'S 'MISSION SCRIPTING' ?
You know, in the campaign, you have missions with objectives to do. Here, we'll see how to add these objectives to your map !

STEPS

0.5 Before Starting
Hidden/Spoiler:
-I'll do this on a conquest lua
-I might do some stupid english grammar errors
-I'll probably say wrong things while explaining some code (tell me when I'm wrong, if I am)
-You MUST get Notepad ++ (So useful) or, better, Marth8880' Lua API extension for Visual Studio Code
-There's this program, can be useful ! (mission scripter) http://www.gametoast.com/viewtopic.php?f=64&t=12029
-While reading this, play badass music, like this https://www.youtube.com/watch?v=Tj4FA7BGGkQ&t=1926s
-The mission will be for the ATT team (republic and empire if I'm right)

1 Get our mission start
Hidden/Spoiler:
That's the code that starts the mission.

[code]SetAIDifficulty(0, 2, "hard")
AllowAISpawn(ATT, true)
AllowAISpawn(DEF, true)
EnableSPScriptedHeroes()
ScriptCB_SetGameRules("campaign")
DisableAIAutoBalance()

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)
StartTimer(timeoutTimer)
end,
objectives_timer
)
end
end
)[/code]

You have to put that right after [code]function ScriptPostLoad()[/code].

--

[code]SetAIDifficulty(0, 2, "hard")
AllowAISpawn(ATT, true)
AllowAISpawn(DEF, true)
EnableSPScriptedHeroes()
ScriptCB_SetGameRules("campaign")
DisableAIAutoBalance()[/code]
I think everything here explains itself - I don't know what DisableAIAutoBalance() do, but it's something that's on every mission of the vanilla game, so that may be important.

--

[code]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)
StartTimer(timeoutTimer)
end,
objectives_timer
)
end
end
)[/code]

This will check if at your first spawn you're a human player, and if you're a human player, it will start a timer of 2 secs. After 2 secs, your first objective start !
2 Objectives
Hidden/Spoiler:
We'll do 2 objectives (of course you can add more) :
-Destroy an object
-Capture a CP

--FIRST OBJECTIVE--

Here's what you'll have to put right after the first step [code]

--objective: assault
Dobjekt = Target:New{name = "object_name"}
Dobjekt.OnDestroy = function(self)

end

Objective1 = ObjectiveAssault:New{teamATT = ATT, teamDEF = DEF,
text = "level.AAA.objectives.1", popupText = "level.AAA.objectives.1"}
Objective1:AddTarget(Dobjekt)


Objective1.OnStart = function(self)


end

Objective1.OnComplete = function(self)
ShowMessageText("game.objectives.complete", ATT)

end

[/code]

*Be sure to replace AAA by your 3 letter world name, and replace Objective1 by Objective2 if it's your second obj, Objective3 if it's your third one etc...

--

[code]Dobjekt = Target:New{name = "object_name"}
Dobjekt.OnDestroy = function(self)

end[/code]

This sets up what object in your map needs to be destroyed.

--

[code]Objective2 = ObjectiveAssault:New{teamATT = ATT, teamDEF = DEF,
text = "level.AAA.objectives.1", popupText = "level.AAA.objectives.1"}[/code]

That's about the localization.

[code]level.AAA.objectives.1[/code] is the path in the localization tool, and it will show the text and the popup text that will apear at the beginning of the objective

--

[code]Objective1:AddTarget(Dobjekt)


Objective1.OnStart = function(self)

end[/code]

Not very important yet, but it needs to be there.

--

[code]Objective1.OnComplete = function(self)
ShowMessageText("game.objectives.complete", ATT)

end[/code]

End the objective and shows 'objective complete'

--SECOND OBJECTIVE--

What you need to add right after the first objective

[code]--objective: conquest
Objective2CP = CommandPost:New{name = "CP2"}
Objective2 = ObjectiveConquest:New{teamATT = ATT, teamDEF = DEF, text = "level.AAA.objectives.2", popupText = "level.AAA.objectives.2", AIGoalWeight = 0}
Objective1:AddCommandPost(Objective2CP)

Objective2:AddHint("level.geo1.hints.capture_cp")

Objective2.OnStart = function(self)
AICanCaptureCP("CP2", ATT, false)
AICanCaptureCP("CP2", DEF, false)
att_obj1_aigoal = AddAIGoal(ATT, "Defend", 50, "CP2")
def_obj1_aigoal = AddAIGoal(DEF, "Defend", 50, "CP2")
att_obj1_aigoal2 = AddAIGoal(ATT, "Deathmatch", 100)
def_obj1_aigoal2 = AddAIGoal(DEF, "Deathmatch", 100)
end

Objective2.OnComplete = function(self)
ShowMessageText("game.objectives.complete", ATT)
DeleteAIGoal(att_obj1_aigoal)
DeleteAIGoal(att_obj1_aigoal2)
DeleteAIGoal(def_obj1_aigoal)
DeleteAIGoal(def_obj1_aigoal2)
SetProperty("CP2", "Team", 1)
SetProperty("CP2", "CaptureRegion", "")

end[/code]

--

*Be sure to replace AAA by your 3 letter world name, CP2 by the name of your CP, and replace Objective1 by Objective2 if it's your second obj, Objective3 if it's your thirs one etc...

[code]Objective2CP = CommandPost:New{name = "CP2"}
Objective2 = ObjectiveConquest:New{teamATT = ATT, teamDEF = DEF, text = "level.AAA.objectives.2", popupText = "level.AAA.objectives.2", AIGoalWeight = 0}
Objective1:AddCommandPost(Objective2CP)[/code]

Defines which CP needs to be captured and where is the text and the popup text (like for the first objective).

--

[code]Objective2:AddHint("level.geo1.hints.capture_cp")

Objective2.OnStart = function(self)
AICanCaptureCP("CP2", ATT, false)
AICanCaptureCP("CP2", DEF, false)
att_obj1_aigoal = AddAIGoal(ATT, "Defend", 50, "CP2")
def_obj1_aigoal = AddAIGoal(DEF, "Defend", 50, "CP2")
att_obj1_aigoal2 = AddAIGoal(ATT, "Deathmatch", 100)
def_obj1_aigoal2 = AddAIGoal(DEF, "Deathmatch", 100)
end[/code]

Add goals to the AI ; I think you can see yourself what everything does here ^^

--

[code]Objective2.OnComplete = function(self)
ShowMessageText("game.objectives.complete", ATT)
DeleteAIGoal(att_obj1_aigoal)
DeleteAIGoal(att_obj1_aigoal2)
DeleteAIGoal(def_obj1_aigoal)
DeleteAIGoal(def_obj1_aigoal2)
SetProperty("CP2", "Team", 1)
SetProperty("CP2", "CaptureRegion", "")

end[/code]

When the objective is done, this part will delete AI goals and show 'objective complete'
3 Localization
Hidden/Spoiler:
That may be the easiest part !

Open the localization tool and :
-Add a scope to level and name it AAA (where AAA is your 3 letters world name)
-Add a scope to AAA and name it objectives
-Add any number of keys to objectives ! The keys have to get the same name in the lua - in this tutorial we need 2 scopes : 1 and 2, because in your lua there's

[code]level.AAA.objectives.1[/code]
or
[code]level.AAA.objectives.2[/code]

That's it !
4 Load the objectives
Hidden/Spoiler:
At the top of your lua, add this

[code]ScriptCB_DoFile("setup_teams")
ScriptCB_DoFile("ObjectiveConquest")
ScriptCB_DoFile("ObjectiveAssault")
ScriptCB_DoFile("MultiObjectiveContainer")
ScriptCB_SetGameRules("campaign")[/code]

This will load every scripts we'll need for our mission.

--

Right before [code]---------------------------------------------------------------------------
-- FUNCTION: ScriptInit
-- PURPOSE: This function is only run once
-- INPUT:
-- OUTPUT:
-- NOTES: The name, 'ScriptInit' is a chosen convention, and each
-- mission script must contain a version of this function, as
-- it is called from C to start the mission.
---------------------------------------------------------------------------

function ScriptInit()

ReadDataFile("ingame.lvl")



SetMaxFlyHeight(10000)
SetMaxPlayerFlyHeight(10000)[/code]

Add this

[code]function StartObjectives()
objectiveSequence = MultiObjectiveContainer:New{delayVictoryTime = 2.0 }
objectiveSequence:AddObjectiveSet(Objective1)
objectiveSequence:AddObjectiveSet(Objective2)
objectiveSequence:Start()
end[/code]

This is super important too : it's that part that loads your objectives ! If there's something wrong here, your objectives will just not show up and you'll get a regular conquest map.

--

[code]objectiveSequence = MultiObjectiveContainer:New{delayVictoryTime = 2.0 }[/code]

At delayVictoryTime = 2.0 enter the number of objectives in your mission. Here we put 2.0 because we have 2 objectives.

--
[code]objectiveSequence:AddObjectiveSet(Objective1)
objectiveSequence:AddObjectiveSet(Objective2)[/code]

Add [code]objectiveSequence:AddObjectiveSet(Objective*)[/code] when you create a new objective. For exemple there's 7 objectives in your map, so you'll have 7 times this [code]objectiveSequence:AddObjectiveSet(Objective*)[/code]

That's it for now ! I don't have enough time now to make something more complete, but I'm gonna update this a lot in the next days !

I hope this tutorial has helped you :D
Last edited by CT108 on Sun Jan 21, 2018 11:45 am, edited 1 time in total.
Marth8880
Resistance Leader
Posts: 5042
Joined: Tue Feb 09, 2010 8:43 pm
Projects :: DI2 + Psychosis
Games I'm Playing :: Silent Hill 2
xbox live or psn: Marth8880
Location: Edinburgh, UK
Contact:

Re: [Tutorial] Mission Scripting

Post by Marth8880 »

Pretty good start to an overview of the different components that make up a mission! :thumbs: It would be great to see some more detailed overviews of the individual components, like what each does, what parameters each takes, when you could/should use certain components over others, etc.

Also, I'd personally recommend using Visual Studio Code over Notepad++ for anything and everything scripting-related - largely because a certain someone has documented the game's scripting API as a special plugin for the program. ;)

See here for the plugin: http://www.gametoast.com/viewtopic.php?f=64&t=33418
User avatar
CT108
Rebel Sergeant
Rebel Sergeant
Posts: 186
Joined: Mon Aug 22, 2016 6:20 am
Projects :: None
Games I'm Playing :: CS2
xbox live or psn: Captain CT108
Location: Xanadu

Re: [Tutorial] Mission Scripting

Post by CT108 »

Thanks ! Visual Studio Code added to the list :wink:

Yeah I'm going to put more informations about the mission scripting the next week :D
Post Reply