Skip to content

Commit 94a79e8

Browse files
authored
Merge pull request #121 from nzp-team/cypress_restartfixes
SERVER: Fix Perk and Power Switch related Restart issues close nzp-team/nzportable#1116 close nzp-team/nzportable#1125 close nzp-team/nzportable#1126
2 parents 9e45d96 + f77fe7b commit 94a79e8

8 files changed

Lines changed: 201 additions & 9 deletions

File tree

progs/ssqc.src

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ tests/test_weapons.qc
8484
tests/test_misc_model.qc
8585
tests/test_score.qc
8686
tests/test_ai.qc
87+
tests/test_power.qc
8788
tests/test_module.qc
8889
#endif
8990
#endlist

source/server/clientfuncs.qc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,13 @@ float() crandom =
651651

652652
float(entity them, entity me) PlayerIsLooking =
653653
{
654+
655+
#ifdef QUAKEC_TEST
656+
657+
return true;
658+
659+
#else
660+
654661
float ret = false;
655662
float old_solid = me.solid;
656663
me.solid = SOLID_BBOX;
@@ -674,4 +681,7 @@ float(entity them, entity me) PlayerIsLooking =
674681
me.solid = old_solid;
675682
setorigin(me, me.origin);
676683
return ret;
684+
685+
#endif // QUAKEC_TEST
686+
677687
};

source/server/defs/standard.qc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,5 @@ void (entity who, float low_frequency, float high_frequency, float duration)
474474
#define FILE_READ 0
475475
#define FILE_APPEND 1
476476
#define FILE_WRITE 2
477+
478+
void (string out) print = {bprint(PRINT_HIGH, out);}

source/server/player/player_core.qc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,14 @@ void(entity who, entity active_ent, float type, float cost, float weapon) Player
470470
//
471471
float(entity who, entity active_ent) Player_UseButtonPressed =
472472
{
473+
#ifdef QUAKEC_TEST
474+
475+
if (who.button7)
476+
return true;
477+
478+
return false;
479+
480+
#else
473481
// Small delay before we can interact with a new entity to
474482
// mitigate overlapping bboxes causing problems.
475483
if (who.last_looked_time >= time && active_ent != who.last_looked_ent)
@@ -480,6 +488,7 @@ float(entity who, entity active_ent) Player_UseButtonPressed =
480488
}
481489

482490
return false;
491+
#endif // QUAKEC_TEST
483492
};
484493

485494
void() PlayerJump =
@@ -827,8 +836,9 @@ void() PlayerPostThink =
827836

828837
#ifdef QUAKEC_TEST
829838

830-
if (time_before_gamestart != 0)
839+
if (time_before_gamestart != 0) {
831840
Test_RunAllTests();
841+
}
832842

833843
#endif // QUAKEC_TEST
834844
};

source/server/tests/test_module.qc

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,28 @@ void(string message) Test_Skip =
5757
skipped_message_buffer = sprintf("[SKIP]: %s\n", message);
5858
}
5959

60+
void(entity object) Test_SimulateUse =
61+
{
62+
float old_power_on = isPowerOn;
63+
isPowerOn = true;
64+
65+
entity old_self = self;
66+
67+
self.button7 = true;
68+
self.fire_delay = self.reload_delay = self.dive_delay = self.reload_delay = self.switch_delay = 0;
69+
70+
self = object;
71+
other = old_self;
72+
object.touch();
73+
self = old_self;
74+
other = world;
75+
76+
self.button7 = false;
77+
self.semi_actions &= ~SEMIACTION_USE;
78+
79+
isPowerOn = old_power_on;
80+
}
81+
6082
void(void() test_func, string test_name) Test_Run =
6183
{
6284
print(sprintf("[INFO]: Running test [%s]..", test_name));
@@ -107,6 +129,7 @@ var struct {
107129
{ Test_Math_ClampReturnsMin, "Test_Math_ClampReturnsMin" },
108130
{ Test_Math_ClampReturnsMax, "Test_Math_ClampReturnsMax" },
109131
{ Test_Perks_QuickRevive_ValidateFields, "Test_Perks_QuickRevive_ValidateFields" },
132+
{ Test_Perks_QuickRevive_NoCostChangeOnRestart, "Test_Perks_QuickRevive_NoCostChangeOnRestart" },
110133
{ Test_Perks_JuggerNog_ValidateFields, "Test_Perks_JuggerNog_ValidateFields" },
111134
{ Test_Perks_SpeedCola_ValidateFields, "Test_Perks_SpeedCola_ValidateFields" },
112135
{ Test_Perks_DoubleTap_ValidateFields, "Test_Perks_DoubleTap_ValidateFields" },
@@ -115,6 +138,7 @@ var struct {
115138
{ Test_Perks_DeadshotDaiquiri_ValidateFields, "Test_Perks_DeadshotDaiquiri_ValidateFields" },
116139
{ Test_Perks_Random_LegacyFields, "Test_Perks_Random_LegacyFields" },
117140
{ Test_Perks_MuleKick_ValidateFields, "Test_Perks_MuleKick_ValidateFields" },
141+
{ Test_Perks_Drink_WorkOnReset, "Test_Perks_Drink_WorkOnReset" },
118142
{ Test_Weapons_Gewehr_MagazineSize, "Test_Weapons_Gewehr_MagazineSize" },
119143
{ Test_Weapons_BowieKnife_RemovedAfterRespawn, "Test_Weapons_BowieKnife_RemovedAfterRespawn" },
120144
{ Test_Weapons_HoldTwoWeapons, "Test_Weapons_HoldTwoWeapons" },
@@ -131,7 +155,8 @@ var struct {
131155
{ Test_AddScore_NonClient, "Test_AddScore_NonClient" },
132156
{ Test_AddScore_DamageTypes, "Test_AddScore_DamageTypes" },
133157
{ Test_AddScore_MysteryBoxLeave, "Test_AddScore_MysteryBoxLeave" },
134-
{ Test_AI_HellhoundsDetected, "Test_AI_HellhoundsDetected" }
158+
{ Test_AI_HellhoundsDetected, "Test_AI_HellhoundsDetected" },
159+
{ Test_Power_HandleResetOnRestart, "Test_Power_HandleResetOnRestart" }
135160
};
136161

137162
void() Test_RunAllTests =

source/server/tests/test_perksacola.qc

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
*/
2727
float(float condition, string message) Test_Assert;
2828
void(string message) Test_Skip;
29+
void(entity object) Test_SimulateUse;
30+
31+
// MARK: Quick Revive
2932

3033
//
3134
// Test_Perks_QuickRevive_ValidatePrice()
@@ -48,6 +51,48 @@ void() Test_Perks_QuickRevive_ValidateFields =
4851
remove(machine);
4952
};
5053

54+
//
55+
// Test_Perks_QuickRevive_NoCostChangeOnRestart()
56+
// Validates that on a Soft_Restart the price of Quick
57+
// Revive does not change.
58+
// (https://github.com/nzp-team/nzportable/issues/1116)
59+
//
60+
void() Test_Perks_QuickRevive_NoCostChangeOnRestart =
61+
{
62+
entity perk_revive = find(world, classname, "perk_revive");
63+
64+
// We need to simulate buying the perk to see the cost reduction,
65+
// so give us points.
66+
self.points = 10000;
67+
float start_score = self.points;
68+
69+
// Simulate purchase
70+
Test_SimulateUse(perk_revive);
71+
72+
float score_diff_before = start_score - self.points;
73+
74+
Test_Assert((score_diff_before != 0), "Could not buy Quick Revive before restart!");
75+
76+
Soft_Restart();
77+
78+
// Do everything again and then assert
79+
// the diffs are the same.
80+
self.points = 10000;
81+
start_score = self.points;
82+
83+
Test_SimulateUse(perk_revive);
84+
85+
float score_diff_after = start_score - self.points;
86+
87+
Test_Assert((score_diff_before != 0), "Could not buy Quick Revive after restart!");
88+
Test_Assert((score_diff_before == score_diff_after), sprintf("Quick Revive price changed after Soft_Restart, expected [%d] but got [%d]!", score_diff_before, score_diff_after));
89+
90+
// Restart at end of test to not cause conflicts with tests ran afterwards.
91+
Soft_Restart();
92+
};
93+
94+
// MARK: Jugger-Nog
95+
5196
//
5297
// Test_Perks_JuggerNog_ValidatePrice()
5398
// Spawns a Jugger-Nog machine and validates its
@@ -69,6 +114,8 @@ void() Test_Perks_JuggerNog_ValidateFields =
69114
remove(machine);
70115
};
71116

117+
// MARK: Speed Cola
118+
72119
//
73120
// Test_Perks_SpeedCola_ValidatePrice()
74121
// Spawns a Speed Cola machine and validates its
@@ -90,6 +137,8 @@ void() Test_Perks_SpeedCola_ValidateFields =
90137
remove(machine);
91138
};
92139

140+
// MARK: Double Tap
141+
93142
//
94143
// Test_Perks_DoubleTap_ValidateFields()
95144
// Spawns a Double Tap machine and validates its
@@ -111,6 +160,8 @@ void() Test_Perks_DoubleTap_ValidateFields =
111160
remove(machine);
112161
};
113162

163+
// MARK: Stamin-Up
164+
114165
//
115166
// Test_Perks_StaminUp_ValidateFields()
116167
// Spawns a Stamin-Up machine and validates its
@@ -132,6 +183,8 @@ void() Test_Perks_StaminUp_ValidateFields =
132183
remove(machine);
133184
};
134185

186+
// MARK: PhD Flopper
187+
135188
//
136189
// Test_Perks_PhDFlopper_ValidateFields()
137190
// Spawns a PhD Flopper machine and validates its
@@ -153,6 +206,8 @@ void() Test_Perks_PhDFlopper_ValidateFields =
153206
remove(machine);
154207
};
155208

209+
// MARK: Deadshot Daiquiri
210+
156211
//
157212
// Test_Perks_DeadshotDaiquiri_ValidateFields()
158213
// Spawns a Deadshot Daiquiri machine and validates its
@@ -174,6 +229,8 @@ void() Test_Perks_DeadshotDaiquiri_ValidateFields =
174229
remove(machine);
175230
};
176231

232+
// MARK: Mule Kick
233+
177234
//
178235
// Test_Perks_MuleKick_ValidateFields()
179236
// Spawns a Deadshot Daiquiri machine and validates its
@@ -195,6 +252,8 @@ void() Test_Perks_MuleKick_ValidateFields =
195252
remove(machine);
196253
};
197254

255+
// MARK: Random Perk
256+
198257
//
199258
// Test_Perks_Random_LegacyFields()
200259
// Attempts to spawn a random Perk-A-Cola
@@ -212,4 +271,20 @@ void() Test_Perks_Random_LegacyFields =
212271
self = old_self;
213272

214273
remove(random);
274+
};
275+
276+
// MARK: Misc.
277+
278+
//
279+
// Test_Perks_Drink_WorkOnReset()
280+
// Verifies that drinking a Perk and then
281+
// triggering a Soft_Restart does not
282+
// prevent purchase of additional Perks.
283+
// (https://github.com/nzp-team/nzportable/issues/1126)
284+
//
285+
void() Test_Perks_Drink_WorkOnReset =
286+
{
287+
self.isBuying = true;
288+
Soft_Restart();
289+
Test_Assert((self.isBuying == false), "isBuying state not reset!");
215290
};

source/server/tests/test_power.qc

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
server/tests/test_power.qc
3+
4+
Unit tests for the Power Switch
5+
6+
Copyright (C) 2021-2025 NZ:P Team
7+
8+
This program is free software; you can redistribute it and/or
9+
modify it under the terms of the GNU General Public License
10+
as published by the Free Software Foundation; either version 2
11+
of the License, or (at your option) any later version.
12+
13+
This program is distributed in the hope that it will be useful,
14+
but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16+
17+
See the GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with this program; if not, write to:
21+
22+
Free Software Foundation, Inc.
23+
59 Temple Place - Suite 330
24+
Boston, MA 02111-1307, USA
25+
26+
*/
27+
float(float condition, string message) Test_Assert;
28+
void(string message) Test_Skip;
29+
30+
//
31+
// Test_Power_HandleResetOnRestart()
32+
// Turns on the Power and validates the
33+
// Power Switch handle's angles are reset
34+
// on Soft_Restart.
35+
// (https://github.com/nzp-team/nzportable/issues/1125)
36+
//
37+
void() Test_Power_HandleResetOnRestart =
38+
{
39+
entity power_switch = find(world, classname, "power_switch");
40+
41+
Test_Assert((power_switch.boxweapon.angles == power_switch.angles), "Power Switch handle angles are not correct at start of test!");
42+
43+
// Simulated switch flip
44+
power_switch.boxweapon.angles_x += 180;
45+
46+
Soft_Restart();
47+
48+
Test_Assert((power_switch.boxweapon.angles == power_switch.angles), "Power Switch handle angles are not correct at end of test!");
49+
};

source/server/utilities/game_restart.qc

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ void() GameRestart_ResetMysteryBox =
171171
// Check if there is a Mystery Box in the map
172172
entity mystery_box = find(world, classname, "mystery");
173173

174+
if (mystery_box.boxstatus == 0 && mystery_box.frame == 0 && mystery_box.spins == 0)
175+
return;
176+
174177
if (mystery_box != world) {
175178
mystery_box.boxstatus = 0;
176179
mystery_box.frame = 0;
@@ -284,6 +287,25 @@ void() GameRestart_OpenClosedDoors =
284287
}
285288
}
286289

290+
//
291+
// GameRestart_ResetPower()
292+
// Turns off Power and resets Power Switch state.
293+
//
294+
void() GameRestart_ResetPower =
295+
{
296+
entity power_switch;
297+
power_switch = find(world, classname, "power_switch");
298+
299+
if (power_switch) {
300+
isPowerOn = false;
301+
power_switch.frame = 0;
302+
303+
if (!(power_switch.spawnflags & 1)) {
304+
power_switch.boxweapon.angles = power_switch.angles;
305+
}
306+
}
307+
};
308+
287309
void() Soft_Restart = {
288310
entity who, oldself, endgame;
289311
self = find(world,classname,"player");
@@ -320,6 +342,7 @@ void() Soft_Restart = {
320342
GameRestart_ResetMysteryBox(); // Clean up the Mystery Box, delete floating weapon, etc.
321343
GameRestart_RestoreFakeRemovals(); // Puts back everything "removed" using Ent_FakeRemove().
322344
GameRestart_OpenClosedDoors(); // Restores doors that were previously opened in last session.
345+
GameRestart_ResetPower(); // Turns off Power and resets Power Switch state.
323346

324347
//reset buyable ending
325348
endgame = find(world, classname, "func_ending");
@@ -339,18 +362,13 @@ void() Soft_Restart = {
339362
tp.think = SUB_Null;
340363
}
341364

342-
local entity power;
343-
power = find(world, classname, "power_switch");
344-
if(power) {
345-
isPowerOn = false;
346-
power.frame = 0;
347-
}
348-
349365
self = oldself;
350366
self.downed = 0;
351367
self.progress_bar = 0;
352368
self.progress_bar_time = 0;
353369
self.progress_bar_percent = 0;
370+
self.isBuying = false;
371+
self.style = 0;
354372
in_endgame_sequence = false;
355373
rounds = 0;
356374
self.score = 0;
@@ -365,6 +383,8 @@ void() Soft_Restart = {
365383
self.grenades = 1;
366384
self.pri_grenade_state = 0;
367385

386+
player_count = 0;
387+
368388
InitRounds();
369389
PutClientInServer();
370390

0 commit comments

Comments
 (0)