New TDM, gametype, Idea..

Defender

Member
I am thinking about a new TDM, gametype, that has a capture point in the middle of the map, or some place that two teams fight over, no ammo stations.. This is based on ideas from realmwars, its an old game on TGE..
Its simple, each time a player captures the capture point, his team owns the trigger, and his team gets like 50 points, and any team players within the trigger area get ammo reloads every few seconds as long as they stay in the trigger, and hold it for their team, to do this they must keep enemy players away, or lose the trigger, the second an enemy enters it, the trigger team owner changes. I can help code this, the trigger part is easy, can port part of it from realmwars, need help with the gametype coding, and scoring... Anyone like this idea?
 

Defender

Member
I don't think I need a new TDM gametype, just some help adding a few lines of code to this function, after I update it to work in legions, that gives the capturing team a score when they capture the trigger. This will be used in a new TDM map, if i get the scoring part working...

I need to replace this, to give a team a score when they capture, does TDM, have a team score, or just player scores?
Code:
// Just give the object's team a point.
         $Game::TeamObjectives[%obj.client.team]++;




Code:
//-----------------------------------------------------------------------------
// Realm Wars - Team Objective Module
//
// Author:     James Lupiani (JL) <defiant@flyingtemple.com> and Phil Carlisle
// Created:    21 Mar 2002 (JL)
// Revised:    22 Mar 2002 (JL)
//
// Notes:   This is a hack, but it more or less works.
//          - It will have to be overhauled once team support is fully in.
//            The number and names of teams and the number of objectives to win
//            are right in here. That sort of info should come from the mission.
//
//          - If the mission time runs out, the number of objectives from the
//            last mission will remain. See above note for suggested fix. +)
//
//          - Does the particle emitter need to be added to MissionCleanup?
//
//          - Isn't there a cleaner way of implementing smoke that's simply
//            a different color?
//
// Copyright (c) 2001 GarageGames.Com
//-----------------------------------------------------------------------------

// Trigger count

$Game::TeamObjectives[1] = 0;
$Game::TeamObjectives[2] = 0;
$Game::TeamScores[1] = 0;
$Game::TeamScores[2] = 0;
$Game::TeamFlagCaptures[1] = 0;
$Game::TeamFlagCaptures[2] = 0;
$Game::PointsForCapture = 50;

//--------------------------------------------------------------
// Particle data
//--------------------------------------------------------------
datablock ParticleData( ObjectiveSmoke )
{
   textureName          = "~/data/shapes/particles/smoke";
   dragCoeffiecient     = 0.0;
   gravityCoefficient   = -0.5;   // rises slowly
   inheritedVelFactor   = 0.00;
   lifetimeMS           = 3500;
   lifetimeVarianceMS   = 250;
   useInvAlpha = false;
   spinRandomMin = -30.0;
   spinRandomMax = 30.0;

   colors[0]     = "0.6 0.6 0.6 0.1";
   colors[1]     = "0.6 0.6 0.6 0.1";
   colors[2]     = "0.6 0.6 0.6 0.0";

   sizes[0]      = 1.75;
   sizes[1]      = 2.0;
   sizes[2]      = 3.25;

   times[0]      = 0.0;
   times[1]      = 0.5;
   times[2]      = 1.0;
};

datablock ParticleEmitterData( ObjectiveSmokeEmitter )
{
   ejectionPeriodMS = 20;
   periodVarianceMS = 5;

   ejectionVelocity = 0.25;
   velocityVariance = 0.10;

   thetaMin         = 0.0;
   thetaMax         = 90.0;

   particles = ObjectiveSmoke;
};

datablock ParticleEmitterNodeData( ObjectiveEmitterNode )
{
   timeMultiple = 1;
};


//--------------------------------------------------------------
// Derived particle datablocks
//--------------------------------------------------------------
datablock ParticleData( RedObjSmoke : ObjectiveSmoke )
{
   colors[0]     = "1.0 0.2 0.2 0.1";
   colors[1]     = "1.0 0.3 0.3 0.1";
   colors[2]     = "1.0 0.4 0.4 0.0";
};

datablock ParticleData( BlueObjSmoke : ObjectiveSmoke )
{
   colors[0]     = "0.2 0.2 1.0 0.1";
   colors[1]     = "0.3 0.3 1.0 0.1";
   colors[2]     = "0.4 0.4 1.0 0.0";
};

datablock ParticleEmitterData( RedObjSmokeEmitter : ObjectiveSmokeEmitter )
{
   particles = RedObjSmoke;
};

datablock ParticleEmitterData( BlueObjSmokeEmitter : ObjectiveSmokeEmitter )
{
   particles = BlueObjSmoke;
};


//--------------------------------------------------------------
// Trigger datablock
//--------------------------------------------------------------
datablock TriggerData(TeamTrigger)
{
    tickPeriodMS = 100;
    team = -1;
    teamEmitter = 0;
};

//--------------------------------------------------------------
// Events
//--------------------------------------------------------------
function TeamTrigger::onEnterTrigger( %this, %trigger, %obj )
{
   // This method is called whenever an object enters the %trigger
   // area, the object is passed as %obj.  The default onEnterTrigger
   // method (in the C++ code) invokes the ::onTrigger(%trigger,1) method on
   // every object (whatever it's type) in the same group as the trigger.
   Parent::onEnterTrigger( %this, %trigger, %obj );

   // Does the objective belong to the capper's team?
   if( %obj.client.team != %trigger.team )
   {
      // Has this objective been taken yet?
      if( %trigger.team != -1 )
      {
             // Someone's had this before. Switch team scores
         // and remove the emitter.
       $Game::TeamObjectives[%trigger.team]--;
         $Game::TeamObjectives[%obj.client.team]++;
    
         %trigger.teamEmitter.delete();
      }
      else
      {
         // Just give the object's team a point.
         $Game::TeamObjectives[%obj.client.team]++;
      }

      // Make a new particle emitter for the capping team.
       if( %obj.client.team == 1 )
       {
         %trigger.teamEmitter = new ParticleEmitterNode(%trigger.getName() @ "Emitter")
         {
            position = %trigger.getWorldBoxCenter();
            datablock = ObjectiveEmitterNode;
            emitter = RedObjSmokeEmitter;
            velocity = 1;
         };
      }
      else if( %obj.client.team == 2 )
      {
         %trigger.teamEmitter = new ParticleEmitterNode(%trigger.getName() @ "Emitter")
         {
            position = %trigger.getWorldBoxCenter();
            datablock = ObjectiveEmitterNode;
            emitter = BlueObjSmokeEmitter;
            velocity = 1;
         };
      }
 
      // Do the actual claiming.
      %trigger.team = %obj.client.team;
 
      messageAll( 'MsgObjective', '\c2Team %1 took an objective!', %obj.client.team );
      messageAll( 'MsgObjective', '\c2Skarj Objectives: %1, Krall Objectives: %2', $Game::TeamObjectives[1], $Game::TeamObjectives[2] );
 
  }
}

function TeamTrigger::onLeaveTrigger( %this, %trigger, %obj )
{
   // This method is called whenever an object leaves the %trigger
   // area, the object is passed as %obj.  The default onLeaveTrigger
   // method (in the C++ code) invokes the ::onTrigger(%trigger,0) method on
   // every object (whatever it's type) in the same group as the trigger.
   Parent::onLeaveTrigger( %this, %trigger, %obj );
}


function TeamTrigger::onTickTrigger( %this, %trigger )
{
   // This method is called every tickPerioMS, as long as any
   // objects intersect the trigger. The default onTriggerTick
   // method (in the C++ code) invokes the ::onTriggerTick(%trigger) method on
   // every object (whatever it's type) in the same group as the trigger.

   // You can iterate through the objects in the list by using these
   // methods:
   //    %this.getNumObjects();
   //    %this.getObject(n);
   Parent::onTickTrigger( %this, %trigger );

   echo("TeamTrigger: " @ %this.getClassName());
   // PC: added in to make things a bit more fun.. adds ammo to the player
   // as long as they are in thier own trigger.
   for (%i = 0; %i < %trigger.getNumObjects(); %i++)
   {
           %obj = %trigger.getName().getObject(%i);
           echo("object: " @ %i @ " " @ %obj.getClassName());
           if (%obj.client.team == %trigger.team)
           {
      
               // give ammo to this guy.. he's on our "team" :)
               %obj.incInventory(CrossbowAmmo,20);
           }
           else
           {
               echo("Cant get ammo at a spawn that aint yours!");
           }
       }

}
 
Last edited:

Fixious

Test Lead
I believe player scores are added to create each team's score. I can't remember what the winning score needs to be, 75 or something like that.

The unused FCNC and CNC code will probably interest you (should still be in gametypes), since it sounds similar to what you're trying to achieve.
 

Defender

Member
This works right now, it goes at the bottom of the map file, so the team capture count variable gets reset on map load.
Still need to add code so a team gets a score each time they capture the objective.
But everything else works, I wanted, the emitters change color each time a team captures, and I have the team capture messages added, also the trigger owner team gets ammo reloads when in the trigger.. The coding is not that great looking, but it works..
This may be fun to add on a new TDM, map.
Have one capture trigger in the middle on a stand that's sort of easy to defend, like some tribes2, maps had for capture points....






Code:
//-----------------------------------------------------------------------------
// Fallen Empire: Legions
// Copyright (C) GarageGames.com, Inc.
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// RealmWar objective code, recoded by Defender!
// Author:  James Lupiani (JL) <defiant@flyingtemple.com> and Phil Carlisle
// Created:  21 Mar 2002 (JL)
// Revised:  22 Mar 2002 (JL)
// Revised:  10 Apr 2014 (Defender)
//-----------------------------------------------------------------------------

datablock SFXProfile(TDMGameObjectiveSound) 
{
  filename = "legions/data/sound/player/Overdrive_End" @ $profileAudioExt;
  description = Audio2D;
  preload = true;
};

// Trigger count
$TDMGame::TeamObjectives[0] = 0;
$TDMGame::TeamObjectives[1] = 0;
//$TDMGame::TeamScores[1] = 0;
//$TDMGame::TeamScores[2] = 0;
//$TDMGame::TeamFlagCaptures[1] = 0;
//$TDMGame::TeamFlagCaptures[2] = 0;
//$TDMGame::PointsForCapture = 50;

//--------------------------------------------------------------
// Particle data
//--------------------------------------------------------------
datablock ParticleData( TDMGameObjectiveSmoke )
{
  textureName  = "legions/data/shapes/particles/smoke06.dds";//DXT5
  dragCoeffiecient  = 0.0;
  gravityCoefficient  = -0.5;  // rises slowly
  inheritedVelFactor  = 0.00;
  lifetimeMS  = 9000;
  lifetimeVarianceMS  = 4500;
  useInvAlpha = false;
  spinRandomMin = -30.0;
  spinRandomMax = 30.0;

  colors[0]  = "0.6 0.6 0.6 0.1";
  colors[1]  = "0.6 0.6 0.6 0.1";
  colors[2]  = "0.6 0.6 0.6 0.0";

  sizes[0]  = 6.75;
  sizes[1]  = 10.0;
  sizes[2]  = 14.25;

  times[0]  = 0.0;
  times[1]  = 0.5;
  times[2]  = 1.0;
};

datablock ParticleEmitterData( TDMGameObjectiveSmokeEmitter )
{
  ejectionPeriodMS = 40;
  periodVarianceMS = 5;
  ejectionVelocity = 0.25;

  velocityVariance = 0.10;
  ejectionOffset = 2.0;

  thetaMin  = 0.0;
  thetaMax  = 90.0;
  phiVariance = 360;
  phiReferenceVel = 0;

  particles = TDMGameObjectiveSmoke;

  doDistanceFade = true;
  startFadeDistance = 10;
  endFadeDistance = 900;
};

//--------------------------------------------------------------
// particle datablocks
//--------------------------------------------------------------
datablock ParticleData( TDMGameRedObjSmoke : TDMGameObjectiveSmoke )
{
  colors[0]  = "1.0 0.2 0.2 0.1";
  colors[1]  = "1.0 0.3 0.3 0.1";
  colors[2]  = "1.0 0.4 0.4 0.0";
};

datablock ParticleData( TDMGameBlueObjSmoke : TDMGameObjectiveSmoke )
{
  colors[0]  = "0.2 0.2 1.0 0.1";
  colors[1]  = "0.3 0.3 1.0 0.1";
  colors[2]  = "0.4 0.4 1.0 0.0";
};

datablock ParticleEmitterData( TDMGameRedObjSmokeEmitter : TDMGameObjectiveSmokeEmitter )
{
  particles = TDMGameRedObjSmoke;
};

datablock ParticleEmitterData( TDMGameBlueObjSmokeEmitter : TDMGameObjectiveSmokeEmitter )
{
  particles = TDMGameBlueObjSmoke;
};


//--------------------------------------------------------------
// Trigger datablock
//--------------------------------------------------------------
datablock TriggerData(TDMGameTeamTrigger)
{
  tickPeriodMs = 1000;
  team = -1;
  teamEmitter = 0;
};

//--------------------------------------------------------------
// Events
//--------------------------------------------------------------
function TDMGameTeamTrigger::onEnterTrigger( %this, %trigger, %obj )
{
  if (%obj.getClassName() $= "Player" && %trigger.teamIndex == %obj.client.teamIndex){
  %obj.refillAmmo();
  }
 
  // Does the objective belong to the capper's team?
  if (%obj.getClassName() $= "Player" && %obj.client.teamIndex != %trigger.teamIndex)
  {
  // Has this objective been taken yet?
  if( %trigger.teamIndex != -1 )
  {
        // Someone's had this before. Switch team scores
  //$TDMGame::TeamObjectives[%trigger.teamIndex]--;
  $TDMGame::TeamObjectives[%obj.client.teamIndex]++;
  // and remove the emitter.
  %trigger.teamEmitter.delete();
  }else{
  // Just give the object's team a point.
  $TDMGame::TeamObjectives[%obj.client.teamIndex]++;
  }
  
 // Make a new particle emitter for the capping team.
  if( %obj.client.teamIndex == 0) // Alpha
  {
  %total = $TDMGame::TeamObjectives[%obj.client.teamIndex];
  messageAll( 'MsgObjective1', '~gTeam Alpha took the objective!');
  messageAll( 'MsgObjective2', '~gAlpha Objectives: %1. ', %total);
  topPrintAll('Team Alpha took the objective!', '');
  %trigger.teamEmitter = new ParticleEmitterNode(%trigger.getName() @ "Emitter")
  {
  position = %trigger.getWorldBoxCenter();
  datablock = defaultParticleEmitterNode;
  emitter = TDMGameBlueObjSmokeEmitter;
  //velocity = 1;
  };
  }
  else  // Beta
  { 
  %total = $TDMGame::TeamObjectives[%obj.client.teamIndex];
  messageAll( 'MsgObjective1', '~gTeam Beta took the objective!');
  messageAll( 'MsgObjective2', '~gBeta Objectives: %1. ', %total);
  topPrintAll('Team Beta took the objective!', '');
  %trigger.teamEmitter = new ParticleEmitterNode(%trigger.getName() @ "Emitter")
  {
  position = %trigger.getWorldBoxCenter();
  datablock = defaultParticleEmitterNode;
  emitter = TDMGameRedObjSmokeEmitter;
  //velocity = 1;
  };
  }
  MissionCleanup.add(%trigger.teamEmitter);
 
  // Do the actual claiming.
  %trigger.teamIndex = %obj.client.teamIndex;
  schedule(0, 0, "ServerPlay2d", TDMGameObjectiveSound);
  }
}

function TDMGameTeamTrigger::onTickTrigger( %this, %trigger)
{
  %numObjects = %trigger.getNumObjects();
  for (%i = 0; %i < %numObjects; %i++)
  %this.onEnterTrigger(%trigger, %trigger.getObject(%i));
}

function TDMGameTeamTrigger::onLeaveTrigger(%this, %trigger, %obj){
}
 
Last edited:

Fixious

Test Lead
What are you using for the capture point, a Reactor or something else? Is it possible to add objects to it, like team-specific heal pads and such?
 

Defender

Member
Its up to the mapper, this is just a simple trigger, nothing fancy, just some thing to fight over on a TDM, map with no inventorys...
I am going to use the Reactor for my shape, and scale the trigger to about 10 10 10, and place it on the floor around the bottom of the Reactor..
Maybe have it protected by walls or some thing like those tribes2 maps did, for their capture points..
We could add simple global variables, and have team-specific heal pads and such, should be easy...
I never spent much time coding this kinda stuff for maps, but I have lots of custom tribes2 maps, with stuff like that coding using custom functions, I will look in to it...
We already have nice capture code in the CNC, fcnc, but its complected, right?
 

Fixious

Test Lead
It exists somewhere, I think. If not publicly than maybe Pop or Volt have the older code. After they were scrapped along with Engineer I suggested a simpler game mode in the dev forums, where there'd just be a center capture point tied to sensors throughout the map. Your new TDM mode reminds me of what I was going after.

The reason I'm pushing for FCNC is because it doesn't remove any elements from Legions' gameplay. CNC isn't very enjoyable if you're a capper or enjoy flag play in general, since it removes capping entirely. To be honest I really can't remember testing FCNC a whole lot, it was mainly CNC and literally only one map the entire testing period. While the cave fights were fun for a while, over time it got a bit tiring.

Back when I was trying to get this working I used Zenith as a starting point. I didn't have to modify any part of the map to get something feasible. No terrain changes, no structures needed moving. Just a simple capture point in the middle with sensors on the outer-middle towers.

Wqt3QfHh.png


8W4tgK6h.png


This same concept can work on a number of other maps: http://imgur.com/a/0SiIz (the editor doesn't really work on Fallout, but you get the idea)

I no longer have the previous version of test with CNC and FCNC code so I can't really tinker with this anymore. Just something to think about.

A mode with simple assets like sensors or healpads would at least give the Repair gun a reason exist, too.
 

Defender

Member
That would be doable, and much more simpler to just make in a new map, and have destroyable assets in the map like tribes2.
For the function I just made, I can easily have heal-pads and ammo stations in my map, that are team only, for the team that captures the trigger, like CNC... The harder part is having the targets for them like CNC, not sure I need those for a basic map..
 

Defender

Member
Thought it still worked a little, it did a few months ago.
Don't think I can bring it back, in my mod I bypassed all that, and made deploying stuff vary simple like in tribes2.
 

Fixious

Test Lead
You'd have to add in the deployable limit code for turrets and stuff to work, which I've forgotten unfortunately. I can't really remember what state Engineer is in, to be honest. I know deploying should still work. A stripped down version (i.e. no turrets) would be fine on a lot of maps, in my opinion. There's just no one left to code. The people (or person) primarily involved with working on Engineer is no longer present. I've thrown out suggestions before about making things a bit less complex, like the sensor network idea, but no one can really invest anymore time into doing that.
 

Defender

Member
Hes code is vary well thought out, looks advanced, reminds me of a tribes1, mod called AAOD..
It would take me a few weeks of just reading, rereading it, to get a good handle on it.
Even after all my years of modding, I am slow to learn new ways of doing things, that's how come my mods deployables are coded like those in tribes2..
 
Last edited:
Top