Mission failure on Cp loss [Solved]

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
Oceans14
Command Sergeant Major
Command Sergeant Major
Posts: 296
Joined: Mon Apr 27, 2015 7:09 pm
Projects :: Athenova Campaign
Games I'm Playing :: SWBF2
Location: Planet 4546b

Mission failure on Cp loss [Solved]

Post by Oceans14 »

I'm trying to script an objective where the player has to defend a CP for 60 seconds. If the CP is lost at any point during that time, the mission is failed. Otherwise, once the timer elapses (and the CP is still in friendly hands) the objective is complete and the next one starts. The problem is, I'm having a hard time figuring out just how to script this. So far I've figured I could do something like:

Code: Select all

Objective1.OnStart = function(self)
	
		defendtimer = CreateTimer("defendtimer")
		SetTimerValue(defendtimer, 60.0)
		MapAddEntityMarker("c_cp1", "hud_objective_icon", 4.0, ATT, "YELLOW", true)
		
		StartTimer(defendtimer)
                OnTimerElapse(
        			function(timer)
            			--end the objective?()            			
            			DestroyTimer(timer)
        			end,
        		defendtimer
		
	Objective2.OnComplete = function(self)
		GetCommandPostTeam(c_cp1)
			if (c_cp1, Team, 2)
			--MissionDefeat and display some sad text
			elseif (c_cp1, Team, 1)
			--Continue on to next obj
			
The commented stuff is what I'm not sure about. Unfortunately I can't find/think of any instances in the stock scripts where this is all laid out. If anyone could help me out that would be awesome :D
Last edited by Oceans14 on Tue Feb 23, 2016 10:09 pm, edited 1 time in total.
jedimoose32
Field Commander
Field Commander
Posts: 938
Joined: Thu Jan 24, 2008 12:41 am
Projects :: Engineering Degree
Location: The Flatlands of Canada

Re: Mission failure on Cp loss

Post by jedimoose32 »

I've never used the Objective containers before, so I can't really say much about that part of it. But aside from that, your current code is somewhat correct. A good way to do it would be to make use of the game's OnFinishCaptureName() function, which has a similar setup to the OnTimerElapse() function in that you have two arguments, the first of which is a function and the second being the name of something (in this case, the CP that was just captured). See my example below. If you want defeat to come as soon as the attacking team neutralizes the post, you would use OnFinishNeutralizeName() instead of OnFinishCaptureName().

Code: Select all

defendtimer = CreateTimer("defendtimer")
SetTimerValue(defendtimer, 60.0)
MapAddEntityMarker("c_cp1", "hud_objective_icon", 4.0, ATT, "YELLOW", true)
StartTimer(defendtimer)

OnTimerElapse(
  function(timer)
    StopTimer(defendtimer)
    if GetObjectTeam("c_cp1") == 1 then
      --end the objective and start the next one
    else MissionDefeat(1)
    end
    DestroyTimer(defendtimer)
  end,
  defendtimer
)

CPTaken = OnFinishCaptureName(
  function(postPtr)
    if GetObjectTeam(postPtr) ~= 1 then
      MissionDefeat(1)
      ReleaseFinishCapture(CPTaken)
    end
  end,
  "c_cp1"
)
User avatar
Oceans14
Command Sergeant Major
Command Sergeant Major
Posts: 296
Joined: Mon Apr 27, 2015 7:09 pm
Projects :: Athenova Campaign
Games I'm Playing :: SWBF2
Location: Planet 4546b

Re: Mission failure on Cp loss

Post by Oceans14 »

Thanks Jedi, that worked - I just had to add "ShowTimer", and then it performed as expected. The only problem was that after the timer elapsed it wasn't killed, I think because I haven't yet figured out how to get the next objective to start if the CP belongs to team 1 after 60 seconds. The timer stopped counting, but when team 2 captured the CP about 15 seconds later it caused a mission failure. I'll update when I get that ironed out.
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: Mission failure on Cp loss

Post by Marth8880 »

Oceans14 wrote:I haven't yet figured out how to get the next objective to start if the CP belongs to team 1 after 60 seconds.
You should use a MultiObjectiveContainer. Setting one up is a fairly simple process, almost as simple as adding CPs to a conquest mission script.

If you assign each Objective:New{} object call to a variable, like so:
Hidden/Spoiler:
[code] --==========================
-- ACTIVATE HANGAR CONSOLE
--==========================

-- Objective 1: Activate the console
Objective1 = Objective:New{teamATT = ATT, teamDEF = DEF,
text = "level.eur.objectives.1",
popupText = "level.eur.objectives.1_popup",
multiplayerRules = false }

Objective1.OnStart = function(self)
MapAddEntityMarker("hangar_console", "hud_objective_icon", 3.0, ATT, "YELLOW", true)
local CZ_Hangar = OnObjectRepairName(
function(objPtr, characterId)
-- Test output
print("EURn_c.CZ_Hangar: Activated console")
ShowMessageText("level.EUR.interactions.test.received")

MapRemoveEntityMarker("hangar_console")

-- Complete the objective so we can move on to the next one
Objective1:Complete(ATT)

-- Disable this combat zone's trigger
ReleaseObjectRepair(CZ_Hangar)
CZ_Hangar = nil
end,
"hangar_console"
)
end

Objective1.OnComplete = function(self)
--BroadcastVoiceOver("GEO_obj_59", ATT)
ShowMessageText("game.objectives.complete", ATT)
end


--==========================
-- COMBAT ZONE : S0 -- HANGAR
--==========================

-- Objective 2: Secure the hangar
Objective2 = Objective:New{teamATT = ATT, teamDEF = DEF,
text = "level.eur.objectives.2",
popupText = "level.eur.objectives.2_popup",
multiplayerRules = false }

Objective2.OnStart = function(self)
HangarCaptured = OnFinishCaptureName(
function(postPtr)
if GetObjectTeam(postPtr) ~= ATT then
-- Complete the objective, ending the game if this is final objective
Objective2:Complete(ATT)

-- Stop listening for OnFinishCaptureName()
ReleaseFinishCapture(HangarCaptured )
HangarCaptured = nil
end
end,
"cp1"
)
end

Objective2.OnComplete = function(self)
--BroadcastVoiceOver("GEO_obj_59", ATT)
ShowMessageText("game.objectives.complete", ATT)
end[/code]
You can then add the objectives to an objective container, like so:
Hidden/Spoiler:
[code]-- Both of these functions should go somewhere between the
-- ScriptPostLoad() and ScriptInit() functions.

-- Call this function somewhere in ScriptPostLoad() to start the objective sequence.
--
function BeginObjectivesTimer()
beginobjectivestimer = CreateTimer("beginobjectivestimer")
OnTimerElapse(BeginObjectives, beginobjectivestimer)
SetTimerValue(beginobjectivestimer, 2.5)
StartTimer(beginobjectivestimer)
end


-- AddObjectiveSet() only takes one parameter, which must be an objective
-- variable, like the ones we assigned previously: Objective1 & Objective2.
-- The way in which AddObjectiveSet() is ordered in the code determines the
-- order that the container executes the objectives. In this example, Objective1
-- would be called first, and then when it's completed, Objective2 would be
-- called, and so on for any remaining objectives. When an objective is completed
-- and there are no more objectives remaining, the game ends.
--
function BeginObjectives()
objectiveSequence = MultiObjectiveContainer:New{delayVictoryTime = 4}
objectiveSequence:AddObjectiveSet(Objective1) -- Add one of these lines for each objective!
objectiveSequence:AddObjectiveSet(Objective2) -- And update the input parameter to reflect the objective variable name!

objectiveSequence:Start()
end[/code]
Typically you would call BeginObjectivesTimer() somewhere in your first-spawn event, if you have one:
Hidden/Spoiler:
[code] -- Don't let the AI spawn until the player has done so first!
AllowAISpawn(REP, false)
AllowAISpawn(CIS, false)


--==========================
-- FIRST SPAWN
--==========================

onfirstspawn = OnCharacterSpawn(
function(character)
if character == 0 then
ReleaseCharacterSpawn(onfirstspawn)
onfirstspawn = nil

-- Somewhere such as here, perhaps
BeginObjectivesTimer()

ScriptCB_EnableCommandPostVO(0)
ScriptCB_PlayInGameMusic("eur_amb_explore_01a")

-- Allow the AI to spawn
AllowAISpawn(REP, true)
AllowAISpawn(CIS, true)
end
end
)[/code]
One last thing: make sure you are loading the MultiObjectiveContainer script using ScriptCB_DoFile(), otherwise objective container stuff won't work! The script is also fairly well-commented in case you get confused or anything, too, so keep that in mind. ;)
User avatar
Oceans14
Command Sergeant Major
Command Sergeant Major
Posts: 296
Joined: Mon Apr 27, 2015 7:09 pm
Projects :: Athenova Campaign
Games I'm Playing :: SWBF2
Location: Planet 4546b

Re: Mission failure on Cp loss

Post by Oceans14 »

The only problem was that after the timer elapsed it wasn't killed, I think because I haven't yet figured out how to get the next objective to start if the CP belongs to team 1 after 60 seconds.
I have learned that these two things were not related. I found the line "Objective2:Complete(ATT)" in Marth's examples and successfully used that to start the next objective on the timer's elapse. What I now know is that that timer isn't going away because I used the ShowTimer command, and evidently KillTimer doesn't hide it as well. (Or am I wrong?)

After browsing through the lua commands thread, I noticed a distinct lack of a HideTimer function to compliment ShowTimer. Is this a command I could use, or could I just do something like ShowTimer(defendtimer) = 0?

@Marth - I was already using the multi objective containers since I just gutted the stock geo campaign, but your examples were better explained and more organized, plus I hadn't thought to go look at all the objective scripts - really interesting stuff, thank you :thumbs:
jedimoose32
Field Commander
Field Commander
Posts: 938
Joined: Thu Jan 24, 2008 12:41 am
Projects :: Engineering Degree
Location: The Flatlands of Canada

Re: Mission failure on Cp loss

Post by jedimoose32 »

ShowTimer(nil) will hide all your timers.

Edit: And if you are displaying multiple timers simultaneously and only want to hide one then simply use ShowTimer again for the timers you want to stay unhidden.
User avatar
Oceans14
Command Sergeant Major
Command Sergeant Major
Posts: 296
Joined: Mon Apr 27, 2015 7:09 pm
Projects :: Athenova Campaign
Games I'm Playing :: SWBF2
Location: Planet 4546b

Re: Mission failure on Cp loss

Post by Oceans14 »

jedimoose32 wrote:ShowTimer(nil) will hide all your timers.

Edit: And if you are displaying multiple timers simultaneously and only want to hide one then simply use ShowTimer again for the timers you want to stay unhidden.
Perfect! Thank you for all the help, I appreciate it.

Here is the relevant section of script, should anybody need to see it later on:
Hidden/Spoiler:
[code]--Objective 2: Hold off the droids--------------------------------------

Objective2 = Objective:New{teamATT = ATT, teamDEF = DEF, text = "level.PR1.objectives.campaign.2", popupText = "level.PR1.objectives.campaign.2_popup", AIGoalWeight = 100}

Objective2.OnStart = function(self)

defattackCP = AddAIGoal(DEF, "Conquest", 100, "c_cp1")
defendtimer = CreateTimer("defendtimer")
SetTimerValue(defendtimer, 90.0)
MapAddEntityMarker("c_cp1", "hud_objective_icon", 4.0, ATT, "YELLOW", true)
StartTimer(defendtimer)
ShowTimer(defendtimer)

OnTimerElapse(
function(timer)
StopTimer(defendtimer)
if GetObjectTeam("c_cp1") == 1 then
-- Complete the objective and go to the next one
Objective2:Complete(ATT)
else MissionDefeat(1)
end
DestroyTimer(defendtimer)
end,
defendtimer
)

CPTaken = OnFinishCaptureName(
function(postPtr)
if GetObjectTeam(postPtr) ~= 1 then
MissionDefeat(1)
ReleaseFinishCapture(CPTaken)
end
end,
"c_cp1"
)

end

Objective2.OnComplete = function(self)
ShowMessageText("game.objectives.complete", ATT)
MapRemoveEntityMarker("c_cp1")
ShowTimer(nil) --unshow the timer
end[/code]
jedimoose32
Field Commander
Field Commander
Posts: 938
Joined: Thu Jan 24, 2008 12:41 am
Projects :: Engineering Degree
Location: The Flatlands of Canada

Re: Mission failure on Cp loss [Solved]

Post by jedimoose32 »

For the record, I don't know for sure if it makes a difference, but I highly recommend referencing your timers using their string name as opposed to their instance name. I was having random issues with timers when I was working on Assassination mode, and I remembered reading from either Mav or Zerted that referencing the timer's string name can solve some problems (maybe I'm remembering incorrectly). So, if you set up your timer like this:

Code: Select all

timername = CreateTimer("timerstring")
Then later you would use ShowTimer() like this:

Code: Select all

ShowTimer("timerstring")
Instead of this:

Code: Select all

ShowTimer(timername)
Again, maybe this doesn't really matter. Just something that I've gone through in the past. *shrugs*
Post Reply