So, lets get started.
our first step is to make two new .qc files. Call the first one
and the secondmoddefs.qc
.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: Select all
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.
};
so right below the "Menus" function you just made. put this:
Code: Select all
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;
};
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: Select all
// Function defs
void() PutObserverInServer;
void(float inp) Select;
void() SecondImpulse;
// floats and globals
.float menutime;
.float pteam;
.float menu;
next we'll move on to client.qc.
search for SelectSpawnPoint.
replace that entire function with this:
Code: Select all
/*
============
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;
};
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: Select all
/*
===========
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);
};
Code: Select all
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: Select all
/*
===========
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 ();
};
once your in weapons.qc scroll down or search for impulse commands.
edit it to look like this:
Code: Select all
/*
============
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
}
};
then add this right below that function:
Code: Select all
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);
};
next we'll make a new .qc file called "observer.qc". in this file put this:
Code: Select all
/*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);
}
};
ok and the last part is to add all the new .qc files in to the progs.src.
it should look like this:
Code: Select all
../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'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!