quakec/source/server/rounds.qc
2024-06-16 14:16:30 -07:00

375 lines
7.7 KiB
C++

/*
server/rounds.qc
wave logic
Copyright (C) 2021-2024 NZ:P Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
void() SUB_UseTargets;
float() spawn_a_dogA;
void() zapper_cooldown;
void() Spawn_Enemy =
{
// temporarily prevent spawning
if (nuke_powerup_spawndelay > time)
return;
if (roundtype == 1)
{
if (spawn_a_zombieA())
{
Current_Zombies = Current_Zombies + 1;
}
}
else if (roundtype == 2)
{
if (spawn_a_dogA())
{
Current_Zombies = Current_Zombies + 1;
}
}
}
float(float a, float b) qc_max =
{
if (a < b)
return b;
return a;
}
float() getZombieTotal = {
if (roundtype == 1) {
float count, multiplier, plrcnt;
count = 24;
plrcnt = player_count + 1;
multiplier = qc_max(rounds/5, 1);
if (rounds >= 10)
multiplier *= rounds * 0.15;
if (plrcnt == 1)
count += rint((0.5 * 6) * multiplier);
else
count += rint(((plrcnt - 1) * 6) * multiplier);
if (rounds < 2)
count = floor(count * 0.25);
else if (rounds < 3)
count = floor(count * 0.30);
else if (rounds < 4)
count = floor(count * 0.50);
else if (rounds < 5)
count = floor(count * 0.70);
else if (rounds < 6)
count = floor(count * 0.90);
return count;
} else { //dogs
// 2 waves
if (rounds <= 14)
return 6 * (player_count + 1);
return 8 * (player_count + 1);
}
return 0;
}
//
// Rounds_PlayTransition(sound_path)
// A nice wrapper for sound() that checks if
// music is playing and proceeds if not.
//
void(string sound_path) Rounds_PlayTransition =
{
// Don't play any round stuff while there's a song egg happening.
if (music_override > time)
return;
// Pick a random player because it needs a source.
entity some_player = find(world, classname, "player");
sound(some_player, CHAN_AUTO, sound_path, 1, ATTN_NONE);
}
void() updateDogRound =
{
float r = random();
if (r < 0.33) {
dogRound = rounds + 5;
} else if (r < 0.66) {
dogRound = rounds + 6;
} else {
dogRound = rounds + 7;
}
}
void() PlayerSpawn;
void() EndRound =
{
entity who = find(world,classname,"spectator");
while(who != world)
{
if(who.isspec)
{
self = who;
PlayerSpawn();
}
who = find(who, classname, "spectator");
}
rounds_change = 4;
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
if (gotdog && rounds == dogRound) {
Rounds_PlayTransition("sounds/rounds/droundend.wav");
dogWave = false;
} else {
Rounds_PlayTransition("sounds/rounds/eround.wav");
}
round_changetime = time + 10;
// No Perks? No Problem & Abstinence Program
if (rounds >= 10) {
entity players;
players = find(world, classname, "player");
while(players != world) {
if (players.ach_tracker_abst == 0) {
GiveAchievement(8, players);
}
if (rounds >= 16) {
if (players.ach_tracker_npnp == 0) {
GiveAchievement(5, players);
}
}
players = find(players, classname, "player");
}
}
// Fire off all trigger_atroundent ents
entity triggers = find(world, classname, "trigger_atroundend");
while(triggers != world) {
if (triggers.health == rounds) {
entity oldself = self;
self = triggers;
SUB_UseTargets();
self = oldself;
}
triggers = find(triggers, classname, "trigger_atroundend");
}
}
void() NewRound =
{
entity tempe;
round_changetime = 0;
spawn_time = time + 5;
sounds_playing = 0;//just in case it ever somehow glitches
if (delay_at_round > 0.08)
{
delay_at_round = delay_at_round*0.95;
if (delay_at_round < 0.08)
delay_at_round = 0.08;
}
if (rounds != 0)
{
if (gotdog && rounds == (dogRound - 1)) {
Rounds_PlayTransition("sounds/rounds/droundstart.wav");
dogWave = true;
dog_round_count++;
} else {
Rounds_PlayTransition("sounds/rounds/nround.wav");
}
rounds_change = 6;
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
blink_return = time + 2;
}
// if we just had a dog round, set the next
if (gotdog && rounds == dogRound) {
updateDogRound();
}
rounds = rounds + 1;
#ifdef FTE
// FTE-Specific - alert CSQC of the round increment for HUD display
FTE_IncrementRound(rounds);
#endif // FTE
tempe = find(world, classname, "player");
while (tempe)
{
if(tempe.grenades & 1)
{
tempe.primary_grenades = tempe.primary_grenades + 2;
if (tempe.primary_grenades > 4)
tempe.primary_grenades = 4;
}
if(tempe.grenades & 2)
{
tempe.secondary_grenades = tempe.secondary_grenades + 2;
if (tempe.secondary_grenades > 2)
tempe.secondary_grenades = 2;
}
// Set everyone to full health.
tempe.health = tempe.max_health;
// Reset total repaired barricades for this round
tempe.barricade_reward = 0;
tempe = find(tempe, classname, "player");
}
set_z_health();
barricade_reward_maximum = 50 * rounds;
if (barricade_reward_maximum > 500)
barricade_reward_maximum = 500;
Current_Zombies = 0;
spawn_delay = 0;
totalpowerups = 0;
if (rounds == dogRound && gotdog) {
roundtype = 2;
localcmd("fog 200 525 54 55 60\n");
} else {
roundtype = 1;
if (world.fog) {
localcmd(strcat("fog ", world.fog));
} else {
localcmd("fog 0 0 0 0 0\n");
}
}
Remaining_Zombies = Total_Zombies = getZombieTotal();
switch(rounds) {
case 5: GiveAchievement(0); break;
case 10: GiveAchievement(1); break;
case 15: GiveAchievement(2); break;
default: break;
}
// Set up delay for zombie spawning
local float spawndelay;
spawndelay = zombie_spawn_delay;
if (spawndelay > 0.08) {
zombie_spawn_delay *= 0.95;
} else {
zombie_spawn_delay = 0.08;
}
// 2 seconds by default
if (rounds == 1)
zombie_spawn_delay = 2;
// Actually start the timer
zombie_spawn_timer = 2 + time;
if (rounds >= 10 && ach_tracker_spin == 0) {
GiveAchievement(10);
}
// Refresh Electric Traps
entity zaps = find(world, classname, "zapper_switch");
while(zaps != world) {
if (zaps.mode == 1) {
zaps.think = zapper_cooldown;
zaps.nextthink = time + 0.1;
}
zaps = find(zaps, classname, "zapper_switch");
}
}
void() Round_Core =
{
if (game_over)
return;
if (round_changetime) {
if (round_changetime <= (time + 2)) {
if (!rounds)
rounds_change = 2;
else
rounds_change = 5;
}
}
if (blink_return && blink_return < time) {
if (rounds_change == 6) {
blink_return = time + 3;
rounds_change = 7;
} else {
blink_return = 0;
rounds_change = 0;
}
}
if (round_changetime < time && round_changetime != 0) {
roundtype = 1;
NewRound();
return;
} else if (round_changetime != 0) return;
if (Total_Zombies > Current_Zombies && spawn_time < time) {
Spawn_Enemy();
}
if (Remaining_Zombies < 1 && !Delay_Time) {
Delay_Time = time + 1;
rounds_change = 3;
} else if (Delay_Time && Delay_Time < time) {
Delay_Time = 0;
EndRound();
}
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
}
void() InitRounds =
{
roundtype = 1;
delay_at_round = 2/0.95;
totalpowerups = 0;
powerup_activate = 2000;
powerup_score_threshold = ((player_count + 1) * G_STARTPOINTS) + powerup_activate;
// cypress -- fix Soft_Restart spawning multiple
// pairs of zombie spawn points.
if (!roundinit)
spawnAllZombEnts();
round_changetime = time + 3.5;
rounds_change = 1;
roundinit = 1;
SetUpdate(self, UT_ROUNDS_CHANGE, rounds_change, 0, 0);
}