mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2024-11-23 04:32:28 +00:00
Elder:
Code updates for VM 0-08-00 Server-side
This commit is contained in:
parent
3408381bf7
commit
f4cf1c8a3b
12 changed files with 373 additions and 156 deletions
|
@ -1345,6 +1345,7 @@ char *eventnames[] = {
|
||||||
"EV_BULLET_HIT_FLESH",
|
"EV_BULLET_HIT_FLESH",
|
||||||
"EV_BULLET_HIT_WALL",
|
"EV_BULLET_HIT_WALL",
|
||||||
"EV_SSG3000_HIT_FLESH", //Elder: SSG3000 blood spray
|
"EV_SSG3000_HIT_FLESH", //Elder: SSG3000 blood spray
|
||||||
|
"EV_JUMPKICK", //Elder: sound + jumpkick message
|
||||||
|
|
||||||
"EV_MISSILE_HIT",
|
"EV_MISSILE_HIT",
|
||||||
"EV_MISSILE_MISS",
|
"EV_MISSILE_MISS",
|
||||||
|
|
|
@ -1953,6 +1953,56 @@ static void PM_Weapon( void ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Elder: New 3rb Code
|
||||||
|
//force fire button down if STAT_BURST is < proper amount
|
||||||
|
//Otherwise release the button
|
||||||
|
if ( (pm->ps->weapon == WP_M4 &&
|
||||||
|
(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE) ||
|
||||||
|
(pm->ps->weapon == WP_MP5 &&
|
||||||
|
(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MP5MODE) == RQ3_MP5MODE))
|
||||||
|
{
|
||||||
|
int weaponNum = pm->ps->weapon;
|
||||||
|
|
||||||
|
if (pm->ps->ammo[weaponNum] == 0)
|
||||||
|
{
|
||||||
|
pm->ps->stats[STAT_BURST] = 0;
|
||||||
|
}
|
||||||
|
else if (pm->cmd.buttons & BUTTON_ATTACK)// && client->ps.stats[STAT_BURST] > 0)
|
||||||
|
{
|
||||||
|
if ( pm->ps->stats[STAT_BURST] >= 0 && pm->ps->stats[STAT_BURST] < 3)
|
||||||
|
pm->cmd.buttons |= BUTTON_ATTACK;
|
||||||
|
else
|
||||||
|
pm->cmd.buttons &= ~BUTTON_ATTACK;
|
||||||
|
}
|
||||||
|
else if (pm->ps->stats[STAT_BURST] > 2)
|
||||||
|
{
|
||||||
|
pm->ps->stats[STAT_BURST] = 0;
|
||||||
|
pm->ps->weaponTime += 300;
|
||||||
|
}
|
||||||
|
//Don't need?
|
||||||
|
else if (pm->ps->stats[STAT_BURST] > 0)
|
||||||
|
pm->cmd.buttons |= BUTTON_ATTACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Elder: New semi-auto code
|
||||||
|
if ( pm->ps->weapon == WP_PISTOL &&
|
||||||
|
(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE)
|
||||||
|
{
|
||||||
|
if (pm->ps->ammo[WP_PISTOL] == 0)
|
||||||
|
{
|
||||||
|
pm->ps->stats[STAT_BURST] = 0;
|
||||||
|
}
|
||||||
|
else if ((pm->cmd.buttons & BUTTON_ATTACK) && pm->ps->stats[STAT_BURST])
|
||||||
|
{
|
||||||
|
pm->cmd.buttons &= ~BUTTON_ATTACK;
|
||||||
|
}
|
||||||
|
else if (pm->ps->stats[STAT_BURST])
|
||||||
|
{
|
||||||
|
pm->ps->weaponTime += 200;
|
||||||
|
pm->ps->stats[STAT_BURST] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check for item using
|
// check for item using
|
||||||
// Elder: removed
|
// Elder: removed
|
||||||
/*
|
/*
|
||||||
|
@ -2083,7 +2133,6 @@ static void PM_Weapon( void ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ( ! (pm->cmd.buttons & BUTTON_ATTACK) ) {
|
if ( ! (pm->cmd.buttons & BUTTON_ATTACK) ) {
|
||||||
pm->ps->weaponTime = 0;
|
pm->ps->weaponTime = 0;
|
||||||
|
@ -2136,6 +2185,17 @@ static void PM_Weapon( void ) {
|
||||||
|
|
||||||
pm->ps->weaponstate = WEAPON_FIRING;
|
pm->ps->weaponstate = WEAPON_FIRING;
|
||||||
|
|
||||||
|
// Elder: increment stat if alt-fire mode --needs to be predicted as well
|
||||||
|
if ( (pm->ps->weapon == WP_M4 &&
|
||||||
|
(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE) ||
|
||||||
|
(pm->ps->weapon == WP_MP5 &&
|
||||||
|
(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MP5MODE) == RQ3_MP5MODE) ||
|
||||||
|
(pm->ps->weapon == WP_PISTOL &&
|
||||||
|
(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE))
|
||||||
|
{
|
||||||
|
pm->ps->stats[STAT_BURST]++;
|
||||||
|
}
|
||||||
|
|
||||||
//Elder: M4 kick code
|
//Elder: M4 kick code
|
||||||
//ent->client->ps.delta_angles[0] = ANGLE2SHORT(SHORT2ANGLE(ent->client->ps.delta_angles[0]) - 0.7);
|
//ent->client->ps.delta_angles[0] = ANGLE2SHORT(SHORT2ANGLE(ent->client->ps.delta_angles[0]) - 0.7);
|
||||||
if ( pm->ps->weapon == WP_M4 && ((pm->ps->persistant[PERS_WEAPONMODES] & RQ3_M4MODE) != RQ3_M4MODE) )
|
if ( pm->ps->weapon == WP_M4 && ((pm->ps->persistant[PERS_WEAPONMODES] & RQ3_M4MODE) != RQ3_M4MODE) )
|
||||||
|
|
|
@ -160,6 +160,7 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RQ3_SOUND_KICK,
|
RQ3_SOUND_KICK,
|
||||||
RQ3_SOUND_HEADSHOT,
|
RQ3_SOUND_HEADSHOT,
|
||||||
|
RQ3_SOUND_KNIFEHIT,
|
||||||
RQ3_SOUND_KNIFEDEATH,
|
RQ3_SOUND_KNIFEDEATH,
|
||||||
RQ3_SOUND_LCA, //lights, camera, action!
|
RQ3_SOUND_LCA, //lights, camera, action!
|
||||||
RQ3_SOUND_KEVLARHIT,
|
RQ3_SOUND_KEVLARHIT,
|
||||||
|
@ -710,6 +711,7 @@ typedef enum {
|
||||||
EV_BULLET_HIT_FLESH,
|
EV_BULLET_HIT_FLESH,
|
||||||
EV_BULLET_HIT_WALL,
|
EV_BULLET_HIT_WALL,
|
||||||
EV_SSG3000_HIT_FLESH,
|
EV_SSG3000_HIT_FLESH,
|
||||||
|
EV_JUMPKICK, // Elder: sound + jumpkick message
|
||||||
|
|
||||||
EV_MISSILE_HIT,
|
EV_MISSILE_HIT,
|
||||||
EV_MISSILE_MISS,
|
EV_MISSILE_MISS,
|
||||||
|
|
|
@ -128,6 +128,8 @@ void P_DamageFeedback( gentity_t *player ) {
|
||||||
//Elder: headshot sound
|
//Elder: headshot sound
|
||||||
case LOCATION_HEAD:
|
case LOCATION_HEAD:
|
||||||
case LOCATION_FACE:
|
case LOCATION_FACE:
|
||||||
|
if (client->lasthurt_mod == MOD_KNIFE || client->lasthurt_mod == MOD_KNIFE_THROWN)
|
||||||
|
G_AddEvent( player, EV_RQ3_SOUND, RQ3_SOUND_KNIFEDEATH);
|
||||||
//Elder: do nothing -- sound is handled in g_combat.c again
|
//Elder: do nothing -- sound is handled in g_combat.c again
|
||||||
//tent = G_TempEntity2(client->ps.origin, EV_RQ3_SOUND, RQ3_SOUND_HEADSHOT);
|
//tent = G_TempEntity2(client->ps.origin, EV_RQ3_SOUND, RQ3_SOUND_HEADSHOT);
|
||||||
//Elder: takes more bandwidth but guarantees a headshot sound
|
//Elder: takes more bandwidth but guarantees a headshot sound
|
||||||
|
@ -137,14 +139,6 @@ void P_DamageFeedback( gentity_t *player ) {
|
||||||
/*
|
/*
|
||||||
case LOCATION_CHEST:
|
case LOCATION_CHEST:
|
||||||
case LOCATION_SHOULDER:
|
case LOCATION_SHOULDER:
|
||||||
//Play metal impact if vest was hit
|
|
||||||
|
|
||||||
if (client->damage_vest == qtrue)
|
|
||||||
{
|
|
||||||
tent = G_TempEntity2(client->ps.origin, EV_RQ3_SOUND, RQ3_SOUND_KEVLARHIT);
|
|
||||||
client->damage_vest = qfalse;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
G_AddEvent( player, EV_PAIN, player->health );
|
G_AddEvent( player, EV_PAIN, player->health );
|
||||||
break;
|
break;
|
||||||
*/
|
*/
|
||||||
|
@ -853,10 +847,11 @@ void BotTestSolid(vec3_t origin);
|
||||||
ThrowWeapon
|
ThrowWeapon
|
||||||
|
|
||||||
XRAY FMJ
|
XRAY FMJ
|
||||||
|
Returns the number of the weapon thrown
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ThrowWeapon( gentity_t *ent )
|
int ThrowWeapon( gentity_t *ent, qboolean forceThrow )
|
||||||
{
|
{
|
||||||
gclient_t *client;
|
gclient_t *client;
|
||||||
usercmd_t *ucmd;
|
usercmd_t *ucmd;
|
||||||
|
@ -875,15 +870,16 @@ void ThrowWeapon( gentity_t *ent )
|
||||||
//Elder: TODO: have to add a reloading case:
|
//Elder: TODO: have to add a reloading case:
|
||||||
//weaponTime > 0 or weaponState == weapon_dropping? Or both?
|
//weaponTime > 0 or weaponState == weapon_dropping? Or both?
|
||||||
//Still firing
|
//Still firing
|
||||||
if ( (ucmd->buttons & BUTTON_ATTACK) == BUTTON_ATTACK || client->ps.weaponTime > 0) {
|
if (!forceThrow)
|
||||||
return;
|
if ( (ucmd->buttons & BUTTON_ATTACK) == BUTTON_ATTACK || client->ps.weaponTime > 0)
|
||||||
}
|
return 0;
|
||||||
//Elder: Bandaging case
|
|
||||||
|
//Elder: Bandaging case -- handled in cgame
|
||||||
//else if (client->isBandaging) {
|
//else if (client->isBandaging) {
|
||||||
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
|
//if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
|
||||||
trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging...\n\""));
|
//trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging...\n\""));
|
||||||
return;
|
//return;
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
weap = 0;
|
weap = 0;
|
||||||
|
@ -900,7 +896,9 @@ void ThrowWeapon( gentity_t *ent )
|
||||||
weap = WP_HANDCANNON;
|
weap = WP_HANDCANNON;
|
||||||
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000) ) == (1 << WP_SSG3000))
|
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000) ) == (1 << WP_SSG3000))
|
||||||
weap = WP_SSG3000;
|
weap = WP_SSG3000;
|
||||||
if (weap == 0 ) return;
|
if (weap == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
xr_item = BG_FindItemForWeapon( weap );
|
xr_item = BG_FindItemForWeapon( weap );
|
||||||
|
|
||||||
//Elder: Send a server command instead of force-setting
|
//Elder: Send a server command instead of force-setting
|
||||||
|
@ -915,6 +913,8 @@ void ThrowWeapon( gentity_t *ent )
|
||||||
xr_drop->count= -1; // XRAY FMJ 0 is already taken, -1 means no ammo
|
xr_drop->count= -1; // XRAY FMJ 0 is already taken, -1 means no ammo
|
||||||
client->uniqueWeapons--;
|
client->uniqueWeapons--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return weap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1123,9 +1123,11 @@ void ClientThink_real( gentity_t *ent ) {
|
||||||
ent->client->pers.cmd.buttons |= BUTTON_GESTURE;
|
ent->client->pers.cmd.buttons |= BUTTON_GESTURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//**************Elder: moved to bg_pmove.c (PM_Weapon)************//
|
||||||
//Elder: New 3rb Code
|
//Elder: New 3rb Code
|
||||||
//force fire button down if STAT_BURST is < proper amount
|
//force fire button down if STAT_BURST is < proper amount
|
||||||
//Otherwise release the button
|
//Otherwise release the button
|
||||||
|
/*
|
||||||
if ( (client->ps.weapon == WP_M4 &&
|
if ( (client->ps.weapon == WP_M4 &&
|
||||||
(client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE) ||
|
(client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE) ||
|
||||||
(client->ps.weapon == WP_MP5 &&
|
(client->ps.weapon == WP_MP5 &&
|
||||||
|
@ -1172,6 +1174,7 @@ void ClientThink_real( gentity_t *ent ) {
|
||||||
client->ps.stats[STAT_BURST] = 0;
|
client->ps.stats[STAT_BURST] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef MISSIONPACK
|
#ifdef MISSIONPACK
|
||||||
// check for invulnerability expansion before doing the Pmove
|
// check for invulnerability expansion before doing the Pmove
|
||||||
|
@ -1637,6 +1640,14 @@ void ClientEndFrame( gentity_t *ent ) {
|
||||||
ent->client->consecutiveShots = 0;
|
ent->client->consecutiveShots = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check to reset our openDoor boolean
|
||||||
|
if ( ent->client->openDoorTime &&
|
||||||
|
level.time - ent->client->openDoorTime > MAXDOORTIME )
|
||||||
|
{
|
||||||
|
ent->client->openDoor = qfalse;
|
||||||
|
ent->client->openDoorTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ( bg_itemlist[ent->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_LASER )
|
if ( bg_itemlist[ent->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_LASER )
|
||||||
{
|
{
|
||||||
//Try to turn the laser on if it's off
|
//Try to turn the laser on if it's off
|
||||||
|
|
|
@ -1253,6 +1253,7 @@ void ClientSpawn(gentity_t *ent) {
|
||||||
|
|
||||||
//Blaze: Set the opendoor flag to 0
|
//Blaze: Set the opendoor flag to 0
|
||||||
client->openDoor = qfalse;
|
client->openDoor = qfalse;
|
||||||
|
client->openDoorTime = 0;
|
||||||
|
|
||||||
// don't allow full run speed for a bit
|
// don't allow full run speed for a bit
|
||||||
client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
|
client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
|
||||||
|
|
|
@ -868,6 +868,29 @@ void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText )
|
||||||
char text[MAX_SAY_TEXT];
|
char text[MAX_SAY_TEXT];
|
||||||
char location[64];
|
char location[64];
|
||||||
|
|
||||||
|
int validation;
|
||||||
|
|
||||||
|
// Elder: validate the client
|
||||||
|
validation = RQ3_ValidateSay( ent );
|
||||||
|
|
||||||
|
if (validation != SAY_OK)
|
||||||
|
{
|
||||||
|
// Only send one message for the initial offense
|
||||||
|
if (ent->client->pers.sayMuteTime == level.time)
|
||||||
|
{
|
||||||
|
if (validation == SAY_WARNING)
|
||||||
|
{
|
||||||
|
trap_SendServerCommand( ent-g_entities, va("print \"Exceeded message limit - ^3WARNING ^7(%i seconds).\n\"", SAY_WARNING_TIME));
|
||||||
|
}
|
||||||
|
else if (validation == SAY_BAN)
|
||||||
|
{
|
||||||
|
trap_SendServerCommand( ent-g_entities, va("print \"Exceeded message limit - ^1BAN ^7(%i seconds).\n\"", SAY_BAN_TIME));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( g_gametype.integer < GT_TEAM && mode == SAY_TEAM ) {
|
if ( g_gametype.integer < GT_TEAM && mode == SAY_TEAM ) {
|
||||||
mode = SAY_ALL;
|
mode = SAY_ALL;
|
||||||
}
|
}
|
||||||
|
@ -2082,10 +2105,11 @@ void Cmd_OpenDoor(gentity_t *ent)
|
||||||
{
|
{
|
||||||
if (Q_stricmp (door->classname, "func_door_rotating") == 0) {
|
if (Q_stricmp (door->classname, "func_door_rotating") == 0) {
|
||||||
ent->client->openDoor = qtrue;
|
ent->client->openDoor = qtrue;
|
||||||
//ent->client->ps.stats[STAT_OPENDOOR] = 1;
|
ent->client->openDoorTime = level.time;
|
||||||
}
|
}
|
||||||
else if (Q_stricmp (door->classname, "func_door") == 0) {
|
else if (Q_stricmp (door->classname, "func_door") == 0) {
|
||||||
ent->client->openDoor = qtrue;
|
ent->client->openDoor = qtrue;
|
||||||
|
ent->client->openDoorTime = level.time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2288,18 +2312,19 @@ Cmd_DropWeapon_f XRAY FMJ
|
||||||
*/
|
*/
|
||||||
void Cmd_DropWeapon_f( gentity_t *ent ) {
|
void Cmd_DropWeapon_f( gentity_t *ent ) {
|
||||||
|
|
||||||
//Elder: added
|
//Elder: added -- checked in cgame
|
||||||
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK)
|
//if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK)
|
||||||
{
|
//{
|
||||||
trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging!\n\""));
|
//trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging!\n\""));
|
||||||
return;
|
//return;
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
//Elder: remove zoom bits
|
//Elder: remove zoom bits
|
||||||
Cmd_Unzoom(ent);
|
Cmd_Unzoom(ent);
|
||||||
ThrowWeapon( ent );
|
//Throwing away return here
|
||||||
}
|
ThrowWeapon( ent, qfalse );
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2347,7 +2372,7 @@ PlayerStats
|
||||||
*/
|
*/
|
||||||
void Cmd_PlayerStats_f( gentity_t *ent )
|
void Cmd_PlayerStats_f( gentity_t *ent )
|
||||||
{
|
{
|
||||||
char textbuf[1024];
|
//char textbuf[1024];
|
||||||
|
|
||||||
|
|
||||||
trap_SendServerCommand( ent-g_entities, va("print \"%s:\n\"",ent->client->pers.netname ));
|
trap_SendServerCommand( ent-g_entities, va("print \"%s:\n\"",ent->client->pers.netname ));
|
||||||
|
@ -2506,3 +2531,70 @@ void ClientCommand( int clientNum ) {
|
||||||
else
|
else
|
||||||
trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) );
|
trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
RQ3_ValidateSay
|
||||||
|
|
||||||
|
Added by Elder
|
||||||
|
Ensure that the client is not spamming because we need
|
||||||
|
sv_floodProtect off for fast reloads and what-not.
|
||||||
|
It's not perfect (ideally we'd cut them off in cgame
|
||||||
|
but messagemodes by-pass it), but at least it prevents
|
||||||
|
spam from reaching other clients.
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
|
||||||
|
int RQ3_ValidateSay ( gentity_t *ent )
|
||||||
|
{
|
||||||
|
int timeCheck;
|
||||||
|
|
||||||
|
if (ent->client->pers.sayWarnings)
|
||||||
|
timeCheck = SAY_WARNING_TIME * 1000;
|
||||||
|
else
|
||||||
|
timeCheck = SAY_BAN_TIME * 1000;
|
||||||
|
|
||||||
|
// check if already warned/banned
|
||||||
|
if (ent->client->pers.sayMuteTime &&
|
||||||
|
level.time - ent->client->pers.sayMuteTime < timeCheck)
|
||||||
|
{
|
||||||
|
if (ent->client->pers.sayWarnings)
|
||||||
|
return SAY_WARNING;
|
||||||
|
else
|
||||||
|
return SAY_BAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if a flooder
|
||||||
|
if (ent->client->pers.sayCount >= SAY_MAX_NUMBER &&
|
||||||
|
level.time - ent->client->pers.sayTime < SAY_PERIOD_TIME * 1000)
|
||||||
|
{
|
||||||
|
ent->client->pers.sayMuteTime = level.time;
|
||||||
|
|
||||||
|
// determine penalty level
|
||||||
|
if (ent->client->pers.sayWarnings >= SAY_MAX_WARNINGS)
|
||||||
|
{
|
||||||
|
// bans never reset, but warnings do
|
||||||
|
ent->client->pers.sayBans++;
|
||||||
|
ent->client->pers.sayWarnings = 0;
|
||||||
|
return SAY_BAN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ent->client->pers.sayWarnings++;
|
||||||
|
return SAY_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// regular say check
|
||||||
|
if (level.time - ent->client->pers.sayTime > SAY_PERIOD_TIME * 1000)
|
||||||
|
{
|
||||||
|
ent->client->pers.sayCount = 0;
|
||||||
|
ent->client->pers.sayTime = level.time;
|
||||||
|
ent->client->pers.sayMuteTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent->client->pers.sayCount++;
|
||||||
|
|
||||||
|
return SAY_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -817,6 +817,9 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
|
||||||
self->client->ps.torsoAnim =
|
self->client->ps.torsoAnim =
|
||||||
( ( self->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
|
( ( self->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
|
||||||
|
|
||||||
|
// Elder: only do death sounds if not hit in the head
|
||||||
|
if ((self->client->lasthurt_location & LOCATION_HEAD) != LOCATION_HEAD &&
|
||||||
|
(self->client->lasthurt_location & LOCATION_FACE) != LOCATION_FACE )
|
||||||
G_AddEvent( self, EV_DEATH1 + i, killer );
|
G_AddEvent( self, EV_DEATH1 + i, killer );
|
||||||
|
|
||||||
// the body can still be gibbed
|
// the body can still be gibbed
|
||||||
|
@ -1516,8 +1519,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
|
||||||
//Elder: do shotgun report like AQ2
|
//Elder: do shotgun report like AQ2
|
||||||
int playernum = targ - g_entities;
|
int playernum = targ - g_entities;
|
||||||
|
|
||||||
playernum--;
|
//playernum--;
|
||||||
if (playernum >= 0 && playernum <= MAX_CLIENTS - 1)
|
if (playernum >= 0 && playernum < MAX_CLIENTS)
|
||||||
tookShellHit[playernum] = 1;
|
tookShellHit[playernum] = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1649,7 +1652,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
|
||||||
break;
|
break;
|
||||||
case LOCATION_SHOULDER:
|
case LOCATION_SHOULDER:
|
||||||
case LOCATION_CHEST:
|
case LOCATION_CHEST:
|
||||||
//Vest stuff
|
//Vest stuff - is the knife supposed to be affected?
|
||||||
if (bg_itemlist[targ->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR)
|
if (bg_itemlist[targ->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR)
|
||||||
{
|
{
|
||||||
//if ((attacker->client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000)) == (1 << WP_SSG3000))
|
//if ((attacker->client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000)) == (1 << WP_SSG3000))
|
||||||
|
@ -1669,8 +1672,6 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
|
||||||
}
|
}
|
||||||
//Kevlar sound
|
//Kevlar sound
|
||||||
tent = G_TempEntity2(targ->s.pos.trBase, EV_RQ3_SOUND, RQ3_SOUND_KEVLARHIT);
|
tent = G_TempEntity2(targ->s.pos.trBase, EV_RQ3_SOUND, RQ3_SOUND_KEVLARHIT);
|
||||||
//Elder: flag for sound in feedback
|
|
||||||
//targ->client->damage_vest = qtrue;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,8 @@ typedef enum {
|
||||||
#define SP_AUTOOPEN 4 // Elder: revert to Q3 behaviour
|
#define SP_AUTOOPEN 4 // Elder: revert to Q3 behaviour
|
||||||
#define SP_DOORTOGGLE 8 // Elder: added to enable mover toggling
|
#define SP_DOORTOGGLE 8 // Elder: added to enable mover toggling
|
||||||
|
|
||||||
|
#define MAXDOORTIME 100 // Elder: max time the opendoor key can stay open
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
typedef struct gentity_s gentity_t;
|
typedef struct gentity_s gentity_t;
|
||||||
|
@ -262,10 +264,32 @@ typedef struct {
|
||||||
int teamVoteCount; // to prevent people from constantly calling votes
|
int teamVoteCount; // to prevent people from constantly calling votes
|
||||||
qboolean teamInfo; // send team overlay updates?
|
qboolean teamInfo; // send team overlay updates?
|
||||||
qboolean hadUniqueWeapon[MAX_WEAPONS]; //Elder: for "ammo" in last gun
|
qboolean hadUniqueWeapon[MAX_WEAPONS]; //Elder: for "ammo" in last gun
|
||||||
|
int sayTime; // Elder: say validation stuff
|
||||||
|
int sayCount;
|
||||||
|
int sayWarnings;
|
||||||
|
int sayBans;
|
||||||
|
int sayMuteTime;
|
||||||
|
|
||||||
} clientPersistant_t;
|
} clientPersistant_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Elder: spam prevention defaults
|
||||||
|
#define SAY_MAX_NUMBER 6
|
||||||
|
#define SAY_MAX_WARNINGS 3
|
||||||
|
#define SAY_PERIOD_TIME 3 // Elder: in seconds
|
||||||
|
#define SAY_WARNING_TIME 15
|
||||||
|
#define SAY_BAN_TIME 60 // Technically should drop client
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SAY_BAN,
|
||||||
|
SAY_WARNING,
|
||||||
|
SAY_OK,
|
||||||
|
|
||||||
|
SAY_TOTAL
|
||||||
|
} sayValidations_t;
|
||||||
|
|
||||||
|
|
||||||
// this structure is cleared on each ClientSpawn(),
|
// this structure is cleared on each ClientSpawn(),
|
||||||
// except for 'client->pers' and 'client->sess'
|
// except for 'client->pers' and 'client->sess'
|
||||||
struct gclient_s {
|
struct gclient_s {
|
||||||
|
@ -350,10 +374,11 @@ struct gclient_s {
|
||||||
int numClips[MAX_WEAPONS]; // Number of clips each weapon has
|
int numClips[MAX_WEAPONS]; // Number of clips each weapon has
|
||||||
// End Duffman
|
// End Duffman
|
||||||
|
|
||||||
qboolean openDoor;//Blaze: used to hold if someone has hit opendoor key
|
qboolean openDoor; //Blaze: used to hold if someone has hit opendoor key
|
||||||
|
int openDoorTime;
|
||||||
|
|
||||||
// timeResidual is used to handle events that happen every second
|
// timeResidual is used to handle events that happen every second
|
||||||
// like health / armor countdowns and regeneration
|
// like health / armor countdowns and regeneration
|
||||||
|
|
||||||
int timeResidual;
|
int timeResidual;
|
||||||
|
|
||||||
//Elder: C3A laser tutorial
|
//Elder: C3A laser tutorial
|
||||||
|
@ -374,25 +399,13 @@ struct gclient_s {
|
||||||
//qboolean semi; // hawkins (semiauto mode for m4, mp5, pistol)
|
//qboolean semi; // hawkins (semiauto mode for m4, mp5, pistol)
|
||||||
int shots; //Blaze: Number of shots fired so far with this weapon
|
int shots; //Blaze: Number of shots fired so far with this weapon
|
||||||
|
|
||||||
// Homer: weaponstate vars for Cmd_Weapon
|
|
||||||
// make these a single bitmask? worth the effort?
|
|
||||||
// Moved to PERS_WEAPONMODES in bg_public.h
|
|
||||||
/* int mk23semi; // pistol to semi-auto
|
|
||||||
int mp5_3rb; // MP5 to 3rb
|
|
||||||
int m4_3rb; // M4 to 3rb
|
|
||||||
int grenRange; // range to throw grenade (short/medium/long)
|
|
||||||
int throwKnife; // knife to throwing
|
|
||||||
*/
|
|
||||||
//qboolean isBandaging; //Elder: player in the process of bandaging
|
|
||||||
// end Homer
|
|
||||||
|
|
||||||
int weaponfireNextTime; // for akimbos
|
int weaponfireNextTime; // for akimbos
|
||||||
int lastzoom; // Elder: save last zoom state when firing
|
int lastzoom; // Elder: save last zoom state when firing
|
||||||
|
|
||||||
int fastReloads; // Elder: for queuing M3/SSG reloads
|
int fastReloads; // Elder: for queuing M3/SSG reloads
|
||||||
int lastReloadTime; // Elder: for queuing M3/SSG reloads
|
int lastReloadTime; // Elder: for queuing M3/SSG reloads
|
||||||
int reloadAttempts; // Elder: for queuing M3/SSG reloads
|
int reloadAttempts; // Elder: for queuing M3/SSG reloads
|
||||||
int reloadStage;
|
int reloadStage; // Elder: 0, 1, 2 for sound queuing - move to stats?
|
||||||
|
|
||||||
int consecutiveShots; // Elder: for M4 ride-up/kick
|
int consecutiveShots; // Elder: for M4 ride-up/kick
|
||||||
int uniqueWeapons; // Elder: formerly a stat, now just a server var
|
int uniqueWeapons; // Elder: formerly a stat, now just a server var
|
||||||
|
@ -408,6 +421,7 @@ struct gclient_s {
|
||||||
char *areabits;
|
char *areabits;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Begin Duffman
|
// Begin Duffman
|
||||||
int G_LocationDamage(vec3_t point, gentity_t* targ, gentity_t* attacker, int take);
|
int G_LocationDamage(vec3_t point, gentity_t* targ, gentity_t* attacker, int take);
|
||||||
void Cmd_Reload( gentity_t *ent ); // reloads the current weapon
|
void Cmd_Reload( gentity_t *ent ); // reloads the current weapon
|
||||||
|
@ -510,7 +524,7 @@ typedef struct {
|
||||||
void CheckBleeding(gentity_t *targ);
|
void CheckBleeding(gentity_t *targ);
|
||||||
void StartBandage(gentity_t *ent);
|
void StartBandage(gentity_t *ent);
|
||||||
|
|
||||||
void ThrowWeapon( gentity_t *ent );
|
int ThrowWeapon( gentity_t *ent, qboolean forceThrow );
|
||||||
void ThrowItem( gentity_t *ent );
|
void ThrowItem( gentity_t *ent );
|
||||||
gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags ); // XRAY FMJ
|
gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags ); // XRAY FMJ
|
||||||
//Blaze Reaction knife stuff
|
//Blaze Reaction knife stuff
|
||||||
|
@ -540,7 +554,8 @@ void Cmd_OpenDoor(gentity_t *ent);
|
||||||
//Elder: C3A laser tutorial
|
//Elder: C3A laser tutorial
|
||||||
void Laser_Gen (gentity_t *ent, qboolean enabled);
|
void Laser_Gen (gentity_t *ent, qboolean enabled);
|
||||||
void Laser_Think( gentity_t *self );
|
void Laser_Think( gentity_t *self );
|
||||||
|
//Elder: anti-spam stuff
|
||||||
|
int RQ3_ValidateSay ( gentity_t *ent );
|
||||||
//Elder: commented out for Homer
|
//Elder: commented out for Homer
|
||||||
//void toggleSemi(gentity_t *ent);
|
//void toggleSemi(gentity_t *ent);
|
||||||
|
|
||||||
|
|
|
@ -468,7 +468,7 @@ void G_BreakGlass( gentity_t *ent, vec3_t point, int mod )
|
||||||
//Once it's below 255, we can send a more appropriate event
|
//Once it's below 255, we can send a more appropriate event
|
||||||
//This way, the mappers can use a single func_breakable
|
//This way, the mappers can use a single func_breakable
|
||||||
//while we process it on the server-side.
|
//while we process it on the server-side.
|
||||||
//Places to stuff: eventParm, generic1
|
//Places to stuff: eventParm
|
||||||
|
|
||||||
if( ent->health <= 0 ) {
|
if( ent->health <= 0 ) {
|
||||||
//G_Printf("Original eParm: %i \n", ent->s.eventParm);
|
//G_Printf("Original eParm: %i \n", ent->s.eventParm);
|
||||||
|
|
|
@ -322,8 +322,7 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
|
||||||
//Elder: added
|
//Elder: added
|
||||||
if ( !(ent->s.weapon == WP_KNIFE && other->s.eType == ET_BREAKABLE) ) {
|
if ( !(ent->s.weapon == WP_KNIFE && other->s.eType == ET_BREAKABLE) ) {
|
||||||
G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
|
G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
|
||||||
ent->s.origin, ent->damage,
|
ent->s.origin, ent->damage, 0, ent->methodOfDeath);
|
||||||
0, ent->methodOfDeath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -753,12 +752,6 @@ gentity_t *fire_knife (gentity_t *self, vec3_t start, vec3_t dir)
|
||||||
|
|
||||||
gentity_t *bolt;
|
gentity_t *bolt;
|
||||||
|
|
||||||
// vec3_t gVec;
|
|
||||||
|
|
||||||
// gVec[0] = 0;
|
|
||||||
// gVec[1] = g_gravity.value;
|
|
||||||
// gVec[2] = 0;
|
|
||||||
|
|
||||||
VectorNormalize (dir);
|
VectorNormalize (dir);
|
||||||
|
|
||||||
bolt = G_Spawn();
|
bolt = G_Spawn();
|
||||||
|
@ -787,9 +780,10 @@ gentity_t *fire_knife (gentity_t *self, vec3_t start, vec3_t dir)
|
||||||
VectorCopy (dir, bolt->s.apos.trBase);
|
VectorCopy (dir, bolt->s.apos.trBase);
|
||||||
VectorCopy (dir, bolt->r.currentAngles);
|
VectorCopy (dir, bolt->r.currentAngles);
|
||||||
|
|
||||||
|
//Elder: not needed anymore
|
||||||
//Saving stuff for Makro's knife equations
|
//Saving stuff for Makro's knife equations
|
||||||
VectorCopy( start, bolt->s.origin2);
|
//VectorCopy( start, bolt->s.origin2);
|
||||||
VectorCopy( dir, bolt->s.angles2);
|
//VectorCopy( dir, bolt->s.angles2);
|
||||||
|
|
||||||
return bolt;
|
return bolt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1095,6 +1095,7 @@ void Touch_DoorTrigger( gentity_t *ent, gentity_t *other, trace_t *trace ) {
|
||||||
//G_Printf("Using a door\n");
|
//G_Printf("Using a door\n");
|
||||||
Use_BinaryMover( ent->parent, ent, other );
|
Use_BinaryMover( ent->parent, ent, other );
|
||||||
other->client->openDoor = qfalse;
|
other->client->openDoor = qfalse;
|
||||||
|
other->client->openDoorTime = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ void G_BounceProjectile( vec3_t start, vec3_t impact, vec3_t dir, vec3_t endout
|
||||||
/*
|
/*
|
||||||
======================================================================
|
======================================================================
|
||||||
|
|
||||||
RQ3 Jump Kick
|
RQ3_JumpKick
|
||||||
Moved from g_active.c to g_weapon.c
|
Moved from g_active.c to g_weapon.c
|
||||||
Because it is a weapon!
|
Because it is a weapon!
|
||||||
|
|
||||||
|
@ -54,18 +54,19 @@ qboolean JumpKick( gentity_t *ent )
|
||||||
|
|
||||||
// set aiming directions
|
// set aiming directions
|
||||||
AngleVectors (ent->client->ps.viewangles, forward, right, up);
|
AngleVectors (ent->client->ps.viewangles, forward, right, up);
|
||||||
|
|
||||||
CalcMuzzlePoint ( ent, forward, right, up, muzzle );
|
CalcMuzzlePoint ( ent, forward, right, up, muzzle );
|
||||||
|
// Elder: AQ2 offset
|
||||||
VectorMA (muzzle, 32, forward, end);
|
muzzle[2] -= (ent->client->ps.viewheight - 20);
|
||||||
|
VectorMA (muzzle, 25, forward, end);
|
||||||
|
//VectorMA (muzzle, 32, forward, end);
|
||||||
|
|
||||||
//VectorCopy( ent->s.origin, muzzle );
|
//VectorCopy( ent->s.origin, muzzle );
|
||||||
//muzzle[2] += 32;
|
//muzzle[2] += 32;
|
||||||
// the muzzle really isn't the right point to test the jumpkick from
|
// the muzzle really isn't the right point to test the jumpkick from
|
||||||
|
|
||||||
trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT);
|
trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT);
|
||||||
//trap_Trace (&tr, ent->s.origin, ent->r.mins, ent->r.maxs, end, ent->s.number, MASK_SHOT);
|
|
||||||
//trap_Trace (&tr, ent->s.origin, NULL, NULL, end, ent->s.number, MASK_SHOT);
|
//trap_Trace (&tr, ent->s.origin, NULL, NULL, end, ent->s.number, MASK_SHOT);
|
||||||
|
|
||||||
if ( tr.surfaceFlags & SURF_NOIMPACT ) {
|
if ( tr.surfaceFlags & SURF_NOIMPACT ) {
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
@ -99,26 +100,41 @@ qboolean JumpKick( gentity_t *ent )
|
||||||
damage, DAMAGE_NO_LOCATIONAL, MOD_KICK );
|
damage, DAMAGE_NO_LOCATIONAL, MOD_KICK );
|
||||||
}
|
}
|
||||||
|
|
||||||
// send blood impact
|
// send blood impact + event stuff
|
||||||
|
/*
|
||||||
if ( traceEnt->takedamage && traceEnt->client ) {
|
if ( traceEnt->takedamage && traceEnt->client ) {
|
||||||
tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
|
//tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
|
||||||
|
tent = G_TempEntity( tr.endpos, EV_JUMPKICK );
|
||||||
tent->s.otherEntityNum = traceEnt->s.number;
|
tent->s.otherEntityNum = traceEnt->s.number;
|
||||||
tent->s.eventParm = DirToByte( tr.plane.normal );
|
tent->s.eventParm = DirToByte( tr.plane.normal );
|
||||||
tent->s.weapon = ent->s.weapon;
|
tent->s.weapon = ent->s.weapon;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (traceEnt->client && traceEnt->client->uniqueWeapons > 0)
|
if (traceEnt->client && traceEnt->takedamage)
|
||||||
|
{
|
||||||
|
tent = G_TempEntity( tr.endpos, EV_JUMPKICK );
|
||||||
|
tent->s.otherEntityNum = traceEnt->s.number;
|
||||||
|
tent->s.otherEntityNum2 = ent->s.number;
|
||||||
|
tent->s.eventParm = DirToByte( tr.plane.normal );
|
||||||
|
tent->s.weapon = 0;
|
||||||
|
|
||||||
|
if (traceEnt->client->uniqueWeapons > 0)
|
||||||
{
|
{
|
||||||
//Elder: toss a unique weapon if kicked
|
//Elder: toss a unique weapon if kicked
|
||||||
//Todo: Need to make sure to cancel any reload attempts
|
//Need to make sure to cancel any reload attempts - test this
|
||||||
//Todo: need to send a message to attacker and target about weapon kick
|
|
||||||
Cmd_Unzoom(traceEnt);
|
Cmd_Unzoom(traceEnt);
|
||||||
ThrowWeapon(traceEnt);
|
traceEnt->client->fastReloads = 0;
|
||||||
//trap_SendServerCommand( ent-g_entities, va("print \"You kicked %s's %s from his hands!\n\"", traceEnt->client->pers.netname, (traceEnt->client->ps.weapon)->pickup_name);
|
traceEnt->client->reloadAttempts = 0;
|
||||||
//trap_SendServerCommand( targ-g_entities, va("print \"Head Damage.\n\""));
|
traceEnt->client->ps.weaponTime = 0;
|
||||||
|
|
||||||
|
//Set the entity's weapon to the target's weapon before he/she throws it
|
||||||
|
tent->s.weapon = ThrowWeapon(traceEnt, qtrue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't need other sound event
|
||||||
|
kickSuccess = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,7 +169,9 @@ qboolean JumpKick( gentity_t *ent )
|
||||||
|
|
||||||
//Elder: Our set of locally called sounds
|
//Elder: Our set of locally called sounds
|
||||||
if (kickSuccess)
|
if (kickSuccess)
|
||||||
|
{
|
||||||
G_AddEvent ( ent, EV_RQ3_SOUND, RQ3_SOUND_KICK);
|
G_AddEvent ( ent, EV_RQ3_SOUND, RQ3_SOUND_KICK);
|
||||||
|
}
|
||||||
|
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
}
|
||||||
|
@ -1012,20 +1030,16 @@ void Knife_Attack ( gentity_t *self, int damage)
|
||||||
{
|
{
|
||||||
trace_t tr;
|
trace_t tr;
|
||||||
vec3_t end;
|
vec3_t end;
|
||||||
// vec3_t start;
|
|
||||||
// vec3_t aimdir;
|
|
||||||
gentity_t *hitent;
|
gentity_t *hitent;
|
||||||
int passent;
|
gentity_t *tent;
|
||||||
|
|
||||||
|
|
||||||
//VectorMA (start, 90, aimdir, end);
|
|
||||||
passent = self->s.number;
|
|
||||||
VectorMA( muzzle, KNIFE_RANGE, forward, end );
|
VectorMA( muzzle, KNIFE_RANGE, forward, end );
|
||||||
trap_Trace (&tr,muzzle, NULL, NULL, end, passent, MASK_SHOT);
|
trap_Trace (&tr, muzzle, NULL, NULL, end, self->s.number, MASK_SHOT);
|
||||||
hitent = &g_entities[ tr.entityNum ];
|
hitent = &g_entities[ tr.entityNum ];
|
||||||
|
|
||||||
// don't need to check for water
|
// don't need to check for water
|
||||||
if (!((tr.surfaceFlags) && (tr.surfaceFlags & SURF_SKY)))
|
//if (!((tr.surfaceFlags) && (tr.surfaceFlags & SURF_SKY)))
|
||||||
|
if (!(tr.surfaceFlags & SURF_SKY))
|
||||||
{
|
{
|
||||||
if (tr.fraction < 1.0)
|
if (tr.fraction < 1.0)
|
||||||
{
|
{
|
||||||
|
@ -1033,19 +1047,24 @@ void Knife_Attack ( gentity_t *self, int damage)
|
||||||
{
|
{
|
||||||
//Elder: no knock-back on knife slashes
|
//Elder: no knock-back on knife slashes
|
||||||
G_Damage (hitent, self, self, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_KNIFE );
|
G_Damage (hitent, self, self, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_KNIFE );
|
||||||
return;
|
if (hitent->client)
|
||||||
//return -2;
|
{
|
||||||
|
tent = G_TempEntity(tr.endpos, EV_RQ3_SOUND);
|
||||||
|
tent->s.eventParm = RQ3_SOUND_KNIFEHIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
//return 0;
|
{
|
||||||
return;
|
//Elder TODO: take into account surface flags for clank
|
||||||
|
tent = G_TempEntity(tr.endpos, EV_MISSILE_MISS);
|
||||||
|
tent->s.eventParm = DirToByte(tr.plane.normal);
|
||||||
|
tent->s.weapon = WP_KNIFE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
//return 0; // we hit the sky, call it a miss
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int knives = 0;
|
//static int knives = 0;
|
||||||
|
|
||||||
|
|
||||||
//Elder: this function does not appear to be in use
|
//Elder: this function does not appear to be in use
|
||||||
|
@ -1258,7 +1277,7 @@ void Weapon_M4_Fire(gentity_t *ent)
|
||||||
// Homer: increment burst if needed
|
// Homer: increment burst if needed
|
||||||
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE )
|
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE )
|
||||||
{
|
{
|
||||||
ent->client->ps.stats[STAT_BURST]++;
|
//ent->client->ps.stats[STAT_BURST]++;
|
||||||
spread = M4_SPREAD * 0.7;
|
spread = M4_SPREAD * 0.7;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1298,7 +1317,7 @@ void Weapon_MK23_Fire(gentity_t *ent)
|
||||||
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE )
|
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE )
|
||||||
{
|
{
|
||||||
spread = PISTOL_SPREAD * 0.7;
|
spread = PISTOL_SPREAD * 0.7;
|
||||||
ent->client->ps.stats[STAT_BURST]++;
|
//ent->client->ps.stats[STAT_BURST]++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1316,16 +1335,13 @@ SSG3000 Attack
|
||||||
void Weapon_SSG3000_FireOld(gentity_t *ent)
|
void Weapon_SSG3000_FireOld(gentity_t *ent)
|
||||||
{
|
{
|
||||||
float spread;
|
float spread;
|
||||||
//Elder: Don't print - will broadcast to server
|
|
||||||
//G_Printf("Zoom Level: %d\n", ent->client->zoomed);
|
|
||||||
//Elder: changed to use RQ3_Spread as well
|
//Elder: changed to use RQ3_Spread as well
|
||||||
//Elder: using new stat
|
if (RQ3_isZoomed(ent))
|
||||||
//if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW ||
|
{
|
||||||
//(ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
|
|
||||||
if (RQ3_isZoomed(ent)) {
|
|
||||||
spread = 0;
|
spread = 0;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
spread = RQ3_Spread(ent, SNIPER_SPREAD);
|
spread = RQ3_Spread(ent, SNIPER_SPREAD);
|
||||||
}
|
}
|
||||||
Bullet_Fire( ent, spread, SNIPER_DAMAGE, MOD_SNIPER);
|
Bullet_Fire( ent, spread, SNIPER_DAMAGE, MOD_SNIPER);
|
||||||
|
@ -1359,6 +1375,7 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
gentity_t *unlinkedEntities[MAX_SSG3000_HITS];
|
gentity_t *unlinkedEntities[MAX_SSG3000_HITS];
|
||||||
|
|
||||||
qboolean hitBreakable;
|
qboolean hitBreakable;
|
||||||
|
qboolean hitKevlar;
|
||||||
float r;
|
float r;
|
||||||
float u;
|
float u;
|
||||||
float spread;
|
float spread;
|
||||||
|
@ -1367,16 +1384,24 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
VectorMA (muzzle, 8192*16, forward, end);
|
VectorMA (muzzle, 8192*16, forward, end);
|
||||||
|
|
||||||
//Elder: added to assist in zoom crap
|
//Elder: added to assist in zoom crap
|
||||||
if (RQ3_isZoomed(ent)) {
|
if (RQ3_isZoomed(ent))
|
||||||
|
{
|
||||||
spread = 0;
|
spread = 0;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
spread = RQ3_Spread(ent, SNIPER_SPREAD);
|
{
|
||||||
|
/*
|
||||||
r = random() * M_PI * 2.0f;
|
r = random() * M_PI * 2.0f;
|
||||||
u = sin(r) * crandom() * spread * 16;
|
u = sin(r) * crandom() * spread * 16;
|
||||||
r = cos(r) * crandom() * spread * 16;
|
r = cos(r) * crandom() * spread * 16;
|
||||||
VectorMA (end, r, right, end);
|
VectorMA (end, r, right, end);
|
||||||
VectorMA (end, u, up, end);
|
VectorMA (end, u, up, end);
|
||||||
|
*/
|
||||||
|
spread = RQ3_Spread(ent, SNIPER_SPREAD);
|
||||||
|
u = crandom() * spread * 16;
|
||||||
|
r = crandom() * spread * 16;
|
||||||
|
VectorMA (end, r, right, end);
|
||||||
|
VectorMA (end, u, up, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1394,6 +1419,7 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
//Elder: need to store this flag because
|
//Elder: need to store this flag because
|
||||||
//the entity may get wiped out in G_Damage
|
//the entity may get wiped out in G_Damage
|
||||||
hitBreakable = qfalse;
|
hitBreakable = qfalse;
|
||||||
|
hitKevlar = qfalse;
|
||||||
|
|
||||||
//G_Printf("(%d) SSG: Trapping trace\n", level.time);
|
//G_Printf("(%d) SSG: Trapping trace\n", level.time);
|
||||||
|
|
||||||
|
@ -1422,6 +1448,10 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
tent[unlinked] = G_TempEntity( trace.endpos, EV_SSG3000_HIT_FLESH );
|
tent[unlinked] = G_TempEntity( trace.endpos, EV_SSG3000_HIT_FLESH );
|
||||||
//tent[unlinked]->s.eventParm = DirToByte( trace.plane.normal );
|
//tent[unlinked]->s.eventParm = DirToByte( trace.plane.normal );
|
||||||
tent[unlinked]->s.eventParm = traceEnt->s.number;
|
tent[unlinked]->s.eventParm = traceEnt->s.number;
|
||||||
|
//Check to see if we've hit kevlar
|
||||||
|
if (bg_itemlist[traceEnt->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR)
|
||||||
|
hitKevlar = qtrue;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1440,7 +1470,7 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
|
|
||||||
//Elder: go through non-solids and breakables
|
//Elder: go through non-solids and breakables
|
||||||
//If we ever wanted to "shoot through walls" we'd do stuff here
|
//If we ever wanted to "shoot through walls" we'd do stuff here
|
||||||
if ( hitBreakable == qfalse && (trace.contents & CONTENTS_SOLID)) {
|
if ( hitKevlar || (hitBreakable == qfalse && (trace.contents & CONTENTS_SOLID))) {
|
||||||
//G_Printf("(%d) SSG: did not hit breakable and hit solid, exiting loop\n", level.time);
|
//G_Printf("(%d) SSG: did not hit breakable and hit solid, exiting loop\n", level.time);
|
||||||
break; // we hit something solid enough to stop the beam
|
break; // we hit something solid enough to stop the beam
|
||||||
}
|
}
|
||||||
|
@ -1535,7 +1565,7 @@ void Weapon_MP5_Fire(gentity_t *ent)
|
||||||
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_MP5MODE) == RQ3_MP5MODE )
|
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_MP5MODE) == RQ3_MP5MODE )
|
||||||
{
|
{
|
||||||
spread = MP5_SPREAD * 0.7;
|
spread = MP5_SPREAD * 0.7;
|
||||||
ent->client->ps.stats[STAT_BURST]++;
|
//ent->client->ps.stats[STAT_BURST]++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1620,49 +1650,58 @@ void RQ3_InitShotgunDamageReport( void )
|
||||||
memset(tookShellHit, 0, MAX_CLIENTS * sizeof(int));
|
memset(tookShellHit, 0, MAX_CLIENTS * sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Elder: almost straight out of the AQ2 source
|
//Elder: similar to AQ2 source
|
||||||
|
#define MAX_NAME_REPORTS 8
|
||||||
void RQ3_ProduceShotgunDamageReport(gentity_t *self)
|
void RQ3_ProduceShotgunDamageReport(gentity_t *self)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
int l;
|
int totalNames = 0;
|
||||||
int total_to_print = 0;
|
|
||||||
int printed = 0;
|
int printed = 0;
|
||||||
static char textbuf[1024];
|
char textbuf[1024];
|
||||||
|
gclient_t *hitClient;
|
||||||
|
|
||||||
for (l = 1; l <= g_maxclients.integer; l++)
|
//for (l = 1; l <= g_maxclients.integer; l++)
|
||||||
|
|
||||||
|
// Run through array to see if anyone was hit
|
||||||
|
for (i = 0; i < MAX_CLIENTS; i++)
|
||||||
{
|
{
|
||||||
if (tookShellHit[l - 1])
|
if (tookShellHit[i])
|
||||||
total_to_print++;
|
totalNames++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (total_to_print)
|
if (totalNames)
|
||||||
{
|
{
|
||||||
if (total_to_print > 10)
|
// Clamp number of names to report
|
||||||
total_to_print = 10;
|
if (totalNames > MAX_NAME_REPORTS)
|
||||||
|
totalNames = MAX_NAME_REPORTS;
|
||||||
|
|
||||||
|
//Q_strncpyz(textbuf, "You hit", sizeof(textbuf));
|
||||||
strcpy(textbuf, "You hit ");
|
strcpy(textbuf, "You hit ");
|
||||||
for (l = 1; l <= g_maxclients.integer; l++)
|
for (i = 0; i < MAX_CLIENTS; i++)
|
||||||
{
|
{
|
||||||
if (tookShellHit[l - 1])
|
if (tookShellHit[i])
|
||||||
{
|
{
|
||||||
if (printed == (total_to_print - 1))
|
//grammar set
|
||||||
|
if (printed == (totalNames - 1))
|
||||||
{
|
{
|
||||||
if (total_to_print == 2)
|
if (totalNames == 2)
|
||||||
strcat(textbuf, " and ");
|
Q_strcat(textbuf, sizeof(textbuf), "^7 and ");
|
||||||
else if (total_to_print != 1)
|
else if (totalNames != 1)
|
||||||
strcat(textbuf, ", and ");
|
Q_strcat(textbuf, sizeof(textbuf), "^7, and ");
|
||||||
}
|
}
|
||||||
else if (printed)
|
else if (printed)
|
||||||
strcat(textbuf, ", ");
|
Q_strcat(textbuf, sizeof(textbuf), "^7, ");
|
||||||
|
|
||||||
strcat(textbuf, g_entities[l].client->pers.netname);
|
//add to text buffer
|
||||||
//strcat(textbuf, g_edicts[l].client->pers.netname);
|
hitClient = g_entities[i].client;
|
||||||
|
Q_strcat(textbuf, sizeof(textbuf), hitClient->pers.netname);
|
||||||
printed++;
|
printed++;
|
||||||
}
|
}
|
||||||
if (printed == total_to_print)
|
|
||||||
|
if (printed == totalNames)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trap_SendServerCommand( self-g_entities, va("print \"%s^7\n\"", textbuf));
|
trap_SendServerCommand( self-g_entities, va("print \"%s^7.\n\"", textbuf));
|
||||||
//gi.cprintf(self, PRINT_HIGH, "%s\n", textbuf);
|
//gi.cprintf(self, PRINT_HIGH, "%s\n", textbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue