2022-02-08 18:42:28 +00:00
|
|
|
/*
|
2022-12-16 18:53:17 +00:00
|
|
|
server/player.qc
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
Various stuff done for the player, including per-frame functions
|
|
|
|
like PlayerPreThink and PlayerPostThink, also client specific
|
|
|
|
stuff like PutClientInServer etc.
|
|
|
|
|
2022-12-16 17:49:38 +00:00
|
|
|
Copyright (C) 2021-2022 NZ:P Team
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
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(entity e) Light_None;
|
|
|
|
|
2023-03-10 16:47:42 +00:00
|
|
|
#define PLAYER_START_HEALTH 100
|
|
|
|
|
2022-12-27 21:23:17 +00:00
|
|
|
//
|
|
|
|
// Player 3rd Person Animations
|
|
|
|
//
|
|
|
|
|
|
|
|
// Enter Last Stand
|
|
|
|
void() PAnim_GetDown1 =[ 1, PAnim_GetDown2 ] {self.frame = 32;};
|
|
|
|
void() PAnim_GetDown2 =[ 1, PAnim_GetDown3 ] {self.frame = 33;};
|
|
|
|
void() PAnim_GetDown3 =[ 1, PAnim_GetDown4 ] {self.frame = 34;};
|
|
|
|
void() PAnim_GetDown4 =[ 1, PAnim_GetDown5 ] {self.frame = 35;};
|
|
|
|
void() PAnim_GetDown5 =[ 1, PAnim_GetDown6 ] {self.frame = 36;};
|
|
|
|
void() PAnim_GetDown6 =[ 1, PAnim_GetDown6 ] {self.frame = 37;};
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
//
|
|
|
|
void() playreload =[ 1, playreload1 ] {self.frame = 11;}
|
|
|
|
void() playreload1 =[ 2, playreload2 ] {self.frame = 12;}
|
|
|
|
void() playreload2 =[ 3, playreload3 ] {self.frame = 13;}
|
|
|
|
void() playreload3 =[ 4, playreload4 ] {self.frame = 14;}
|
|
|
|
void() playreload4 =[ 5, playreload5 ] {self.frame = 15;}
|
|
|
|
void() playreload5 =[ 6, playreload6 ] {self.frame = 16;}
|
|
|
|
void() playreload6 =[ 7, playreload7 ] {self.frame = 17;}
|
|
|
|
void() playreload7 =[ 8, playreload8 ] {self.frame = 18;}
|
|
|
|
void() playreload8 =[ 9, playreload9 ] {self.frame = 19;}
|
|
|
|
void() playreload9 =[ 10, playreload10 ] {self.frame = 20;}
|
|
|
|
void() playreload10 =[ 11, playreload11 ] {self.frame = 21;}
|
|
|
|
void() playreload11 =[ 12, playreload12 ] {self.frame = 22;}
|
|
|
|
void() playreload12 =[ 13, playreload13 ] {self.frame = 23;}
|
|
|
|
void() playreload13 =[ 14, playreload13 ] {self.frame = 24;}
|
|
|
|
//
|
|
|
|
void() playdownfire =[ 1, playdownfire1 ] {self.frame = 38;}
|
|
|
|
void() playdownfire1 =[ 2, playdownfire1 ] {self.frame = 39;}
|
|
|
|
//
|
|
|
|
void() playaim =[ 1, playaim1 ] {self.frame = 8;} // naievil -- player aimin anim
|
|
|
|
void() playaim1 =[ 2, playaim1 ] {self.frame = 9;} // naievil -- second player aimin anim
|
|
|
|
//
|
|
|
|
void() playout =[ 1, playout1 ] {self.frame = 10;} // naievil -- player aim out anim
|
|
|
|
void() playout1 =[ 2, playout1 ] {self.frame = 11;} // naievil -- second player aim out anim
|
|
|
|
//
|
|
|
|
void() playrun1 =[ 1, playrun2 ] {self.frame = 25;}
|
|
|
|
void() playrun2 =[ 2, playrun3 ] {self.frame = 26;}
|
|
|
|
void() playrun3 =[ 3, playrun4 ] {self.frame = 27;}
|
|
|
|
void() playrun4 =[ 4, playrun5 ] {self.frame = 28;}
|
|
|
|
void() playrun5 =[ 5, playrun6 ] {self.frame = 29;}
|
|
|
|
void() playrun6 =[ 6, playrun7 ] {self.frame = 30;}
|
|
|
|
void() playrun7 =[ 7, playrun8 ] {self.frame = 31;}
|
|
|
|
void() playrun8 =[ 8, playrun9 ] {self.frame = 25;}
|
|
|
|
void() playrun9 =[ 9, playrun10 ] {self.frame = 26;}
|
|
|
|
void() playrun10 =[ 10, playrun11 ] {self.frame = 27;}
|
|
|
|
void() playrun11 =[ 11, playrun12 ] {self.frame = 28;}
|
|
|
|
void() playrun12 =[ 12, playrun13 ] {self.frame = 29;}
|
|
|
|
void() playrun13 =[ 13, playrun14 ] {self.frame = 30;}
|
|
|
|
void() playrun14 =[ 14, playrun15 ] {self.frame = 25;}
|
|
|
|
void() playrun15 =[ 15, playrun16 ] {self.frame = 26;}
|
|
|
|
void() playrun16 =[ 16, playrun17 ] {self.frame = 27;}
|
|
|
|
void() playrun17 =[ 17, playrun18 ] {self.frame = 28;}
|
|
|
|
void() playrun18 =[ 18, playrun19 ] {self.frame = 29;}
|
|
|
|
void() playrun19 =[ 19, playrun20 ] {self.frame = 30;}
|
|
|
|
void() playrun20 =[ 20, playrun21 ] {self.frame = 31;}
|
|
|
|
void() playrun21 =[ 21, playrun22 ] {self.frame = 25;}
|
|
|
|
void() playrun22 =[ 22, playrun23 ] {self.frame = 26;}
|
|
|
|
void() playrun23 =[ 23, playrun24 ] {self.frame = 27;}
|
|
|
|
void() playrun24 =[ 24, playrun25 ] {self.frame = 28;}
|
|
|
|
void() playrun25 =[ 25, playrun26 ] {self.frame = 29;}
|
|
|
|
void() playrun26 =[ 26, playrun27 ] {self.frame = 30;}
|
|
|
|
void() playrun27 =[ 27, playrun28 ] {self.frame = 25;}
|
|
|
|
void() playrun28 =[ 28, playrun29 ] {self.frame = 26;}
|
|
|
|
void() playrun29 =[ 29, playrun30 ] {self.frame = 27;}
|
|
|
|
void() playrun30 =[ 30, playrun31 ] {self.frame = 28;}
|
|
|
|
void() playrun31 =[ 31, playrun32 ] {self.frame = 29;}
|
|
|
|
void() playrun32 =[ 32, playrun33 ] {self.frame = 30;}
|
|
|
|
void() playrun33 =[ 33, playrun33 ] {self.frame = 31;}
|
|
|
|
//
|
|
|
|
void() playwalk =[ 1, playwalk1 ] {if (self.velocity) { self.frame = 0; }}
|
|
|
|
void() playwalk1 =[ 2, playwalk2 ] {if (self.velocity) { self.frame = 1; }}
|
|
|
|
void() playwalk2 =[ 3, playwalk3 ] {if (self.velocity) { self.frame = 2; }}
|
|
|
|
void() playwalk3 =[ 4, playwalk4 ] {if (self.velocity) { self.frame = 3; }}
|
|
|
|
void() playwalk4 =[ 5, playwalk5 ] {if (self.velocity) { self.frame = 4; }}
|
|
|
|
void() playwalk5 =[ 6, playwalk6 ] {if (self.velocity) { self.frame = 5; }}
|
|
|
|
void() playwalk6 =[ 7, playwalk7 ] {if (self.velocity) { self.frame = 6; }}
|
|
|
|
void() playwalk7 =[ 8, playwalk8 ] {if (self.velocity) { self.frame = 7; }}
|
|
|
|
void() playwalk8 =[ 9, playwalk8 ] {if (self.velocity) { self.frame = 8; }}
|
|
|
|
//
|
|
|
|
void() playgetup =[ 1, playgetup1 ] {self.frame = 38;}
|
|
|
|
void() playgetup1 =[ 2, playgetup2 ] {self.frame = 39;}
|
|
|
|
void() playgetup2 =[ 3, playgetup3 ] {self.frame = 40;}
|
|
|
|
void() playgetup3 =[ 4, playgetup4 ] {self.frame = 41;}
|
|
|
|
void() playgetup4 =[ 5, playgetup5 ] {self.frame = 42;}
|
|
|
|
void() playgetup5 =[ 6, playgetup6 ] {self.frame = 43;}
|
|
|
|
void() playgetup6 =[ 7, playgetup7 ] {self.frame = 44;}
|
|
|
|
void() playgetup7 =[ 8, playgetup8 ] {self.frame = 45;}
|
|
|
|
void() playgetup8 =[ 9, playgetup9 ] {self.frame = 46;}
|
|
|
|
void() playgetup9 =[ 10, playgetup10 ] {self.frame = 47;}
|
|
|
|
void() playgetup10 =[ 11, playgetup10 ] {self.frame = 48;}
|
|
|
|
|
|
|
|
#define forward 0
|
|
|
|
#define backward 1
|
|
|
|
#define left 2
|
|
|
|
#define right 3
|
|
|
|
#define all_move -1
|
2022-09-03 00:19:25 +00:00
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
float(float dir) checkMovement =
|
2023-02-09 03:23:17 +00:00
|
|
|
{
|
2022-02-08 18:42:28 +00:00
|
|
|
switch(dir) {
|
|
|
|
case forward:
|
2023-02-09 03:23:17 +00:00
|
|
|
if (self.movement_x > 0)
|
2022-02-08 18:42:28 +00:00
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case backward:
|
2023-02-09 03:23:17 +00:00
|
|
|
if (self.movement_x < 0)
|
2022-02-08 18:42:28 +00:00
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case right:
|
2023-02-09 03:23:17 +00:00
|
|
|
if (self.movement_y > 0)
|
2022-02-08 18:42:28 +00:00
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case left:
|
2023-02-09 03:23:17 +00:00
|
|
|
if (self.movement_y < 0)
|
2022-02-08 18:42:28 +00:00
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case all_move:
|
2023-02-09 03:23:17 +00:00
|
|
|
if (self.movement_x || self.movement_y)
|
2022-02-08 18:42:28 +00:00
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void() PlayerJump =
|
|
|
|
{
|
|
|
|
if (!(self.flags & FL_ONGROUND)
|
|
|
|
|| !(self.flags & FL_JUMPRELEASED)
|
|
|
|
|| self.downed
|
|
|
|
|| self.dive ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
|
|
|
|
sound(self, CHAN_VOICE, "sounds/player/jump.wav", 1, 1.75);
|
|
|
|
|
|
|
|
if (self.button2)
|
|
|
|
self.button2 = 0;
|
|
|
|
|
|
|
|
self.oldz = self.origin_z;
|
|
|
|
|
|
|
|
self.velocity_z = 230;
|
|
|
|
}
|
|
|
|
|
|
|
|
void(float override) JumpCheck =
|
|
|
|
{
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#ifndef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
override = 0;
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
if(self.button2 || override) {
|
|
|
|
if (self.downed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (self.stance == 2) {
|
|
|
|
// naievil -- stop sprinting if we jump, which is a real mechanic from the game that we never implemented
|
|
|
|
if (self.sprinting) {
|
|
|
|
W_SprintStop();
|
|
|
|
}
|
|
|
|
PlayerJump();
|
|
|
|
} else if (self.view_ofs_z == self.new_ofs_z && (self.flags & FL_ONGROUND)) {
|
|
|
|
switch(self.stance) {
|
|
|
|
case 0:
|
|
|
|
self.new_ofs_z = self.view_ofs_z + 42;
|
|
|
|
self.stance = 2;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
self.new_ofs_z = self.view_ofs_z + 24;
|
|
|
|
self.stance = 2;
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
self.flags = self.flags | FL_JUMPRELEASED;
|
|
|
|
}
|
|
|
|
|
2022-09-03 00:19:25 +00:00
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
void() PlayerPreThink =
|
|
|
|
{
|
|
|
|
if (self.downed) {
|
|
|
|
self.maxspeed = 30;
|
|
|
|
} else {
|
2023-03-09 01:03:35 +00:00
|
|
|
self.maxspeed = 190;
|
2022-02-08 18:42:28 +00:00
|
|
|
if (self.sprinting) {
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#ifdef FTE
|
|
|
|
|
2023-03-06 18:56:59 +00:00
|
|
|
if (self.viewzoom > 0.97)
|
2022-02-08 18:42:28 +00:00
|
|
|
self.viewzoom -= 0.015;
|
2023-03-06 18:56:59 +00:00
|
|
|
else if (self.viewzoom < 0.97)
|
|
|
|
self.viewzoom = 0.97;
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
// viewbob when running
|
2023-03-06 19:15:10 +00:00
|
|
|
self.punchangle_y = 0.6*sin(time*10);
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
playrun1();
|
2023-03-09 01:03:35 +00:00
|
|
|
self.maxspeed *= 1.5; // down from 1.66x, to match WaW
|
2022-02-08 18:42:28 +00:00
|
|
|
} else if (!self.sprinting && !self.zoom) {
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#ifdef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
if (self.viewzoom < 1)
|
|
|
|
self.viewzoom += 0.015;
|
|
|
|
else
|
|
|
|
self.viewzoom = 1;
|
|
|
|
|
|
|
|
if (checkMovement(-1))
|
2023-02-05 21:03:57 +00:00
|
|
|
self.punchangle_x = 0.25*sin(time*15);
|
|
|
|
|
|
|
|
#endif // FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
} else if (self.zoom != 3) {
|
|
|
|
self.maxspeed *= 0.5;
|
2022-04-06 01:46:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Speed Penalty
|
|
|
|
if (self.speed_penalty_time > time)
|
|
|
|
{
|
|
|
|
self.maxspeed *= self.speed_penalty;
|
|
|
|
} else {
|
|
|
|
self.speed_penalty = 1;
|
2022-02-08 18:42:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch(self.stance) {
|
|
|
|
case 1:
|
|
|
|
self.maxspeed *= 0.5;
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
self.maxspeed *= 0.25;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#ifdef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
if (checkMovement(backward)) {
|
|
|
|
self.maxspeed *= 0.7;
|
|
|
|
} else if (checkMovement(left) || checkMovement(right)) {
|
|
|
|
self.maxspeed *= 0.8;
|
|
|
|
}
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
self.maxspeed *= GetWeaponWalkSpeed(self.perks, self.weapon);
|
|
|
|
}
|
|
|
|
if(self.isspec != 0 && !self.downed)
|
|
|
|
{
|
|
|
|
if(self.button0)
|
|
|
|
{
|
|
|
|
self.aiment = find(self.aiment, classname, "player");
|
|
|
|
if(self.aiment != world)
|
|
|
|
{
|
|
|
|
sprint(self, PRINT_HIGH, "Now spectating ");
|
|
|
|
sprint(self, PRINT_HIGH, self.aiment.netname);
|
|
|
|
sprint(self, PRINT_HIGH, "\n");
|
|
|
|
|
|
|
|
self.solid = SOLID_NOT;
|
|
|
|
self.movetype = MOVETYPE_NONE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprint(self, PRINT_HIGH, "Freefly spectate\n");
|
|
|
|
self.movetype = MOVETYPE_FLY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(self.aiment != world)
|
|
|
|
{
|
|
|
|
self.origin = self.aiment.origin;
|
|
|
|
self.angles = self.aiment.v_angle;
|
|
|
|
self.velocity = self.aiment.velocity;
|
|
|
|
self.fixangle = TRUE;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cvar("waypoint_mode")) {
|
|
|
|
Waypoint_Logic();
|
|
|
|
} else {
|
|
|
|
Weapon_Logic();
|
|
|
|
}
|
|
|
|
|
|
|
|
JumpCheck(0);
|
|
|
|
|
|
|
|
// refuel/cool m2
|
|
|
|
if (self.ltime < time) {
|
|
|
|
if (self.currentmag == 0 && !self.cooldown) {
|
|
|
|
self.cooldown = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.cooldown && self.currentmag > 20)
|
|
|
|
self.cooldown = false;
|
|
|
|
|
|
|
|
if (self.weapon == W_M2 || self.weapon == W_FIW && self.currentmag < getWeaponMag(self.weapon))
|
|
|
|
self.currentmag += 1;
|
|
|
|
|
|
|
|
self.ltime = time + 0.1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
float player_trace_time;
|
2022-02-08 18:42:28 +00:00
|
|
|
void() PlayerPostThink =
|
|
|
|
{
|
|
|
|
if(self.isspec)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//landsound
|
|
|
|
if((self.oldvelocity_z < -10) && (self.flags & FL_ONGROUND))
|
|
|
|
{
|
|
|
|
if(self.oldvelocity_z < -270)
|
|
|
|
sound(self, CHAN_BODY, "sounds/player/land.wav", 1, 1.75);
|
|
|
|
self.lastsound_time = time - 0.15;
|
|
|
|
}
|
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#ifdef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
//footsteps
|
|
|
|
if((vlen(self.velocity) > 100) &&(( time - self.lastsound_time > 0.4) || (time - self.lastsound_time > 0.3 && self.sprinting)) && (self.flags & FL_ONGROUND))
|
|
|
|
{
|
|
|
|
local float movelen = vlen(input_movevalues);
|
|
|
|
if(movelen > 300)
|
|
|
|
{
|
|
|
|
if (!self.sprinting)
|
|
|
|
playwalk();
|
|
|
|
|
|
|
|
local float ran = random();
|
|
|
|
if(ran > 0.8)
|
|
|
|
sound(self, CHAN_BODY, "sounds/player/footstep1.wav", 0.8, 2.5);
|
|
|
|
else if(ran > 0.6)
|
|
|
|
sound(self, CHAN_BODY, "sounds/player/footstep2.wav", 0.8, 2.5);
|
|
|
|
else if(ran > 0.4)
|
|
|
|
sound(self, CHAN_BODY, "sounds/player/footstep3.wav", 0.8, 2.5);
|
|
|
|
else if(ran > 0.2)
|
|
|
|
sound(self, CHAN_BODY, "sounds/player/footstep4.wav", 0.8, 2.5);
|
|
|
|
else
|
|
|
|
sound(self, CHAN_BODY, "sounds/player/footstep5.wav", 0.8, 2.5);
|
|
|
|
self.lastsound_time = time;
|
|
|
|
}
|
|
|
|
}
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
2022-02-08 18:42:28 +00:00
|
|
|
|
2023-03-10 17:20:43 +00:00
|
|
|
// Health Regeneration
|
2022-02-08 18:42:28 +00:00
|
|
|
if (self.health_delay < time && self.health != self.max_health && !self.downed)
|
|
|
|
{
|
2023-03-10 17:20:43 +00:00
|
|
|
// If we weren't super low on health, regen is instant.
|
|
|
|
if (self.health_was_very_low == true) {
|
|
|
|
self.health += 120 * frametime;
|
|
|
|
} else {
|
2023-03-10 17:24:19 +00:00
|
|
|
// Was 100% instant, but this delays it by only a few
|
|
|
|
// frames so the graphic doesn't just vanish when healed.
|
|
|
|
self.health += 300 * frametime;
|
2023-03-10 17:20:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we mark that we weren't just super hurt anymore.
|
|
|
|
if (self.max_health <= self.health) {
|
|
|
|
self.health = self.max_health;
|
|
|
|
self.health_was_very_low = false;
|
|
|
|
}
|
2022-02-08 18:42:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (self.progress_bar) {
|
|
|
|
if (self.progress_bar < time) {
|
|
|
|
if (self.downed)
|
|
|
|
GetUp();
|
|
|
|
|
|
|
|
if (self.reviving)
|
|
|
|
self.revived = 1;
|
|
|
|
|
|
|
|
self.progress_bar = 0;
|
|
|
|
self.progress_bar_time = 0;
|
|
|
|
self.progress_bar_percent = 0;
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
float remaining = self.progress_bar - time;
|
|
|
|
self.progress_bar_percent = invertfloat((remaining / self.progress_bar_time));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.sprinting) {
|
|
|
|
self.sprint_timer = self.sprint_duration + (time - self.sprint_start_time);
|
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#ifndef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
if (!self.velocity || self.stance != 2) {
|
|
|
|
W_SprintStop();
|
|
|
|
}
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
if (!self.velocity || !checkMovement(0) || self.stance != 2) { //moto (FIXME) -- move me!
|
|
|
|
W_SprintStop();
|
|
|
|
}
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
if (self.perks & P_STAMIN) {
|
|
|
|
if (self.sprint_timer > sprint_max_time * 2) {
|
|
|
|
W_SprintStop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (self.sprint_timer > sprint_max_time) {
|
|
|
|
W_SprintStop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (self.sprint_duration > 0.0) {
|
|
|
|
self.sprint_rest_time = (time - self.sprint_stop_time);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.oldvelocity = self.velocity;
|
|
|
|
|
|
|
|
// Perform a traceline to keep track of entities directly
|
|
|
|
// in front of the player.
|
2023-02-09 03:49:38 +00:00
|
|
|
// Also don't do it every frame because that's really tough
|
|
|
|
// on perf.
|
|
|
|
if (player_trace_time < time) {
|
|
|
|
vector source;
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
makevectors (self.v_angle);
|
|
|
|
source = self.origin + self.view_ofs;
|
2022-02-08 18:42:28 +00:00
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#ifdef FTE
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
self.dimension_hit = HITBOX_DIM_LIMBS | HITBOX_DIM_ZOMBIES;
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#endif // FTE
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
traceline (source, source + v_forward*800*1.2, 0, self);
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#ifdef FTE
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
self.dimension_hit = HITBOX_DIM_ZOMBIES;
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#endif // FTE
|
2023-01-16 08:37:30 +00:00
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
// use .head here to avoid expanding ent struct
|
|
|
|
self.head = trace_ent;
|
2022-02-08 18:42:28 +00:00
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
// check whether we're looking at an entity separately to communicate
|
|
|
|
// with the client more reasonably
|
|
|
|
if (trace_ent.classname == "ai_zombie" || trace_ent.classname == "ai_zombie_head"
|
|
|
|
|| trace_ent.classname == "ai_zombie_rarm" ||trace_ent.classname == "ai_zombie_larm"
|
|
|
|
|| trace_ent.classname == "ai_dog")
|
|
|
|
self.facingenemy = true;
|
|
|
|
else
|
|
|
|
self.facingenemy = false;
|
2023-01-17 23:47:31 +00:00
|
|
|
|
2023-02-09 03:49:38 +00:00
|
|
|
// 1/4 of a second is enough of a delay to not kill the effect.
|
|
|
|
player_trace_time = time + 0.25;
|
|
|
|
}
|
2022-02-08 18:42:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void() ClientKill = {};
|
|
|
|
|
|
|
|
//called when a client connects to the server
|
|
|
|
void() ClientConnect =
|
2023-02-07 07:32:14 +00:00
|
|
|
{
|
2022-02-08 18:42:28 +00:00
|
|
|
if(cvar("developer") || player_count > 1) {
|
|
|
|
bprint(PRINT_HIGH, self.netname); //print player name
|
|
|
|
bprint(PRINT_HIGH, " connected.\n");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void() PollPlayerPoints =
|
|
|
|
{
|
|
|
|
float i, breakpoint;
|
|
|
|
entity pollent;
|
|
|
|
breakpoint = 0;
|
|
|
|
|
|
|
|
for (i = 1; i <= 4 && !breakpoint; i++)
|
|
|
|
{
|
|
|
|
pollent = findfloat(world, playernum, i);
|
|
|
|
|
|
|
|
if (pollent == world) {
|
|
|
|
breakpoint = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
UpdatePlayerPoints(i, pollent.points, pollent.kills, 0, pollent.netname, pollent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void() PlayerSpawn =
|
|
|
|
{
|
2023-01-17 17:15:50 +00:00
|
|
|
entity spawnpoint = world;
|
2022-02-08 18:42:28 +00:00
|
|
|
local_client = self;
|
2023-01-13 16:42:27 +00:00
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
self.isspec = FALSE;
|
|
|
|
self.classname = "player";
|
|
|
|
self.solid = SOLID_BBOX;
|
2023-02-05 21:03:57 +00:00
|
|
|
|
2023-01-15 18:10:25 +00:00
|
|
|
// We can only collide with zombies (and not their limbs)
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#ifdef FTE
|
|
|
|
|
2023-01-15 18:10:25 +00:00
|
|
|
self.dimension_hit = HITBOX_DIM_ZOMBIES;
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
setmodel(self, "models/player.mdl");
|
|
|
|
self.movetype = MOVETYPE_WALK;
|
2023-03-10 16:47:42 +00:00
|
|
|
self.max_health = self.health = PLAYER_START_HEALTH;
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
entity who = find(world,classname,"player");
|
|
|
|
while(who != self && !self.playernum)
|
|
|
|
{
|
|
|
|
if(who)
|
|
|
|
{
|
|
|
|
coop = 1;
|
|
|
|
player_count++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-13 16:42:27 +00:00
|
|
|
if (!self.playernum) {
|
|
|
|
self.playernum = player_count + 1;
|
|
|
|
if (self.playernum == 1)
|
|
|
|
pl1 = self;
|
2022-02-08 18:42:28 +00:00
|
|
|
}
|
2023-01-13 16:42:27 +00:00
|
|
|
|
2023-01-31 21:12:06 +00:00
|
|
|
float viable_spawnpoint = false;
|
|
|
|
|
|
|
|
// if the mapper doesn't have the co-op ents set up, just plop everyone at the
|
|
|
|
// normal start.
|
|
|
|
if (find(world, classname, "info_player_tank") == world &&
|
|
|
|
find(world, classname, "info_player_nikolai") == world &&
|
|
|
|
find(world, classname, "info_player_takeo") == world &&
|
|
|
|
find(world, classname, "info_player_doctor") == world) {
|
|
|
|
spawnpoint = find(world, classname, "info_player_start");
|
|
|
|
viable_spawnpoint = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// pick a random spawn point regardless of solo or co-op
|
|
|
|
//
|
|
|
|
|
|
|
|
while(!viable_spawnpoint) {
|
2023-01-13 16:42:27 +00:00
|
|
|
float number = random();
|
|
|
|
|
2023-01-31 21:12:06 +00:00
|
|
|
// assign one of the spawnpoints
|
2023-01-13 16:42:27 +00:00
|
|
|
if (number < 0.25)
|
|
|
|
spawnpoint = find(world, classname, "info_player_tank");
|
|
|
|
else if (number < 0.50)
|
|
|
|
spawnpoint = find(world, classname, "info_player_nikolai");
|
|
|
|
else if (number < 0.75)
|
|
|
|
spawnpoint = find(world, classname, "info_player_takeo");
|
|
|
|
else
|
|
|
|
spawnpoint = find(world, classname, "info_player_doctor");
|
2023-01-31 21:12:06 +00:00
|
|
|
|
|
|
|
float found_player_here = false;
|
|
|
|
|
|
|
|
entity ents_in_spawn_range = findradius(spawnpoint.origin, 32);
|
|
|
|
|
|
|
|
// check if there's a player in the way
|
|
|
|
while(ents_in_spawn_range != world) {
|
|
|
|
if (ents_in_spawn_range.classname == "player")
|
|
|
|
found_player_here = true;
|
|
|
|
|
|
|
|
ents_in_spawn_range = ents_in_spawn_range.chain;
|
2023-01-13 16:42:27 +00:00
|
|
|
}
|
2023-01-31 21:12:06 +00:00
|
|
|
|
|
|
|
// no player in the way, this spawn is good.
|
|
|
|
if (found_player_here == false)
|
|
|
|
viable_spawnpoint = true;
|
2022-02-08 18:42:28 +00:00
|
|
|
}
|
2023-01-13 16:42:27 +00:00
|
|
|
|
2023-01-31 21:12:06 +00:00
|
|
|
// Mapper doesn't have our specific co-op spawn set up..
|
2023-01-17 17:15:50 +00:00
|
|
|
if (spawnpoint == world)
|
2023-01-13 16:42:27 +00:00
|
|
|
spawnpoint = find(world, classname, "info_player_start");
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
self.origin = spawnpoint.origin + [0,0,1];
|
|
|
|
self.angles = spawnpoint.angles;
|
|
|
|
self.fixangle = TRUE;
|
|
|
|
setsize(self, [-16, -16, -32], [16, 16, 40]);
|
|
|
|
self.view_ofs = VEC_VIEW_OFS; // naievil -- set view_ofs to 32 to maintain half life (64) sizes
|
|
|
|
self.stance = 2;
|
|
|
|
self.new_ofs_z = self.view_ofs_z;
|
|
|
|
self.oldz = self.origin_z;
|
|
|
|
|
|
|
|
self.currentammo = G_STARTWEAPON[2];
|
|
|
|
self.currentmag = G_STARTWEAPON[1];
|
|
|
|
self.weapon = G_STARTWEAPON[0];
|
|
|
|
self.grenades = self.grenades | 1; // add frag grenades to player inventory
|
|
|
|
|
|
|
|
if (rounds)
|
|
|
|
self.primary_grenades = 2;
|
|
|
|
else
|
|
|
|
self.primary_grenades = 0; // start off without grenades
|
|
|
|
|
|
|
|
self.pri_grenade_state = 0; // defines that frag grenades are for player first, not betty
|
|
|
|
self.secondary_grenades = -1; // shows that we both don't have betties AND shouldn't draw the image onscreen
|
|
|
|
|
|
|
|
if (!self.points)
|
|
|
|
addmoney(self, G_STARTPOINTS, 0);
|
|
|
|
|
|
|
|
self.weaponmodel = GetWeaponModel(self.weapon, 0);// Give weapon model
|
|
|
|
self.weapon2model = GetWeapon2Model(self.weapon);
|
|
|
|
|
|
|
|
SwitchWeapon(self.weapon);
|
|
|
|
|
|
|
|
self.stamina = 3;
|
|
|
|
self.reviving = 0;
|
|
|
|
self.weaponnum = 0;
|
|
|
|
self.perks = G_PERKS;
|
|
|
|
SetPerk(self, self.perks);
|
|
|
|
|
|
|
|
//self.zoom = 1; // This is to fix an aimin bug for the kar scope
|
|
|
|
|
2023-01-11 15:24:04 +00:00
|
|
|
if (rounds < 1 && player_count == 0) {
|
2022-02-08 18:42:28 +00:00
|
|
|
sound(self, CHAN_AUTO, "sounds/rounds/splash.wav", 1, ATTN_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
PromptLevelChange(self.nextthink + 3, 1, self);
|
|
|
|
UpdatePlayerCount(player_count);
|
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#ifdef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
PollPlayerPoints();
|
|
|
|
UpdateV2model("", 0);
|
|
|
|
stuffcmd(self, "cl_gunx 8;cl_guny 16;cl_gunz 25\n");
|
|
|
|
SetRound(self, G_STARTROUND);
|
|
|
|
self.viewzoom = 1;
|
|
|
|
self.weapon_animduration = getWeaponDelay(self.weapon, FIRE);
|
|
|
|
|
|
|
|
if (G_WORLDTEXT)
|
|
|
|
WorldText(world.chaptertitle, world.location, world.date, world.person, self);
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
self.Weapon_Name = GetWeaponName(self.weapon);
|
|
|
|
self.Flash_Offset = GetWeaponFlash_Offset(self.weapon);
|
|
|
|
self.Flash_Size = GetWeaponFlash_Size(self.weapon);
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
2022-02-08 18:42:28 +00:00
|
|
|
|
|
|
|
if (G_STARTROUND != 1) {
|
|
|
|
rounds = G_STARTROUND - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void() SpectatorSpawn =
|
|
|
|
{
|
|
|
|
local entity spawnpoint;
|
|
|
|
spawnpoint = find(world, classname, "info_player_start");
|
|
|
|
|
|
|
|
self.isspec = TRUE;
|
2023-01-13 16:46:14 +00:00
|
|
|
self.health = 420;
|
2022-02-08 18:42:28 +00:00
|
|
|
self.classname = "spectator";
|
|
|
|
self.solid = SOLID_NOT;
|
|
|
|
setmodel(self, "");
|
|
|
|
self.movetype = MOVETYPE_FLY;
|
|
|
|
self.origin = spawnpoint.origin + [0,0,1];
|
|
|
|
self.fixangle = TRUE;
|
|
|
|
setsize(self, [-16, -16, -24], [16, 16, 32]);
|
|
|
|
self.view_ofs = '0 0 22';
|
|
|
|
self.aiment = world;
|
|
|
|
};
|
|
|
|
|
|
|
|
//called when a client loads a map
|
|
|
|
void() PutClientInServer =
|
|
|
|
{
|
|
|
|
if(cvar("developer") || player_count > 1) {
|
|
|
|
bprint(PRINT_HIGH, self.netname);
|
|
|
|
bprint(PRINT_HIGH, " has joined the game.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spawn_time > time || !rounds)
|
|
|
|
PlayerSpawn();
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#ifdef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
else
|
|
|
|
SpectatorSpawn();
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//called when client disconnects from the server
|
|
|
|
void() ClientDisconnect =
|
|
|
|
{
|
|
|
|
bprint(PRINT_HIGH, self.netname);
|
|
|
|
bprint(PRINT_HIGH, " has left the game.\n");
|
|
|
|
player_count--;
|
|
|
|
UpdatePlayerCount(player_count);
|
2023-01-11 15:21:16 +00:00
|
|
|
|
|
|
|
self.classname = "disconnected";
|
|
|
|
self.solid = SOLID_NOT;
|
|
|
|
self.movetype = MOVETYPE_TOSS;
|
|
|
|
self.nextthink = -1;
|
|
|
|
setmodel(self, "models/sprites/null.spr");
|
2022-02-08 18:42:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void() SetNewParms =
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
void() SetChangeParms =
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
2023-02-05 21:03:57 +00:00
|
|
|
#ifdef FTE
|
|
|
|
|
2022-02-08 18:42:28 +00:00
|
|
|
void() SV_RunClientCommand =
|
|
|
|
{
|
|
|
|
runstandardplayerphysics(self);
|
|
|
|
}
|
2023-02-05 21:03:57 +00:00
|
|
|
|
|
|
|
#endif // FTE
|