Inside3D!
     

[Tutorial] Team Specific Gameplay

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
ceriux



Joined: 06 Sep 2008
Posts: 969
Location: Florida, USA

PostPosted: Fri Dec 25, 2009 9:31 pm    Post subject: [Tutorial] Team Specific Gameplay Reply with quote

Ok, because i was having issues with setting skins to the player model and figured it out. i wanted to write a tutorial. But i cant find a really basic way to just set it up. SO im going to write a fairly large tutorial on coding in team specific gameplay. this code is basic and could be expanded upon. but, it should be a good start for anyone trying to learn. ill try and add in as many comments as possible.

So, lets get started.

our first step is to make two new .qc files. Call the first one
Quote:
moddefs.qc
and the second
Quote:
menu.qc
.

the reason in which i say to make your own defs.qc files is its easier to keep try of all of your custom definitions this way.

Next : open up menu.qc.

in this file is where you will handle about 99% of your menu code.

the first thing we want to do is make the menu it's self.

so TYPE THIS OUT YOURSELF into the top of your menu.qc.



Code:


void() Menus =

{
   if (!self.menu) // if your not in a menu , do NOT print it " ! means not"
      return;
   if (self.menu == 1) // but if the menu equals " == means equals or equal to" 1.
   
      centerprint(self, "Select Your Team \n 1. Green Team \n 2. Red Team \n"); // then print the menu. centerprint() prints a message in the center of the players screen. self means your printing the message to the owner - the player in this case. after the comma  you put your message or menu text, it must be quoted.

};



the next step "still in menu .qc" is to make the first part of the menu selection code.

so right below the "Menus" function you just made. put this:

Code:


void(float inp) Select =

{
   if (!self.menu) // if not in a menu do nothing.
      return;
   if (self.menu == 1) // if the menu is on menu 1.
   {
      if (inp == 1) // and if inp equals 1. do stuff.
      {
         stuffcmd(self,"color 3 3"); // this is a stuffcmd stuffcmds can be used for a lot of things how you use them are up to you. this one sets the players colors to green.
         self.pteam = 1; // sets the players team through pteam, pteam is a .float.
         setmodel(self,"progs/player.mdl"); // sets the players model.
         self.skin = 1; // sets the players skin number on the model.
         modelindex_player = self.modelindex; // im not exactly sure how to explain this but i know with out it the skin will not set  , YOU MUST HAVE THIS.
         self.movetype = MOVETYPE_WALK; // sets the players move type to walk.
                   self.menu = 0; // turns the menu off.
         self.impulse = 0; // resets the impulse number.
         centerprint(self,"\n"); // prints nothing and closes the menu.
      }
      if (inp == 2) // all the same stuff but for the other team.
      {
         stuffcmd(self,"color 4 4");
         self.pteam = 2;
         setmodel(self,"progs/player.mdl");
         self.skin = 2;
         modelindex_player = self.modelindex;
         self.movetype = MOVETYPE_WALK;
         self.menu = 0;
         self.impulse = 0;
         centerprint(self,"\n");
      }

   }
   Menus();
   self.menutime = time + 0.2;
};

that last function sets up the first part of the in menu selection. basically if your in a certain menu and "inp" the number of the key you press. it does that action.

now your finished in menu.qc

our next step is to go to moddefs.qc.

if you want you can just paste all this in there.

Code:

// Function defs
void() PutObserverInServer;
void(float inp) Select;
void() SecondImpulse;

// floats and globals
.float menutime;
.float pteam;
.float menu;


all finished here. save and close.

next we'll move on to client.qc.

search for SelectSpawnPoint.

replace that entire function with this:

Code:
/*
============
SelectSpawnPoint

Returns the entity to spawn at
============
*/
entity() SelectSpawnPoint =
{
   local   entity spot;
   local   entity thing;
   local   float  pcount;
   
// testinfo_player_start is only found in regioned levels
   spot = find (world, classname, "testplayerstart");
   if (spot)
      return spot;
      
   
   if (deathmatch && self.pteam == 1) // if the game is deathmatch and your team is team 1. do stuff.
   {
      spot = lastspawn;
      while (1)
      {
         spot = find(spot, classname, "info_player_deathmatch"); // sets the classname "name of the mapping entitie" to this.
         if (spot != world)
         {
            if (spot == lastspawn)
               return lastspawn;
            pcount = 0;
            thing = findradius(spot.origin, 32);
            while(thing)
            {
               if (thing.classname == "player")
                  pcount = pcount + 1;
               thing = thing.chain;
            }
            if (pcount == 0)
            {
               lastspawn = spot;
               return spot;
            }
         }
      }
   }

   else if (deathmatch && self.pteam == 2) // if the game type is deathmatch and your team is team 2. do stuff.
   {
      spot = lastspawn;
      while (1)
      {
         spot = find(spot, classname, "info_player_deathmatch2"); // new classname for team two's spawn point.
         if (spot != world)
         {
            if (spot == lastspawn)
               return lastspawn;
            pcount = 0;
            thing = findradius(spot.origin, 32);
            while(thing)
            {
               if (thing.classname == "player")
                  pcount = pcount + 1;
               thing = thing.chain;
            }
            if (pcount == 0)
            {
               lastspawn = spot;
               return spot;
            }
         }
      }
   }

   else if (coop && self.pteam == 1) // if the gametype is coop and your team is team 1. do stuff. (we only have it set for team 1 for a reason.)
   {
      spot = lastspawn;
      while (1)
      {
         spot = find(spot, classname, "info_player_coop"); // same as the rest. uses an already existing classname.
         if (spot != world)
         {
            if (spot == lastspawn)
               return lastspawn;
            pcount = 0;
            thing = findradius(spot.origin, 32);
            while(thing)
            {
               if (thing.classname == "player")
                  pcount = pcount + 1;
               thing = thing.chain;
            }
            if (pcount == 0)
            {
               lastspawn = spot;
               return spot;
            }
         }
      }
   }

   
   else if (!self.pteam) // else if you dont have a team.
   {
      spot = lastspawn;
      while (1)
      {
         spot = find(spot, classname, "info_player_observer"); // new classname for a mapping entitie.
         if (spot != world)
         {
            if (spot == lastspawn)
               return lastspawn;
            pcount = 0;
            thing = findradius(spot.origin, 32);
            while(thing)
            {
               if (thing.classname == "observer") // and your class name is OBSERVER  not player. (this is important)
                  pcount = pcount + 1;
               thing = thing.chain;
            }
            if (pcount == 0)
            {
               lastspawn = spot;
               return spot;
            }
         }
      }
   }
   
   
   
   if (serverflags)
   {   // return with a rune to start
      spot = find (world, classname, "info_player_start2");
      if (spot)
         return spot;
   }
   
   spot = find (world, classname, "info_player_start");
   if (!spot)
      error ("PutClientInServer: no info_player_start on level");
   
   return spot;
};


most of that code is literally just copys of the existing code thats already there so i didnt take as much time commenting it.

our next step is in PutClientInServer so scroll down to there or do a search for it. should be right after what we just did.

edit it to look like so:


Code:
/*
===========
PutClientInServer

called each time a player is spawned
============
*/
void() DecodeLevelParms;
void() PlayerDie;


void() PutClientInServer =
{
   if (!self.pteam) // if you dont have a team.
   {
      PutObserverInServer(); // spawn as an observer instead.
      return;
   }
   
   
   
   local   entity spot;

   spot = SelectSpawnPoint ();

   self.classname = "player";
   self.health = 100;
   self.takedamage = DAMAGE_AIM;
   self.solid = SOLID_SLIDEBOX;
   self.movetype = self.movetype;
   self.show_hostile = 0;
   self.max_health = 100;
   self.flags = FL_CLIENT;
   self.air_finished = time + 12;
   self.dmg = 2;         // initial water damage
   self.super_damage_finished = 0;
   self.radsuit_finished = 0;
   self.invisible_finished = 0;
   self.invincible_finished = 0;
   self.effects = 0;
   self.invincible_time = 0;




   DecodeLevelParms ();
   
   W_SetCurrentAmmo ();

   self.attack_finished = time;
   self.th_pain = player_pain;
   self.th_die = PlayerDie;
   
   self.deadflag = DEAD_NO;
// paustime is set by teleporters to keep the player from moving a while
   self.pausetime = 0;
   
//   spot = SelectSpawnPoint ();

//   self.origin = spot.origin + '0 0 1';
   self.origin = self.oldorigin = spot.origin + '0 0 1';   // 1998-07-21 Respawning where player died fix by Robert Field
   self.angles = spot.angles;
   self.fixangle = TRUE;      // turn this way immediately

// oh, this is a hack!
   setmodel (self, "progs/eyes.mdl");
   modelindex_eyes = self.modelindex;
   
   setmodel (self, "progs/player.mdl");
   modelindex_player = self.modelindex;
   
   
   
   

   setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
   
   self.view_ofs = '0 0 22';
   
   self.velocity = '0 0 0';   // 1998-07-21 Player moves after respawn fix by Xian

   player_stand1 ();
   
   if (deathmatch || coop)
   {
      makevectors(self.angles);
      spawn_tfog (self.origin + v_forward*20);
   }

   spawn_tdeath (self.origin, self);
};


next right below this function add two new functions like the other you see below it like this:

Code:
void() info_player_deathmatch2 =
{
};

void() info_player_observer =
{
};




and our last stop in client.qc is in ClientConnect so go there now.

edit it like this:



















Code:
/*
===========
ClientConnect

called when a player connects to a server
============
*/
void() ClientConnect =
{
   bprint (self.netname);
   bprint (" entered the game\n");
   if (deathmatch) // if the gametype is deathmatch, do this.
   {
      self.pteam = 0; // on connecting you start with out a team.
      self.menu = 1; // opens up your menu.
   }
   else if (coop) // else if the gametype is coop.
   {
      self.pteam = 1; // your team is automatically set to one, since its a coop game you only need 1 team.
      self.menu = 0; // makes sure the menu is off, since you dont need to select a team.
   }
   
   
// a client connecting during an intermission can cause problems
   if (intermission_running)
      ExitIntermission ();
};


OK! now we're all finished in client.qc lets move on to weapons.qc i promise this will be quicker. there's only 1 or 2 steps to this part.

once your in weapons.qc scroll down or search for impulse commands.

edit it to look like this:

Code:
/*
============
ImpulseCommands

============
*/
void() ImpulseCommands =
{
   
   if (self.menu < 1) // if menu equals less than 1.
    {
        if (self.impulse >= 1 && self.impulse <= 8)
            W_ChangeWeapon ();

        if (self.impulse == 9)
            CheatCommand ();
        if (self.impulse == 10)
            CycleWeaponCommand ();
        if (self.impulse == 11)
            ServerflagsCommand ();
        if (self.impulse == 12)
            CycleWeaponReverseCommand ();

        if (self.impulse == 255)
            QuadCheat ();
      
   self.impulse = 0;
   }
   else // otherwise ...
   {
        SecondImpulse(); // call special impulse commands below
   }
};


its basically the same just slightly modified.

then add this right below that function:





Code:
void() SecondImpulse =
// this is the second part of the menu select code its a special set of impulse commands. if you add on to the menu just simply add another impulse to the list.
{
   if (self.impulse == 1)
        Select(1);
   if (self.impulse == 2)
        Select(2);
};


ok almost finished 2 more steps left and your DONE!

next we'll make a new .qc file called "observer.qc". in this file put this:



Code:
               /*Observer*/
//========================================================================================

void() PutObserverInServer =
{
   if (self.team >= 1) // if you have a team.
   {
      PutClientInServer();  // do this.
   }
   
      local   entity spot;

   spot = SelectSpawnPoint ();
   
   self.classname = "observer"; // sets the players classname to observer.
   self.health = 100;
   self.takedamage = DAMAGE_NO;
   self.solid = SOLID_NOT;
   self.movetype = MOVETYPE_NONE;
   self.show_hostile = 0;
   self.max_health = 100;
   self.flags = FL_CLIENT;
   self.air_finished = time + 12;
   self.super_damage_finished = 0;
   self.radsuit_finished = 0;
   self.invisible_finished = 0;
   self.invincible_finished = 0;
   self.effects = 0;
   self.invincible_time = 0;
   self.pteam = 0;




self.items = self.items - ( // take all of their stuff.
            IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN
            | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_KEY1 | IT_KEY2);

   
   W_SetCurrentAmmo ();


   
   self.deadflag = DEAD_NO;
// paustime is set by teleporters to keep the player from moving a while
   self.pausetime = 0;
   
//   spot = SelectSpawnPoint ();

//   self.origin = spot.origin + '0 0 1';
   self.origin = self.oldorigin = spot.origin + '0 0 1';   // 1998-07-21 Respawning where player died fix by Robert Field
   self.angles = spot.angles;
   self.fixangle = TRUE;      // turn this way immediately

// oh, this is a hack!  these set the observers model to the "eye.mdl" model.
   setmodel (self, "progs/eyes.mdl");
   modelindex_eyes = self.modelindex;

   setmodel (self, "progs/eyes.mdl");
   modelindex_player = self.modelindex;

   setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
   
   self.view_ofs = '0 0 22';
   
   self.velocity = '0 0 0';   // 1998-07-21 Player moves after respawn fix by Xian

   player_stand1 ();
   
   if (deathmatch || coop)
   {
      makevectors(self.angles);
      spawn_tfog (self.origin + v_forward*20);
   }
};


this is basically just a modified putclientinserver. pretty simple.

ok and the last part is to add all the new .qc files in to the progs.src.

it should look like this:




Code:
../progs.dat

defs.qc
moddefs.qc
subs.qc
fight.qc
ai.qc
combat.qc
items.qc
weapons.qc
world.qc
client.qc
observer.qc
player.qc
monsters.qc
doors.qc
buttons.qc
triggers.qc
plats.qc
misc.qc

ogre.qc
demon.qc
shambler.qc
knight.qc
soldier.qc
wizard.qc
dog.qc
zombie.qc
boss.qc

menu.qc

tarbaby.qc      // registered
hknight.qc      // registered
fish.qc         // registered
shalrath.qc      // registered
enforcer.qc      // registered
oldone.qc      // registered


there you go! your all finished! compile and try it out!

there's also a plus that all of this should work in vanilla quake.

also here's a player.mdl with two skins on it all ready setup to use!
Download

Merry Christmas! Razz
_________________
QuakeDB - Quake ModDB Group
Back to top
View user's profile Send private message Yahoo Messenger
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group