Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions progs/ssqc.src
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ gamemodes/hardcore.qc
gamemodes/wild_west.qc
gamemodes/sticks_and_stones.qc
gamemodes/festive.qc
gamemodes/lockdown.qc
gamemodes/core.qc
#ifdef QUAKEC_TEST
tests/test_math.qc
Expand Down
6 changes: 6 additions & 0 deletions source/client/main.qc
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,12 @@ noref void() CSQC_Parse_Event =
date = "";
person = "";
break;
case GAMEMODE_LOCKDOWN:
chaptertitle = "LOCKDOWN";
location = "Don't open the damn door!";
Comment thread
katniny marked this conversation as resolved.
Outdated
date = "";
person = "";
break;
default:
break;
}
Expand Down
3 changes: 2 additions & 1 deletion source/menu/menu_gset.qc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void() Menu_GameSettings_ApplyGameMode =
float current_gamemode = cvar("sv_gamemode");
current_gamemode += 1;

if (current_gamemode > 6)
if (current_gamemode > 7)
current_gamemode = 0;

cvar_set("sv_gamemode", ftos(current_gamemode));
Expand Down Expand Up @@ -115,6 +115,7 @@ void() Menu_GameSettings =
case 4: gamemode_description = "Ole Fashioned stand-off between you and the Dead."; gamemode_string = "WILD WEST"; break;
case 5: gamemode_description = "Knives-and-Nades only. Grenades Explode on Contact."; gamemode_string = "STICKS & STONES"; break;
case 6: gamemode_description = "The cycle continues. Old meets new in this Cold War inspired mode!"; gamemode_string = "FEVER"; break;
case 7: gamemode_description = "No Escape. Survive as Long as Possible."; gamemode_string = "LOCKDOWN"; break;
Comment thread
katniny marked this conversation as resolved.
Outdated
default: gamemode_description = "???"; break;
}
Menu_Button(1, "ge_mode", "GAME MODE", gamemode_description) ? Menu_GameSettings_ApplyGameMode() : 0;
Expand Down
1 change: 1 addition & 0 deletions source/menu/menu_loby.qc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ void() Menu_Lobby =
case 4: gamemode = "WILD WEST"; break;
case 5: gamemode = "STICKS & STONES"; break;
case 6: gamemode = "FEVER"; break;
case 7: gamemode = "LOCKDOWN"; break;
default: gamemode = "???"; break;
}

Expand Down
1 change: 1 addition & 0 deletions source/server/defs/custom.qc
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ float game_modifier_powerup_free_perk;
float game_modifier_powerup_free_perk_is_rare;
float game_modifier_powerup_max_ammo;
float game_modifier_powerup_weapon_upgrade;
float game_modifier_powerup_random_weapon;
float game_modifier_powerup_bonus_points;
float game_modifier_powerup_toast_for_all;
float game_modifier_perk_purchase_limit;
Expand Down
56 changes: 56 additions & 0 deletions source/server/entities/powerups.qc
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ string(string file) PU_ResolveVOPath =
case GAMEMODE_STICKSNSTONES: path = strcat("sounds/modes/sticks/", file); break;
case GAMEMODE_WILDWEST: path = strcat("sounds/modes/wildwest/", file); break;
case GAMEMODE_FESTIVE: path = strcat("sounds/modes/festive/", file); break;
case GAMEMODE_LOCKDOWN: path = strcat("sounds/modes/lockdown/", file); break;
default: path = strcat("sounds/pu/", file); break;
}

Expand Down Expand Up @@ -588,6 +589,15 @@ float() PU_BonusPointsRequirement =
return game_modifier_powerup_bonus_points;
}

//
// PU_RandomWeaponRequirement()
// Requirements for Random Weapon Power-Up
//
float() PU_RandomWeaponRequirement =
{
return game_modifier_powerup_random_weapon;
}

//
// PU_MaxAmmo()
// Max Ammo Power-Up Function
Expand Down Expand Up @@ -637,6 +647,50 @@ void() PU_MaxAmmo =
}
};

//
// PU_RandomWeapon()
// Random Weapon Power-Up Function
//
void() PU_RandomWeapon =
{
entity players = find(world, classname, "player");
while(players != world) {
float random_weapon_id = -1;
float valid_weapon_found = false;

while(!valid_weapon_found) {
random_weapon_id = rint(random() * 59);

// skip bad weapons
if (random_weapon_id == W_NOWEP || random_weapon_id == W_GRENADE
|| random_weapon_id == W_BETTY || random_weapon_id == W_BOWIE
|| random_weapon_id == W_RESERVED || random_weapon_id == W_RESERVED2)
continue;

// skip if they already have this weapon or an equivalent
if (EqualNonPapWeapon(players.weapons[0].weapon_id) == EqualNonPapWeapon(random_weapon_id) ||
EqualNonPapWeapon(players.weapons[1].weapon_id) == EqualNonPapWeapon(random_weapon_id) ||
EqualNonPapWeapon(players.weapons[2].weapon_id) == EqualNonPapWeapon(random_weapon_id))
continue;


valid_weapon_found = true;
}

// assign and sweap weapon
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the behavior if they're in the middle of drinking something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swaps weapons but keeps you in a state like you're still drinking a perk (can't shoot, interact, so on)... good catch, I'll fix that 😓

entity old_self = self;
self = players;
W_SprintStop();
W_AimOut();
Weapon_GiveWeapon(EqualNonPapWeapon(random_weapon_id), 0, 0, 0);
Weapon_AssignWeapon(0, EqualNonPapWeapon(random_weapon_id), 0, 0, 0);
Weapon_SwapWeapons(true);
self = old_self;

players = find(players, classname, "player");
}
}

//
// PU_FreePerk()
// Free Perk Power-Up Function
Expand Down Expand Up @@ -781,6 +835,8 @@ void() PU_Init =
PU_UpgradeWeaponRequirement );
PU_AddToStruct(PU_BONUSPOINTS, "models/pu/points!.mdl", "bonus_points.wav", PU_BonusPoints,
PU_BonusPointsRequirement );
PU_AddToStruct(PU_RANDOMWEAPON, "models/weapons/mp40/g_mp40.mdl", "random_weapon.wav", PU_RandomWeapon,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't reference a weapon world model. If you want to duplicate the mp40 mesh with a Power-Up texture however that is OK.

PU_RandomWeaponRequirement );

// Nuke requires an extra Precache
precache_sound("sounds/pu/nuke.wav");
Expand Down
3 changes: 3 additions & 0 deletions source/server/gamemodes/core.qc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ void() Gamemode_Init =
case GAMEMODE_STICKSNSTONES: Gamemode_Sticks_Init(); break;
case GAMEMODE_WILDWEST: Gamemode_WW_Init(); break;
case GAMEMODE_FESTIVE: Gamemode_Festive_Init(); break;
case GAMEMODE_LOCKDOWN: Gamemode_Lockdown_Init(); break;
default: error("Received unrecognized gamemode."); break;
}
};
Expand All @@ -83,6 +84,7 @@ void() Gamemode_Frame =
case GAMEMODE_STICKSNSTONES: Gamemode_Sticks_Frame(); break;
case GAMEMODE_WILDWEST: Gamemode_WW_Frame(); break;
case GAMEMODE_FESTIVE: Gamemode_Festive_Frame(); break;
case GAMEMODE_LOCKDOWN: Gamemode_Lockdown_Frame(); break;
default: error("Received unrecognized gamemode."); break;
}

Expand Down Expand Up @@ -111,6 +113,7 @@ void() Gamemode_PlayerSpawn =
case GAMEMODE_STICKSNSTONES: Gamemode_Sticks_PlayerSpawn(); break;
case GAMEMODE_WILDWEST: Gamemode_WW_PlayerSpawn(); break;
case GAMEMODE_FESTIVE: Gamemode_Festive_PlayerSpawn(); break;
case GAMEMODE_LOCKDOWN: Gamemode_Lockdown_PlayerSpawn(); break;
default: error("Received unrecognized gamemode."); break;
}
};
Expand Down
224 changes: 224 additions & 0 deletions source/server/gamemodes/lockdown.qc
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
/*
server/gamemodes/lockdown.qc

Core Logic for Lockdown.

Copyright (C) 2021-2026 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

*/

float lock_ran_post_init_logic;
float lock_ran_endgame;
float lock_last_perk_shuffle_round;
entity lock_perks[32];
vector lock_positions[32];
vector lock_angs[32];

float(float count, string cvar) Gamemode_Lockdown_CollectPerks =
Comment thread
katniny marked this conversation as resolved.
Outdated
{
entity e;

e = find(world, classname, cvar);
while (e != world) {
lock_perks[count] = e;
lock_positions[count] = e.origin;
lock_angs[count] = e.angles;
count = count + 1;

e = find(e, classname, cvar);
}

return count;
};

void() Gamemode_Lockdown_RandomizePerkLocations =
{
float count;
count = 0;

entity e;

// Collect all perk machines
count = Gamemode_Lockdown_CollectPerks(count, "perk_revive");
count = Gamemode_Lockdown_CollectPerks(count, "perk_juggernog");
count = Gamemode_Lockdown_CollectPerks(count, "perk_speed");
count = Gamemode_Lockdown_CollectPerks(count, "perk_double");
count = Gamemode_Lockdown_CollectPerks(count, "perk_flopper");
count = Gamemode_Lockdown_CollectPerks(count, "perk_staminup");
count = Gamemode_Lockdown_CollectPerks(count, "perk_deadshot");
count = Gamemode_Lockdown_CollectPerks(count, "perk_mule");
count = Gamemode_Lockdown_CollectPerks(count, "perk_pap");
Comment on lines +60 to +68
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can clean this up significantly if we just make a list and reference the list. Also, why are we doing this every time it's called?


// Shuffle positions of all perks
float i;
for (i = count - 1; i > 0; i = i - 1) {
float j;
j = floor(random() * (i + 1));

vector tmp_v;
tmp_v = lock_positions[i];
lock_positions[i] = lock_positions[j];
lock_positions[j] = tmp_v;

tmp_v = lock_angs[i];
lock_angs[i] = lock_angs[j];
lock_angs[j] = tmp_v;
}

// Apply shuffled positions
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make sure we never get an item spawning in the same place it was before. Also, we should play the sparkle effect when it moves so it seems less janky.

for (i = 0; i < count; i = i + 1) {
entity p;
p = lock_perks[i];

setorigin(p, lock_positions[i]);
p.angles = lock_angs[i];
p.oldorigin = p.origin;

// Fix Pack-a-Punch attachments or they'll
// float in their old locations (which is obviously incorrect!)
if (p.classname == "perk_pap") {
makevectors(p.angles);

vector newpos;

// Move roller
if (p.active_door) {
entity roller;
roller = p.active_door;

newpos = p.origin;
newpos = newpos + v_right * p.box1_y;
newpos = newpos + v_forward * p.box1_x;
newpos = newpos + v_up * p.box1_z;

setorigin(roller, newpos);
roller.angles = p.angles;
}

// Move flag
if (p.boxweapon) {
entity flag;
flag = p.boxweapon;

newpos = p.origin;
newpos = newpos + v_right * p.box3_y;
newpos = newpos + v_forward * p.box3_x;
newpos = newpos + v_up * p.box3_z;

setorigin(flag, newpos);
flag.angles = p.angles;
}

// Recalculate spark offset
vector tempv;
tempv = p.origin;
tempv = tempv + v_right * p.box2_y;
tempv = tempv + v_forward * p.box2_x;
tempv = tempv + v_up * p.box2_z;
p.box2 = tempv;
}

setorigin(lock_perks[i], lock_positions[i]);
lock_perks[i].angles = lock_angs[i];
lock_perks[i].oldorigin = lock_perks[i].origin;
}
}

void() Gamemode_Lockdown_Init =
{
// enable the free perk and weapon upgrade drops
game_modifier_powerup_free_perk = true;
game_modifier_powerup_weapon_upgrade = true;
game_modifier_powerup_random_weapon = true;

// precache audio
Comment thread
katniny marked this conversation as resolved.
precache_sound("sounds/modes/lockdown/intro.wav");
precache_sound("sounds/modes/lockdown/carpenter.wav");
precache_sound("sounds/modes/lockdown/double_points.wav");
precache_sound("sounds/modes/lockdown/free_perk.wav");
precache_sound("sounds/modes/lockdown/insta_kill.wav");
precache_sound("sounds/modes/lockdown/kaboom.wav");
precache_sound("sounds/modes/lockdown/maxammo.wav");
precache_sound("sounds/modes/lockdown/random_weapon.wav");
precache_sound("sounds/modes/lockdown/upgrade.wav");
precache_sound("sounds/modes/lockdown/lose.wav");
};

void() Gamemode_Lockdown_Frame =
{
// Intro voiceline
if (lock_ran_post_init_logic == false) {
// Play intro voiceline
Sound_PlaySound(world, "sounds/modes/lockdown/intro.wav", SOUND_TYPE_ENV_VOICE, SOUND_PRIORITY_PLAYALWAYS);
// Randomize perk locations
Gamemode_Lockdown_RandomizePerkLocations();
Comment thread
katniny marked this conversation as resolved.
Outdated

lock_ran_post_init_logic = true;
}

// Every 5 rounds, reroll the perks to help the player
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're checking this and doing the door stuff every frame?

// progress in the game
if (floor(rounds / 5) * 5 == rounds) {
// Prevents the perks from shuffling all round
if (rounds != lock_last_perk_shuffle_round) {
lock_last_perk_shuffle_round = rounds;

// Avoid running on round 0 & round 1 since we run on
// game start anyways
if (rounds > 0 && rounds != 1) {
Gamemode_Lockdown_RandomizePerkLocations();
}
}
}

// Disable Doors
entity doors = find(world, classname, "door_nzp");
while(doors != world) {
doors.use = SUB_Null;
doors.touch = SUB_Null;

if (doors.trigger_field != world)
remove(doors.trigger_field);

doors = find(doors, classname, "door_nzp");
}
doors = find(world, classname, "door_nzp_cost");
while(doors != world) {
doors.use = SUB_Null;
doors.touch = SUB_Null;

if (doors.trigger_field != world)
remove(doors.trigger_field);

doors = find(doors, classname, "door_nzp_cost");
}

// Losing voiceline
if ((find(world, classname, "gameover_watcher")) && lock_ran_endgame == false) {
lock_ran_endgame = true;
Sound_PlaySound(world, "sounds/modes/lockdown/lose.wav", SOUND_TYPE_ENV_VOICE, SOUND_PRIORITY_PLAYALWAYS);
}
};

void() Gamemode_Lockdown_PlayerSpawn =
{
return;
};
1 change: 1 addition & 0 deletions source/server/main.qc
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ void() worldspawn =
game_modifier_powerup_free_perk = false;
game_modifier_powerup_max_ammo = true;
game_modifier_powerup_weapon_upgrade = false;
game_modifier_powerup_random_weapon = false;
game_modifier_powerup_bonus_points = false;
game_modifier_powerup_toast_for_all = false;
game_modifier_can_packapunch = true;
Expand Down
Loading
Loading