Elder: Worked in conjunction with the cgame module

Fixed bugs, added some new functionality
(e.g. akimbos, func_breakable+, etc.)
This commit is contained in:
Victor Chow 2001-06-08 04:47:30 +00:00
parent 18668685ab
commit 85a0dece4b
17 changed files with 726 additions and 243 deletions

View file

@ -141,8 +141,8 @@ gitem_t bg_itemlist[] =
//Shotgun
{
"weapon_m3",
"sound/weapons/shotgun/m3in.wav",
{ "models/weapons2/shotgun/shotgun.md3",
"sound/weapons/m3/m3in.wav",
{ "models/weapons2/m3/m3.md3",
0, 0, 0},
/* icon */ "icons/iconw_m3",
/* pickup */ "M3 Super Shotgun",
@ -187,9 +187,9 @@ gitem_t bg_itemlist[] =
//Knife
{
"3rd_knife",
"knife_3rd",
NULL,
{"models/weapons2/knife/3rd_knife.md3",0,0,0},
{"models/weapons2/knife/knife_3rd.md3",0,0,0},
"icons/iconw_knife",
"Knife",
1,
@ -201,9 +201,9 @@ gitem_t bg_itemlist[] =
//Pistol
{
"3rd_pistol",
"pistol_3rd",
NULL,
{ "models/weapons2/mk23/3rd_mk23.md3",
{ "models/weapons2/mk23/mk23_3rd.md3",
0, 0, 0},
"icons/iconw_mk23",
"MK23",
@ -216,9 +216,9 @@ gitem_t bg_itemlist[] =
//M4
{
"3rd_m4",
"m4_3rd",
NULL,
{ "models/weapons2/m4/3rd_m4.md3",
{ "models/weapons2/m4/m4_3rd.md3",
0, 0, 0},
"icons/iconw_m4",
"M4",
@ -231,9 +231,9 @@ gitem_t bg_itemlist[] =
//SSG3000
{
"3rd_ssg3000",
"ssg3000_3rd",
NULL,
{ "models/weapons2/ssg3000/3rd_ssg3000.md3",
{ "models/weapons2/ssg3000/ssg3000_3rd.md3",
0, 0, 0},
"icons/iconw_ssg",
"SSG3000",
@ -246,9 +246,9 @@ gitem_t bg_itemlist[] =
//MP5
{
"3rd_mp5",
"mp5_3rd",
NULL,
{ "models/weapons2/mp5/3rd_mp5.md3",
{ "models/weapons2/mp5/mp5_3rd.md3",
0, 0, 0},
"icons/iconw_mp5",
"MP5",
@ -261,9 +261,9 @@ gitem_t bg_itemlist[] =
//Handcannon
{
"3rd_handcannon",
"handcannon_3rd",
NULL,
{ "models/weapons2/handcannon/3rd_handcannon.md3",
{ "models/weapons2/handcannon/handcannon_3rd.md3",
0, 0, 0},
"icons/iconw_sawedoff",
"Hand Cannon",
@ -276,9 +276,9 @@ gitem_t bg_itemlist[] =
//Shotgun
{
"3rd_m3",
"m3_3rd",
NULL,
{ "models/weapons2/shotgun/3rd_shotgun.md3",
{ "models/weapons2/m3/m3_3rd.md3",
0, 0, 0},
"icons/iconw_m3",
"M3 Super Shotgun",
@ -291,9 +291,9 @@ gitem_t bg_itemlist[] =
//Akimbo Placeholder
{
"3rd_akimbo",
"akimbo_3rd",
NULL,
{ "models/weapons2/akimbo/3rd_akimbo.md3",
{ "models/weapons2/akimbo/akimbo_3rd.md3",
0, 0, 0},
"icons/iconw_akimbo",
"Akimbo Pistols",
@ -307,9 +307,9 @@ gitem_t bg_itemlist[] =
//Grenade
{
"3rd_grenade",
"grenade_3rd",
NULL,
{ "models/weapons2/grenade/3rd_grenade.md3",
{ "models/weapons2/grenade/grenade_3rd.md3",
0, 0, 0},
"icons/iconw_grenade",
"Grenade",
@ -839,40 +839,82 @@ qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTim
/*
==================
ClipAmountForWeapon for Cmd_Reload
Elder: changed from ClipAmountForWeapon - which was an ambiguous name
ClipAmountForReload for Cmd_Reload
Added by Duffman
Returns the amount of ammo a weapon can hold
==================
Returns the amount of ammo a weapon reloads by
==================
*/
int ClipAmountForWeapon( int w ) {
int ClipAmountForReload( int w ) {
//How much each clip holds
//Elder: this function is very misleading.
//It returns the amount to add when reloading,
//Not the actual amount in a weapon clip!!
//For that, you should check ClipAmountForAmmo below
//Changed to use constants defined in bg_public.h
switch(w){
case WP_PISTOL:
return 12;
return RQ3_PISTOL_RELOAD;
case WP_KNIFE:
return 1;
return RQ3_KNIFE_RELOAD;
case WP_M4:
return 24;
return RQ3_M4_RELOAD;
case WP_SSG3000:
return 1;
return RQ3_SSG3000_RELOAD;
case WP_MP5:
return 30;
return RQ3_MP5_RELOAD;
case WP_HANDCANNON:
return 2;
return RQ3_HANDCANNON_RELOAD;
case WP_M3:
return 1;
return RQ3_M3_RELOAD;
case WP_AKIMBO:
return 24;
return RQ3_AKIMBO_RELOAD;
case WP_GRENADE:
return 1;
return RQ3_GRENADE_RELOAD;
default:
return 12;
return RQ3_PISTOL_RELOAD;
}
// return 12; //this wont happen unless you copy-and-paste too much
}
/*
==================
ClipAmountForAmmo
Added by Elder
Returns the amount of ammo a weapon can hold
==================
*/
int ClipAmountForAmmo( int w ) {
//How much each GUN holds!
//Elder: don't confuse with the reload one
switch(w){
case WP_PISTOL:
return RQ3_PISTOL_AMMO;
case WP_KNIFE:
return RQ3_KNIFE_AMMO;
case WP_M4:
return RQ3_M4_AMMO;
case WP_SSG3000:
return RQ3_SSG3000_AMMO;
case WP_MP5:
return RQ3_MP5_AMMO;
case WP_HANDCANNON:
return RQ3_HANDCANNON_AMMO;
case WP_M3:
return RQ3_M3_AMMO;
case WP_AKIMBO:
return RQ3_AKIMBO_AMMO;
case WP_GRENADE:
return RQ3_GRENADE_AMMO;
default:
return RQ3_PISTOL_AMMO;
}
}
/*
================
BG_CanItemBeGrabbed
@ -1183,6 +1225,7 @@ char *eventnames[] = {
"EV_GENERAL_SOUND",
"EV_GLOBAL_SOUND", // no attenuation
"EV_GLOBAL_TEAM_SOUND",
"EV_RQ3_SOUND", // Elder: play local sounds - primarily for kick
"EV_BULLET_HIT_FLESH",
"EV_BULLET_HIT_WALL",

View file

@ -1592,6 +1592,11 @@ Generates weapon events and modifes the weapon counter
static void PM_Weapon( void ) {
int addTime;
//Elder: PISTOL always gets set to 12 if akimbos have >11 based on AQ2 observation
if (pm->ps->weapon == WP_AKIMBO && pm->ps->ammo[WP_AKIMBO] > 11) {
pm->ps->ammo[WP_PISTOL] = 12;
}
// don't allow attack until all buttons are up
if ( pm->ps->pm_flags & PMF_RESPAWNED ) {
return;
@ -1664,9 +1669,12 @@ static void PM_Weapon( void ) {
if ( ! (pm->cmd.buttons & BUTTON_ATTACK) ) {
pm->ps->weaponTime = 0;
pm->ps->weaponstate = WEAPON_READY;
// Homer: not firing, reset burst value (cheaper than a non-zero check)
pm->ps->stats[STAT_BURST] = 0;
return;
}
//Elder: custom fire animations go here
// start the animation even if out of ammo
if ( pm->ps->weapon == WP_KNIFE ) {
// the guantlet only "fires" when it actually hits something
@ -1680,10 +1688,27 @@ static void PM_Weapon( void ) {
PM_StartTorsoAnim( TORSO_ATTACK );
}
//Elder: works great server side, but client needs to predict it
// Homer: if weapon can set to be burst mode, check for burst value
// M4
if ( pm->ps->weapon == WP_M4 && pm->ps->stats[STAT_BURST] > 2 ) {
return;
}
// MP5
if ( pm->ps->weapon == WP_MP5 && pm->ps->stats[STAT_BURST] > 2 ) {
return;
}
// MK23
if ( pm->ps->weapon == WP_PISTOL && pm->ps->stats[STAT_BURST] > 0 ) {
return;
}
// end Homer
pm->ps->weaponstate = WEAPON_FIRING;
// check for out of ammo
if ( ! pm->ps->ammo[ pm->ps->weapon ] ) {
// check for out of ammo or one bullet in akimbo
if ( ! pm->ps->ammo[ pm->ps->weapon ] ||
pm->ps->weapon == WP_AKIMBO && pm->ps->ammo[ pm->ps->weapon ] == 1) {
PM_AddEvent( EV_NOAMMO );
pm->ps->weaponTime += 500;
return;
@ -1692,10 +1717,23 @@ static void PM_Weapon( void ) {
// take an ammo away if not infinite
if ( pm->ps->ammo[ pm->ps->weapon ] != -1 ) {
//Blaze: Dont remove ammo for knife
//if (pm->ps->weapon != WP_KNIFE)
pm->ps->ammo[ pm->ps->weapon ]--;
//Elder: can't access throwKnife?
//if ( pm->ps->weapon != WP_KNIFE)
pm->ps->ammo[ pm->ps->weapon ]--;
//Elder: remove one more bullet/shell if handcannon/akimbo
if (pm->ps->weapon == WP_HANDCANNON || pm->ps->weapon == WP_AKIMBO) {
pm->ps->ammo[ pm->ps->weapon ]--;
}
//Elder: sync bullets a la AQ2 style
if (pm->ps->weapon == WP_AKIMBO && pm->ps->ammo[pm->ps->weapon] < 12) {
pm->ps->ammo[WP_PISTOL] = pm->ps->ammo[WP_AKIMBO];
}
else if (pm->ps->weapon == WP_PISTOL && pm->ps->ammo[WP_AKIMBO] > 0) {
pm->ps->ammo[WP_AKIMBO]--;
}
}
// fire weapon
PM_AddEvent( EV_FIRE_WEAPON );

View file

@ -8,7 +8,8 @@
#define GAME_VERSION "baseq3-1"
#define DEFAULT_GRAVITY 800
#define GIB_HEALTH -40
//Elder: lowered from -40 so falling deaths don't gib so easily
#define GIB_HEALTH -500
#define ARMOR_PROTECTION 0.66
#define MAX_ITEMS 256
@ -34,6 +35,66 @@
#define CROUCH_VIEWHEIGHT 12
#define DEAD_VIEWHEIGHT -16
//Elder: debris bit parms to pass to break_glass - maybe I should enum this?
#define RQ3_DEBRIS_SMALL 0x00000001
#define RQ3_DEBRIS_MEDIUM 0x00000002
#define RQ3_DEBRIS_LARGE 0x00000004
#define RQ3_DEBRIS_TONS 0x00000008
#define RQ3_DEBRIS_GLASS 0x00000010
#define RQ3_DEBRIS_WOOD 0x00000020
#define RQ3_DEBRIS_METAL 0x00000040
#define RQ3_DEBRIS_CERAMIC 0x00000080
#define RQ3_DEBRIS_PAPER 0x00000100
#define RQ3_DEBRIS_POPCAN 0x00000200
//Elder: to stop some of the hardcoding
//This is some ammo amounts per clip/item pick up
#define RQ3_SSG3000_CLIP 6
#define RQ3_MP5_CLIP 30
#define RQ3_M3_CLIP 7
#define RQ3_M4_CLIP 24
#define RQ3_PISTOL_CLIP 12
#define RQ3_KNIFE_CLIP 1
#define RQ3_AKIMBO_CLIP 24
#define RQ3_HANDCANNON_CLIP 7
#define RQ3_GRENADE_CLIP 1
//Elder: this is the maximum reserve hold sans bandolier
#define RQ3_SSG3000_MAXCLIP 20
#define RQ3_MP5_MAXCLIP 2
#define RQ3_M3_MAXCLIP 14
#define RQ3_M4_MAXCLIP 1
#define RQ3_PISTOL_MAXCLIP 2
#define RQ3_KNIFE_MAXCLIP 10
#define RQ3_AKIMBO_MAXCLIP 2
#define RQ3_HANDCANNON_MAXCLIP 14
#define RQ3_GRENADE_MAXCLIP 2
//Elder: this is the amount to add when reloading
#define RQ3_SSG3000_RELOAD 1 //Elder: note - one at a time
#define RQ3_MP5_RELOAD 30
#define RQ3_M3_RELOAD 1 //Elder: note - one at a time
#define RQ3_M4_RELOAD 24
#define RQ3_PISTOL_RELOAD 12
#define RQ3_KNIFE_RELOAD 1 //Elder: shouldn't need to reload
#define RQ3_AKIMBO_RELOAD 24
#define RQ3_HANDCANNON_RELOAD 2
#define RQ3_GRENADE_RELOAD 1 //Elder: shouldn't need to reload
//Elder: this is the amount for a full chamber
#define RQ3_SSG3000_AMMO 6
#define RQ3_MP5_AMMO 30
#define RQ3_M3_AMMO 7
#define RQ3_M4_AMMO 24
#define RQ3_PISTOL_AMMO 12
#define RQ3_KNIFE_AMMO 1 //Elder: shouldn't need this value
#define RQ3_AKIMBO_AMMO 24
#define RQ3_HANDCANNON_AMMO 2
#define RQ3_GRENADE_AMMO 1 //Elder: shouldn't need this value
//Elder: confused?
//
// config strings are a general means of communicating variable length strings
// from the server to all connected clients.
@ -195,11 +256,14 @@ typedef enum {
// Begin Duffman
STAT_CLIPS, // Num Clips player currently has
// End Duffman
// Homer: for bursting
STAT_BURST, // number of shots in burst
STAT_CLIENTS_READY, // bit mask of clients wishing to exit the intermission (FIXME: configstring?)
// STAT_MAX_HEALTH, // health / armor limit, changable by handicap
STAT_JUMPTIME, //Blaze RE: Double jump
STAT_UNIQUEWEAPONS,
STAT_FALLDAMAGE,
STAT_BANDAGE, //Elder: holds bandage need
} statIndex_t;
@ -226,7 +290,6 @@ typedef enum {
PERS_CAPTURES // captures
} persEnum_t;
// entityState_t->eFlags
#define EF_DEAD 0x00000001 // don't draw a foe marker over players with EF_DEAD
#ifdef MISSIONPACK
@ -312,6 +375,14 @@ typedef enum {
} weapon_t;
//Elder: added
//
//bg_misc.c
//
int ClipAmountForReload( int w );
int ClipAmountForAmmo( int w );
// reward sounds (stored in ps->persistant[PERS_PLAYEREVENTS])
#define PLAYEREVENT_DENIEDREWARD 0x0001
#define PLAYEREVENT_GAUNTLETREWARD 0x0002
@ -362,7 +433,7 @@ typedef enum {
EV_NOAMMO,
EV_CHANGE_WEAPON,
EV_FIRE_WEAPON,
EV_ZOOM, // SSG zoom(reaction)
//EV_ZOOM, // SSG zoom(reaction)
EV_USE_ITEM0,
EV_USE_ITEM1,
@ -391,6 +462,7 @@ typedef enum {
EV_GENERAL_SOUND,
EV_GLOBAL_SOUND, // no attenuation
EV_GLOBAL_TEAM_SOUND,
EV_RQ3_SOUND, // Elder: play local sounds - intended for kick
EV_BULLET_HIT_FLESH,
EV_BULLET_HIT_WALL,

View file

@ -101,6 +101,8 @@ qboolean JumpKick( gentity_t *ent )
G_Damage( traceEnt, ent, ent, forward, tr.endpos,
damage, DAMAGE_NO_LOCATIONAL, MOD_KICK );
//Elder: Our set of locally called sounds
G_AddEvent ( ent, EV_RQ3_SOUND, 0);
return qtrue;
}
@ -156,7 +158,6 @@ void P_DamageFeedback( gentity_t *player ) {
client->ps.damageEvent++;
}
client->ps.damageCount = count;
//
@ -677,9 +678,9 @@ void ClientEvents( gentity_t *ent, int oldEventSequence ) {
FireWeapon( ent );
break;
// For Reaction unzooming
case EV_CHANGE_WEAPON:
ent->client->zoomed=0;
//Elder: not a good place to put stuff
//ent->client->zoomed=0;
break;
/* case EV_ZOOM:
@ -839,6 +840,7 @@ void ThrowWeapon( gentity_t *ent )
//if( client->ps.weapon == WP_KNIFE || client->ps.weapon == WP_PISTOL || client->ps.weapon == WP_GRENADE || ( ucmd->buttons & BUTTON_ATTACK ))
// return;
//Elder: better change conditional to include bandaging case... re: "You are too busy bandaging..."
if (ucmd->buttons & BUTTON_ATTACK) return;
weap=0;
if (client->ps.stats[STAT_UNIQUEWEAPONS] > 0)
@ -852,6 +854,7 @@ void ThrowWeapon( gentity_t *ent )
if (weap == 0 ) return;
xr_item = BG_FindItemForWeapon( weap );
//Elder: do you really want to do this?
client->ps.ammo[ weap ] = 0;
client->ps.stats[STAT_WEAPONS] &= ~( 1 << weap);
@ -1317,6 +1320,10 @@ void ClientEndFrame( gentity_t *ent ) {
// End Duffman
ent->client->ps.stats[STAT_HEALTH] = ent->health; // FIXME: get rid of ent->health...
//Elder: bleeding
//TODO: add in when you get leg damage
ent->client->ps.stats[STAT_BANDAGE] = ent->client->bleeding; // + ent->client->legDamage;
G_SetClientSound (ent);
// set the latest infor

View file

@ -2,6 +2,8 @@
//
#include "g_local.h"
#define RQ3_NONAMEPLAYER "Nameless"
// g_client.c -- client functions that don't happen every frame
static vec3_t playerMins = {-15, -15, -24};
@ -477,14 +479,15 @@ respawn
================
*/
void respawn( gentity_t *ent ) {
gentity_t *tent;
//gentity_t *tent;
CopyToBodyQue (ent);
ClientSpawn(ent);
// add a teleportation effect
tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
tent->s.clientNum = ent->s.clientNum;
//Elder: removed
//tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
//tent->s.clientNum = ent->s.clientNum;
}
/*
@ -659,7 +662,8 @@ static void ClientCleanName( const char *in, char *out, int outSize ) {
// don't allow empty names
if( *p == 0 || colorlessLen == 0 ) {
Q_strncpyz( p, "UnnamedPlayer", outSize );
//Elder: change to what we want
Q_strncpyz( p, RQ3_NONAMEPLAYER, outSize );
}
}
@ -990,7 +994,8 @@ void ClientBegin( int clientNum ) {
if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
// send event
tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
//Elder: removed
//tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
tent->s.clientNum = ent->s.clientNum;
if ( g_gametype.integer != GT_TOURNAMENT ) {
@ -1165,7 +1170,8 @@ void ClientSpawn(gentity_t *ent) {
// Begin Duffman
// Initial amount of ammo when spawning, this will be changed when weapons are added.
//Blaze: Changed from WP_MACHINEGUN to WP_PISTOL
client->ps.ammo[WP_PISTOL] = ClipAmountForWeapon(WP_PISTOL);
//Elder: changed to Ammo function instead of Reload
client->ps.ammo[WP_PISTOL] = ClipAmountForAmmo(WP_PISTOL);
client->numClips[WP_PISTOL] = 0;
// End Duffman
@ -1215,6 +1221,7 @@ void ClientSpawn(gentity_t *ent) {
// Hawkins reset zoomed flag
client->zoomed=0;
// set default animations
client->ps.torsoAnim = TORSO_STAND;

View file

@ -7,7 +7,8 @@
//Blaze for door code
void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator );
//Blaze: Get amount of ammo a clip holds
int ClipAmountForWeapon( int );
//Elder: def'd in bg_public.h
//int ClipAmountForWeapon( int );
/*
==================
DeathmatchScoreboardMessage
@ -242,6 +243,9 @@ void Cmd_Give_f (gentity_t *ent)
{
//Blaze: Removed ( 1 << WP_GRAPPLING_HOOK ) -
//I have no clue what that does
//Elder: basically it sets all the STAT_WEAPONS bits to 1 EXCEPT for WP_NONE and
//the initial bit (I don't know what that is)
//http://www.iota-six.freeserve.co.uk/c/bitwise.htm
ent->client->ps.stats[STAT_WEAPONS] = (1 << WP_NUM_WEAPONS) - 1 - ( 1 << WP_NONE );
if (!give_all)
@ -252,7 +256,7 @@ void Cmd_Give_f (gentity_t *ent)
{
for ( i = 0 ; i < MAX_WEAPONS ; i++ ) {
//Blaze: Give right amount of shots to each gun
ent->client->ps.ammo[i] = ClipAmountForWeapon(i);
ent->client->ps.ammo[i] = ClipAmountForAmmo(i);
}
if (!give_all)
return;
@ -1585,10 +1589,12 @@ void Cmd_Stats_f( gentity_t *ent ) {
void Cmd_Bandage (gentity_t *ent)
{
// Zoom out when bandaging.
if(ent->client->zoomed){
ent->client->zoomed=0;
G_AddEvent(ent,EV_ZOOM,0);
if( ent->client->zoomed ){
ent->client->zoomed = 0;
}
//Elder: can't use events
//G_AddEvent(ent,EV_ZOOM,0);
//}
if (ent->client->bleeding)
{
ent->client->ps.weaponstate = WEAPON_DROPPING;
@ -1617,43 +1623,68 @@ void Cmd_Reload( gentity_t *ent ) {
// void Cmd_Reload_f (edict_t *ent)
int weapon;
int ammotoadd;
int delay;
weapon = ent->client->ps.weapon;
ammotoadd = ClipAmountForWeapon(weapon);
delay = 0;
/*if (ent->client->ps.ammo[weapon] >= ClipAmountForWeapon(weapon))
{ trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}*/
int ammotoadd;
int delay;
weapon = ent->client->ps.weapon;
//Elder: changed to new function
ammotoadd = ClipAmountForReload(weapon);
delay = 0;
/*if (ent->client->ps.ammo[weapon] >= ClipAmountForWeapon(weapon))
{ trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}*/
// Hawkins: Zoom out when reloading.
// To Do: Must remember to zoom back in
if(ent->client->zoomed){
ent->client->zoomed=0;
G_AddEvent(ent,EV_ZOOM,0);
}
switch(weapon)
{
// Hawkins: Zoom out when reloading.
//Elder: shouldn't need to know about it
// To Do: Must remember to zoom back in
if( ent->client->zoomed ){
ent->client->zoomed=0;
}
//Elder: can't use events
//G_AddEvent(ent,EV_ZOOM,0);
//Elder: serious debug code
/*
G_Printf("STAT: %d, KNIFE: %d, MK23: %d, M4: %d, SSG: %d, MP5: %d, M3: %d, HC: %d, AKIMBO: %d, GREN: %d\n",
ent->client->ps.stats[STAT_WEAPONS], WP_KNIFE, WP_PISTOL, WP_M4, WP_SSG3000,
WP_MP5, WP_M3, WP_HANDCANNON, WP_AKIMBO, WP_GRENADE);
*/
switch(weapon) {
case WP_KNIFE:
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
break;
case WP_PISTOL:
delay = 2500;
if (ent->client->ps.ammo[weapon] >= RQ3_PISTOL_AMMO)
{
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}
break;
//Elder: was missing?
case WP_M4:
delay = 2500;
if (ent->client->ps.ammo[weapon] >= RQ3_M4_AMMO)
{
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}
break;
case WP_M3:
ammotoadd += ent->client->ps.ammo[weapon];
delay = 400; // from 1000 to 400 by hawkins. reloads too slowly.
if (ent->client->ps.ammo[weapon] >= 7)
if (ent->client->ps.ammo[weapon] >= RQ3_M3_AMMO)
{
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}
break;
case WP_HANDCANNON:
ammotoadd = 2;
delay = 2500;
if (ent->client->ps.ammo[weapon] >= 2)
{
if (ent->client->ps.ammo[weapon] >= RQ3_HANDCANNON_AMMO) {
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}
@ -1661,7 +1692,22 @@ void Cmd_Reload( gentity_t *ent ) {
case WP_SSG3000:
delay = 1000;
ammotoadd += ent->client->ps.ammo[weapon];
if (ent->client->ps.ammo[weapon] >= 6)
if (ent->client->ps.ammo[weapon] >= RQ3_SSG3000_AMMO) {
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}
break;
case WP_AKIMBO:
//Elder: added- but I don't think it's the right value
delay = 2500;
if (ent->client->ps.ammo[weapon] >= RQ3_AKIMBO_AMMO) {
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}
break;
case WP_MP5:
delay = 2000;
if (ent->client->ps.ammo[weapon] >= RQ3_MP5_AMMO)
{
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
@ -1669,29 +1715,67 @@ void Cmd_Reload( gentity_t *ent ) {
break;
default:
delay = 2500;
if (ent->client->ps.ammo[weapon] >= ClipAmountForWeapon(weapon))
//Elder: changed function
if (ent->client->ps.ammo[weapon] >= ClipAmountForAmmo(weapon))
{
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return;
}
break;
}
if (ent->client->numClips[weapon] == 0)
{ trap_SendServerCommand( ent-g_entities, va("print \"No more clips\n\""));
return;
}
//Elder: added handcannon and akimbo conditional
if (ent->client->numClips[weapon] == 0) {
trap_SendServerCommand( ent-g_entities, va("print \"Out of ammo\n\""));
return;
}
else if ( (weapon == WP_HANDCANNON || weapon == WP_AKIMBO) && ent->client->numClips[weapon] < 2 ) {
trap_SendServerCommand( ent-g_entities, va("print \"Not enough of ammo\n\""));
return;
}
//ent->client->ps.weaponstate = WEAPON_RELOADING;
ent->client->ps.weaponstate = WEAPON_DROPPING;
ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT )
^ ANIM_TOGGLEBIT ) | TORSO_DROP;
ent->client->ps.weaponTime += delay;
// add ammo to weapon
if (ent->client->numClips[weapon] > 0)
{ ent->client->ps.ammo[weapon] = ammotoadd;
ent->client->numClips[weapon]--;
}
//Elder: at this point there should be sufficient ammo requirements to reload
if (ent->client->numClips[weapon] > 0) {
//Elder: more attempts to synchronize the mk23 and akimbos
if (weapon == WP_PISTOL && (ent->client->ps.stats[STAT_WEAPONS] & (1 << WP_AKIMBO) ) ) {
ent->client->ps.ammo[WP_AKIMBO] = ent->client->ps.ammo[WP_AKIMBO] - ent->client->ps.ammo[WP_PISTOL] + ammotoadd;
if (ent->client->ps.ammo[WP_AKIMBO] > RQ3_AKIMBO_AMMO) {
ent->client->ps.ammo[WP_AKIMBO] = RQ3_AKIMBO_AMMO;
}
}
else if (weapon == WP_AKIMBO) {
//Elder: refill the MK23 as well
ent->client->ps.ammo[WP_PISTOL] = RQ3_PISTOL_AMMO;
}
ent->client->ps.ammo[weapon] = ammotoadd;
ent->client->numClips[weapon]--;
//Elder: remove an extra "clip" if it's the handcannon or akimbo
if (weapon == WP_HANDCANNON || weapon == WP_AKIMBO)
ent->client->numClips[weapon]--;
//Elder: sync hc and m3 ammo + mk23 and akimbo ammo - a switch might look nicer
if (weapon == WP_M3) {
ent->client->numClips[WP_HANDCANNON] = ent->client->numClips[WP_M3];
}
else if (weapon == WP_HANDCANNON) {
ent->client->numClips[WP_M3] = ent->client->numClips[WP_HANDCANNON];
}
else if(weapon == WP_PISTOL) {
ent->client->numClips[WP_AKIMBO] = ent->client->numClips[WP_PISTOL];
}
else if (weapon == WP_AKIMBO) {
ent->client->numClips[WP_PISTOL] = ent->client->numClips[WP_AKIMBO];
}
}
}
/*
==================
@ -1701,6 +1785,7 @@ void Cmd_Reload( gentity_t *ent ) {
==================
*/
//Blaze: Moved to bg_misc.c because of needs for this funcion else
//Elder: def'd in bg_public.h
/*
int ClipAmountForWeapon( int w ) {
//How much each clip holds
@ -1753,6 +1838,7 @@ void Cmd_OpenDoor(gentity_t *ent)
}
// Hawkisn todo: Must be set on a per-weapon basis, not a per-user basis.
/* Homer: This function is useful only if it applies to all weapons, which is not the case here.
void toggleSemi(gentity_t *ent){
ent->client->semi = !(ent->client->semi);
if(ent->client->semi)
@ -1760,34 +1846,56 @@ void toggleSemi(gentity_t *ent){
else
trap_SendServerCommand( ent-g_entities, va("print \"Switched to full automatic.\n\""));
}
*/
/* Hawkins. Reaction weapon command */
void Cmd_Weapon(gentity_t *ent)
{
switch(ent->s.weapon){
case WP_SSG3000:
// zoom is done by client. zoom 3 levels, then zoom out
if(ent->client->zoomed==3)
ent->client->zoomed=0;
else
//Elder: This is just for the server to track when calcing the spread
if(ent->client->zoomed == 3) {
ent->client->zoomed = 0;
}
else {
ent->client->zoomed++;
G_Printf("zoomlevel = %d\n",ent->client->zoomed);
G_AddEvent(ent,EV_ZOOM,ent->client->zoomed);
}
//Elder: don't print - will broadcast to server
//G_Printf("zoomlevel = %d\n",ent->client->zoomed);
//G_AddEvent(ent,EV_ZOOM,ent->client->zoomed);
break;
case WP_PISTOL:
toggleSemi(ent);
// semiauto toggle (increase accuracy)
ent->client->mk23semi = !(ent->client->mk23semi);
if (ent->client->mk23semi)
trap_SendServerCommand( ent-g_entities, va("print \"Switched to semi-automatic.\n\""));
else
trap_SendServerCommand( ent-g_entities, va("print \"Switched to full automatic.\n\""));
break;
case WP_M4:
toggleSemi(ent);
// 3rb/full auto toggle
ent->client->m4_3rb = !(ent->client->m4_3rb);
if (ent->client->m4_3rb)
trap_SendServerCommand( ent-g_entities, va("print \"Switched to 3 round burst.\n\""));
else
trap_SendServerCommand( ent-g_entities, va("print \"Switched to full automatic.\n\""));
break;
case WP_MP5:
toggleSemi(ent);
// 3rb/full auto toggle
ent->client->mp5_3rb = !(ent->client->mp5_3rb);
if (ent->client->mp5_3rb)
trap_SendServerCommand( ent-g_entities, va("print \"Switched to 3 round burst.\n\""));
else
trap_SendServerCommand( ent-g_entities, va("print \"Switched to full automatic.\n\""));
break;
case WP_KNIFE:
// toggle throwing/slashing
ent->client->throwKnife = !(ent->client->throwKnife);
if (ent->client->throwKnife)
trap_SendServerCommand( ent-g_entities, va("print \"Switched to throwing.\n\""));
else
trap_SendServerCommand( ent-g_entities, va("print \"Switched to slashing.\n\""));
break;
case WP_HANDCANNON:
// nothing
@ -1800,6 +1908,15 @@ void Cmd_Weapon(gentity_t *ent)
break;
case WP_GRENADE:
// short, medium, long throws
ent->client->grenRange++;
if ( ent->client->grenRange > 2 )
ent->client->grenRange = 0;
if ( ent->client->grenRange == 0 )
trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for short range throw.\n\""));
else if (ent->client->grenRange == 1)
trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for medium range throw.\n\""));
else
trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for long range throw.\n\""));
break;
default:
break;
@ -1808,12 +1925,13 @@ void Cmd_Weapon(gentity_t *ent)
}
/*
// Hawkins make sure spread comes back
void Cmd_Unzoom(gentity_t *ent){
ent->client->zoomed=0;
//G_Printf("Got to Cmd_Unzoom\n");
ent->client->zoomed = 0;
}
*/
/*
=================
@ -1822,7 +1940,7 @@ Cmd_Drop_f XRAY FMJ
*/
void Cmd_Drop_f( gentity_t *ent ) {
ent->client->zoomed=0;
G_AddEvent(ent,EV_ZOOM,0);
//G_AddEvent(ent,EV_ZOOM,0);
ThrowWeapon( ent );
}
@ -1947,6 +2065,8 @@ void ClientCommand( int clientNum ) {
// Hawkins
else if (Q_stricmp (cmd, "weapon") == 0)
Cmd_Weapon (ent);
else if (Q_stricmp (cmd, "unzoom") == 0)
Cmd_Unzoom (ent);
// end hawkins
else if (Q_stricmp (cmd, "dropweapon") == 0) // XRAY FMJ
Cmd_Drop_f( ent );

View file

@ -437,16 +437,18 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
int i;
char *killerName, *obit;
// Hawkins put spread back and zoom out
self->client->zoomed=0;
G_AddEvent(self,EV_ZOOM,0);
//Elder: Can't send events.
//G_AddEvent(self,EV_ZOOM,0);
//Blaze: Stop bleeding when dead
if ( self->client )
{
// Hawkins put spread back and zoom out
//Elder: removed
self->client->zoomed = 0;
self->client->bleeding = 0;
//targ->client->bleedcount = 0;
self->client->bleed_remain = 0;
}
if ( self->client->ps.pm_type == PM_DEAD ) {
@ -952,7 +954,7 @@ int G_InvulnerabilityEffect( gentity_t *targ, vec3_t dir, vec3_t point, vec3_t i
#endif
/*
============
T_Damage
G_Damage
targ entity that is being damaged
inflictor entity that is causing the damage
@ -1008,6 +1010,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
if ( level.intermissionQueued ) {
return;
}
#ifdef MISSIONPACK
if ( targ->client && mod != MOD_JUICED) {
if ( targ->client->invulnerabilityTime > level.time) {
@ -1255,7 +1258,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
mod == MOD_KNIFE)
{
bleeding = 1;
instant_dam = 0;
instant_dam = 0;
// Point[2] is the REAL world Z. We want Z relative to the clients feet

View file

@ -24,7 +24,8 @@
#define RESPAWN_POWERUP 120
//Blaze: used for setting amount of ammo a gun has when picked up around line 249
extern int ClipAmountForWeapon(int);
//Elder: Def'd in bg_public.h which g_local.h looks up
//extern int ClipAmountForWeapon(int);
//======================================================================
int Pickup_Powerup( gentity_t *ent, gentity_t *other ) {
@ -190,32 +191,41 @@ int Pickup_Holdable( gentity_t *ent, gentity_t *other ) {
void Add_Ammo (gentity_t *ent, int weapon, int count)
{
//Blaze: Reaction stuff, add to clip when picking up ammo packs
//Elder: Modified to use constants def'd in bg_public.h
ent->client->numClips[weapon] += count;
switch (weapon)
{
case WP_KNIFE:
//Blaze: you get more knifes by picking up the "gun" as opposed to ammo
break;
case WP_PISTOL:
if (ent->client->numClips[weapon] > 2) ent->client->numClips[weapon] = 2;
if (ent->client->numClips[weapon] > RQ3_PISTOL_MAXCLIP)
ent->client->numClips[weapon] = RQ3_PISTOL_MAXCLIP;
break;
case WP_AKIMBO:
if (ent->client->numClips[weapon] > 2) ent->client->numClips[weapon] = 2;
if (ent->client->numClips[weapon] > RQ3_AKIMBO_MAXCLIP)
ent->client->numClips[weapon] = RQ3_AKIMBO_MAXCLIP;
break;
case WP_MP5:
if (ent->client->numClips[weapon] > 2) ent->client->numClips[weapon] = 2;
if (ent->client->numClips[weapon] > RQ3_MP5_MAXCLIP)
ent->client->numClips[weapon] = RQ3_MP5_MAXCLIP;
break;
case WP_M4:
if (ent->client->numClips[weapon] > 1) ent->client->numClips[weapon] = 1;
if (ent->client->numClips[weapon] > RQ3_M4_MAXCLIP)
ent->client->numClips[weapon] = RQ3_M4_MAXCLIP;
break;
case WP_M3:
if (ent->client->numClips[weapon] > 14) ent->client->numClips[weapon] = 14;
if (ent->client->numClips[weapon] > RQ3_M3_MAXCLIP)
ent->client->numClips[weapon] = RQ3_M3_MAXCLIP;
break;
case WP_HANDCANNON:
if (ent->client->numClips[weapon] > 14) ent->client->numClips[weapon] = 14;
if (ent->client->numClips[weapon] > RQ3_HANDCANNON_MAXCLIP)
ent->client->numClips[weapon] = RQ3_HANDCANNON_MAXCLIP;
break;
case WP_SSG3000:
if (ent->client->numClips[weapon] > 20) ent->client->numClips[weapon] = 20;
if (ent->client->numClips[weapon] > RQ3_SSG3000_MAXCLIP)
ent->client->numClips[weapon] = RQ3_SSG3000_MAXCLIP;
break;
case WP_GRENADE:
//Blaze: you get more knifes by picking up the "gun" as opposed to ammo
@ -226,6 +236,21 @@ void Add_Ammo (gentity_t *ent, int weapon, int count)
break;
}
//Elder: sync HC and M3 ammo
if(weapon == WP_M3) {
ent->client->numClips[WP_HANDCANNON] = ent->client->numClips[WP_M3];
}
else if (weapon == WP_HANDCANNON){
ent->client->numClips[WP_M3] = ent->client->numClips[WP_HANDCANNON];
}
//Elder: sync Akimbo and MK23 ammo
else if(weapon == WP_PISTOL) {
ent->client->numClips[WP_AKIMBO] = ent->client->numClips[WP_PISTOL];
}
else if (weapon == WP_AKIMBO){
ent->client->numClips[WP_PISTOL] = ent->client->numClips[WP_AKIMBO];
}
//ent->client->ps.ammo[weapon] += count;
//if ( ent->client->ps.ammo[weapon] > 200 ) {
// ent->client->ps.ammo[weapon] = 200;
@ -252,9 +277,6 @@ int Pickup_Ammo (gentity_t *ent, gentity_t *other)
int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
int quantity,ammotoadd;
if ( ent->count < 0 ) {
quantity = 0; // None for you, sir!
} else {
@ -284,50 +306,77 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
switch (ent->item->giTag)
{
case WP_KNIFE:
if (other->client->ps.ammo[ent->item->giTag] < 10)
if (other->client->ps.ammo[ent->item->giTag] < RQ3_KNIFE_MAXCLIP)
{
//G_Printf("(%d)\n",other->client->ps.ammo[ent->item->giTag]);
ammotoadd=other->client->ps.ammo[ent->item->giTag]+1;
}
else
{
ammotoadd=10;
ammotoadd = RQ3_KNIFE_MAXCLIP;
}
break;
case WP_PISTOL:
ammotoadd=12;
//Elder: special case
//Someone can optimize this code later, but for now, it works.
if ( !(other->client->ps.stats[STAT_WEAPONS] & (1 << WP_AKIMBO) ) ) {
//give akimbo
G_Printf("Dual MK23 pistols\n");
other->client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_AKIMBO );
other->client->ps.ammo[WP_AKIMBO] = other->client->ps.ammo[WP_PISTOL] + RQ3_PISTOL_AMMO;
ammotoadd = other->client->ps.ammo[WP_PISTOL];
}
//Elder: Already have akimbo - technically should have pistol
else if (other->client->numClips[ WP_PISTOL ] < 2) {
//give an extra clip - make < 2 + 2 * hasBandolier(0/1) or something for bando when it's in
G_Printf("Picked up an extra clip\n");
other->client->numClips[ WP_PISTOL ]++;
other->client->numClips[ WP_AKIMBO ]++;
ammotoadd = other->client->ps.ammo[WP_PISTOL];
}
else {
//Elder: maxed out on clips, have akimbo - can't take more!
ammotoadd = other->client->ps.ammo[WP_PISTOL];
}
break;
case WP_AKIMBO:
ammotoadd=24;
//Elder: Should not need to come here
ammotoadd= RQ3_AKIMBO_AMMO;
break;
case WP_MP5:
ammotoadd=30;
ammotoadd= RQ3_MP5_AMMO;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
break;
case WP_M4:
ammotoadd=24;
ammotoadd= RQ3_M4_AMMO;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
break;
case WP_M3:
ammotoadd=7;
ammotoadd= RQ3_M3_AMMO ;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
break;
case WP_HANDCANNON:
ammotoadd=2;
ammotoadd= RQ3_HANDCANNON_AMMO;
//Elder: HC gets 2 in chamber and 5 in reserve
//Also sync with M3
//Removed until we can store the amount of ammo in the gun
//When it's dropped
//other->client->numClips[ WP_HANDCANNON ] += 5;
//other->client->numClips[ WP_M3 ] += 5;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
break;
case WP_SSG3000:
ammotoadd=6;
ammotoadd= RQ3_SSG3000_AMMO;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
break;
case WP_GRENADE:
if (other->client->ps.ammo[ent->item->giTag] < 2)
if (other->client->ps.ammo[ent->item->giTag] < RQ3_GRENADE_MAXCLIP)
{
ammotoadd=other->client->ps.ammo[ent->item->giTag]+1;
}
else
{
ammotoadd=2;
ammotoadd= RQ3_GRENADE_MAXCLIP;
}
break;
default:
@ -522,32 +571,55 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
switch(ent->item->giTag)
{
//Blaze: Check to see if we already have the weapon, If not so check and see if we have less then full ammo, if so pick up gun
//Elder: this is really confusing - FIXME
case WP_KNIFE:
if (!other->client->ps.stats[STAT_WEAPONS] & WP_KNIFE == WP_KNIFE && (other->client->ps.ammo[ent->item->giTag] >= 10) ) return;
if (!other->client->ps.stats[STAT_WEAPONS] & WP_KNIFE == WP_KNIFE &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_KNIFE_MAXCLIP) )
return;
break;
case WP_PISTOL:
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_PISTOL == WP_PISTOL) && (other->client->ps.stats[STAT_CLIPS] >= 2) ) return;
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_PISTOL == WP_PISTOL) &&
(other->client->ps.stats[STAT_CLIPS] >= RQ3_PISTOL_MAXCLIP) )
//Elder: why are we checking clips here but ammo in the others and what-not??
return;
break;
case WP_M3:
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_M3 == WP_M3) && (other->client->ps.ammo[ent->item->giTag] >= 7) ) return;
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_M3 == WP_M3) &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_M3_AMMO) )
return;
break;
case WP_HANDCANNON:
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_HANDCANNON == WP_HANDCANNON) && (other->client->ps.ammo[ent->item->giTag] >= 2) ) return;
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_HANDCANNON == WP_HANDCANNON) &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_HANDCANNON_AMMO) )
return;
break;
case WP_MP5:
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_MP5 == WP_MP5) && (other->client->ps.stats[STAT_CLIPS] >= 2) ) return;
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_MP5 == WP_MP5) &&
(other->client->ps.stats[STAT_CLIPS] >= RQ3_MP5_MAXCLIP) )
return;
break;
case WP_M4:
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_M4 == WP_M4) && (other->client->ps.stats[STAT_CLIPS] >= 1) ) return;
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_M4 == WP_M4) &&
(other->client->ps.stats[STAT_CLIPS] >= RQ3_M4_MAXCLIP) )
return;
break;
case WP_SSG3000:
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_SSG3000 == WP_SSG3000) && (other->client->ps.ammo[ent->item->giTag] >= 6) )return;
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_SSG3000 == WP_SSG3000) &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_SSG3000_AMMO ) )
return;
break;
case WP_AKIMBO:
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_AKIMBO == WP_AKIMBO) && (other->client->ps.stats[STAT_CLIPS] >= 24) ) return;
//Elder: uhh- 24 clips?
//if (!(other->client->ps.stats[STAT_WEAPONS] & WP_AKIMBO == WP_AKIMBO) &&
//(other->client->ps.stats[STAT_CLIPS] >= 24) ) return;
if (!(other->client->ps.stats[STAT_WEAPONS] & WP_AKIMBO == WP_AKIMBO) &&
(other->client->ps.stats[STAT_CLIPS] >= RQ3_AKIMBO_MAXCLIP) )
return;
break;
case WP_GRENADE:
if (!other->client->ps.stats[STAT_WEAPONS] & WP_GRENADE == WP_GRENADE && (other->client->ps.ammo[ent->item->giTag] >= 2)) return;
if (!other->client->ps.stats[STAT_WEAPONS] & WP_GRENADE == WP_GRENADE &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_GRENADE_MAXCLIP))
return;
break;
}
//Blaze: Check and see if it's a unique weapon, and if so make sure they dont have too many already
@ -578,25 +650,25 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
if (other->client->numClips[ent->item->giTag] >= 0) return;//No clips for knifes
break;
case WP_PISTOL:
if (other->client->numClips[ent->item->giTag] >= 2 ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_PISTOL_MAXCLIP ) return;
break;
case WP_M3:
if (other->client->numClips[ent->item->giTag] >= 14) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_M3_MAXCLIP) return;
break;
case WP_HANDCANNON:
if (other->client->numClips[ent->item->giTag] >= 14) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_HANDCANNON_MAXCLIP) return;
break;
case WP_MP5:
if (other->client->numClips[ent->item->giTag] >= 2 ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_MP5_MAXCLIP ) return;
break;
case WP_M4:
if (other->client->numClips[ent->item->giTag] >= 1 ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_M4_MAXCLIP ) return;
break;
case WP_SSG3000:
if (other->client->numClips[ent->item->giTag] >= 20 ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_SSG3000_MAXCLIP ) return;
break;
case WP_AKIMBO:
if (other->client->numClips[ent->item->giTag] >= 2 ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_AKIMBO_MAXCLIP ) return;
break;
case WP_GRENADE:
if (other->client->numClips[ent->item->giTag] >= 0 ) return;//no clips for grenades

View file

@ -40,7 +40,9 @@
#define FL_NO_BOTS 0x00002000 // spawn point not for bot use
#define FL_NO_HUMANS 0x00004000 // spawn point just for bots
#define FL_FORCE_GESTURE 0x00008000 // force gesture on client
#define FL_THROWN_ITEM 0x00016000 // XRAY FMJ weapon throwing
//Elder: err - this looks funny... should it be 0x00010000 ?
//#define FL_THROWN_ITEM 0x00016000 // XRAY FMJ weapon throwing
#define FL_THROWN_ITEM 0x00010000 // XRAY FMJ weapon throwing
// movers are things like doors, plats, buttons, etc
typedef enum {
@ -328,9 +330,18 @@ struct gclient_s {
//qboolean isbleeding;//Blaze: is client bleeding
int legDamage;//Blaze: Client has leg damage
int bleedtick;//Blaze: Holds # of seconds till bleeding stops.
//Elder: server only needs to know for sniper spread - ARGH
int zoomed; // Hawkins (SSG zoom)
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
// Homer: weaponstate vars for Cmd_Weapon
// make these a single bitmask? worth the effort?
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
// end Homer
#ifdef MISSIONPACK
gentity_t *persistantPowerup;
int portalID;
@ -344,7 +355,8 @@ struct gclient_s {
// Begin Duffman
int G_LocationDamage(vec3_t point, gentity_t* targ, gentity_t* attacker, int take);
void Cmd_Reload( gentity_t *ent ); // reloads the current weapon
int ClipAmountForWeapon( int w ); // returns the maximum ammo for the current weapon
// Elder: removed - prototype in bg_public.h
// int ClipAmountForWeapon( int w ); // returns the maximum ammo for the current weapon
// End Duffman
//
@ -465,7 +477,8 @@ void StopFollowing( gentity_t *ent );
void BroadcastTeamChange( gclient_t *client, int oldTeam );
void SetTeam( gentity_t *ent, char *s );
void Cmd_FollowCycle_f( gentity_t *ent, int dir );
void toggleSemi(gentity_t *ent);
//Elder: commented out for Homer
//void toggleSemi(gentity_t *ent);
//
// g_items.c
@ -505,6 +518,8 @@ void G_SetMovedir ( vec3_t angles, vec3_t movedir);
void G_InitGentity( gentity_t *e );
gentity_t *G_Spawn (void);
gentity_t *G_TempEntity( vec3_t origin, int event );
//Elder: added
gentity_t *G_TempEntity2( vec3_t origin, int event, int eParm );
void G_Sound( gentity_t *ent, int channel, int soundIndex );
void G_FreeEntity( gentity_t *e );
@ -589,7 +604,6 @@ void DropPortalDestination( gentity_t *ent );
void G_BreakGlass( gentity_t *ent, vec3_t point, int mod );//Blaze: Breakable glass
//
// g_weapon.c
//

View file

@ -314,87 +314,133 @@ Fires at either the target or the current direction.
//}
//Blaze: Breakable glasss
//Elder: Breakable anything!* -- we define, that is
/*QUAKED func_breakable (1 0 0) (-16 -16 -16) (16 16 16)
Explodes glass
Explodes any defined type of debris
"health" overrides the default health value of 5
"debris" overrides the default glass shards
0 - glass
1 - wood
2 - metal
3 - ceramics
4 - paper
5 - pop cans
"amount" overrides the default quantity
0 - small: about 10 pieces
1 - medium: about 25 pieces
2 - large: about 50 pieces
3 - tons (watch out when using this)
*/
void SP_func_breakable( gentity_t *ent ) {
int health;
void SP_func_breakable( gentity_t *ent ) {
int amount;
int health;
int debris;
int temp;
// Make it appear as the brush
trap_SetBrushModel( ent, ent->model );
// Lets give it 5 health if the mapper did not set its health
G_SpawnInt( "health", "0", &health );
if( health <= 0 )
health = 5;
ent->health = health;
// Let it take damage
ent->takedamage = qtrue;
// Let it know it is a breakable object
ent->s.eType = ET_BREAKABLE;
// If the mapper gave it a model, use it
if ( ent->model2 ) {
ent->s.modelindex2 = G_ModelIndex( ent->model2 );
}
// Link all ^this^ info into the ent
trap_LinkEntity (ent);
}
// Make it appear as the brush
trap_SetBrushModel( ent, ent->model );
// Lets give it 5 health if the mapper did not set its health
G_SpawnInt( "health", "0", &health );
if( health <= 0 )
health = 5;
G_SpawnInt( "debris", "0", &temp );
//Elder: hardcoded - I guess I should enum this
if (temp < 0 || temp > 3)
debris = RQ3_DEBRIS_GLASS;
else
debris = (1 << temp + 4);
G_SpawnInt( "amount", "0", &temp );
if (temp < 0 || temp > 3)
amount = RQ3_DEBRIS_MEDIUM;
else
amount = (1 << amount);
//Elder: merge the bits
ent->s.eventParm = 0;
ent->s.eventParm |= debris;
ent->s.eventParm |= amount;
ent->health = health;
// Let it take damage
ent->takedamage = qtrue;
// Let it know it is a breakable object
ent->s.eType = ET_BREAKABLE;
// If the mapper gave it a model, use it
if ( ent->model2 ) {
ent->s.modelindex2 = G_ModelIndex( ent->model2 );
}
// Link all ^this^ info into the ent
trap_LinkEntity (ent);
}
/*
=================
G_BreakGlass
=================
*/
void G_BreakGlass(gentity_t *ent, vec3_t point, int mod) {
gentity_t *tent;
void G_BreakGlass(gentity_t *ent, vec3_t point, int mod) {
gentity_t *tent;
vec3_t size;
vec3_t center;
vec3_t center;
qboolean splashdmg;
int eParm;
// Get the center of the glass
VectorSubtract(ent->r.maxs, ent->r.mins, size);
VectorScale(size, 0.5, size);
VectorAdd(ent->r.mins, size, center);
VectorSubtract(ent->r.maxs, ent->r.mins, size);
VectorScale(size, 0.5, size);
VectorAdd(ent->r.mins, size, center);
// If the glass has no more life, BREAK IT
if( ent->health <= 0 ) {
G_FreeEntity( ent );
// Tell the program based on the gun if it has no splash dmg, no reason to ad ones with
// splash dmg as qtrue as is that is the default
switch( mod ) {
case MOD_GAUNTLET:
splashdmg = qfalse;
break;
case MOD_KICK:
splashdmg = qfalse;
break;
case MOD_SHOTGUN:
splashdmg = qfalse;
break;
case MOD_MACHINEGUN:
splashdmg = qfalse;
break;
case MOD_RAILGUN:
splashdmg = qfalse;
break;
case MOD_LIGHTNING:
splashdmg = qfalse;
break;
default:
splashdmg = qtrue;
break;
}
// Call the function to show the glass shards in cgame
// center can be changed to point which will spawn the
// where the killing bullet hit but wont work with Splash Damage weapons
// so I just use the center of the glass
switch( splashdmg ){
case qtrue:
tent = G_TempEntity( center, EV_BREAK_GLASS );
break;
case qfalse:
tent = G_TempEntity( point, EV_BREAK_GLASS );
break;
}
tent->s.eventParm = 0;
//Elder: using event param to specify debris type
eParm = ent->s.eventParm;
//G_Printf("eParm: %d, original: %d\n", eParm, ent->s.eventParm);
//Elder: free it after the eventParm assignment
G_FreeEntity( ent );
// Tell the program based on the gun if it has no splash dmg, no reason to ad ones with
// splash dmg as qtrue as is that is the default
switch( mod ) {
//Elder: added + compacted
case MOD_KNIFE:
case MOD_KNIFE_THROWN:
case MOD_M4:
case MOD_M3:
case MOD_PISTOL:
case MOD_HANDCANNON:
case MOD_AKIMBO:
case MOD_SNIPER:
case MOD_GAUNTLET:
case MOD_KICK:
//case MOD_SHOTGUN:
//case MOD_MACHINEGUN:
//case MOD_RAILGUN:
//case MOD_LIGHTNING:
splashdmg = qfalse;
break;
default:
splashdmg = qtrue;
break;
}
// Call the function to show the glass shards in cgame
// center can be changed to point which will spawn the
// where the killing bullet hit but wont work with Splash Damage weapons
// so I just use the center of the glass
switch( splashdmg ) {
case qtrue:
//Elder: use TempEntity2 to stuff params
//tent = G_TempEntity( center, EV_BREAK_GLASS );
tent = G_TempEntity2( center, EV_BREAK_GLASS, eParm );
break;
case qfalse:
//tent = G_TempEntity( point, EV_BREAK_GLASS );
tent = G_TempEntity2( point, EV_BREAK_GLASS, eParm );
break;
}
//Elder: maybe we can use this to tell the client to spawn different debris
//tent->s.eventParm = 0;
tent->s.eventParm = eParm;
}
}

View file

@ -329,8 +329,14 @@ qboolean G_MoverPush( gentity_t *pusher, vec3_t move, vec3_t amove, gentity_t **
// the move was blocked an entity
// bobbing entities are instant-kill and never get blocked
//Elder: Pendulum killer code - commented out for now
//But it has to PUSH the client off... I don't know how just yet :(
if ( pusher->s.pos.trType == TR_SINE || pusher->s.apos.trType == TR_SINE ) {
G_Damage( check, pusher, pusher, NULL, NULL, 99999, 0, MOD_CRUSH );
//Elder: debug code
G_Printf("RQ3: TR_SINE crusher code removed\n");
//Elder: temp - player will stop the pendulum from going
return qfalse;
//G_Damage( check, pusher, pusher, NULL, NULL, 99999, 0, MOD_CRUSH );
continue;
}

View file

@ -183,7 +183,8 @@ void SP_trigger_push( gentity_t *self ) {
self->r.svFlags &= ~SVF_NOCLIENT;
// make sure the client precaches this sound
G_SoundIndex("sound/world/jumppad.wav");
//Elder: edited for now TODO: let mappers use a key pair
//G_SoundIndex("sound/world/jumppad.wav");
self->s.eType = ET_PUSH_TRIGGER;
self->touch = trigger_push_touch;
@ -227,9 +228,11 @@ void SP_target_push( gentity_t *self ) {
VectorScale (self->s.origin2, self->speed, self->s.origin2);
if ( self->spawnflags & 1 ) {
self->noise_index = G_SoundIndex("sound/world/jumppad.wav");
//Elder: edited for now TODO: let mappers use a key pair
//self->noise_index = G_SoundIndex("sound/world/jumppad.wav");
} else {
self->noise_index = G_SoundIndex("sound/misc/windfly.wav");
//Elder: edited for now TODO: let mappers use a key pair
//self->noise_index = G_SoundIndex("sound/misc/windfly.wav");
}
if ( self->target ) {
VectorCopy( self->s.origin, self->r.absmin );

View file

@ -485,6 +485,33 @@ gentity_t *G_TempEntity( vec3_t origin, int event ) {
return e;
}
/*
=================
G_TempEntity2
Elder: Like above, except can sneak in event parameters
=================
*/
gentity_t *G_TempEntity2( vec3_t origin, int event, int eParm ) {
gentity_t *e;
vec3_t snapped;
e = G_Spawn();
e->s.eType = ET_EVENTS + event;
e->s.eventParm = eParm;
e->classname = "tempEntity";
e->eventTime = level.time;
e->freeAfterEvent = qtrue;
VectorCopy( origin, snapped );
SnapVector( snapped ); // save network bandwidth
G_SetOrigin( e, snapped );
// find cluster for PVS
trap_LinkEntity( e );
return e;
}
/*

View file

@ -165,7 +165,8 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) {
gentity_t *traceEnt;
int i, passent;
damage *= s_quadFactor;
//Elder: removed - for some reason it's set to 0
//damage *= s_quadFactor;
r = random() * M_PI * 2.0f;
u = sin(r) * crandom() * spread * 16;
@ -282,7 +283,7 @@ qboolean ShotgunPellet( vec3_t start, vec3_t end, gentity_t *ent ) {
}
if ( traceEnt->takedamage) {
damage = DEFAULT_SHOTGUN_DAMAGE * s_quadFactor;
damage = DEFAULT_SHOTGUN_DAMAGE; // * s_quadFactor;
#ifdef MISSIONPACK
if ( traceEnt->client && traceEnt->client->invulnerabilityTime > level.time ) {
if (G_InvulnerabilityEffect( traceEnt, forward, tr.endpos, impactpoint, bouncedir )) {
@ -868,7 +869,8 @@ G_Printf("Knife Touched Something\n");
G_FreeEntity (ent);
}
gentity_t *Knife_Throw (gentity_t *self,vec3_t start, vec3_t dir, int damage, int speed )
//gentity_t *Knife_Throw (gentity_t *self,vec3_t start, vec3_t dir, int damage, int speed )
gentity_t* Knife_Throw (gentity_t *self,vec3_t start, vec3_t dir, int damage, int speed )
{
gentity_t *bolt;
@ -930,6 +932,13 @@ void Weapon_Knife_Fire(gentity_t *ent)
// Knife_Attack(ent,THROW_DAMAGE);
gentity_t *m;
// Homer: if client is supposed to be slashing, go to that function instead
if ( !ent->client->throwKnife )
{
Knife_Attack(ent,SLASH_DAMAGE);
return;
}
// extra vertical velocity
forward[2] += 0.2f;
@ -937,8 +946,9 @@ void Weapon_Knife_Fire(gentity_t *ent)
VectorNormalize( forward );
m = Knife_Throw(ent,muzzle,forward, THROW_DAMAGE, 1200);
m->damage *= s_quadFactor;
m->splashDamage *= s_quadFactor;
// m->damage *= s_quadFactor;
// m->splashDamage *= s_quadFactor;
// ^^^^ Homer: got quad?
@ -952,8 +962,11 @@ M4 Attack
void Weapon_M4_Fire(gentity_t *ent)
{
float spread;
spread = (ent->client->semi? M4_SPREAD*.7 : M4_SPREAD);
Bullet_Fire( ent, RQ3Spread(ent, spread), M4_DAMAGE, MOD_M4);
// Homer: increment burst if needed
if ( ent->client->m4_3rb )
ent->client->ps.stats[STAT_BURST]++;
spread = (ent->client->m4_3rb? M4_SPREAD*.7 : M4_SPREAD);
Bullet_Fire( ent, RQ3Spread(ent, M4_SPREAD), M4_DAMAGE, MOD_M4);
}
@ -965,7 +978,10 @@ MK23 Attack
void Weapon_MK23_Fire(gentity_t *ent)
{
float spread;
spread = (ent->client->semi? PISTOL_SPREAD*.7 : PISTOL_SPREAD);
// Homer: increment burst if needed
if ( ent->client->mk23semi )
ent->client->ps.stats[STAT_BURST]++;
spread = (ent->client->mk23semi? PISTOL_SPREAD*.7 : PISTOL_SPREAD);
Bullet_Fire( ent, RQ3Spread(ent, spread), PISTOL_DAMAGE, MOD_PISTOL);
}
@ -977,7 +993,8 @@ SSG3000 Attack
*/
void Weapon_SSG3000_Fire(gentity_t *ent)
{
//Elder: Don't print - will broadcast to server
//G_Printf("Zoom Level: %d\n", ent->client->zoomed);
Bullet_Fire( ent, ( ent->client->zoomed?0:SNIPER_SPREAD), SNIPER_DAMAGE, MOD_SNIPER);
}
@ -990,8 +1007,11 @@ MP5 Attack
void Weapon_MP5_Fire(gentity_t *ent)
{
float spread;
spread = (ent->client->semi? MP5_SPREAD*.7 : MP5_SPREAD);
Bullet_Fire( ent, RQ3Spread(ent, spread), MP5_DAMAGE, MOD_MP5);
// Homer: increment burst if needed
if ( ent->client->mp5_3rb )
ent->client->ps.stats[STAT_BURST]++;
spread = (ent->client->mp5_3rb? MP5_SPREAD*.7 : MP5_SPREAD);
Bullet_Fire( ent, RQ3Spread(ent, MP5_SPREAD), MP5_DAMAGE, MOD_MP5);
}
/*
@ -1052,8 +1072,8 @@ void Weapon_Akimbo_Fire(gentity_t *ent)
//Blaze: Will need 2 of these
spread = AKIMBO_SPREAD;
Bullet_Fire( ent, RQ3Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO);
//Bullet_Fire( ent, AKIMBO_SPREAD, AKIMBO_DAMAGE, MOD_AKIMBO);
//Elder: should there be a small delay or is that just the sound effect in AQ2?
Bullet_Fire( ent, RQ3Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO);
}
/*
@ -1070,8 +1090,9 @@ void Weapon_Grenade_Fire(gentity_t *ent)
VectorNormalize( forward );
m = fire_grenade (ent, muzzle, forward);
m->damage *= s_quadFactor;
m->splashDamage *= s_quadFactor;
//Elder: removed
//m->damage *= s_quadFactor;
//m->splashDamage *= s_quadFactor;
// VectorAdd( m->s.pos.trDelta, ent->client->ps.velocity, m->s.pos.trDelta ); // "real" physics
@ -1149,11 +1170,13 @@ FireWeapon
===============
*/
void FireWeapon( gentity_t *ent ) {
/* Homer: got quad?
if (ent->client->ps.powerups[PW_QUAD] ) {
s_quadFactor = g_quadfactor.value;
} else {
s_quadFactor = 1;
}
} else {*/
//Elder: uncommented so it won't be zero!
s_quadFactor = 1;
//}
#ifdef MISSIONPACK
if( ent->client->persistantPowerup && ent->client->persistantPowerup->item && ent->client->persistantPowerup->item->giTag == PW_DOUBLER ) {
s_quadFactor *= 2;

View file

@ -1,4 +1,4 @@
set path=c:\quake3\bin_nt;%PATH%
rem set path=c:\quake3\bin_nt;%PATH%
rem The following line is to circumvent MS Platform SDK install crap
set include=
mkdir vm

View file

@ -275,7 +275,8 @@ typedef enum {
#define PROP_GAP_WIDTH 3
#define PROP_SPACE_WIDTH 8
#define PROP_HEIGHT 27
//Elder: changed to fit new font from 27
#define PROP_HEIGHT 24
#define PROP_SMALL_SIZE_SCALE 0.75
#define BLINK_DIVISOR 200

View file

@ -25,6 +25,7 @@ void CheckBleeding(gentity_t *targ)
}
}
//Elder: apparently does nothing
void StartBandage(gentity_t *ent)
{
ent->client->bleeding = 0;