This assumes you the POQ Modern 0.5 source open and these changes will add "deathmatch 3" as "Last Man Standing Mode" or Rounds.
1. progs.src
Add this after client.qc, these are the 2 new files.
utilities.qc //BAM MATCH ROUNDS
match.qc //BAM MATCH ROUNDS
2. Add match.qc (
download) and utilities.qc (
download) to your source folder.
3. buttons.qc
Add the yellow. You don't want observing dead players -- who are invisible to all -- being able to press buttons do you?
4. weapons.qc
No shooting before round countdown begins, no observing dead players shooting either ... obviously.
void() W_Attack =
{
local float r;
if (!W_CheckNoAmmo ())
return;
//MATCH ROUNDS: No attacking before round starts, and while observer
if ((mode == MATCH_STARTING && counter <= 8 ) || self.status & STS_OBSERVER)
return;
makevectors (self.v_angle); // calculate forward angle for velocity
self.show_hostile = time + 1; // wake monsters up
if (self.weapon == IT_AXE)
{
sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
r = random();
if (r < 0.25)
player_axe1 ();
else if (r<0.5)
player_axeb1 ();
else if (r<0.75)
player_axec1 ();
else
player_axed1 ();
self.attack_finished = time + 0.5;
}
else if (self.weapon == IT_SHOTGUN)
{
player_shot1 ();
W_FireShotgun ();
self.attack_finished = time + 0.5;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
player_shot1 ();
W_FireSuperShotgun ();
self.attack_finished = time + 0.7;
}
else if (self.weapon == IT_NAILGUN)
{
player_nail1 ();
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
player_nail1 ();
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
player_rocket1();
W_FireGrenade();
self.attack_finished = time + 0.6;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
player_rocket1();
W_FireRocket();
self.attack_finished = time + 0.8;
}
else if (self.weapon == IT_LIGHTNING)
{
player_light1();
self.attack_finished = time + 0.1;
sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
}
};
5. player.qc
Force player to become observer when dead instead of allowing them to respawn.
void() PlayerDie =
{
local float i;
//BAM v0.5: Remove powerups and prevent glowing dead bodies
self.items = self.items - (self.items & (IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD));
self.effects = 0;
self.invisible_finished = 0; // don't die as eyes
self.invincible_finished = 0;
self.super_damage_finished = 0;
self.radsuit_finished = 0;
self.modelindex = modelindex_player; // don't use eyes
if (deathmatch || coop)
DropBackpack();
///////////////////////
// MATCH ROUNDS
//BAM: Wait, then force observer
if (mode == MATCH_PLAYING)
observer_init (2.5);
// MATCH ROUNDS
///////////////////////
self.weaponmodel="";
self.view_ofs = '0 0 -8';
self.deadflag = DEAD_DYING;
self.solid = SOLID_NOT;
self.flags = self.flags - (self.flags & FL_ONGROUND);
self.movetype = MOVETYPE_TOSS;
if (self.velocity_z < 10)
self.velocity_z = self.velocity_z + random()*300;
if (self.health < -40)
{
GibPlayer ();
return;
}
DeathSound();
self.angles_x = 0;
self.angles_z = 0;
if (self.weapon == IT_AXE)
{
player_die_ax1 ();
return;
}
i = cvar("temp1");
if (!i)
i = 1 + floor(random()*6);
if (i == 1)
player_diea1();
else if (i == 2)
player_dieb1();
else if (i == 3)
player_diec1();
else if (i == 4)
player_died1();
else
player_diee1();
};
6. misc.qc
Observing players aren't affected by fire and don't take damage from it.
void() fire_touch =
{
//BAM
if (other.status & STS_OBSERVER)
return;
T_Damage (other, self, self, 20);
remove(self);
};
7. func.qc --- add this to the end ... these are function prototypes for the rest of the qc to know they exist
Code: Select all
///////////////////////
// MATCH ROUNDS
float (float pteam) team_allowed;
void() round_think;
void (float n, string s) centerprint_to;
void () match_end;
void (entity ent, float clientshirt, float clientpants) setcolor;
void (float DELAY) observer_init;
void () observer;
void (entity e, float chan, string samp, float vol, float atten) sound;
// MATCH ROUNDS
///////////////////////
8. plats.qc
Dead observing players can't start platforms.
void() plat_center_touch =
{
if (other.classname != "player")
return;
if (other.health <= 0)
return;
//BAM
if (other.status & STS_OBSERVER)
return;
self = self.enemy;
if (self.state == STATE_BOTTOM)
plat_go_up ();
else if (self.state == STATE_TOP)
self.nextthink = self.ltime + 1; // delay going down
};
void() plat_outside_touch =
{
if (other.classname != "player")
return;
if (other.health <= 0)
return;
//BAM
if (other.status & STS_OBSERVER)
return;
//dprint ("plat_outside_touch\n");
self = self.enemy;
if (self.state == STATE_TOP)
plat_go_down ();
};
9. initiate.qc
I am rather certain this isn't a stock progs 1.06 QuakeC source file name.
Prevents a newly connected client from barging in and playing a round in progress. Nope ... they get to watch instead of crash the party.
/*
============
PutClientInServer_Mod ()
Called everytime (minus intermission) PutClientInServer () is called. (this also means after
every map change) This function is a place for future mods to keep a player's non-parm
settings across but not limited to map changes.
IE: In the case of an observer mode, PutClientInServer () will revert a
player's non-parm settings after a map change, but PutClientInServer_Mod ()
should be the place to identify this and keep these observer settings.
============
*/
void ()
PutClientInServer_Mod =
{
local float isobserver;
if (self.status & STS_OBSERVER)
{
isobserver = TRUE;
self.status = self.status - STS_OBSERVER;
}
// for new players connecting
if (!self.status & STS_BINDINGS)
{
// The player is not yet ready to recieve commands stuffed
// to the client so we enforce a delay before any are sent.
send_commands ();
}
// after every map change
if (!self.status & STS_CONNECTED)
{
// reset player state, but keep observer
if (mode)
{
self.team2 = 0;
self.team = 1;
self.player_flag = PLAYER_WAITING;
setcolor (self, 0, 0); // Immediately sets client colors
// Keep player's observer status across map changes
if (isobserver)
observer ();
else if (mode != MATCH_WAITING)
observer ();
}
self.status = self.status | STS_CONNECTED;
}
};
10. Add this to the end of defs.qc, it is support for the rounds and observer mode
Code: Select all
/////////////////////////////////////
// BAM: Match defs
/////////////////////////////////////
float STS_OBSERVER = 32; // The player is currently an observer
float STS_QUEUE = 64; // The player is currently in queue to join the match
// Identifies and controls the status of the match.
float mode;
float MATCH_PLAYING = 1;
float MATCH_STARTING = 2;
float MATCH_WAITING = 3;
float MATCH_POSTROUND = 4;
// Because players become observers after they die mid-round we don't
// want their match status to change. They may be observer at the time,
// but they are still playing in the match.
.float player_flag;
float PLAYER_PLAYING = 1; // In match, whether or not this player is currently observer
float PLAYER_WAITING = 2; // Not in match, whether or not this player is currently observer
entity first_place, second_place, third_place, fourth_place; // For simplicity, global (top 4) entities are used
float gamecheck, counter, round, matchvar, match_ready, match_overtime, players_ready; // Used for round rules/status
.float team2, teamcheck; // team2: checks for team validation, teamcheck: delay color check
.string refresh; // Items refreshed between rounds are given a universal classname to identify them
Just 5 more files to go ... to be continued ...