Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785

Warning: Division by zero in /home/g/gronnevik/gronnevik/gronnevik.se/www/rjukan/index.php on line 785
The Rjukan Project - Main - LiberationInMOHAA

Menu

Wiki usage

Creative Commons License
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 License.
Edit Sidebar
Main > LiberationInMOHAA

Liberation mode gameplay in MOH:AA

There is no need to buy MOH:BT to make your map support the Liberation mode gameplay. It can be produced inMOH:AA by a little scripting and some creative mapping. See also LegalAndMoralIssues.

Content

On this page...

Introduction

The Liberation gameplay mode is based on two teams batteling each other and trying to put all of the opposing team in prison. It is a respawning game mode, but not as you are used to. Because there is a bigger punishment for getting killed than respawning a bit away. Instead you will spawn inside a locked area that only one of your teammates can open(one that is still not in prison that is). A Liberation game may be as quick as 2 teams killing each others off, or it may be a very long battle that flows back and forth as both teams open the opposing prison and lets their teammembers out, getting well needed reinforcements in the process.

Prisons

This is just what you would think it is: a space you cant get out of if you are locked in. Here is an example of what I consider a good prison.

In MOH:AA:

( pic 1 )

And in MOHRadiant

( pic 2 )

Prison gates

The simplest way to make the prison door would be to make it a solid brush, but that would make the prisoned players unable to follow the events outside. And if thay can't see what is going on outside, it will be very boring to be in prison ( yes it is a punishment for sucking, but depriving players of enjoying the game is just stupid. Remember: they will not play it if it is not fun. )

So I make the gate like this:

( pic 3 )

The clip brush inside the gate is "common/clip". Be sure to check the "playerclip", "monsterclip", and "weaponclip" in the SurfacePropertiesDialog? box. This way the 2 teams can see each other, but cant hurt each other through the bars.

Also make sure the clip is thick enough to prevent bashing through. About 20 units thick should be enough.

Select all the brushes making up the gate and turn it into a script_object, because we need to be able to open it ( moving it out of the way in some way to let prisoners out ).

Then wee need to set some key / values on it. Select the script_object and press 'n' to bring up the EntityDialog box and set these key / values on it:

KeyValueExplanation
targetnameaxis_prison_gateTo be able to refer to the script_object in the script, it must have a unique targetname ( the Allied prison vould have targetname / allies_prison_gate )
dmg10Because a player may stand in the way to prevent the movement of an entity, we make it do damage if blocked. 10 is a good number because it is small enough to let players try heroic deeds, but big enough to kill him within about 8 seconds.

Prison open triggers

We need some way to break out our mates, right? So we need some trigger_use triggers. And its good practice to put these triggers around some obvoius thig to use, like a button or a lever. So place a nice model ( like the pulsating lever in pic 1, 2 and 3, named "animate_equipment_trainswitch-pulsating" ) and place a trigger_use brush around it ( make the brush and select "trigger->use" from the pop up menu ).

Give it these names in the EntityDialog :

KeyValueExplanation
targetnameaxis_jailbreak_triggerTo be able to refer to the trigger_use in the script, it must have a unique targetname ( the Allied prison trigger would have targetname / allies_jailbreak_trigger )

That should be all you need to get working triggers. Another idea is to just put the triggers outside the prison gate and make it work like a regular door ( but only from the outside ).

Spawns

We need two different sets of spawns for each team. One set that is placed where spawns regularely are placed to offer a good starting spawn for the team. And one set inside the enemy prison ( see pic 1 )

As we need to manipulate the spawns during play, we must set some key / values on them:

KeyValueWhat spawns to give the Key / Values
targetnameallied_start_spawnAll spawns that are intended for the Allied players to spawn at when the map starts
targetnameaxis_start_spawnAll spawns that are intended for the Axis players to spawn at when the map starts
targetnameallies_prison_spawnThese are set on the Allied spawns inside the Axis prison on the other side of the map from the Allied start spawns
targetnameaxis_prison_spawnThese are set on the Axis spawns inside the Allied prison on the other side of the map from the Axis start spawns

Scripting

OK, now whe should have the components that wee need in the map, so lets tie it together with some nice scripting.

The complete script is listed further down. Here follows a description and explanation of the major parts ot the script.

The "main" method:

This is the default method called by MOH:AA after loading a map, this is where it all starts. There is really nothing special to this method, and it will look a lot like other objective main methods. Three things are worth mentioning here:

  1. Note the use of the line level.dmrespawning = 1, this causes respawning of killed players, and without it there would be no real point in the Liberation mode at all...

  2. The two '/':s starting the line // level waittill roundstart means that this line will be ignored. And because of this MOH:AA will not wait for roundstart (roundstart = at least one person per team ). This is a good thing when testing the map by yourself. Just remember to remove the two '/':s before releasing the map. BUT! You will get errors when running this map alone with this line commented out! Something like "Script Error: Cannot cast 'NIL' to listener". This is because when alone on the map, the $player object will be just the player, and as soon as another player joins; it will becone an array of players. ( this is a complex way for me to say: you cant test it alone without re-writing the script, get a friend to help you by joining your game while testing ).

  3. The lines thread start_liberation_system and waitthread initial_spawn_setup is the commands that kicks the Liberation mode into action, so don't remove those without a good cause.

The "start_liberation_system" method:

This starts the jailbreak sensors ( see below ) and the player scanner ( see below ). then it waits for 10 seconds before it activates the prison spawns and de-activates all other spawns ( see below ).

The "initial_spawn_setup" method:

Disables all the spawns in the prisons.

The "activate_prison_spawn_setup" method:

Disables all the "normal" spawns and enables all the spawns in the prisons.

The "axis_jailbreak_sensor" and "allied_jailbreak_sensor" methods:

Waits for the triggers to be activated. When activated it animates the switch and opens the prison, or if the triggerer is from the wrong team: tells the player to "Stop that!".

The "allied_prison_open" and "axis_prison_open" methods:

Opens the prison gate while palying some fitting sounds. Waits a short while, and then closes it again.

The "player_scanner" method:

This is an important method. Once called it will continually scan all players, and based on the results of that scan: decide if a team has won yet.

The "detect_player_status" method:

A helper method used by the "player_scanner" method. It will fing out if the player given to it is: 1) - in the game ( not just spectating ). 2) - Inside the enemy prison.

The "player_exists_setthread" method:

This will be called by the trigger spawned in "detect_player_status" if the player is in the game ( not just spectating ).

The "test_winning_conditions" method:

Use all the gathered data from the methods above to determine if the match is won. Called by "player_scanner".

How the strange "player is in the game" detection works

The method "detect_player_status" spawns a trigger_multiple with the target / value of setthread / player_exists_setthread at the origin of the player. This means that a player will trigger this if he is in the game ( not just spectating ). And if he triggers it, the trigger will call the player_exists_setthread method that will in turn mark the triggering player as "activated" ( really playing the game ).

If you find this a bit strange, you are correct. It is used because you can not rely on checking the isAlive command because it will say the player is alive as soon as he selects a team ( if he selects no weapon: he is seen as alive until he does without actually entering the game ).


 //   -Liberation tutorial-
 // - Liberation objective -
 //
 // ARCHITECTURE: M.S
 // SCRIPTING: Bjarne Grönnevik
 // TEXTURES: W.S
 // OPTIMIZING:  Bjarne Grönnevik
 main:
   // set scoreboard messages
   setcvar "g_obj_alliedtext1" "-Kill all Axis.  "
   setcvar "g_obj_alliedtext2" "-Free your friends. "
   setcvar "g_obj_alliedtext3" "0 of 0 Allies jailed"
   setcvar "g_obj_axistext1"   "-Kill all Allies.  "
   setcvar "g_obj_axistext2"   "-Free your friends. "
   setcvar "g_obj_axistext3"   "0 of 0 Axis jailed  "
   setcvar "g_scoreboardpic" "lib_canal_scoreboard"

   level waitTill prespawn
   // set the parameters for this round
   level.dmrespawning = 1 // 1 or 0
   level.dmroundlimit = 10 // round time limit in minutes
   level.clockside = kills // set to axis, allies, kills, or draw
   exec global/DMprecache.scr
   level.script = maps/obj/lib_canal.scr
   exec global/door_locked.scr::lock
   exec global/ambient.scr lib_canal
   waitthread initial_spawn_setup
   level waittill spawn
 //   level waittill roundstart
   thread start_liberation_system
 end

 start_liberation_system:
   thread player_scanner
   thread allied_jailbreak_sensor
   thread axis_jailbreak_sensor
   wait 10
   thread activate_prison_spawn_setup
 end

 allied_jailbreak_sensor:
   while(true)
   {
     $allied_jailbreak_trigger waittill trigger
     if(parm.other.dmteam == axis)
     {
       parm.other iprint "You have released your friends!" 0
       $allied_jailbreak_switch playsound track_switch1
       $allied_jailbreak_switch anim move
       waitthread allied_prison_open
       $allied_jailbreak_switch anim idle
     }
     else
     {
       if(parm.other.dmteam == allies)
       {
         parm.other iprint "Stop that!" 0
       }
     }
   }
 end

 allied_prison_open:
   if(!$allies_prison_gate.busy)
   {
     $allies_prison_gate.busy = 1
     $allies_prison_gate time 4
     wait 1
     $allies_prison_gate moveUp 120
     $allies_prison_gate playsound elevator_run
     $allies_prison_gate waitmove
     iprintlnbold_noloc "The Allied prison is open!"
     wait 10
     $allies_prison_gate damage 100
     $allies_prison_gate moveDown 120
     $allies_prison_gate playsound elevator_run
     $allies_prison_gate waitmove
     $allies_prison_gate.busy = 0
   }
 end

 axis_jailbreak_sensor:
   while(true)
   {
     $axis_jailbreak_trigger waittill trigger
     if(parm.other.dmteam == allies)
     {
       parm.other iprint "You have released your friends!" 0
       $axis_jailbreak_switch playsound track_switch1
       $axis_jailbreak_switch anim move
       waitthread axis_prison_open
       $axis_jailbreak_switch anim idle
     }
     else
     {
       if(parm.other.dmteam == axis)
       {
         parm.other iprint "Stop that!" 0
       }
     }
   }
 end

 axis_prison_open:
   if(!$axis_prison_gate.busy)
   {
     $axis_prison_gate.busy = 1
     $axis_prison_gate time 4
     wait 1
     $axis_prison_gate moveUp 120
     $axis_prison_gate playsound elevator_run
     $axis_prison_gate waitmove
     iprintlnbold_noloc "The Axis prison is open!"
     wait 10
     $axis_prison_gate moveDown 120
     $axis_prison_gate playsound elevator_run
     $axis_prison_gate waitmove
     $axis_prison_gate.busy = 0
   }
 end

 player_scanner:
   while (true)
   {
     level.allies_in_game = 0
     level.axis_in_game = 0
     level.allies_in_prison = 0
     level.axis_in_prison = 0
     for(local.i = 1; local.i <= $player.size; local.i++)
     {
       waitthread detect_player_status $player[local.i]
       waitframe
     }
     waitthread test_winning_conditions
     wait 1
   }
 end

 detect_player_status local.player:
   // Test if the player has spawned into the map, or are still choosing weapon
   local.trigger = spawn trigger_multiple "targetname" "player_position_trigger" setthread player_exists_setthread
   local.trigger.origin = local.player.origin
   waitframe
   waitframe
   waitframe
   $player_position_trigger delete
   if(local.player.activated && isAlive local.player)
   {
     if(local.player.dmteam == allies)
     {
       level.allies_in_game++
       if(local.player istouching $axis_prison_volume)
       {
         level.allies_in_prison++
       }
     }
     else
     {
       if(local.player.dmteam == axis)
       {
         level.axis_in_game++
         if(local.player istouching $allied_prison_volume)
         {
           level.axis_in_prison++
         }
       }
       else
       {
         if(local.player.dmteam == spectator)
         {
           iprintln "Spectating player detected " local.player.dmteam
           local.player.activated = false
         }
         else
         {
           iprintln "Undefined player detected " local.player.dmteam
           local.player.activated = false
         }
       }
     }
   }
 end

 player_exists_setthread:
   parm.other.activated = true
 end

 test_winning_conditions:
   local.temp_string = string(level.axis_in_prison) + " of " + string(level.axis_in_game) + " Axis jailed  "
   setcvar "g_obj_axistext3" local.temp_string
   local.temp_string = string(level.allies_in_prison) + " of " + string(level.allies_in_game) + " Allies jailed"
   setcvar "g_obj_alliedtext3" local.temp_string
   if(level.allies_in_game > 0)
   {
     if(level.allies_in_game == level.allies_in_prison)
     {
       // iprintln "Axis win!"
       teamwin axis
     }
   }
   if (level.axis_in_game > 0)
   {
     if( level.axis_in_game == level.axis_in_prison)
     {
       // iprintln "Allies win!"
       teamwin allies
     }
   }
 end

 initial_spawn_setup:
   $allies_prison_spawn disablespawn
   $axis_prison_spawn disablespawn
 end

 activate_prison_spawn_setup:
   $allies_prison_spawn enablespawn
   $axis_prison_spawn enablespawn
   $allied_start_spawn disablespawn
   $axis_start_spawn disablespawn
 end

Example map file

Attach:user-lib_tutorial.zip (47.15 Kb)

Recent Changes Printable View Page History Edit Page [Attributes] [Printable View] [WikiHelp]
Page last modified on February 01, 2005, at 08:02 PM