Making an Assault Mode Objective Map

Now that you have an idea about what things do, it's time to put them together to create a map. Don't let the amount of information already presented keep you from at least trying this out. Since this tutorial is for the beginner, I will be going through each step in great detail and will explain many of the fields in the script pairs of the entities that you'll use in this example. (I will update with pictures soon.)

Getting the map floor ready

First, open up the Map Editor. (Like I said, great detail.) Be sure to save the map and place it in the proper folder so it can be played when you save and compile. For this example, we will call it o_example1. Check the box next to Script Mode in the Render Settings box. Script Mode will allow you to see some extra things like the flow of logic and is useful when making sure that muxes and entities point to the correct thing.

Next, create a new floor with four points and make it into a simple tall rectangle.

Select one of the floor points at the top of the rectagle and make four new floor points between the top two points. Arrange the new points to create a box area at the top of the rectangle in the dead center. This will be the area that you will place your objective object.

Setting up your objective

Click new -> entity or use the toolbar button, select DestroyablePropObject(dpo) and click create. Something looking like a surface beacon will appear at the center of the map. Copy and paste this twice, for this example we will need three of them. Place one dpo in the area for the objective and place the other two in opposite corners.

Before we do anything else we will make the dpo in the box into an objective. Click view -> script pairs, a window should pop up that says Entity Script Pairs. Keep the window open and click on the dpo. The script pair window should be displaying a long list with three columns in it. Click on one of the fields in the window to see its description at the bottom of the window. Most are self explanitory, others I will describe in detail when needed.

Change the TargetName from DestroyablePropObject to Station_Obj and press enter. The name above the dpo should change to match the name you have entered into the field. Leave the Tooltip field blank. Since this is your objective the Objective entity will place a tooltip for you.

In the Model and DestroyedModel fields the middle column has a filepath indicating that this dpo is currently using the model file for the surface beacon. Replace surface_beacon and surface_beacon_destroyed with prop_ctrlstation_big and prop_ctrlstation_big_destroyed respectively. Now when you play the map you will see a Station instead of surface beacon where you have placed your objective.

Even though you have set otherwise in the entity's script pairs, having a surface beacon as your objective in the map editor could possibly lead to confusion as to which is the objective and which is the surface beacon.  To reduce confusion, click view -> properties while having the dpo still highlighted (if you don't have it highlighted click on it to make it so).  A new window should pop up similar to the script pair window.  In it you should see the Editor''Model field that has a familiar file path.  Once again replace surface_beacon with prop_ctrlstation_big and press enter.
There should be a change in the look of the model in the editor window.  The model in the editor is now the same one that will be used in-game.

Continuing with the objective object we will leave HealthMax and Health set at 2000 for this example. However, these numbers can be set as high or as low as you wish, but it is suggested that the number be neither too high or too low. Your own testing will confirm that the higher the number the longer it will take to destroy the objective.

Change False to True in the CompletelyDestroy field. This will make it so that once your objective is destroyed it cannot be repaired.

EffectDestroyed plays a certain effect when your objective dies based on the number in the field. Feel free to try out all the effects when you are testing your own maps. For this map enter in 7, it is the same effect when a ship dies but it is also the effect used in numerous official objective maps.

Leave EffectRepaired alone since your objective won't have the chance to be repaired after it's destroyed.

Enter 1 in RepairableByTeams so that only Team0(defenders) will be able to repair the objective when it is damaged. This also has the effect of assigning the objective to Team0 and allying it to any defesive ships.

Enter 2 in DestroyableByTeams so that only Team1(attackers) can damage and destroy the objective. This will also keep Team0 from inadvertently damaging the objective.

Leave RepairedTarget alone and DestroyedTarget blank until later when you will place the name of a mux in the field.

Leave ShowOwnerEffect as it is, change CaptureByRadius to False and you are done with the script pairs for your objective object, for now.

Setting Up Surface Beacons

Click new -> entity, this time create a PlayerStart. Copy and paste until you have eight of them. Place four player starts near each dpo that will be your surface beacons.

Click new -> entity again and create a Multiplexer. Copy and paste for six muxes and split evenly to each dpo like you did with the player starts and line them up next to the surface beacons. These will be what we will call surface beacon muxes from now on.

Now, here's where it gets kind of complicated. What we're going to do now is link three different types of entities to create one effect that will allow surface beacons to be captureable by both teams so that the team that owns the surface beacon can surface at the start points but not the other team and not allow anyone to surface when the beacon is empty or contested. I would suggest reading each instruction twice (maybe more).

We will start with the attackers surface beacon. Select the bottom dpo and view its script pairs. Change the name to SurfaceBeacon1 and enter ENTITY_TOOLTIP_SURFACEBEACON_CPT in the tooltip field.

Leave Model, DestroyedModel, Health, HealthMax, CompletelyDestroy, EffectDestroyed and EffectRepair as they are. Change RepairableByTeams to 2 and DestroyableByTeams 0 to assign the beacon to Team1 and to keep ANYONE from destroying it.

Surface beacons, if you haven't noticed, actually rotate slowly on maps. The RotationRate is set a 0.1, do this for your own surface beacons from now on.

Next scroll down to the bottom of the list, we'll be taking care of the rest of the easier stuff first. Set CaptureZoneRadius to 128. If you have script mode enabled you'll be able to see a circle around the surface beacon.

Now set InitialCaptureStatus from empty to team1_gaining. In the field below change 16 to 1.

Ok, scroll back up a couple of fields and look for one that says UncapturedTarget. In the empty space type UncapturedSB1. For CapturedTeam0Target two lines down type Team0_OnCapturedSB1. Two more lines down type Team1_OnCapturedSB1 for CapturedTeam1Target. Deselect the surface beacon, you're done with that part.

Setting up the Surface Beacon Multiplexers and PlayerStarts

Select the nearest mux. Study the layout of the script pairs for the mux. A mux can target no more than four entities at a time and it can fire only one command to each entity. The lines with the word Time1, Time2, etc. give the mux the ability to delay firing the command to a target. This is especially useful when commanding your cameras, which we will talk about later.

First job is to rename the mux. Name it to.. oh say.. UncapturedSB1 (sound familiar?). The one and only target this mux has will be called PS_SB1 and the command to this target is enable -1.

Select the next mux and rename it Team0_OnCaptureSB1. The target is once again PS_SB1 but the command will be enable 0.

Select the third mux and rename it Team1_OnCaptureSB1. The target is yet again PS_SB1 but the command will be enable 1.

Now select the four player starts near this surface beacon either by box selection or by holding the shift button and selecting each one with the mouse. Set the team number to 1 (Note that the default is 0) and make the name of all four to be PS_SB1. These arrows indicate that the muxes are properly pointing to the playerstarts.

Leave SurfaceEffectStartPos alone for now as custom start positions for the surface effect is not necessary for this example. However, you can change the position if you wish.

Note from Vek:  You don't need to use multiplexers for surface beacons.  A much simpler layout is to simply have the surface beacon directly target the start points and tell them to enable for that particular team.  So here's a simple way to do it:
Drop the surface beacon down and set its initial capture progress to 0
Drop a bunch of start points down and set their team to -1 and their targetname to whatever you want, as long as they are all the same.  So for example, I would use "SB0_ALLSTARTS"
Set its CapturedTeam0Target to "SB0_ALLSTARTS" so when its captured by team0 it will fire a message to all the start points
Set its CapturedTeam0Command to "enable 0"
Set its CapturedTeam1Target to "SB0_ALLSTARTS"
Set its CapturedTeam1Command to "enable 1"
same for uncaptured: -1
As you see, multiplexers are only really useful for when you want a sequence of timed events, or several DIFFERENT commands to be fed to entities.  If you need the same command ("enable 0") to be fed to all targets, there is no need for a multiplexer.

Setting up Surface Beacon 2

Basically repeat the previous sections adjusting the setup for Team0 instead of Team1 and SurfaceBeacon2 instead of SurfaceBeacon1.

Examples of fields that will be different:

  • RepairableByTeams = 1

  • InitialCaptureStatus = team0_gaining

  • Surface beacon mux target = PS_SB2

At this point you can save and compile your map so you can play it in-game on your own computer with bots. Fire up an objective round, put the map in the rotation list, add some bots and start the server. If everything was done correctly the surface beacons will capture properly, the objective model will be correct, defenders won't damage it and its destruction effect will be correct.

However, when you do destroy the objective nothing will happen. That's because you haven't specified actual objectives and end level conditions. And that's what we're going to do next.

Giving your map objectives

Click new -> entity -> Objective -> create and move the entity outside of the field of play. Copy and paste for another objective entity. (Note: The following entities will be moved outside of the field of play so that they will not create confusion.) Having two objective entities is critical so that both attackers and defenders will see their own objectives and not just a common one that could lead to player confusion.

Note: It does not matter where you place the entities for objective functionality.  However, it is HIGHLY recommended and suggested that they be placed in a well-planned and orderly manner.

Name one Objective_Team1 and name the other Objective_Team0. In Objective_Team1, assign this objective to team 1, leave the State as pending, and make the objective's target Station_Obj(or the name of your objective if you called it something different). Make it so that this is the primay objective for the attackers and enter the target's position in the bottom most field. Leave ObjectiveText as it is, this default value will suffice for our purposes.

In Objective_Team0, assign this objective to team 0, leave the State as pending, and make the objective's target Station_Obj(or the name of your objective if you called it something different). Make it so that this is the primay objective for the defenders and enter the target's position in the bottom most field. This time change ObjectiveText to OBJ_DEFENDHERE. If the default value were left alone this time you would find that the defender's objective text would not display properly.

Getting your objectives to work properly

Even though you now have objectives, they won't update and the round won't end when they are completed. So now, we are going to make sure that happens. You'll need EndLevel entities(3 of them), the AssaultMode entity, MoveCamera entities(3 of those), several muxes, and few more that will be specified in this section.

First, create the AssaltMode entity and three more (new) muxes. Move the AssaultMode between and above the objective entities, move one mux between and below the objective entities and move the reamining two muxes just above the AssaultMode entity.

Select the mux below your objectives and call it OnStationDestroyed. The first target is Objective_Team1 and the first command will be complete. This will tell the objective that it is completed and will display that fact to the attackers in-game.

The second target is Objective_Team0 and the second command will be fail. This will tell the objective that it has been failed and will display that fact to the defenders in-game.

The third target is Trigger_Assault and the third command will remain as activate.

However, none of this will happen unless this mux is itself triggered by another entity. Go back up to your station and click on it. In its script pairs find DestroyedTarget and enter OnStationDestroyed and leave the following command as activate. Now, when the station is destroyed it will trigger the mux which will then trigger everything that it has targeted.

Select one of the muxes above AssaultMode. Name it Trigger_Assault with its first target being AttackCinamatic1 with no time delay. The second target will be AssaultMode with a time delay of 5.

Select the other mux and name it Trigger_Assault_Fail. Its first target being AttackCinamatic1 with no time delay same as the other mux. Its second target is also AssualtMode with the same time delay of 5 but the command this time will be failure. This is necessary so AssaultMode can differentiate failure from completion or you will wind up with both sides being awarded with completing the objective when one or neither team actually succeeds in completing the objective.

Now select AssaultMode, the following names that you will be inputing in the blank spots will be names of muxes that will then point to the proper entities.

In TargetsReset enter OnAssault_Reset.

In ResultInitialAttackersTarget enter Victory_InitialAttackers.

In ResultInitialDefendersTarget enter Victory_InitialDefenders.

In ResultNoneTarget enter Victory_Tie.

Setting Up End Level conditions and the Move Camera Entities

Now before we make and assign new muxes with names we are going to create and place the rest of the entities in the map. You will need seven(7) muxes, three(3) MoveCameras, three(3) EndLevels, two(2) ScriptScreenFades, a CinematicScreen, a GameTimeChecker, and an entity called NoChanceToSurviveCheck.

Move the GameTimeChecker above the Trigger_Assault_Fail mux. Add _PreReset to its name. Its target will be Trigger_Assault_Fail. Set DisableEndGameOnTimeout to True and leave the rest as they are. The reason we have done this is so that the map will reset when the clock reaches 0, both before and after the AssaultMode reset.

Place three muxes somewhere above the objective entities, place three more somewhere below, and place the remaing mux somewhere to the right of the objective entity but not on the floor. The muxes at the top will be your cinematic muxes, the ones below will be victory condition muxes and the one to the right will be a reset mux. (Note: the mux we are considering as the reset mux does no actual reseting, AssaultMode, however, does.)

Take your three MoveCameras, CinematicScreen, and one of the ScriptScreenFades and set them next to the cinematic muxes.

In the first mux make its name AttackCinematic1 and its two targets CinematicScreen and AttackCinematic2.

For the next mux, name it AttackCinematic2 with its targets being: MoveCamera1 (no time delay), MoveCamera2 (time delay of 1), MoveCamera3 (time delay of 2), and AttackCinematic3 (time delay of 3).

For the third mux, name it AttackCinematic3 with its only target being ScriptScreenFade.

Before you ask any questions, let's finish up with the MoveCameras first. If you play your map with out making anychanges you'll see that your cameras will all point downward and look straight at the floor. Since we don't want that to happen, open up the properties window and select the station. Copy the position of the station. This is going to be what the cameras will look at while they move. Select the first move camera and paste what you have in the LookAt field, leave CameraPosition as it is, change speed to 1.

Select MoveCamera2, paste what you have in the LookAt field, change CameraPosition to 500 500 0 and leave everything else as is.

Select MoveCamera3, paste what you have in the LookAt field, change CameraPosition to -500 500 0 and leave everything else as is.

You finally get to ask: "But I have two ScriptScreenFades, which one will it point to?" Both actually, that is until you change the name of the second. Move that second one near the lone mux next to the objectives and change its name to ScriptScreenUnFade. In its script pairs change the one False to True.

Now its set so the screen will fade in upon its activation.

"Activation by what?" Remember that lone mux? Change its name to OnAssault_Reset and make its only target ScriptScreenUnFade.

Now, move the NoChanceToSurviveCheck to between and above the two Trigger_Assault muxes. There are only two fields needing to be filled here. In AttackersEliminated enter Trigger_Assault_Fail. In DefendersEliminated enter Trigger_Assault.

Scroll down to your three remaing muxes and place an EndLevel entity next to each one of them.

Select the first mux, Its name will be Victory_InitialAttackers and its target is EndLevel_InitialAttackers.

For the second mux, its name will be Victory_InitialDefenders and its target is EndLevel_InitialDefenders.

For the third mux, its name will be Victory_Tie and its target is EndLevel_Tie.

Change the three EndLevels name so that each points to it corresponding EndLevel condition i.e. Victory_InitialAttackers -> EndLevel_InitialAttackers, etc.

There are just a few more minor changes we need to make before our map is complete. In EndLevel_InitialAttackers, make the number next to Winner -7. In EndLevel_InitialDefenders, make the number next to Winner -6. In EndLevel_Tie, make the number next to Winner -1.

Now, close out the script pair window, save your map, compile, and create a minimap if you want. You're done!

Right now your map is small but playable and fully functional. You can make it the size you want and place the prefabs you want in the map later. For now, enjoy your first assault mode objective map.

Vek Note:  You hardly ever actually need to use multiplexers (mux) at all.  A lightweight objective map probably only needs 2 multiplexers, total - one for each victory condition.
So for example, your two multiplexers might do the following
DEFENDERWIN:  Enter cinematic mode, move the camera in a cool way, then activate the assault script with "failed"
ATTACKERWIN:  Enter cinematic mode, move the camera in a cool way, then activate the assault script with "activate"
Thats pretty much the only two mux you absolutely need, and thats only because cinematics are involved.
Then you simply activate DEFENDERWIN whenever time runs out (using a time checker), or team 1 has no chance to survive (using a nochancetosurvive checker)
And you activate ATTACKERWIN whenever the objective is destroyed, or team 0 has no chance to survive.
Attackers are always team 1 and are ORANGE initially. (mnemonic = hostile color)
defenders are always team 0 and are GREEN initially. (mnemonic = defensive color)  (Numerical mnemonic = 0 is the first team and they were there first so they are defending).
The assault script itself would target the three different 'end game victory/defeat' scripts directly.
You generally do not need to ever use a multiplexer in surface beacons at all.