as released 1999-06-20
This commit is contained in:
parent
bccddaa7fd
commit
5a8aa10e57
31 changed files with 8112 additions and 5729 deletions
148
CHANGES
148
CHANGES
|
@ -1,3 +1,151 @@
|
|||
CHANGES FROM ACTION 1.51 to ACTION 1.52
|
||||
|
||||
o Support for friendly-fire in teamplay added. IF YOU ARE NOT ALREADY
|
||||
USING THE "NO FRIENDLY FIRE" FLAG IN YOUR DMFLAGS, YOU NEED TO ADD IT NOW
|
||||
IF YOU DON'T WANT TO USE FRIENDLY FIRE. The value for "no friendly fire"
|
||||
is 256. For a normal AQ teamplay game, you should set your dmflags to 256
|
||||
in your server.cfg ("set dmflags 256"). I believe the only other dmflag
|
||||
that would have a worthwhile effect on AQ teamplay is the "spawn farthest"
|
||||
flag (512), no others should be set unless you want the spawn farthest
|
||||
behavior. So...if you want FF in teamplay, set your dmflags to 0. If you
|
||||
don't, set it to 256. No friendly fire is the "normal" style of play, so
|
||||
the default/standard dmflags for AQ teamplay should be considered to be
|
||||
256. When FF is in effect, notification of it will be on the standard
|
||||
MOTD. Temporary banning for people who kill too many team members is
|
||||
available. The "maxteamkills" server cvar can be used to control the
|
||||
maximum number of teamkills that a player can make on a given map before
|
||||
he is kicked and temporarily banned, the default is 0 which means never
|
||||
temporarily ban. The "tkbanrounds" and "twbanrounds" variables affect ban
|
||||
time, see the README file for complete info. Players lose one frag for
|
||||
killing a teammate. Thanks go to Eek and Azerov for providing the patch
|
||||
which we used as a basis for this feature.
|
||||
|
||||
o Shot placement on crouching players is much improved and should
|
||||
basically be consistent with standing players now. Also, the view height
|
||||
of crouching players has been modified somewhat so it's more consistent
|
||||
with the actual amount of height loss that occurs. (thanks go to Mikael
|
||||
Lindh from AQ:Gangsters for lots of help in this area.)
|
||||
|
||||
o The shotgun and handcannon now inform you who you're hitting, when you
|
||||
hit someone, much like all the other weapons already did.
|
||||
|
||||
o New server variable "limchasecam" now available for clan match usage.
|
||||
See info in the README. When the chase cam limits are in effect, a line
|
||||
will be added to the MOTD stating it. (thanks to Black Cross for
|
||||
submitting the patch for this feature.)
|
||||
|
||||
o Breakable glass now added. Two new server variables for this:
|
||||
"breakableglass" and "glassfragmentlimit". This is not recommended for
|
||||
Internet games (much like the ejecting shells, blood splats, and bullet
|
||||
holes). This was contributed by William van der Sterren of the CGF
|
||||
project. It requires maps that are designed with breakable glass. For
|
||||
more info on how to make breakable glass in maps, see
|
||||
http://www.botepidemic.com/aid/cgf/exp_glass.shtml. For more info on the
|
||||
server variables, see the README.
|
||||
|
||||
o Door kicking added. You can now jump-kick a door open when it opens in
|
||||
the opposite direction. If there is a player sitting on the other side of
|
||||
the door, that player will be kicked along with the door. This was
|
||||
contributed by AQDT (written by Hal, sent to us by Homer).
|
||||
|
||||
o Vertical component of kicking has returned. You can kick people upwards
|
||||
or downwards by looking in that direction before kicking them.
|
||||
|
||||
o New commands "use throwing combat knife" and "use slashing combat knife"
|
||||
allow you to pull out the knife in whichever mode you want, instead of
|
||||
pulling out your knife then switching modes.
|
||||
|
||||
o A new item has been added to the secondary teamplay scoreboard: damage
|
||||
dealt. This number is the amount of damage the given player has inflicted
|
||||
upon other players on the current map. Note this is total damage, not
|
||||
just damage required to kill someone. For example, a point blank
|
||||
handcannon blast can count for a lot more than 100 health, even though it
|
||||
only takes 100 to kill someone. This isn't in the scoreboard if you have
|
||||
turned on the "noscore" option.
|
||||
|
||||
o New "sv nextmap" command allows a server operator to skip to the next
|
||||
map in the rotation (thanks go to Black Cross for submitting the patch for
|
||||
this command).
|
||||
|
||||
o The "spawn farthest" dmflag now works on teamplay games. The second
|
||||
team will spawn as far away from the first team as possible (unlike the
|
||||
normal behavior, where the farthest 1-4 spawn candidates are considered,
|
||||
depending on the total number of candidates).
|
||||
|
||||
o The "needpass" variable is now provided. This allows things like
|
||||
GameSpy to prompt you for a password when you try to connect to a
|
||||
passworded server.
|
||||
|
||||
o Players can no longer use say_team when not on a team, or say_partner
|
||||
when they have no partner.
|
||||
|
||||
o Delayed-death attribution bug fixed (you wouldn't get credit for a kill
|
||||
when someone bled for a while).
|
||||
|
||||
o Various reloading changes: switching from a reloading weapon to a new
|
||||
weapon will not cause the new weapon to be reloaded any longer. The
|
||||
reloading "queue" will immediately empty now whenever a player tries to
|
||||
shoot (assuming he has any ammo left in the gun to shoot) or bandage. Your
|
||||
pistol will no longer begin to reload after you get a sniper rifle or
|
||||
shotgun kicked from your hands while reloading it. The "reload" command
|
||||
no longer does anything during the "lights, camera, action" countdown in a
|
||||
teamplay game. You can no longer reload the pistols, M4's, or MP5's when
|
||||
you've already got a full magazine (to be consistent with the way the
|
||||
other weapons work).
|
||||
|
||||
o Switching between slashing and throwing for knives now gives a message.
|
||||
|
||||
o Increased knife slashing damage.
|
||||
|
||||
o Repeating "Out of ammo" message bug fixed.
|
||||
|
||||
o Lasersight now falls in the correct place if you're using one of the
|
||||
"classic" hand modes.
|
||||
|
||||
o Problem with sniper rifle's "weapon" command/bolt animation fixed (you
|
||||
could fire faster than normal using the right aliases).
|
||||
|
||||
o Dropped grenades now do the same amount of damage as thrown grenades.
|
||||
|
||||
o Green flash when players enter the game in a teamplay game removed (for
|
||||
real this time), as well as the red flash when a player exits the game in
|
||||
a teamplay game.
|
||||
|
||||
o The through-eyes chasecam now properly tracks weapon kick (ie with the
|
||||
M4), and also now gives you IR vision if the person you're viewing through
|
||||
the eyes of is using IR.
|
||||
|
||||
o A few bugs fixed in the way bodies fly after death. Floating bodies and
|
||||
bouncing bodies should be gone.
|
||||
|
||||
o Spectators can no longer drop a knife upon entering a teamplay game.
|
||||
|
||||
o Dead bodies no longer appear red when using IR vision.
|
||||
|
||||
o %-vars (ie %W, %H, and the others) are no longer parsed within players'
|
||||
names (ie a player named %W won't appear as his weapon when he says
|
||||
something).
|
||||
|
||||
o Minor bug in bleeding from grenades fixed.
|
||||
|
||||
o Bug where sniper rifle icon would be stuck on your screen if you were
|
||||
zoomed in when the other team all quit and you got "Not enough players to
|
||||
play!" is fixed.
|
||||
|
||||
o Adjusted spacing in MOTD so certain combinations don't cause lines to go
|
||||
off the edge of the screen.
|
||||
|
||||
o Shotgun shell ejection animation (when using "shelloff 0") improved.
|
||||
|
||||
o Fixed crash that occurred when a server ran a huge amount of maps in the
|
||||
rotation (around 100 or more).
|
||||
|
||||
o ReadConfigFile() now closes its file and SelectFarTeamplaySpawnPoint()
|
||||
frees its memory.
|
||||
|
||||
o Updated Action web page URL in MOTD.
|
||||
|
||||
|
||||
CHANGES FROM ACTION 1.5 TO ACTION 1.51
|
||||
|
||||
o Now remembers how many times reload key was pressed.
|
||||
|
|
23
Makefile
23
Makefile
|
@ -34,7 +34,8 @@ GAME_OBJS = \
|
|||
g_monster.o g_phys.o g_save.o g_spawn.o g_svcmds.o \
|
||||
g_target.o g_trigger.o g_turret.o g_utils.o g_weapon.o g_chase.o \
|
||||
p_client.o p_hud.o p_trail.o p_view.o p_weapon.o q_shared.o \
|
||||
m_move.o a_team.o a_game.o a_items.o a_cmds.o a_radio.o a_menu.o
|
||||
m_move.o a_team.o a_game.o a_items.o a_cmds.o a_radio.o a_menu.o \
|
||||
cgf_sfx_glass.o a_doorkick.o
|
||||
|
||||
game$(ARCH).$(SHLIBEXT) : $(GAME_OBJS)
|
||||
$(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(GAME_OBJS)
|
||||
|
@ -63,7 +64,7 @@ g_ai.o: g_ai.c g_local.h q_shared.h game.h a_team.h a_game.h a_menu.h \
|
|||
g_cmds.o: g_cmds.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h m_player.h
|
||||
g_combat.o: g_combat.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
g_func.o: g_func.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
g_items.o: g_items.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
|
@ -71,13 +72,13 @@ g_items.o: g_items.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
|||
g_main.o: g_main.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
g_misc.o: g_misc.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
g_monster.o: g_monster.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
g_phys.o: g_phys.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
g_save.o: g_save.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
g_spawn.o: g_spawn.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
g_svcmds.o: g_svcmds.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
|
@ -91,11 +92,11 @@ g_turret.o: g_turret.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
|||
g_utils.o: g_utils.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
g_weapon.o: g_weapon.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
g_chase.o: g_chase.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
p_client.o: p_client.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h m_player.h
|
||||
a_menu.h a_radio.h m_player.h cgf_sfx_glass.h
|
||||
p_hud.o: p_hud.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
p_trail.o: p_trail.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
|
@ -108,9 +109,9 @@ q_shared.o: q_shared.c q_shared.h
|
|||
m_move.o: m_move.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_team.o: a_team.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
a_game.o: a_game.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
a_items.o: a_items.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
a_cmds.o: a_cmds.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
|
@ -119,3 +120,7 @@ a_radio.o: a_radio.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
|||
a_menu.h a_radio.h
|
||||
a_menu.o: a_menu.c g_local.h q_shared.h game.h a_team.h a_game.h \
|
||||
a_menu.h a_radio.h
|
||||
cgf_sfx_glass.o: cgf_sfx_glass.c g_local.h q_shared.h game.h a_team.h \
|
||||
a_game.h a_menu.h a_radio.h cgf_sfx_glass.h
|
||||
a_doorkick.o: a_doorkick.c g_local.h q_shared.h game.h a_team.h \
|
||||
a_game.h a_menu.h a_radio.h
|
||||
|
|
62
README
62
README
|
@ -1,4 +1,4 @@
|
|||
SERVER/PLAYER DOCUMENTATION FOR ACTION 1.51
|
||||
SERVER/PLAYER DOCUMENTATION FOR ACTION 1.52
|
||||
|
||||
|
||||
ACTION-SPECIFIC SERVER VARIABLES
|
||||
|
@ -56,8 +56,9 @@ allitem: gives all the items to each player in teamplay/DM
|
|||
tgren: sets the number of grenades that come with the bandolier in
|
||||
teamplay (default = 0).
|
||||
|
||||
noscore: if set to 1, individual scores are not in effect for teamplay,
|
||||
the only scores visible will be team wins and total frags (default = 0).
|
||||
noscore: if set to 1, individual scores (and damage stats) are not in
|
||||
effect for teamplay, the only scores visible will be team wins and total
|
||||
frags (default = 0).
|
||||
|
||||
nohud: if set to 1, the standard HUD (health, ammo, etc) is disabled for
|
||||
all players. This can allow you to record better-looking demos of staged
|
||||
|
@ -69,6 +70,33 @@ game directory. This should be used on the Quake2 commandline, ie:
|
|||
quake2 +set game action +set ininame alternate.ini +set dedicated 1 ...
|
||||
(default = "action.ini").
|
||||
|
||||
limchasecam: if set to 1, will prevent all players on teams from free
|
||||
floating, or chase-camming enemy players. If set to 2, will prevent all
|
||||
players on teams from using the normal chase cam as well (only the
|
||||
through-eyes cam on teammates will be allowed). This variable should be
|
||||
set to 2 for clan matches, etc (default = 0).
|
||||
|
||||
shelloff: turns off the dropping of expended shells from your gun
|
||||
(default = 1 [turn off shells, for a faster Internet game]).
|
||||
|
||||
breakableglass: turns on breakable glass. Not recommended for Internet
|
||||
games (default = 0).
|
||||
|
||||
glassfragmentlimit: controls the maximum number of glass fragments present
|
||||
on the map at any time (default = 30).
|
||||
|
||||
maxteamkills: the maximum number of teammates a player can kill in one map
|
||||
before he is temporarily banned from the server. Only applies during
|
||||
friendly-fire enabled teamplay games. Players will also be banned for
|
||||
wounding teammates, if they wound 4*maxteamkills teammates. Setting this
|
||||
to zero disables the feature (default = 0).
|
||||
|
||||
tkbanrounds: the number of maps a player will be banned for when he is
|
||||
banned for killing teammates (default = 2).
|
||||
|
||||
twbanrounds: the number of maps a player will be banned for when he is
|
||||
banned for wounding teammates (default = 2).
|
||||
|
||||
|
||||
ACTION-SPECIFIC PLAYER COMMANDS
|
||||
|
||||
|
@ -158,7 +186,7 @@ unpartner: breaks your current partnership.
|
|||
WEAPON/ITEM NAMES
|
||||
|
||||
These are the exact names of all the weapons/items in the game, for use with
|
||||
commands like "drop", "choose", "give", etc:
|
||||
commands like "use", "drop", "choose", "give", etc:
|
||||
|
||||
MK23 Pistol
|
||||
M3 Super 90 Assault Shotgun
|
||||
|
@ -167,7 +195,8 @@ Handcannon
|
|||
Sniper Rifle
|
||||
M4 Assault Rifle
|
||||
Dual MK23 Pistols
|
||||
Combat Knife
|
||||
Combat Knife (also aliases "throwing combat knife" and
|
||||
"slashing combat knife" for the "use" command)
|
||||
|
||||
Pistol Clip
|
||||
12 Gauge Shells
|
||||
|
@ -205,8 +234,11 @@ Flood protection is supported using the standard Q2 3.20 variables,
|
|||
"flood_msgs" (default 4), "flood_persecond" (default 4), and "flood_waitdelay"
|
||||
(default 10).
|
||||
|
||||
DM teams-by-model, teams-by-skin, friendly fire, etc are supported using the
|
||||
standard Q2 "dmflags" values.
|
||||
DM teams-by-model, teams-by-skin, friendly fire, etc are supported using
|
||||
the standard Q2 "dmflags" values. A server should use dmflags 256 for
|
||||
"normal" play (including no friendly fire), 0 for friendly fire. Some of
|
||||
the other regular dmflags are also available, such as "spawn farthest"
|
||||
(512).
|
||||
|
||||
action/action.ini is the configuration file for map rotation and teamplay team
|
||||
name/model/skin setup. See the example for information on the format.
|
||||
|
@ -234,10 +266,16 @@ default. IP addresses in the filter list will only be prohibited from
|
|||
connecting if the "filterban" variable is set to 1 (this is the default).
|
||||
|
||||
|
||||
OTHER SERVER COMMANDS
|
||||
|
||||
sv reloadmotd: reloads the MOTD file from disk.
|
||||
|
||||
sv nextmap: immediately skips to the next map in the rotation.
|
||||
|
||||
|
||||
REPORTING BUGS OR MAKING COMMENTS
|
||||
|
||||
As of this writing, you can contact the authors of the Action 1.5 server
|
||||
code (Zucchini and Fireblade) at spikard@u.washington.edu and
|
||||
ucs_brf@shsu.edu, respectively. The Action Quake 2 website is at
|
||||
http://action.telefragged.com/ and has a message board where discussions
|
||||
about Action Quake 2 take place.
|
||||
The maintainers of the Action server code, Zucchini and Fireblade, can be
|
||||
contacted at spikard@u.washington.edu and ucs_brf@shsu.edu, respectively.
|
||||
The Action Quake 2 website is at http://aq2.action-web.net/ and has a
|
||||
message board where discussions about Action Quake 2 take place.
|
||||
|
|
112
a_cmds.c
112
a_cmds.c
|
@ -110,6 +110,7 @@ void LaserSightThink (edict_t *self)
|
|||
vec3_t forward,right,up;
|
||||
vec3_t angles;
|
||||
trace_t tr;
|
||||
int height = 0;
|
||||
|
||||
// zucc compensate for weapon ride up
|
||||
VectorAdd (self->owner->client->v_angle, self->owner->client->kick_angles, angles);
|
||||
|
@ -121,13 +122,18 @@ void LaserSightThink (edict_t *self)
|
|||
self->think = G_FreeEdict;
|
||||
}
|
||||
|
||||
if (self->owner->client->pers.firing_style == ACTION_FIRING_CLASSIC)
|
||||
height = 8;
|
||||
|
||||
VectorSet(offset,24 , 0, self->owner->viewheight);
|
||||
|
||||
VectorSet(offset,24 , 8, self->owner->viewheight- height);
|
||||
|
||||
P_ProjectSource (self->owner->client, self->owner->s.origin, offset, forward, right, start);
|
||||
VectorMA(start,8192,forward,end);
|
||||
|
||||
tr = do_trace (start,NULL,NULL, end,self->owner,CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
|
||||
PRETRACE();
|
||||
tr = gi.trace (start,NULL,NULL, end,self->owner,CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
|
||||
POSTTRACE();
|
||||
|
||||
if (tr.fraction != 1) {
|
||||
VectorMA(tr.endpos,-4,forward,endp);
|
||||
|
@ -144,6 +150,11 @@ void LaserSightThink (edict_t *self)
|
|||
|
||||
void Cmd_New_Reload_f( edict_t *ent )
|
||||
{
|
||||
//FB 6/1/99 - refuse to reload during LCA
|
||||
if ((int)teamplay->value && lights_camera_action)
|
||||
return;
|
||||
//FB 6/1/99
|
||||
|
||||
ent->client->reload_attempts++;
|
||||
}
|
||||
|
||||
|
@ -198,11 +209,6 @@ void Cmd_Reload_f (edict_t *ent)
|
|||
|
||||
if(ent->client->pers.inventory[ent->client->ammo_index])
|
||||
{
|
||||
/*if((ent->client->weaponstate != WEAPON_END_MAG) && (ent->client->pers.inventory[ent->client->ammo_index] < rds_left))
|
||||
{
|
||||
gi.centerprintf(ent,"Buy a clue-\nYou're on your last magazine!\n");
|
||||
}
|
||||
else*/
|
||||
//Set the weaponstate...
|
||||
if ( ent->client->curr_weap == M3_NUM )
|
||||
{
|
||||
|
@ -212,10 +218,20 @@ void Cmd_Reload_f (edict_t *ent)
|
|||
}
|
||||
// already in the process of reloading!
|
||||
if ( ent->client->weaponstate == WEAPON_RELOADING && (ent->client->shot_rds < (ent->client->shot_max -1)) && !(ent->client->fast_reload) && ((ent->client->pers.inventory[ent->client->ammo_index] -1) > 0 ))
|
||||
{
|
||||
// don't let them start fast reloading until far enough into the firing sequence
|
||||
// this gives them a chance to break off from reloading to fire the weapon - zucc
|
||||
if ( ent->client->ps.gunframe >= 48 )
|
||||
{
|
||||
ent->client->fast_reload = 1;
|
||||
(ent->client->pers.inventory[ent->client->ammo_index])--;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent->client->reload_attempts++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ent->client->curr_weap == HC_NUM )
|
||||
{
|
||||
|
@ -224,7 +240,6 @@ void Cmd_Reload_f (edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!(ent->client->pers.inventory[ent->client->ammo_index] >= 2))
|
||||
return;
|
||||
}
|
||||
|
@ -235,22 +250,48 @@ void Cmd_Reload_f (edict_t *ent)
|
|||
return;
|
||||
}
|
||||
// already in the process of reloading!
|
||||
if ( ent->client->weaponstate == WEAPON_RELOADING && (ent->client->sniper_rds < (ent->client->sniper_max -1)) && !(ent->client->fast_reload) && ((ent->client->pers.inventory[ent->client->ammo_index] -1) > 0 ))
|
||||
if ( ent->client->weaponstate == WEAPON_RELOADING && (ent->client->sniper_rds < (ent->client->sniper_max -1)) && !(ent->client->fast_reload) && ((ent->client->pers.inventory[ent->client->ammo_index] -1) > 0 ) )
|
||||
{
|
||||
// don't let them start fast reloading until far enough into the firing sequence
|
||||
// this gives them a chance to break off from reloading to fire the weapon - zucc
|
||||
if ( ent->client->ps.gunframe >= 72 )
|
||||
{
|
||||
ent->client->fast_reload = 1;
|
||||
(ent->client->pers.inventory[ent->client->ammo_index])--;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent->client->reload_attempts++;
|
||||
}
|
||||
}
|
||||
ent->client->ps.fov = 90;
|
||||
if ( ent->client->pers.weapon )
|
||||
ent->client->ps.gunindex = gi.modelindex( ent->client->pers.weapon->view_model );
|
||||
|
||||
}
|
||||
if ( ent->client->curr_weap == DUAL_NUM )
|
||||
{
|
||||
if (!(ent->client->pers.inventory[ent->client->ammo_index] >= 2))
|
||||
return;
|
||||
//FIREBLADE 7/11/1999 - stop reloading when weapon already full
|
||||
if (ent->client->dual_rds == ent->client->dual_max)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ent->client->curr_weap == MP5_NUM)
|
||||
{
|
||||
if (ent->client->mp5_rds == ent->client->mp5_max)
|
||||
return;
|
||||
}
|
||||
if (ent->client->curr_weap == M4_NUM)
|
||||
{
|
||||
if (ent->client->m4_rds == ent->client->m4_max)
|
||||
return;
|
||||
}
|
||||
if (ent->client->curr_weap == MK23_NUM)
|
||||
{
|
||||
if (ent->client->mk23_rds == ent->client->mk23_max)
|
||||
return;
|
||||
}
|
||||
//FIREBLADE
|
||||
|
||||
ent->client->weaponstate = WEAPON_RELOADING;
|
||||
//(ent->client->pers.inventory[ent->client->ammo_index])--;
|
||||
|
@ -261,6 +302,14 @@ void Cmd_Reload_f (edict_t *ent)
|
|||
}
|
||||
//+BD END CODE BLOCK
|
||||
|
||||
void Cmd_New_Weapon_f( edict_t *ent )
|
||||
{
|
||||
ent->client->weapon_attempts++;
|
||||
if ( ent->client->weapon_attempts == 1 )
|
||||
Cmd_Weapon_f(ent);
|
||||
}
|
||||
|
||||
|
||||
// function to change the firing mode of weapons (when appropriate)
|
||||
|
||||
void Cmd_Weapon_f ( edict_t *ent )
|
||||
|
@ -269,9 +318,22 @@ void Cmd_Weapon_f ( edict_t *ent )
|
|||
|
||||
dead = (ent->solid == SOLID_NOT || ent->deadflag == DEAD_DEAD);
|
||||
|
||||
ent->client->weapon_attempts--;
|
||||
if ( ent->client->weapon_attempts < 0 )
|
||||
ent->client->weapon_attempts = 0;
|
||||
|
||||
if ( ent->client->bandaging || ent->client->bandage_stopped )
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "You can't mess with your weapon while bandaging!\n");
|
||||
|
||||
gi.cprintf(ent, PRINT_HIGH, "You'll get to your weapon when your done bandaging!\n");
|
||||
ent->client->weapon_attempts++;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ent->client->weaponstate == WEAPON_FIRING || ent->client->weaponstate == WEAPON_BUSY )
|
||||
{
|
||||
//gi.cprintf(ent, PRINT_HIGH, "Try again when you aren't using your weapon.\n");
|
||||
ent->client->weapon_attempts++;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -313,11 +375,14 @@ void Cmd_Weapon_f ( edict_t *ent )
|
|||
if ( ent->client->resp.sniper_mode == SNIPER_1X )
|
||||
{
|
||||
gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/lensflik.wav"), 1, ATTN_NORM, 0);
|
||||
ent->client->weaponstate = WEAPON_BUSY;
|
||||
ent->client->resp.sniper_mode = SNIPER_2X;
|
||||
ent->client->desired_fov = 45;
|
||||
if ( ent->client->weaponstate != WEAPON_RELOADING )
|
||||
{
|
||||
ent->client->idle_weapon = 6; // 6 frames of idleness
|
||||
ent->client->ps.gunframe = 22;
|
||||
ent->client->weaponstate = WEAPON_BUSY;
|
||||
}
|
||||
}
|
||||
else if ( ent->client->resp.sniper_mode == SNIPER_2X )
|
||||
{
|
||||
|
@ -350,9 +415,15 @@ void Cmd_Weapon_f ( edict_t *ent )
|
|||
ent->client->resp.knife_mode = !(ent->client->resp.knife_mode);
|
||||
ent->client->weaponstate = WEAPON_ACTIVATING;
|
||||
if ( ent->client->resp.knife_mode )
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "Switching to throwing\n");
|
||||
ent->client->ps.gunframe = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "Switching to slashing\n");
|
||||
ent->client->ps.gunframe = 106;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -391,6 +462,13 @@ void Cmd_OpenDoor_f (edict_t *ent )
|
|||
void Cmd_Bandage_f ( edict_t *ent )
|
||||
{
|
||||
gitem_t *item;
|
||||
|
||||
|
||||
if ( (ent->client->bleeding != 0 || ent->client->leg_damage != 0) && ent->client->bandaging != 1 )
|
||||
ent->client->reload_attempts = 0; // prevent any further reloading
|
||||
|
||||
|
||||
|
||||
if ( (ent->client->weaponstate == WEAPON_READY || ent->client->weaponstate == WEAPON_END_MAG )
|
||||
&& (ent->client->bleeding != 0 || ent->client->leg_damage != 0 )
|
||||
&& ent->client->bandaging != 1 )
|
||||
|
@ -503,7 +581,9 @@ qboolean loc_CanSee (edict_t *targ, edict_t *inflictor)
|
|||
viewpoint[2] += inflictor->viewheight;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
trace = do_trace (viewpoint, vec3_origin, vec3_origin, targpoints[i], inflictor, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace (viewpoint, vec3_origin, vec3_origin, targpoints[i], inflictor, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction == 1.0)
|
||||
return true;
|
||||
}
|
||||
|
@ -552,7 +632,9 @@ void SetIDView(edict_t *ent)
|
|||
AngleVectors(ent->client->v_angle, forward, NULL, NULL);
|
||||
VectorScale(forward, 8192, forward);
|
||||
VectorAdd(ent->s.origin, forward, forward);
|
||||
tr = do_trace(ent->s.origin, NULL, NULL, forward, ent, MASK_SOLID);
|
||||
PRETRACE();
|
||||
tr = gi.trace(ent->s.origin, NULL, NULL, forward, ent, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (tr.fraction < 1 && tr.ent && tr.ent->client) {
|
||||
ent->client->ps.stats[STAT_ID_VIEW] =
|
||||
CS_PLAYERSKINS + (ent - g_edicts - 1);
|
||||
|
|
135
a_doorkick.c
Normal file
135
a_doorkick.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* a_doorkick.c
|
||||
* Door kicking code by hal[9k]
|
||||
* originally for AQ:Espionage (http://aqdt.fear.net/)
|
||||
* email: hal9000@telefragged.com
|
||||
* Assembled here by Homer (homer@fear.net)
|
||||
*/
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
#define STATE_TOP 0
|
||||
#define STATE_BOTTOM 1
|
||||
#define STATE_UP 2
|
||||
#define STATE_DOWN 3
|
||||
|
||||
#define DOOR_START_OPEN 1
|
||||
#define DOOR_REVERSE 2
|
||||
|
||||
extern void door_use (edict_t *self, edict_t *other, edict_t *activator);
|
||||
|
||||
// needed for KickDoor
|
||||
void VectorRotate(vec3_t in, vec3_t angles, vec3_t out)
|
||||
{
|
||||
float cv, sv, angle, tv;
|
||||
|
||||
VectorCopy(in, out);
|
||||
|
||||
angle = (-angles[PITCH]) * M_PI / 180;
|
||||
cv = cos(angle);
|
||||
sv = sin(angle);
|
||||
tv = (out[0] * cv) - (out[2] * sv);
|
||||
|
||||
out[2] = (out[2] * cv) + (out[0] * sv);
|
||||
out[0] = tv;
|
||||
|
||||
angle = (angles[YAW]) * M_PI / 180;
|
||||
|
||||
cv = cos(angle);
|
||||
sv = sin(angle);
|
||||
tv = (out[0] * cv) - (out[1] * sv);
|
||||
|
||||
out[1] = (out[1] * cv) + (out[0] * sv);
|
||||
out[0] = tv;
|
||||
angle = (angles[ROLL]) * M_PI / 180;
|
||||
|
||||
cv = cos(angle);
|
||||
sv = sin(angle);
|
||||
tv = (out[1] * cv) - (out[2] * sv);
|
||||
out[2] = (out[2] * cv) + (out[1] * sv);
|
||||
out[1] = tv;
|
||||
}
|
||||
|
||||
int KickDoor( trace_t *tr_old, edict_t *ent, vec3_t forward )
|
||||
{
|
||||
trace_t tr;
|
||||
|
||||
vec3_t d_forward, right, end;
|
||||
float d;
|
||||
if ( !Q_strcasecmp( tr_old->ent->classname, "func_door_rotating" ) )
|
||||
{
|
||||
// Make that the door is closed
|
||||
|
||||
tr = *tr_old;
|
||||
#if 1
|
||||
if ( (!(tr.ent->spawnflags & DOOR_START_OPEN) &&
|
||||
!(tr.ent->moveinfo.state == STATE_TOP)) ||
|
||||
( (tr.ent->spawnflags & DOOR_START_OPEN) &&
|
||||
!(tr.ent->moveinfo.state == STATE_BOTTOM)) )
|
||||
#else
|
||||
if ( (!(tr.ent->spawnflags & DOOR_START_OPEN) &&
|
||||
((tr.ent->moveinfo.state == STATE_BOTTOM) ||
|
||||
(tr.ent->moveinfo.state == STATE_DOWN))) ||
|
||||
((tr.ent->spawnflags & DOOR_START_OPEN) &&
|
||||
((tr.ent->moveinfo.state == STATE_TOP) ||
|
||||
(tr.ent->moveinfo.state == STATE_UP))) )
|
||||
#endif
|
||||
{
|
||||
//gi.dprintf( "Kicking a closed door\n" );
|
||||
|
||||
// Find out if we are on the "outside"
|
||||
|
||||
#if 0
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (TE_RAILTRAIL);
|
||||
gi.WritePosition (tr.ent->s.origin);
|
||||
gi.WritePosition (tr.endpos);
|
||||
gi.multicast (tr.ent->s.origin, MULTICAST_PHS);
|
||||
#endif
|
||||
VectorSubtract( tr.endpos, tr.ent->s.origin, d_forward );
|
||||
|
||||
forward[2] = 0;
|
||||
d_forward[2] = 0;
|
||||
VectorNormalize( forward );
|
||||
VectorNormalize( d_forward );
|
||||
VectorSet( right, 0, 90, 0 );
|
||||
VectorRotate( d_forward, right, d_forward );
|
||||
|
||||
d = DotProduct( forward, d_forward );
|
||||
if ( tr.ent->spawnflags & DOOR_REVERSE )
|
||||
d = -d;
|
||||
// d = sin( acos( d ) );
|
||||
if ( d > 0.0 )
|
||||
{
|
||||
// gi.dprintf( "we think we are on the outside\n" );
|
||||
//if ( tr.ent->spawnflags & DOOR_REVERSE )
|
||||
// gi.dprintf( "but DOOR_REVERSE is set\n" );
|
||||
// Only use the door if it's not already opening
|
||||
if ( (!( tr.ent->spawnflags & DOOR_START_OPEN ) &&
|
||||
!( tr.ent->moveinfo.state == STATE_UP )) ||
|
||||
((tr.ent->spawnflags & DOOR_START_OPEN ) &&
|
||||
(tr.ent->moveinfo.state == STATE_DOWN) ) )
|
||||
door_use( tr.ent, ent, ent );
|
||||
// Find out if someone else is on the other side
|
||||
VectorMA( tr.endpos, 25, forward, end );
|
||||
PRETRACE();
|
||||
tr = gi.trace (tr.endpos, NULL, NULL, end, tr.ent, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
|
||||
{
|
||||
if (tr.fraction < 1.0)
|
||||
{
|
||||
if (tr.ent->client)
|
||||
{
|
||||
//gi.dprintf("we found a client on the other side\n");
|
||||
*tr_old = tr;
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
49
a_game.c
49
a_game.c
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
|
||||
#define MAX_MAP_ROTATION 1000 // just in case...
|
||||
#define MAX_STR_LEN 1000
|
||||
|
@ -119,6 +120,8 @@ void ReadConfigFile()
|
|||
sprintf(team1_skin_index, "../players/%s_i", team1_skin);
|
||||
sprintf(team2_skin_index, "../players/%s_i", team2_skin);
|
||||
cur_map = 0;
|
||||
|
||||
fclose(config_file);
|
||||
}
|
||||
|
||||
void ReadMOTDFile()
|
||||
|
@ -167,7 +170,7 @@ void PrintMOTD(edict_t *ent)
|
|||
|
||||
// 3 lines for version number & website (third blank)
|
||||
strcpy(msg_buf, "Welcome to Action Quake v" ACTION_VERSION "\n"
|
||||
"http://action.telefragged.com/\n"
|
||||
"http://aq2.action-web.net/\n"
|
||||
"\n");
|
||||
lines = 3;
|
||||
|
||||
|
@ -259,6 +262,19 @@ void PrintMOTD(edict_t *ent)
|
|||
allitem->value ? "all items" : "");
|
||||
lines++;
|
||||
}
|
||||
if (limchasecam->value)
|
||||
{
|
||||
if ((int)limchasecam->value == 2)
|
||||
sprintf(msg_buf + strlen(msg_buf), "Chase cam disallowed\n");
|
||||
else
|
||||
sprintf(msg_buf + strlen(msg_buf), "Chase cam restricted\n");
|
||||
lines++;
|
||||
}
|
||||
if (teamplay->value && !((int)dmflags->value & DF_NO_FRIENDLY_FIRE))
|
||||
{
|
||||
sprintf(msg_buf + strlen(msg_buf), "Friendly fire enabled\n");
|
||||
lines++;
|
||||
}
|
||||
|
||||
// Teamplay: 2 lines (one blank) for menu instructions
|
||||
if (teamplay->value)
|
||||
|
@ -287,6 +303,8 @@ void PrintMOTD(edict_t *ent)
|
|||
{
|
||||
strcat(msg_buf, "\n");
|
||||
lines++;
|
||||
if (lines >= max_lines)
|
||||
break;
|
||||
chars_on_line = 0;
|
||||
}
|
||||
strcat(msg_buf, *(map_rotation + mapnum));
|
||||
|
@ -298,11 +316,14 @@ void PrintMOTD(edict_t *ent)
|
|||
}
|
||||
}
|
||||
|
||||
if (lines < max_lines)
|
||||
{
|
||||
strcat(msg_buf, "\n");
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
|
||||
if (motd_num_lines)
|
||||
if (motd_num_lines && lines < max_lines)
|
||||
{
|
||||
strcat(msg_buf, "\n");
|
||||
lines++;
|
||||
|
@ -710,7 +731,7 @@ void DecalDie(edict_t *self)
|
|||
G_FreeEdict(self);
|
||||
}
|
||||
|
||||
void AddDecal (edict_t *self, vec3_t point, vec3_t direct)
|
||||
void AddDecal (edict_t *self, trace_t* tr)
|
||||
{
|
||||
edict_t *decal;
|
||||
edict_t *dec;
|
||||
|
@ -738,9 +759,9 @@ void AddDecal (edict_t *self, vec3_t point, vec3_t direct)
|
|||
|
||||
decal->s.modelindex = gi.modelindex("models/objects/holes/hole1/hole.md2");
|
||||
|
||||
VectorCopy (point, decal->s.origin);
|
||||
VectorCopy (tr->endpos, decal->s.origin);
|
||||
|
||||
vectoangles (direct, decal->s.angles);
|
||||
vectoangles (tr->plane.normal, decal->s.angles);
|
||||
|
||||
decal->owner = self;
|
||||
decal->classnum = decals;
|
||||
|
@ -750,7 +771,12 @@ void AddDecal (edict_t *self, vec3_t point, vec3_t direct)
|
|||
decal->classname = "decal";
|
||||
|
||||
gi.linkentity (decal);
|
||||
|
||||
//glass
|
||||
if ((tr->ent) && (0 == Q_stricmp("func_explosive", tr->ent->classname)))
|
||||
{
|
||||
CGF_SFX_AttachDecalToGlass(tr->ent, decal);
|
||||
}
|
||||
//---
|
||||
}
|
||||
|
||||
void SplatDie(edict_t *self)
|
||||
|
@ -758,7 +784,7 @@ void SplatDie(edict_t *self)
|
|||
G_FreeEdict(self);
|
||||
}
|
||||
|
||||
void AddSplat (edict_t *self, vec3_t point, vec3_t direct)
|
||||
void AddSplat (edict_t *self, vec3_t point, trace_t* tr)
|
||||
{
|
||||
edict_t *splat;
|
||||
edict_t *spt;
|
||||
|
@ -795,7 +821,7 @@ void AddSplat (edict_t *self, vec3_t point, vec3_t direct)
|
|||
|
||||
VectorCopy (point, splat->s.origin);
|
||||
|
||||
vectoangles (direct, splat->s.angles);
|
||||
vectoangles (tr->plane.normal, splat->s.angles);
|
||||
|
||||
splat->owner = self;
|
||||
splat->touch = NULL;
|
||||
|
@ -805,7 +831,12 @@ void AddSplat (edict_t *self, vec3_t point, vec3_t direct)
|
|||
splat->classnum = splats;
|
||||
|
||||
gi.linkentity (splat);
|
||||
|
||||
//glass
|
||||
if ((tr->ent) && (0 == Q_stricmp("func_explosive", tr->ent->classname)))
|
||||
{
|
||||
CGF_SFX_AttachDecalToGlass(tr->ent, splat);
|
||||
}
|
||||
//---
|
||||
}
|
||||
|
||||
/* %-variables for chat msgs */
|
||||
|
|
10
a_game.h
10
a_game.h
|
@ -2,7 +2,7 @@
|
|||
* Include for base Action game-related things
|
||||
*/
|
||||
|
||||
#define ACTION_VERSION "1.51"
|
||||
#define ACTION_VERSION "1.52"
|
||||
|
||||
extern char team1_name[];
|
||||
extern char team2_name[];
|
||||
|
@ -13,11 +13,13 @@ extern char team2_skin_index[];
|
|||
extern char *map_rotation[];
|
||||
extern int num_maps, cur_map;
|
||||
extern char *tnames[];
|
||||
extern int *took_damage;
|
||||
|
||||
void ReadConfigFile();
|
||||
void ReadMOTDFile();
|
||||
void PrintMOTD(edict_t *);
|
||||
void stuffcmd(edict_t *, char *);
|
||||
int KickDoor( trace_t *tr_old, edict_t *ent, vec3_t forward );
|
||||
|
||||
// Prototypes of base Q2 functions that weren't included in any Q2 header
|
||||
qboolean loc_CanSee(edict_t *, edict_t *);
|
||||
|
@ -29,3 +31,9 @@ void ParseSayText(edict_t *, char *);
|
|||
#define ACTION_FIRING_CENTER 0
|
||||
#define ACTION_FIRING_CLASSIC 1
|
||||
#define ACTION_FIRING_CLASSIC_HIGH 2
|
||||
|
||||
// maxs[2] of a player when crouching (we modify it from the normal 4)
|
||||
// ...also the modified viewheight -FB 7/18/99
|
||||
#define CROUCHING_MAXS2 16
|
||||
#define CROUCHING_VIEWHEIGHT 8
|
||||
|
||||
|
|
|
@ -33,7 +33,9 @@ static edict_t *FindSpecSpawn(void)
|
|||
|
||||
if (spot == NULL)
|
||||
{
|
||||
/* FB 6/24/99
|
||||
gi.dprintf("Warning: failed to find special item spawn point!\n");
|
||||
*/
|
||||
}
|
||||
|
||||
return spot;
|
||||
|
|
|
@ -494,7 +494,9 @@ edict_t *DetermineViewedTeammate(edict_t *ent)
|
|||
AngleVectors(ent->client->v_angle, forward, NULL, NULL);
|
||||
VectorScale(forward, 8192, forward);
|
||||
VectorAdd(ent->s.origin, forward, forward);
|
||||
tr = do_trace(ent->s.origin, NULL, NULL, forward, ent, MASK_SOLID);
|
||||
PRETRACE();
|
||||
tr = gi.trace(ent->s.origin, NULL, NULL, forward, ent, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (tr.fraction < 1 && tr.ent && tr.ent->client) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
34
a_team.c
34
a_team.c
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
|
||||
qboolean team_game_going = 0; // is a team game going right now?
|
||||
qboolean team_round_going = 0; // is an actual round of a team game going right now?
|
||||
|
@ -659,6 +660,9 @@ void CleanLevel()
|
|||
}
|
||||
|
||||
CleanBodies();
|
||||
|
||||
// fix glass
|
||||
CGF_SFX_RebuildAllBrokenGlass();
|
||||
}
|
||||
|
||||
qboolean StartClient(edict_t *ent)
|
||||
|
@ -812,6 +816,7 @@ void StartRound()
|
|||
void StartLCA()
|
||||
{
|
||||
CleanLevel();
|
||||
|
||||
CenterPrintAll("LIGHTS...\n");
|
||||
gi.sound(&g_edicts[0], CHAN_VOICE | CHAN_NO_PHS_ADD,
|
||||
gi.soundindex("atl/lights.wav"), 1.0, ATTN_NONE, 0.0);
|
||||
|
@ -1071,12 +1076,11 @@ void A_Scoreboard(edict_t *ent)
|
|||
|
||||
void A_ScoreboardMessage (edict_t *ent, edict_t *killer)
|
||||
{
|
||||
char string[1400];
|
||||
char string[1400], damage[50];
|
||||
gclient_t *cl;
|
||||
edict_t *cl_ent;
|
||||
int maxsize = 1000, i, j, k;
|
||||
|
||||
|
||||
if (ent->client->scoreboardnum == 1)
|
||||
{
|
||||
int team, len, deadview;
|
||||
|
@ -1306,8 +1310,8 @@ void A_ScoreboardMessage (edict_t *ent, edict_t *killer)
|
|||
}
|
||||
else
|
||||
{
|
||||
strcpy(string, "xv 0 yv 32 string2 \"Frags Player Time Ping\" "
|
||||
"xv 0 yv 40 string2 \"----- --------------- ---- ----\" ");
|
||||
strcpy(string, "xv 0 yv 32 string2 \"Frags Player Time Ping Damage\" "
|
||||
"xv 0 yv 40 string2 \"----- --------------- ---- ---- ------\" ");
|
||||
}
|
||||
|
||||
for (i = 0; i < total; i++)
|
||||
|
@ -1326,13 +1330,17 @@ void A_ScoreboardMessage (edict_t *ent, edict_t *killer)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (game.clients[sorted[i]].resp.damage_dealt < 1000000)
|
||||
sprintf(damage, "%d", game.clients[sorted[i]].resp.damage_dealt);
|
||||
else
|
||||
strcpy(damage, "******");
|
||||
sprintf(string + strlen(string),
|
||||
"xv 0 yv %d string \"%5d %-15s %4d %4d\" ",
|
||||
"xv 0 yv %d string \"%5d %-15s %4d %4d %6s\" ",
|
||||
48 + i * 8,
|
||||
sortedscores[i],
|
||||
game.clients[sorted[i]].pers.netname,
|
||||
(level.framenum - game.clients[sorted[i]].resp.enterframe)/600,
|
||||
ping);
|
||||
ping, damage);
|
||||
}
|
||||
|
||||
if (strlen(string) > (maxsize - 100) &&
|
||||
|
@ -1485,10 +1493,24 @@ void SelectFarTeamplaySpawnPoint(int team, qboolean teams_assigned[])
|
|||
else
|
||||
preferred_spawn_points = 3;
|
||||
|
||||
//FB 6/1/99 - make DF_SPAWN_FARTHEST force far spawn points in TP
|
||||
if ((int)dmflags->value & DF_SPAWN_FARTHEST)
|
||||
preferred_spawn_points = 1;
|
||||
//FB 6/1/99
|
||||
|
||||
spawn_to_use = newrand(preferred_spawn_points);
|
||||
|
||||
if (team < 0 || team >= MAX_TEAMS)
|
||||
{
|
||||
gi.dprintf("Out-of-range teams value in SelectFarTeamplaySpawnPoint, skipping...\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
teams_assigned[team] = true;
|
||||
teamplay_spawns[team] = spawn_distances[num_potential_spawns - spawn_to_use - 1].s;
|
||||
}
|
||||
|
||||
gi.TagFree(spawn_distances);
|
||||
}
|
||||
|
||||
// SetupTeamSpawnPoints:
|
||||
|
|
26
a_team.h
26
a_team.h
|
@ -14,20 +14,22 @@
|
|||
#define WINNER_TEAM2 2
|
||||
#define WINNER_TIE 3
|
||||
|
||||
// Override normal trace for our teamplay anti-stick stuff. If there are
|
||||
// Pre- and post-trace code for our teamplay anti-stick stuff. If there are
|
||||
// still "transparent" (SOLID_TRIGGER) players, they need to be set to
|
||||
// SOLID_BBOX before a trace is performed, then changed back again
|
||||
// afterwards. do_trace() should be used instead of gi.trace() in all
|
||||
// areas where "transparent" players should be detected.
|
||||
#define do_trace(a, b, c, d, e, f) \
|
||||
(((int)teamplay->value && transparent_list && !lights_camera_action) ? \
|
||||
(TransparentListSet(SOLID_BBOX), \
|
||||
(trace_t_temp = gi.trace(a, b, c, d, e, f)), \
|
||||
TransparentListSet(SOLID_TRIGGER), \
|
||||
trace_t_temp) \
|
||||
: \
|
||||
gi.trace(a, b, c, d, e, f))
|
||||
trace_t our_trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passent, int contentmask);
|
||||
// afterwards. PRETRACE() and POSTTRACE() should be called before and after
|
||||
// traces in all places where combat is taking place (ie "transparent" players
|
||||
// should be detected), ie shots being traced etc.
|
||||
// FB 6/1/99: Now crouching players will have their bounding box adjusted here
|
||||
// too, for better shot areas. (there has to be a better way to do this?)
|
||||
|
||||
#define PRETRACE() \
|
||||
if (transparent_list && (int)teamplay->value && !lights_camera_action) \
|
||||
TransparentListSet(SOLID_BBOX)
|
||||
|
||||
#define POSTTRACE() \
|
||||
if (transparent_list && (int)teamplay->value && !lights_camera_action) \
|
||||
TransparentListSet(SOLID_TRIGGER)
|
||||
|
||||
edict_t *SelectTeamplaySpawnPoint(edict_t *);
|
||||
qboolean FallingDamageAmnesty(edict_t *targ);
|
||||
|
|
704
cgf_sfx_glass.c
Normal file
704
cgf_sfx_glass.c
Normal file
|
@ -0,0 +1,704 @@
|
|||
/****************************************************************************/
|
||||
/* */
|
||||
/* project : CGF (c) 1999 William van der Sterren */
|
||||
/* parts (c) 1998 id software */
|
||||
/* */
|
||||
/* file : cgf_sfx_glass.cpp "special effects for glass entities" */
|
||||
/* author(s): William van der Sterren */
|
||||
/* version : 0.5 */
|
||||
/* */
|
||||
/* date (last revision): Jun 12, 99 */
|
||||
/* date (creation) : Jun 04, 99 */
|
||||
/* */
|
||||
/* */
|
||||
/* revision history */
|
||||
/* -- date ---- | -- revision ---------------------- | -- revisor -- */
|
||||
/* Jun 12, 1999 | fixed knife slash breaks glass | William */
|
||||
/* Jun 08, 1999 | improved fragment limit | William */
|
||||
/* */
|
||||
/******* http://www.botepidemic.com/aid/cgf for CGF for Action Quake2 *******/
|
||||
|
||||
#ifdef __cplusplus
|
||||
// VC++, for CGF
|
||||
#include <cmath> // prevent problems between C and STL
|
||||
extern "C"
|
||||
{
|
||||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
}
|
||||
#else
|
||||
// C, for other AQ2 variants
|
||||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
#endif
|
||||
|
||||
|
||||
// cvar for breaking glass
|
||||
static cvar_t *breakableglass = 0;
|
||||
|
||||
// cvar for max glass fragment count
|
||||
static cvar_t *glassfragmentlimit = 0;
|
||||
|
||||
static int glassfragmentcount = 0;
|
||||
|
||||
|
||||
// additional functions - Q2 expects C calling convention
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void CGF_SFX_TouchGlass(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf);
|
||||
// called whenever an entity hits the trigger spawned for the glass
|
||||
|
||||
void CGF_SFX_EmitGlass (edict_t* aGlassPane, edict_t* anInflictor, vec3_t aPoint);
|
||||
// emits glass fragments from aPoint, to show effects of firing thru window
|
||||
|
||||
void CGF_SFX_BreakGlass(edict_t* aGlassPane, edict_t* anOther, edict_t* anAttacker,
|
||||
int aDamage, vec3_t aPoint, vec_t aPaneDestructDelay
|
||||
);
|
||||
// breaks glass
|
||||
|
||||
void CGF_SFX_InstallBreakableGlass(edict_t* aGlassPane);
|
||||
// when working on a glass pane for the first time, just install trigger
|
||||
// when working on a glass pane again (after a game ended), move
|
||||
// glass back to original location
|
||||
|
||||
void CGF_SFX_HideBreakableGlass(edict_t* aGlassPane);
|
||||
// after being broken, the pane cannot be removed as it is needed in
|
||||
// subsequent missions/games, so hide it at about z = -1000
|
||||
|
||||
void CGF_SFX_ApplyGlassFragmentLimit(const char* aClassName);
|
||||
// updates glassfragmentcount and removes oldest glass fragement if
|
||||
// necessary to meet limit
|
||||
|
||||
void CGF_SFX_MiscGlassUse(edict_t *self, edict_t *other, edict_t *activator);
|
||||
// catches use from unforeseen objects (weapons, debris,
|
||||
// etc. touching the window)
|
||||
|
||||
void CGF_SFX_MiscGlassDie(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
|
||||
// catches die calls caused by unforeseen objects (weapons, debris,
|
||||
// etc. damaging the window)
|
||||
|
||||
void CGF_SFX_GlassThrowDebris (edict_t *self, char *modelname, float speed, vec3_t origin);
|
||||
// variant of id software's ThrowDebris, now numbering the entity (for later removal)
|
||||
|
||||
extern // from a_game.c
|
||||
edict_t *FindEdictByClassnum (char *classname, int classnum);
|
||||
|
||||
// declaration from g_misc.c
|
||||
extern // from g_misc.c
|
||||
void debris_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_InstallGlassSupport()
|
||||
{
|
||||
breakableglass = gi.cvar("breakableglass", "0", 0);
|
||||
glassfragmentlimit = gi.cvar("glassfragmentlimit", "30", 0);
|
||||
}
|
||||
|
||||
|
||||
int CGF_SFX_IsBreakableGlassEnabled()
|
||||
{
|
||||
// returns whether breakable glass is enabled (cvar) and allowed (dm mode)
|
||||
return breakableglass->value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_TestBreakableGlassAndRemoveIfNot_Think(edict_t* aPossibleGlassEntity)
|
||||
{
|
||||
// at level.time == 0.1 the entity has been introduced in the game,
|
||||
// and we can use gi.pointcontents and gi.trace to check the entity
|
||||
vec3_t origin;
|
||||
int breakingglass;
|
||||
trace_t trace;
|
||||
|
||||
// test for cvar
|
||||
if (!CGF_SFX_IsBreakableGlassEnabled())
|
||||
{
|
||||
G_FreeEdict(aPossibleGlassEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
VectorAdd(aPossibleGlassEntity->absmax, aPossibleGlassEntity->absmin, origin);
|
||||
VectorScale(origin, 0.5, origin);
|
||||
|
||||
// detect glass (does not work for complex shapes,
|
||||
// for example, the glass window near the satellite
|
||||
// dish at Q2 base3
|
||||
breakingglass = (gi.pointcontents(origin) & CONTENTS_TRANSLUCENT);
|
||||
|
||||
if (!breakingglass)
|
||||
{
|
||||
// test for complex brushes that happen to be
|
||||
// hollow in their origin (for instance, the
|
||||
// window at Q2 base3, near the satellite dish
|
||||
trace = gi.trace(origin, vec3_origin, vec3_origin, aPossibleGlassEntity->absmax, 0,
|
||||
MASK_PLAYERSOLID
|
||||
);
|
||||
breakingglass = ((trace.ent == aPossibleGlassEntity) &&
|
||||
(trace.contents & CONTENTS_TRANSLUCENT)
|
||||
);
|
||||
trace = gi.trace(origin, vec3_origin, vec3_origin, aPossibleGlassEntity->absmin, 0,
|
||||
MASK_PLAYERSOLID
|
||||
);
|
||||
breakingglass = ((breakingglass) ||
|
||||
((trace.ent == aPossibleGlassEntity) &&
|
||||
(trace.contents & CONTENTS_TRANSLUCENT)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!breakingglass)
|
||||
{
|
||||
// do remove other func_explosives
|
||||
G_FreeEdict (aPossibleGlassEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
// discovered some glass - now make store the origin
|
||||
// we need that after hiding the glass
|
||||
VectorCopy(aPossibleGlassEntity->s.origin, aPossibleGlassEntity->pos1); // IMPORTANT!
|
||||
|
||||
// make a backup of the health in light_level
|
||||
aPossibleGlassEntity->light_level = aPossibleGlassEntity->health;
|
||||
|
||||
// install the glass
|
||||
CGF_SFX_InstallBreakableGlass(aPossibleGlassEntity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_InstallBreakableGlass(edict_t* aGlassPane)
|
||||
{
|
||||
// when working on a glass pane for the first time, just install trigger
|
||||
// when working on a glass pane again (after a game ended), move
|
||||
// glass back to original location
|
||||
edict_t* trigger;
|
||||
vec3_t maxs;
|
||||
vec3_t mins;
|
||||
|
||||
// reset origin based on aGlassPane->pos1
|
||||
VectorCopy(aGlassPane->pos1, aGlassPane->s.origin);
|
||||
|
||||
// reset health based on aGlassPane->light_level
|
||||
aGlassPane->health = aGlassPane->light_level;
|
||||
|
||||
// replace die and use functions by glass specific ones
|
||||
aGlassPane->die = CGF_SFX_MiscGlassDie;
|
||||
aGlassPane->use = CGF_SFX_MiscGlassUse;
|
||||
|
||||
// reset some pane attributes
|
||||
aGlassPane->takedamage = DAMAGE_YES;
|
||||
aGlassPane->solid = SOLID_BSP;
|
||||
aGlassPane->movetype = MOVETYPE_FLYMISSILE;
|
||||
// for other movetypes, cannot move pane to hidden location and back
|
||||
|
||||
// try to establish size
|
||||
VectorCopy(aGlassPane->maxs, maxs);
|
||||
VectorCopy(aGlassPane->mins, mins);
|
||||
|
||||
// set up trigger, similar to triggers for doors
|
||||
// but with a smaller box
|
||||
mins[0] -= 24;
|
||||
mins[1] -= 24;
|
||||
mins[2] -= 24;
|
||||
maxs[0] += 24;
|
||||
maxs[1] += 24;
|
||||
maxs[2] += 24;
|
||||
|
||||
// adjust some settings
|
||||
trigger = G_Spawn ();
|
||||
trigger->classname = "breakableglass_trigger";
|
||||
VectorCopy (mins, trigger->mins);
|
||||
VectorCopy (maxs, trigger->maxs);
|
||||
trigger->owner = aGlassPane;
|
||||
trigger->solid = SOLID_TRIGGER;
|
||||
trigger->movetype = MOVETYPE_NONE;
|
||||
trigger->touch = CGF_SFX_TouchGlass;
|
||||
gi.linkentity (trigger);
|
||||
}
|
||||
|
||||
|
||||
void CGF_SFX_ShootBreakableGlass(edict_t* aGlassPane,
|
||||
edict_t* anAttacker,
|
||||
/*trace_t**/ void* tr,
|
||||
int mod
|
||||
)
|
||||
{
|
||||
// process gunshots thru glass
|
||||
edict_t* trigger;
|
||||
int destruct;
|
||||
|
||||
// depending on mod, destroy window or emit fragments
|
||||
switch (mod)
|
||||
{
|
||||
// break for ap, shotgun, handcannon, and kick, destory window
|
||||
case MOD_M3 :
|
||||
case MOD_HC :
|
||||
case MOD_SNIPER :
|
||||
case MOD_KICK :
|
||||
case MOD_GRENADE :
|
||||
case MOD_G_SPLASH:
|
||||
case MOD_HANDGRENADE:
|
||||
case MOD_HG_SPLASH:
|
||||
case MOD_KNIFE : // slash damage
|
||||
destruct = true;
|
||||
break;
|
||||
default :
|
||||
destruct = (rand() % 3 == 0);
|
||||
break;
|
||||
};
|
||||
|
||||
if (destruct)
|
||||
{
|
||||
// break glass (and hurt if doing kick)
|
||||
CGF_SFX_BreakGlass(aGlassPane, anAttacker, 0, aGlassPane->health, vec3_origin, FRAMETIME);
|
||||
if (mod == MOD_KICK)
|
||||
{
|
||||
vec3_t bloodorigin;
|
||||
vec3_t dir;
|
||||
vec3_t normal;
|
||||
VectorAdd(aGlassPane->absmax, aGlassPane->absmin, bloodorigin);
|
||||
VectorScale(bloodorigin, 0.5, bloodorigin);
|
||||
VectorSubtract(bloodorigin, anAttacker->s.origin, dir);
|
||||
VectorNormalize(dir);
|
||||
VectorMA(anAttacker->s.origin, 32.0, dir, bloodorigin);
|
||||
VectorSet(normal, 0, 0, -1);
|
||||
T_Damage(anAttacker, aGlassPane, anAttacker, dir, bloodorigin, normal, 15.0, 0, 0, MOD_BREAKINGGLASS);
|
||||
}
|
||||
|
||||
// remove corresponding trigger
|
||||
trigger = 0;
|
||||
while (trigger = G_Find(trigger, FOFS(classname), "breakableglass_trigger"))
|
||||
{
|
||||
if (trigger->owner == aGlassPane)
|
||||
{
|
||||
// remove it
|
||||
G_FreeEdict(trigger);
|
||||
// only one to be found
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add decal (if not grenade)
|
||||
if ( (mod != MOD_HANDGRENADE)
|
||||
&& (mod != MOD_HG_SPLASH)
|
||||
&& (mod != MOD_GRENADE)
|
||||
&& (mod != MOD_G_SPLASH)
|
||||
)
|
||||
{
|
||||
AddDecal(anAttacker, (trace_t*) tr);
|
||||
}
|
||||
// and emit glass
|
||||
CGF_SFX_EmitGlass(aGlassPane, anAttacker, ((trace_t*) tr)->endpos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGF_SFX_TouchGlass(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
{
|
||||
// called whenever an entity hits the trigger spawned for the glass
|
||||
|
||||
vec3_t origin;
|
||||
vec3_t normal;
|
||||
vec3_t spot;
|
||||
trace_t trace;
|
||||
edict_t* glass;
|
||||
vec3_t velocity;
|
||||
vec_t speed;
|
||||
vec_t projected_speed;
|
||||
int is_hgrenade;
|
||||
int is_knife;
|
||||
|
||||
is_hgrenade = is_knife = false;
|
||||
|
||||
// ignore non-clients-non-grenade-non-knife
|
||||
if (!other->client)
|
||||
{
|
||||
is_knife = (0 == Q_stricmp("weapon_knife", other->classname));
|
||||
if (!is_knife)
|
||||
{
|
||||
is_hgrenade = (0 == Q_stricmp("hgrenade", other->classname));
|
||||
}
|
||||
|
||||
if ((!is_knife) && (!is_hgrenade))
|
||||
return;
|
||||
if (is_knife)
|
||||
goto knife_and_grenade_handling;
|
||||
}
|
||||
|
||||
// test whether other really hits the glass - deal with
|
||||
// the special case that other hits some boundary close to the border of the glass pane
|
||||
//
|
||||
//
|
||||
// ....trigger.......
|
||||
// +++++++++ +++++++++++
|
||||
// .+---glass------+.
|
||||
// wall .+--------------+.wall
|
||||
// +++++++++ +++++++++++
|
||||
// ----->..................
|
||||
// wrong ^ ^
|
||||
// | |
|
||||
// wrong ok
|
||||
//
|
||||
glass = self->owner;
|
||||
// hack - set glass' movetype to MOVETYPE_PUSH as it is not
|
||||
// moving as long as the trigger is active
|
||||
glass->movetype = MOVETYPE_PUSH;
|
||||
|
||||
VectorAdd(glass->absmax, glass->absmin, origin);
|
||||
VectorScale(origin, 0.5, origin);
|
||||
|
||||
// other needs to be able to trace to glass origin
|
||||
trace = gi.trace(other->s.origin, vec3_origin, vec3_origin, origin, other,
|
||||
MASK_PLAYERSOLID
|
||||
);
|
||||
if (trace.ent != glass)
|
||||
return;
|
||||
|
||||
// we can reach the glass origin, so we have the normal of
|
||||
// the glass plane
|
||||
VectorCopy(trace.plane.normal, normal);
|
||||
|
||||
// we need to check if client is not running into wall next
|
||||
// to the glass (the trigger stretches into the wall)
|
||||
VectorScale(normal, -1000.0, spot);
|
||||
VectorAdd(spot, other->s.origin, spot);
|
||||
// line between other->s.origin and spot (perpendicular to glass
|
||||
// surface should not hit wall but glass instead
|
||||
trace = gi.trace(other->s.origin, vec3_origin, vec3_origin, spot, other,
|
||||
MASK_PLAYERSOLID
|
||||
);
|
||||
if (trace.ent != glass)
|
||||
return;
|
||||
|
||||
// now, we check if the client's speed perpendicular to
|
||||
// the glass plane, exceeds the required 175
|
||||
// (speed should be < -200, as the plane's normal
|
||||
// points towards the client
|
||||
VectorCopy(other->velocity, velocity);
|
||||
speed = VectorNormalize(velocity);
|
||||
projected_speed = speed * DotProduct(velocity, normal);
|
||||
|
||||
// bump projected speed for grenades - they should break
|
||||
// the window more easily
|
||||
if (is_hgrenade)
|
||||
projected_speed *= 1.5;
|
||||
|
||||
// if hitting the glass with sufficient speed (project < -175),
|
||||
// being jumpkicked (speed > 700, project < -5) break the window
|
||||
if (!((projected_speed < -175.0) ||
|
||||
((projected_speed < -5) && (speed > 700))
|
||||
)
|
||||
)
|
||||
goto knife_and_grenade_handling;
|
||||
|
||||
// break glass
|
||||
CGF_SFX_BreakGlass(glass, other, other, glass->health, vec3_origin, 3.0 * FRAMETIME);
|
||||
// glass can take care of itself, but the trigger isn't needed anymore
|
||||
G_FreeEdict (self);
|
||||
|
||||
/* not needed
|
||||
// reduce momentum of the client (he just broke the window
|
||||
// so he should lose speed. in addition, it doesn't feel
|
||||
// right if he overtakes the glass fragments
|
||||
// VectorScale(normal, 200.0, velocity);
|
||||
// VectorAdd(other->velocity, velocity, other->velocity);
|
||||
*/
|
||||
|
||||
// make sure client takes damage
|
||||
T_Damage(other, glass, other, normal, other->s.origin, normal, 15.0, 0, 0, MOD_BREAKINGGLASS);
|
||||
return;
|
||||
|
||||
// goto label
|
||||
knife_and_grenade_handling:
|
||||
// if knife or grenade, bounce them
|
||||
if ((is_knife) || (is_hgrenade))
|
||||
{
|
||||
// change clipmask to bounce of glass
|
||||
other->clipmask = MASK_SOLID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CGF_SFX_BreakGlass(edict_t* aGlassPane, edict_t* anInflictor, edict_t* anAttacker,
|
||||
int aDamage, vec3_t aPoint, vec_t aPaneDestructDelay
|
||||
)
|
||||
{
|
||||
// based on func_explode, but with lotsa subtle differences
|
||||
vec3_t origin;
|
||||
vec3_t old_origin;
|
||||
vec3_t chunkorigin;
|
||||
vec3_t size;
|
||||
int count;
|
||||
int mass;
|
||||
|
||||
// bmodel origins are (0 0 0), we need to adjust that here
|
||||
VectorCopy(aGlassPane->s.origin, old_origin);
|
||||
VectorScale (aGlassPane->size, 0.5, size);
|
||||
VectorAdd (aGlassPane->absmin, size, origin);
|
||||
VectorCopy (origin, aGlassPane->s.origin);
|
||||
|
||||
aGlassPane->takedamage = DAMAGE_NO;
|
||||
|
||||
VectorSubtract (aGlassPane->s.origin, anInflictor->s.origin, aGlassPane->velocity);
|
||||
VectorNormalize (aGlassPane->velocity);
|
||||
// use speed 250 instead of 150 for funkier glass spray
|
||||
VectorScale (aGlassPane->velocity, 250.0, aGlassPane->velocity);
|
||||
|
||||
// start chunks towards the center
|
||||
VectorScale (size, 0.75, size);
|
||||
|
||||
mass = aGlassPane->mass;
|
||||
if (!mass)
|
||||
mass = 75;
|
||||
|
||||
// big chunks
|
||||
if (mass >= 100)
|
||||
{
|
||||
count = mass / 100;
|
||||
if (count > 8)
|
||||
count = 8;
|
||||
while(count--)
|
||||
{
|
||||
CGF_SFX_ApplyGlassFragmentLimit("debris");
|
||||
chunkorigin[0] = origin[0] + crandom() * size[0];
|
||||
chunkorigin[1] = origin[1] + crandom() * size[1];
|
||||
chunkorigin[2] = origin[2] + crandom() * size[2];
|
||||
CGF_SFX_GlassThrowDebris (aGlassPane, "models/objects/debris1/tris.md2", 1, chunkorigin);
|
||||
}
|
||||
}
|
||||
|
||||
// small chunks
|
||||
count = mass / 25;
|
||||
if (count > 16)
|
||||
count = 16;
|
||||
while(count--)
|
||||
{
|
||||
CGF_SFX_ApplyGlassFragmentLimit("debris");
|
||||
chunkorigin[0] = origin[0] + crandom() * size[0];
|
||||
chunkorigin[1] = origin[1] + crandom() * size[1];
|
||||
chunkorigin[2] = origin[2] + crandom() * size[2];
|
||||
CGF_SFX_GlassThrowDebris (aGlassPane, "models/objects/debris2/tris.md2", 2, chunkorigin);
|
||||
}
|
||||
|
||||
// clear velocity, reset origin (that has been abused in ThrowDebris)
|
||||
VectorClear(aGlassPane->velocity);
|
||||
VectorCopy (old_origin, aGlassPane->s.origin);
|
||||
|
||||
if (anAttacker)
|
||||
{
|
||||
// jumping thru
|
||||
G_UseTargets (aGlassPane, anAttacker);
|
||||
}
|
||||
else
|
||||
{
|
||||
// firing thru - the pane has no direct attacker to hurt,
|
||||
// but G_UseTargets expects one. So make it a DIY
|
||||
G_UseTargets (aGlassPane, aGlassPane);
|
||||
}
|
||||
|
||||
// have glass plane be visible for two more frames,
|
||||
// and have it self-destruct then
|
||||
// meanwhile, make sure the player can move thru
|
||||
aGlassPane->solid = SOLID_NOT;
|
||||
aGlassPane->think = CGF_SFX_HideBreakableGlass;
|
||||
aGlassPane->nextthink = level.time + aPaneDestructDelay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_EmitGlass (edict_t* aGlassPane, edict_t* anInflictor, vec3_t aPoint)
|
||||
{
|
||||
// based on func_explode, but with lotsa subtle differences
|
||||
vec3_t old_origin;
|
||||
vec3_t chunkorigin;
|
||||
vec3_t size;
|
||||
int count;
|
||||
|
||||
// bmodel origins are (0 0 0), we need to adjust that here
|
||||
VectorCopy(aGlassPane->s.origin, old_origin);
|
||||
VectorCopy (aPoint, aGlassPane->s.origin);
|
||||
|
||||
VectorSubtract (aGlassPane->s.origin, anInflictor->s.origin, aGlassPane->velocity);
|
||||
VectorNormalize (aGlassPane->velocity);
|
||||
// use speed 250 instead of 150 for funkier glass spray
|
||||
VectorScale (aGlassPane->velocity, 250.0, aGlassPane->velocity);
|
||||
|
||||
// start chunks towards the center
|
||||
VectorScale (aGlassPane->size, 0.25, size);
|
||||
|
||||
count = 4;
|
||||
while(count--)
|
||||
{
|
||||
CGF_SFX_ApplyGlassFragmentLimit("debris");
|
||||
chunkorigin[0] = aPoint[0] + crandom() * size[0];
|
||||
chunkorigin[1] = aPoint[1] + crandom() * size[1];
|
||||
chunkorigin[2] = aPoint[2] + crandom() * size[2];
|
||||
CGF_SFX_GlassThrowDebris (aGlassPane, "models/objects/debris2/tris.md2", 2, chunkorigin);
|
||||
}
|
||||
|
||||
// clear velocity, reset origin (that has been abused in ThrowDebris)
|
||||
VectorClear(aGlassPane->velocity);
|
||||
VectorCopy (old_origin, aGlassPane->s.origin);
|
||||
|
||||
// firing thru - the pane has no direct attacker to hurt,
|
||||
// but G_UseTargets expects one. So make it a DIY
|
||||
G_UseTargets (aGlassPane, aGlassPane);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_HideBreakableGlass(edict_t* aGlassPane)
|
||||
{
|
||||
// remove all attached decals
|
||||
edict_t* decal;
|
||||
decal = 0;
|
||||
while (decal = G_Find(decal, FOFS(classname), "decal"))
|
||||
{
|
||||
if (decal->owner == aGlassPane)
|
||||
{
|
||||
// make it goaway in the next frame
|
||||
decal->nextthink = level.time + FRAMETIME;
|
||||
}
|
||||
}
|
||||
|
||||
while (decal = G_Find(decal, FOFS(classname), "splat"))
|
||||
{
|
||||
if (decal->owner == aGlassPane)
|
||||
{
|
||||
// make it goaway in the next frame
|
||||
decal->nextthink = level.time + FRAMETIME;
|
||||
}
|
||||
}
|
||||
|
||||
// after being broken, the pane cannot be freed as it is needed in
|
||||
// subsequent missions/games, so hide it at about z = -1000 lower
|
||||
aGlassPane->movetype = MOVETYPE_FLYMISSILE;
|
||||
VectorCopy(aGlassPane->s.origin, aGlassPane->pos1);
|
||||
aGlassPane->s.origin[2] -=1000.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_AttachDecalToGlass(edict_t* aGlassPane, edict_t* aDecal)
|
||||
{
|
||||
// just set aDecal's owner to be the glass pane
|
||||
aDecal->owner = aGlassPane;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_RebuildAllBrokenGlass()
|
||||
{
|
||||
// iterate over all func_explosives
|
||||
edict_t* glass;
|
||||
glass = 0;
|
||||
while (glass = G_Find(glass, FOFS(classname), "func_explosive"))
|
||||
{
|
||||
// glass is broken if solid != SOLID_BSP
|
||||
if (glass->solid != SOLID_BSP)
|
||||
{
|
||||
CGF_SFX_InstallBreakableGlass(glass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_ApplyGlassFragmentLimit(const char* aClassName)
|
||||
{
|
||||
edict_t* oldfragment;
|
||||
|
||||
glassfragmentcount++;
|
||||
if (glassfragmentcount > glassfragmentlimit->value)
|
||||
glassfragmentcount = 1;
|
||||
|
||||
// remove fragment with corresponding number if any
|
||||
oldfragment = FindEdictByClassnum((char*) aClassName, glassfragmentcount);
|
||||
|
||||
if (oldfragment)
|
||||
{
|
||||
// oldfragment->nextthink = level.time + FRAMETIME;
|
||||
G_FreeEdict(oldfragment);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_MiscGlassUse(edict_t *self, edict_t *other, edict_t *activator)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
const char* classname;
|
||||
classname = other->classname;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CGF_SFX_MiscGlassDie(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
const char* classname;
|
||||
classname = inflictor->classname;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static vec_t previous_throw_time = 0;
|
||||
static int this_throw_count = 0;
|
||||
|
||||
void CGF_SFX_GlassThrowDebris (edict_t *self, char *modelname, float speed, vec3_t origin)
|
||||
{
|
||||
// based on ThrowDebris from id software - now returns debris created
|
||||
edict_t *chunk;
|
||||
vec3_t v;
|
||||
|
||||
if (level.time != previous_throw_time)
|
||||
{
|
||||
previous_throw_time = level.time;
|
||||
this_throw_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_throw_count++;
|
||||
if (this_throw_count > glassfragmentlimit->value)
|
||||
return;
|
||||
}
|
||||
|
||||
chunk = G_Spawn();
|
||||
VectorCopy (origin, chunk->s.origin);
|
||||
gi.setmodel (chunk, modelname);
|
||||
v[0] = 100 * crandom();
|
||||
v[1] = 100 * crandom();
|
||||
v[2] = 100 + 100 * crandom();
|
||||
VectorMA (self->velocity, speed, v, chunk->velocity);
|
||||
chunk->movetype = MOVETYPE_BOUNCE;
|
||||
chunk->solid = SOLID_NOT;
|
||||
chunk->avelocity[0] = random()*600;
|
||||
chunk->avelocity[1] = random()*600;
|
||||
chunk->avelocity[2] = random()*600;
|
||||
chunk->think = G_FreeEdict;
|
||||
chunk->nextthink = level.time + 5 + random()*5;
|
||||
chunk->s.frame = 0;
|
||||
chunk->flags = 0;
|
||||
chunk->classname = "debris";
|
||||
chunk->takedamage = DAMAGE_YES;
|
||||
chunk->die = debris_die;
|
||||
gi.linkentity (chunk);
|
||||
|
||||
// number chunk
|
||||
chunk->classnum = glassfragmentcount;
|
||||
}
|
||||
|
||||
|
281
cgf_sfx_glass.h
Normal file
281
cgf_sfx_glass.h
Normal file
|
@ -0,0 +1,281 @@
|
|||
/****************************************************************************/
|
||||
/* */
|
||||
/* project : CGF (c) 1999 William van der Sterren */
|
||||
/* parts (c) 1998 id software */
|
||||
/* */
|
||||
/* file : cgf_sfx_glass.h "special effects for glass entities" */
|
||||
/* author(s): William van der Sterren */
|
||||
/* version : 0.5 */
|
||||
/* */
|
||||
/* date (last revision): Jun 12, 99 */
|
||||
/* date (creation) : Jun 04, 99 */
|
||||
/* */
|
||||
/* */
|
||||
/* revision history */
|
||||
/* -- date ---- | -- revision ---------------------- | -- revisor -- */
|
||||
/* Jun 12, 1999 | fixed knife slash breaks glass | William */
|
||||
/* */
|
||||
/******* http://www.botepidemic.com/aid/cgf for CGF for Action Quake2 *******/
|
||||
|
||||
|
||||
#ifndef __CGF_SFX_GLASS_H_
|
||||
#define __CGF_SFX_GLASS_H_
|
||||
|
||||
|
||||
// defines (should be consistent with other weapon defs in g_local.h)
|
||||
#define MOD_BREAKINGGLASS 46
|
||||
|
||||
/*
|
||||
// forward definitions
|
||||
typedef struct edict_s edict_t;
|
||||
*/
|
||||
|
||||
|
||||
// export a number of functions to g_func.c:
|
||||
//
|
||||
//
|
||||
|
||||
void CGF_SFX_InstallGlassSupport();
|
||||
// registers cvar breakableglass (default 0)
|
||||
// registers cvar glassfragmentlimit (default 30)
|
||||
|
||||
|
||||
void CGF_SFX_RebuildAllBrokenGlass();
|
||||
// upon starting a new team play game, reconstruct any
|
||||
// broken glass because we like to break it again
|
||||
|
||||
|
||||
int CGF_SFX_IsBreakableGlassEnabled();
|
||||
// returns whether breakable glass is enabled (cvar breakableglass)
|
||||
|
||||
|
||||
void CGF_SFX_TestBreakableGlassAndRemoveIfNot_Think(edict_t* aPossibleGlassEntity);
|
||||
// initial think function for all func_explosives
|
||||
// because we cannot verify the contents of the entity unless the entity
|
||||
// has been spawned, we need to first introduce the entity, and remove
|
||||
// it later (level.time == 0.1) if required
|
||||
|
||||
|
||||
void CGF_SFX_ShootBreakableGlass(edict_t* aGlassPane,
|
||||
edict_t* anAttacker,
|
||||
/*trace_t*/ void* tr,
|
||||
int mod
|
||||
);
|
||||
// shoot thru glass - depending on bullet types and
|
||||
// random effects, glass just emits fragments, or breaks
|
||||
|
||||
|
||||
void CGF_SFX_AttachDecalToGlass(edict_t* aGlassPane, edict_t* aDecal);
|
||||
// a glass that breaks will remove all decals (blood splashes, bullet
|
||||
// holes) if they are attached
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
further documentation:
|
||||
|
||||
cgf_sfx_glass.cpp can be compiled with ordinary c compilers as
|
||||
well - just change the extension from .cpp to .c
|
||||
|
||||
to install breakable glass in the ActionQuake2 1.51 code base,
|
||||
do the following:
|
||||
|
||||
@ file a_game.h
|
||||
+ modify
|
||||
#define ACTION_VERSION "1.51"
|
||||
to something that tells users breakable glass is supported
|
||||
|
||||
@ file a_team.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ in void CleanLevel()
|
||||
add
|
||||
CGF_SFX_RebuildAllBrokenGlass();
|
||||
as the last statement (thus after CleanBodies();)
|
||||
|
||||
@ file g_misc.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ in void SP_func_explosive (edict_t *self)
|
||||
disable the statements (put them within comments):
|
||||
if (deathmatch->value)
|
||||
{ // auto-remove for deathmatch
|
||||
G_FreeEdict (self);
|
||||
return;
|
||||
}
|
||||
+ in void SP_func_explosive (edict_t *self)
|
||||
add
|
||||
self->think = CGF_SFX_TestBreakableGlassAndRemoveIfNot_Think;
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
as the last statement (thus after gi.linkentity (self);)
|
||||
|
||||
@ file g_save.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ in void InitGame (void)
|
||||
add
|
||||
CGF_SFX_InstallGlassSupport();
|
||||
under (splatlimit = gi.cvar ("splatlimit", "0", 0);)
|
||||
|
||||
@ file g_local.h
|
||||
+ replace
|
||||
void AddDecal (edict_t *self, vec3_t point, vec3_t direct);
|
||||
void AddSplat (edict_t *self, vec3_t point, vec3_t direct);
|
||||
by
|
||||
void AddDecal (edict_t *self, trace_t* tr);
|
||||
void AddSplat (edict_t *self, vec3_t point, trace_t* tr);
|
||||
|
||||
@ file a_game.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ replace
|
||||
void AddDecal (edict_t *self, vec3_t point, vec3_t direct)
|
||||
by
|
||||
void AddDecal (edict_t *self, trace_t* tr)
|
||||
+ replace
|
||||
void AddSplat (edict_t *self, vec3_t point, vec3_t direct);
|
||||
by
|
||||
void AddSplat (edict_t *self, vec3_t point, trace_t* tr);
|
||||
+ in void AddDecal (edict_t *self, trace_t* tr)
|
||||
replace each occurrence of 'point' by tr->endpos
|
||||
+ in void AddDecal (edict_t *self, trace_t* tr)
|
||||
replace each occurrence of 'direct' by tr->plane.normal
|
||||
+ in void AddDecal (edict_t *self, trace_t* tr)
|
||||
add (as the last line, thus under gi.linkentity (decal);)
|
||||
if ((tr->ent) && (0 == Q_stricmp("func_explosive", tr->ent->classname)))
|
||||
{
|
||||
CGF_SFX_AttachDecalToGlass(tr->ent, decal);
|
||||
}
|
||||
+ in void AddSplat (edict_t *self, vec3_t point, trace_t* tr)
|
||||
replace each occurrence of 'direct' by tr->plane.normal
|
||||
+ in void AddSplat (edict_t *self, vec3_t point, trace_t* tr)
|
||||
add (as the last line, thus under gi.linkentity (decal);)
|
||||
if ((tr->ent) && (0 == Q_stricmp("func_explosive", tr->ent->classname)))
|
||||
{
|
||||
CGF_SFX_AttachDecalToGlass(tr->ent, splat);
|
||||
}
|
||||
@ file g_weapon.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ in static void fire_lead (edict_t *self, ...)
|
||||
replace
|
||||
AddDecal (self, tr.endpos, tr.plane.normal);
|
||||
by
|
||||
AddDecal (self, &tr);
|
||||
+ in void fire_lead_ap (edict_t *self, ...)
|
||||
replace
|
||||
AddDecal (self, tr.endpos, tr.plane.normal);
|
||||
by
|
||||
AddDecal (self, &tr);
|
||||
+ in static void fire_lead (edict_t *self, ...)
|
||||
add
|
||||
between
|
||||
tr = do_trace (start, NULL, NULL, end, self, content_mask);
|
||||
and
|
||||
// see if we hit water
|
||||
the following
|
||||
// catch case of firing thru one or breakable glasses
|
||||
while ( (tr.fraction < 1.0)
|
||||
&& (tr.surface->flags & (SURF_TRANS33 | SURF_TRANS66))
|
||||
&& (tr.ent)
|
||||
&& (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
)
|
||||
{
|
||||
// break glass
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, self, &tr, mod);
|
||||
// continue trace from current endpos to start
|
||||
tr = do_trace (tr.endpos, NULL, NULL, end, tr.ent, content_mask);
|
||||
}
|
||||
+ in static void fire_lead_ap (edict_t *self, ...)
|
||||
add
|
||||
between
|
||||
tr = do_trace (start, NULL, NULL, end, self, content_mask);
|
||||
and
|
||||
// see if we hit water
|
||||
the following
|
||||
// catch case of firing thru one or breakable glasses
|
||||
while ( (tr.fraction < 1.0)
|
||||
&& (tr.surface->flags & (SURF_TRANS33 | SURF_TRANS66))
|
||||
&& (tr.ent)
|
||||
&& (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
)
|
||||
{
|
||||
// break glass
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, self, &tr, mod);
|
||||
// continue trace from current endpos to start
|
||||
tr = do_trace (tr.endpos, NULL, NULL, end, tr.ent, content_mask);
|
||||
}
|
||||
+ in void knife_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
replace
|
||||
if (other->takedamage)
|
||||
by
|
||||
if (0 == Q_stricmp(other->classname, "func_explosive"))
|
||||
{
|
||||
// ignore it, so it can bounce
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (other->takedamage)
|
||||
+ in void kick_attack (edict_t * ent )
|
||||
between
|
||||
// zucc stop powerful upwards kicking
|
||||
forward[2] = 0;
|
||||
and
|
||||
T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage, kick, 0, MOD_KICK );
|
||||
add
|
||||
if (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
{
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, ent, &tr, MOD_KICK);
|
||||
}
|
||||
+ in int knife_attack ( edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick)
|
||||
replace
|
||||
if (tr.ent->takedamage)
|
||||
by
|
||||
if (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
{
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, self, &tr, MOD_KNIFE);
|
||||
}
|
||||
else
|
||||
if (tr.ent->takedamage)
|
||||
|
||||
@ file g_phys.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ in void SV_Physics_Toss (edict_t *ent)
|
||||
replace
|
||||
AddSplat (self, tr.endpos, tr.plane.normal);
|
||||
by
|
||||
AddSplat (self, &tr);
|
||||
|
||||
@ file g_combat.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ in void T_Damage (edict_t *targ, ...)
|
||||
replace
|
||||
if ( (mod == MOD_M3) || (mod == MOD_HC) || (mod == MOD_HELD_GRENADE) ||
|
||||
(mod == MOD_HG_SPLASH) || (mod == MOD_G_SPLASH) )
|
||||
by
|
||||
if ( (mod == MOD_M3)
|
||||
|| (mod == MOD_HC)
|
||||
|| (mod == MOD_HELD_GRENADE)
|
||||
|| (mod == MOD_HG_SPLASH)
|
||||
|| (mod == MOD_G_SPLASH)
|
||||
|| (mod == MOD_BREAKINGGLASS)
|
||||
)
|
||||
+ in void T_RadiusDamage (...)
|
||||
add before if (CanDamage (ent, inflictor))
|
||||
if (0 == Q_stricmp(ent->classname, "func_explosive"))
|
||||
{
|
||||
CGF_SFX_ShootBreakableGlass(ent, inflictor, 0, mod);
|
||||
}
|
||||
else
|
||||
|
||||
@ file p_client.c
|
||||
+ add #include "cgf_sfx_glass.h"
|
||||
+ in void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
||||
between
|
||||
switch (mod)
|
||||
{
|
||||
and
|
||||
case MOD_SUICIDE:
|
||||
add
|
||||
case MOD_BREAKINGGLASS:
|
||||
message = "ate too much glass";
|
||||
break;
|
||||
*/
|
38
g_chase.c
38
g_chase.c
|
@ -69,7 +69,9 @@ void UpdateChaseCam(edict_t *ent)
|
|||
if (!targ->groundentity)
|
||||
o[2] += 16;
|
||||
|
||||
trace = do_trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
|
||||
VectorCopy(trace.endpos, goal);
|
||||
|
||||
|
@ -78,7 +80,9 @@ void UpdateChaseCam(edict_t *ent)
|
|||
// pad for floors and ceilings
|
||||
VectorCopy(goal, o);
|
||||
o[2] += 6;
|
||||
trace = do_trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction < 1) {
|
||||
VectorCopy(trace.endpos, goal);
|
||||
goal[2] -= 6;
|
||||
|
@ -86,7 +90,9 @@ void UpdateChaseCam(edict_t *ent)
|
|||
|
||||
VectorCopy(goal, o);
|
||||
o[2] -= 6;
|
||||
trace = do_trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction < 1) {
|
||||
VectorCopy(trace.endpos, goal);
|
||||
goal[2] += 6;
|
||||
|
@ -131,8 +137,11 @@ void UpdateChaseCam(edict_t *ent)
|
|||
}
|
||||
else
|
||||
{
|
||||
VectorCopy(targ->client->v_angle, ent->client->ps.viewangles);
|
||||
VectorCopy(targ->client->v_angle, ent->client->v_angle);
|
||||
VectorAdd(targ->client->v_angle,
|
||||
targ->client->ps.kick_angles,
|
||||
angles);
|
||||
VectorCopy(angles, ent->client->ps.viewangles);
|
||||
VectorCopy(angles, ent->client->v_angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +166,12 @@ void ChaseNext(edict_t *ent)
|
|||
e = g_edicts + i;
|
||||
if (!e->inuse)
|
||||
continue;
|
||||
//Black Cross - Begin
|
||||
if (teamplay->value && limchasecam->value &&
|
||||
ent->client->resp.team != NOTEAM &&
|
||||
ent->client->resp.team != e->client->resp.team)
|
||||
continue;
|
||||
//Black Cross - End
|
||||
if (e->solid != SOLID_NOT || e->deadflag == DEAD_DEAD)
|
||||
break;
|
||||
} while (e != ent->client->chase_target);
|
||||
|
@ -180,6 +195,12 @@ void ChasePrev(edict_t *ent)
|
|||
e = g_edicts + i;
|
||||
if (!e->inuse)
|
||||
continue;
|
||||
//Black Cross - Begin
|
||||
if (teamplay->value && limchasecam->value &&
|
||||
ent->client->resp.team != NOTEAM &&
|
||||
ent->client->resp.team != e->client->resp.team)
|
||||
continue;
|
||||
//Black Cross - End
|
||||
if (e->solid != SOLID_NOT || e->deadflag == DEAD_DEAD)
|
||||
break;
|
||||
} while (e != ent->client->chase_target);
|
||||
|
@ -218,6 +239,12 @@ void GetChaseTarget(edict_t *ent)
|
|||
e = g_edicts + i;
|
||||
if (!e->inuse)
|
||||
continue;
|
||||
//Black Cross - Begin
|
||||
if (teamplay->value && limchasecam->value &&
|
||||
ent->client->resp.team != NOTEAM &&
|
||||
ent->client->resp.team != e->client->resp.team)
|
||||
continue;
|
||||
//Black Cross - End
|
||||
if (e->solid != SOLID_NOT || e->deadflag == DEAD_DEAD)
|
||||
{
|
||||
found = 1;
|
||||
|
@ -235,4 +262,3 @@ void GetChaseTarget(edict_t *ent)
|
|||
ent->client->chase_target = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
52
g_cmds.c
52
g_cmds.c
|
@ -490,6 +490,33 @@ void Cmd_Use_f (edict_t *ent)
|
|||
s = SNIPER_NAME;
|
||||
if (!stricmp(s, "bfg10k"))
|
||||
s = KNIFE_NAME;
|
||||
// zucc - let people pull up a knife ready to be thrown
|
||||
if (!stricmp(s, "throwing combat knife"))
|
||||
{
|
||||
if ( ent->client->curr_weap != KNIFE_NUM )
|
||||
{
|
||||
ent->client->resp.knife_mode = 1;
|
||||
}
|
||||
// switch to throwing mode if a knife is already out
|
||||
else
|
||||
{
|
||||
Cmd_New_Weapon_f( ent );
|
||||
}
|
||||
s = KNIFE_NAME;
|
||||
}
|
||||
if (!stricmp(s, "slashing combat knife"))
|
||||
{
|
||||
if ( ent->client->curr_weap != KNIFE_NUM )
|
||||
{
|
||||
ent->client->resp.knife_mode = 0;
|
||||
}
|
||||
// switch to slashing mode if a knife is already out
|
||||
else
|
||||
{
|
||||
Cmd_New_Weapon_f( ent );
|
||||
}
|
||||
s = KNIFE_NAME;
|
||||
}
|
||||
if (!stricmp(s, "grenade launcher"))
|
||||
s = M4_NAME;
|
||||
if (!stricmp(s, "grenades"))
|
||||
|
@ -969,7 +996,7 @@ Cmd_Say_f
|
|||
*/
|
||||
void Cmd_Say_f (edict_t *ent, qboolean team, qboolean arg0, qboolean partner_msg)
|
||||
{
|
||||
int j, i;
|
||||
int j, i, offset_of_text;
|
||||
edict_t *other;
|
||||
char *p;
|
||||
char text[2048];
|
||||
|
@ -987,17 +1014,35 @@ void Cmd_Say_f (edict_t *ent, qboolean team, qboolean arg0, qboolean partner_msg
|
|||
}
|
||||
|
||||
if (team)
|
||||
{
|
||||
if (ent->client->resp.team == NOTEAM)
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "You're not on a team.\n");
|
||||
return;
|
||||
}
|
||||
Com_sprintf (text, sizeof(text), "%s(%s): ",
|
||||
(teamplay->value && (ent->solid == SOLID_NOT || ent->deadflag == DEAD_DEAD)) ? "[DEAD] " : "",
|
||||
ent->client->pers.netname);
|
||||
}
|
||||
else if (partner_msg)
|
||||
{
|
||||
if (ent->client->resp.radio_partner == NULL)
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "You don't have a partner.\n");
|
||||
return;
|
||||
}
|
||||
Com_sprintf (text, sizeof(text), "[%sPARTNER] %s: ",
|
||||
(teamplay->value && (ent->solid == SOLID_NOT || ent->deadflag == DEAD_DEAD)) ? "DEAD " : "",
|
||||
ent->client->pers.netname);
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_sprintf (text, sizeof(text), "%s%s: ",
|
||||
(teamplay->value && (ent->solid == SOLID_NOT || ent->deadflag == DEAD_DEAD)) ? "[DEAD] " : "",
|
||||
ent->client->pers.netname);
|
||||
}
|
||||
|
||||
offset_of_text = strlen(text); //FB 5/31/99
|
||||
|
||||
if (arg0)
|
||||
{
|
||||
|
@ -1023,9 +1068,10 @@ void Cmd_Say_f (edict_t *ent, qboolean team, qboolean arg0, qboolean partner_msg
|
|||
text[300] = 0;
|
||||
|
||||
if (ent->solid != SOLID_NOT && ent->deadflag != DEAD_DEAD)
|
||||
ParseSayText(ent, text);
|
||||
ParseSayText(ent, text + offset_of_text); //FB 5/31/99 - offset change
|
||||
// this will parse the % variables,
|
||||
// and again check 300 limit afterwards -FB
|
||||
// (although it checks it without the name in front, oh well)
|
||||
|
||||
strcat(text, "\n");
|
||||
|
||||
|
@ -1218,7 +1264,7 @@ void ClientCommand (edict_t *ent)
|
|||
else if (Q_stricmp (cmd, "reload") == 0)
|
||||
Cmd_New_Reload_f (ent);
|
||||
else if (Q_stricmp (cmd, "weapon") == 0)
|
||||
Cmd_Weapon_f (ent);
|
||||
Cmd_New_Weapon_f (ent);
|
||||
else if (Q_stricmp (cmd, "opendoor") == 0)
|
||||
Cmd_OpenDoor_f (ent);
|
||||
else if (Q_stricmp (cmd, "bandage") == 0)
|
||||
|
|
165
g_combat.c
165
g_combat.c
|
@ -1,26 +1,39 @@
|
|||
// g_combat.c
|
||||
|
||||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
|
||||
void Add_TeamWound( edict_t *attacker, edict_t *victim, int mod);
|
||||
|
||||
/*
|
||||
============
|
||||
CanDamage
|
||||
|
||||
Returns true if the inflictor can directly damage the target. Used for
|
||||
explosions and melee attacks.
|
||||
============
|
||||
Returns true if the inflictor can directly damage the target. Used for
|
||||
explosions and melee attacks.
|
||||
============
|
||||
*/
|
||||
qboolean CanDamage (edict_t *targ, edict_t *inflictor)
|
||||
{
|
||||
vec3_t dest;
|
||||
trace_t trace;
|
||||
|
||||
// bmodels need special checking because their origin is 0,0,0
|
||||
if (targ->movetype == MOVETYPE_PUSH)
|
||||
// bmodels need special checking because their origin is 0,0,0
|
||||
//GLASS FX
|
||||
if ((targ->movetype == MOVETYPE_PUSH)
|
||||
||
|
||||
((targ->movetype == MOVETYPE_FLYMISSILE)
|
||||
&&
|
||||
(0 == Q_stricmp("func_explosive", targ->classname))
|
||||
)
|
||||
)
|
||||
//GLASS FX
|
||||
{
|
||||
VectorAdd (targ->absmin, targ->absmax, dest);
|
||||
VectorScale (dest, 0.5, dest);
|
||||
trace = do_trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction == 1.0)
|
||||
return true;
|
||||
if (trace.ent == targ)
|
||||
|
@ -28,35 +41,45 @@ qboolean CanDamage (edict_t *targ, edict_t *inflictor)
|
|||
return false;
|
||||
}
|
||||
|
||||
trace = do_trace (inflictor->s.origin, vec3_origin, vec3_origin, targ->s.origin, inflictor, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, targ->s.origin, inflictor, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction == 1.0)
|
||||
return true;
|
||||
|
||||
VectorCopy (targ->s.origin, dest);
|
||||
dest[0] += 15.0;
|
||||
dest[1] += 15.0;
|
||||
trace = do_trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction == 1.0)
|
||||
return true;
|
||||
|
||||
VectorCopy (targ->s.origin, dest);
|
||||
dest[0] += 15.0;
|
||||
dest[1] -= 15.0;
|
||||
trace = do_trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction == 1.0)
|
||||
return true;
|
||||
|
||||
VectorCopy (targ->s.origin, dest);
|
||||
dest[0] -= 15.0;
|
||||
dest[1] += 15.0;
|
||||
trace = do_trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction == 1.0)
|
||||
return true;
|
||||
|
||||
VectorCopy (targ->s.origin, dest);
|
||||
dest[0] -= 15.0;
|
||||
dest[1] -= 15.0;
|
||||
trace = do_trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
PRETRACE();
|
||||
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (trace.fraction == 1.0)
|
||||
return true;
|
||||
|
||||
|
@ -86,7 +109,7 @@ void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, v
|
|||
|
||||
if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD))
|
||||
{
|
||||
// targ->svflags |= SVF_DEADMONSTER; // now treat as a different content type
|
||||
// targ->svflags |= SVF_DEADMONSTER; // now treat as a different content type
|
||||
if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY))
|
||||
{
|
||||
level.killed_monsters++;
|
||||
|
@ -125,7 +148,7 @@ void SpawnDamage (int type, vec3_t origin, vec3_t normal, int damage)
|
|||
damage = 255;
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (type);
|
||||
// gi.WriteByte (damage);
|
||||
// gi.WriteByte (damage);
|
||||
gi.WritePosition (origin);
|
||||
gi.WriteDir (normal);
|
||||
gi.multicast (origin, MULTICAST_PVS);
|
||||
|
@ -136,25 +159,25 @@ void SpawnDamage (int type, vec3_t origin, vec3_t normal, int damage)
|
|||
============
|
||||
T_Damage
|
||||
|
||||
targ entity that is being damaged
|
||||
inflictor entity that is causing the damage
|
||||
attacker entity that caused the inflictor to damage targ
|
||||
targ entity that is being damaged
|
||||
inflictor entity that is causing the damage
|
||||
attacker entity that caused the inflictor to damage targ
|
||||
example: targ=monster, inflictor=rocket, attacker=player
|
||||
|
||||
dir direction of the attack
|
||||
point point at which the damage is being inflicted
|
||||
normal normal vector from that point
|
||||
damage amount of damage being inflicted
|
||||
knockback force to be applied against targ as a result of the damage
|
||||
dir direction of the attack
|
||||
point point at which the damage is being inflicted
|
||||
normal normal vector from that point
|
||||
damage amount of damage being inflicted
|
||||
knockback force to be applied against targ as a result of the damage
|
||||
|
||||
dflags these flags are used to control how T_Damage works
|
||||
dflags these flags are used to control how T_Damage works
|
||||
DAMAGE_RADIUS damage was indirect (from a nearby explosion)
|
||||
DAMAGE_NO_ARMOR armor does not protect from this damage
|
||||
DAMAGE_ENERGY damage is from an energy based weapon
|
||||
DAMAGE_NO_KNOCKBACK do not affect velocity, just view angles
|
||||
DAMAGE_BULLET damage is from a bullet (used for ricochets)
|
||||
DAMAGE_NO_PROTECTION kills godmode, armor, everything
|
||||
============
|
||||
============
|
||||
*/
|
||||
static int CheckPowerArmor (edict_t *ent, vec3_t point, vec3_t normal, int damage, int dflags)
|
||||
{
|
||||
|
@ -359,17 +382,17 @@ void BloodSprayThink (edict_t *self)
|
|||
{
|
||||
|
||||
|
||||
/* if ( self->dmg > 0 )
|
||||
{
|
||||
self->dmg -= 10;
|
||||
/* if ( self->dmg > 0 )
|
||||
{
|
||||
self->dmg -= 10;
|
||||
// SpawnDamage (TE_BLOOD, self->s.origin, self->movedir, self->dmg);
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (TE_SPLASH);
|
||||
gi.WriteByte (6);
|
||||
gi.WritePosition (self->s.origin);
|
||||
gi.WriteDir (self->movedir);
|
||||
gi.WriteByte (6); //blood
|
||||
gi.multicast (self->s.origin, MULTICAST_PVS);
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (TE_SPLASH);
|
||||
gi.WriteByte (6);
|
||||
gi.WritePosition (self->s.origin);
|
||||
gi.WriteDir (self->movedir);
|
||||
gi.WriteByte (6); //blood
|
||||
gi.multicast (self->s.origin, MULTICAST_PVS);
|
||||
|
||||
}
|
||||
else
|
||||
|
@ -572,6 +595,7 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
|
||||
vec3_t line;
|
||||
vec_t dist;
|
||||
float targ_maxs2; //FB 6/1/99
|
||||
|
||||
// do this before teamplay check
|
||||
if (!targ->takedamage)
|
||||
|
@ -584,7 +608,8 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
return;
|
||||
|
||||
if (targ != attacker && targ->client && attacker->client &&
|
||||
targ->client->resp.team == attacker->client->resp.team)
|
||||
(targ->client->resp.team == attacker->client->resp.team &&
|
||||
((int)(dmflags->value) & (DF_NO_FRIENDLY_FIRE))))
|
||||
return;
|
||||
}
|
||||
//FIREBLADE
|
||||
|
@ -603,19 +628,24 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
item = FindItem(KEV_NAME);
|
||||
|
||||
height = abs(targ->mins[2]) + targ->maxs[2];
|
||||
targ_maxs2 = targ->maxs[2];
|
||||
if (targ_maxs2 == 4)
|
||||
targ_maxs2 = CROUCHING_MAXS2; //FB 6/1/99
|
||||
|
||||
height = abs(targ->mins[2]) + targ_maxs2;
|
||||
|
||||
// locational damage code
|
||||
// base damage is head shot damage, so all the scaling is downwards
|
||||
if (targ->client)
|
||||
{
|
||||
if (!((targ != attacker) && ((deathmatch->value && ((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value) && OnSameTeam (targ, attacker)))
|
||||
if (!((targ != attacker) &&
|
||||
((deathmatch->value && ((int)(dmflags->value)
|
||||
& (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value) &&
|
||||
(attacker && attacker->client &&
|
||||
OnSameTeam (targ, attacker) &&
|
||||
((int)(dmflags->value) & (DF_NO_FRIENDLY_FIRE)))))
|
||||
{
|
||||
|
||||
if ((mod == MOD_MK23) ||
|
||||
|
@ -627,7 +657,9 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
(mod == MOD_KNIFE_THROWN))
|
||||
{
|
||||
z_rel = point[2] - targ->s.origin[2];
|
||||
from_top = targ->maxs[2] - z_rel;
|
||||
from_top = targ_maxs2 - z_rel;
|
||||
if (from_top < 0.0) //FB 6/1/99
|
||||
from_top = 0.0; //Slightly negative values were being handled wrong
|
||||
bleeding = 1;
|
||||
instant_dam = 0;
|
||||
|
||||
|
@ -647,8 +679,8 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
|
||||
//gi.cprintf(targ, PRINT_HIGH, "z_rel is %f\n leg: %f stomach: %f chest: %f\n", z_rel, LEG_DAMAGE, STOMACH_DAMAGE, CHEST_DAMAGE );
|
||||
//gi.cprintf(targ, PRINT_HIGH, "point[2]: %f targ->s.origin[2]: %f height: %d\n", point[2], targ->s.origin[2], height );
|
||||
//gi.cprintf(targ, PRINT_HIGH, "abs(trag->min[2]): %d targ_max[2] %d\n", (int)abs(targ->mins[2]), (int)targ->maxs[2]);
|
||||
//gi.cprintf(attacker, PRINT_HIGH, "abs(trag->min[2]): %d targ_max[2] %d\n", (int)abs(targ->mins[2]), (int)targ->maxs[2]);
|
||||
//gi.cprintf(targ, PRINT_HIGH, "abs(trag->min[2]): %d targ_max[2] %d\n", (int)abs(targ->mins[2]), (int)targ_maxs2);
|
||||
//gi.cprintf(attacker, PRINT_HIGH, "abs(trag->min[2]): %d targ_max[2] %d\n", (int)abs(targ->mins[2]), (int)targ_maxs2);
|
||||
//gi.cprintf(attacker, PRINT_HIGH, "abs(trag->min[0]): %d targ_max[0] %d\n", (int)abs(targ->mins[0]), (int)targ->maxs[0]);
|
||||
//gi.cprintf(attacker, PRINT_HIGH, "abs(trag->min[1]): %d targ_max[1] %d\n", (int)abs(targ->mins[1]), (int)targ->maxs[1]);
|
||||
|
||||
|
@ -658,9 +690,9 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
vec3_t new_point;
|
||||
VerifyHeadShot( point, dir, HEAD_HEIGHT, new_point );
|
||||
VectorSubtract( new_point, targ->s.origin, new_point );
|
||||
//gi.cprintf(attacker, PRINT_HIGH, "z: %d y: %d x: %d\n", (int)(targ->maxs[2] - new_point[2]),(int)(new_point[1]) , (int)(new_point[0]) );
|
||||
//gi.cprintf(attacker, PRINT_HIGH, "z: %d y: %d x: %d\n", (int)(targ_maxs2 - new_point[2]),(int)(new_point[1]) , (int)(new_point[0]) );
|
||||
|
||||
if ( (targ->maxs[2] - new_point[2]) < HEAD_HEIGHT
|
||||
if ( (targ_maxs2 - new_point[2]) < HEAD_HEIGHT
|
||||
&& (abs(new_point[1])) < HEAD_HEIGHT*.8
|
||||
&& (abs(new_point[0])) < HEAD_HEIGHT*.8 )
|
||||
|
||||
|
@ -762,7 +794,10 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
gi.sound(targ, CHAN_VOICE, gi.soundindex("misc/headshot.wav"), 1, ATTN_NORM, 0);
|
||||
} */
|
||||
}
|
||||
|
||||
if (team_round_going && attacker->client && targ != attacker && OnSameTeam(targ, attacker))
|
||||
{
|
||||
Add_TeamWound(attacker, targ, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -809,15 +844,10 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
mod |= MOD_FRIENDLY_FIRE;
|
||||
}
|
||||
}
|
||||
|
||||
meansOfDeath = mod;
|
||||
locOfDeath = damage_type; // location
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
client = targ->client;
|
||||
|
||||
if (dflags & DAMAGE_BULLET)
|
||||
|
@ -905,16 +935,27 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
// team damage avoidance
|
||||
if (!(dflags & DAMAGE_NO_PROTECTION) && CheckTeamDamage (targ, attacker))
|
||||
return;
|
||||
|
||||
if ( (mod == MOD_M3) || (mod == MOD_HC) || (mod == MOD_HELD_GRENADE) ||
|
||||
(mod == MOD_HG_SPLASH) || (mod == MOD_G_SPLASH) )
|
||||
if ( (mod == MOD_M3)
|
||||
|| (mod == MOD_HC)
|
||||
|| (mod == MOD_HELD_GRENADE)
|
||||
|| (mod == MOD_HG_SPLASH)
|
||||
|| (mod == MOD_G_SPLASH)
|
||||
|| (mod == MOD_BREAKINGGLASS)
|
||||
)
|
||||
{
|
||||
//FB 6/3/99 - shotgun damage report stuff
|
||||
int playernum = targ - g_edicts;
|
||||
playernum--;
|
||||
if (playernum >= 0 &&
|
||||
playernum <= game.maxclients - 1)
|
||||
*(took_damage + playernum) = 1;
|
||||
//FB 6/3/99
|
||||
|
||||
bleeding = 1;
|
||||
instant_dam = 0;
|
||||
|
||||
}
|
||||
|
||||
/* if ( (mod == MOD_M3) || (mod == MOD_HC) )
|
||||
/* if ( (mod == MOD_M3) || (mod == MOD_HC) )
|
||||
{
|
||||
instant_dam = 1;
|
||||
remain = take % 2;
|
||||
|
@ -1009,6 +1050,7 @@ void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
|||
}
|
||||
if ( attacker->client )
|
||||
{
|
||||
attacker->client->resp.damage_dealt += damage;
|
||||
client->attacker = attacker;
|
||||
client->attacker_mod = mod;
|
||||
client->attacker_loc = damage_type;
|
||||
|
@ -1056,11 +1098,18 @@ void T_RadiusDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_
|
|||
//points = points * 0.5;
|
||||
if (points > 0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (0 == Q_stricmp(ent->classname, "func_explosive"))
|
||||
{
|
||||
CGF_SFX_ShootBreakableGlass(ent, inflictor, 0, mod);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (CanDamage (ent, inflictor))
|
||||
{
|
||||
VectorSubtract (ent->s.origin, inflictor->s.origin, dir);
|
||||
// zucc scaled up knockback(kick) of grenades
|
||||
T_Damage (ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)(points*.75), (int)(points*.75), DAMAGE_RADIUS, mod);
|
||||
T_Damage (ent, inflictor, attacker, dir, ent->s.origin, vec3_origin, (int)(points*.75), (int)(points*.75), DAMAGE_RADIUS, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -985,8 +985,10 @@ edict_t *Drop_Item (edict_t *ent, gitem_t *item)
|
|||
AngleVectors (ent->client->v_angle, forward, right, NULL);
|
||||
VectorSet(offset, 24, 0, -16);
|
||||
G_ProjectSource (ent->s.origin, offset, forward, right, dropped->s.origin);
|
||||
trace = do_trace (ent->s.origin, dropped->mins, dropped->maxs,
|
||||
PRETRACE();
|
||||
trace = gi.trace (ent->s.origin, dropped->mins, dropped->maxs,
|
||||
dropped->s.origin, ent, CONTENTS_SOLID);
|
||||
POSTTRACE();
|
||||
VectorCopy (trace.endpos, dropped->s.origin);
|
||||
}
|
||||
else
|
||||
|
@ -1065,7 +1067,9 @@ void droptofloor (edict_t *ent)
|
|||
v = tv(0,0,-128);
|
||||
VectorAdd (ent->s.origin, v, dest);
|
||||
|
||||
tr = do_trace (ent->s.origin, ent->mins, ent->maxs, dest, ent, MASK_SOLID);
|
||||
PRETRACE();
|
||||
tr = gi.trace (ent->s.origin, ent->mins, ent->maxs, dest, ent, MASK_SOLID);
|
||||
POSTTRACE();
|
||||
if (tr.startsolid)
|
||||
{
|
||||
gi.dprintf ("droptofloor: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin));
|
||||
|
|
50
g_local.h
50
g_local.h
|
@ -519,12 +519,17 @@ extern cvar_t *deathmatch;
|
|||
extern cvar_t *coop;
|
||||
extern cvar_t *dmflags;
|
||||
//FIREBLADE
|
||||
extern cvar_t *needpass;
|
||||
extern cvar_t *hostname;
|
||||
extern cvar_t *teamplay;
|
||||
extern cvar_t *radiolog;
|
||||
extern cvar_t *motd_time;
|
||||
extern cvar_t *actionmaps;
|
||||
extern cvar_t *roundtimelimit;
|
||||
extern cvar_t *maxteamkills;
|
||||
extern cvar_t *tkbanrounds;
|
||||
extern cvar_t *twbanrounds;
|
||||
extern cvar_t *limchasecam;
|
||||
extern cvar_t *roundlimit;
|
||||
extern cvar_t *skipmotd;
|
||||
extern cvar_t *nohud;
|
||||
|
@ -907,15 +912,9 @@ typedef struct
|
|||
vec3_t cmd_angles; // angles sent over in the last command
|
||||
int game_helpchanged;
|
||||
int helpchanged;
|
||||
int mk23_mode; // firing mode, semi or auto
|
||||
int sniper_mode; //level of zoom
|
||||
int mp5_mode;
|
||||
int m4_mode;
|
||||
int knife_mode;
|
||||
int grenade_mode;
|
||||
int id; // id command on or off
|
||||
int ir; // ir on or off (only matters if player has ir device, currently bandolier)
|
||||
int kills; // real kills
|
||||
int damage_dealt; // keep track of damage dealt by player to other players
|
||||
int streak; // kills in a row
|
||||
gitem_t *item; // item for teamplay
|
||||
gitem_t *weapon; // weapon for teamplay
|
||||
|
@ -928,9 +927,6 @@ typedef struct
|
|||
radio_queue_entry_t radio_queue[MAX_RADIO_QUEUE_SIZE];
|
||||
int radio_queue_size;
|
||||
edict_t *radio_partner; // current partner
|
||||
qboolean radio_partner_mode; // 'radio' command using team or partner
|
||||
qboolean radio_gender; // radiogender
|
||||
qboolean radio_power_off; // radio_power
|
||||
edict_t *partner_last_offered_to; // last person I offered a partnership to
|
||||
edict_t *partner_last_offered_from; // last person I received a partnership offer from
|
||||
edict_t *partner_last_denied_from; // last person I denied a partnership offer from
|
||||
|
@ -940,6 +936,18 @@ typedef struct
|
|||
int last_motd_refresh;
|
||||
edict_t *last_chase_target; // last person they chased, to resume at the same place later...
|
||||
//FIREBLADE
|
||||
//Action
|
||||
int mk23_mode; // firing mode, semi or auto
|
||||
int mp5_mode;
|
||||
int m4_mode;
|
||||
int knife_mode;
|
||||
int grenade_mode;
|
||||
int id; // id command on or off
|
||||
int ir; // ir on or off (only matters if player has ir device, currently bandolier)
|
||||
qboolean radio_partner_mode; // 'radio' command using team or partner
|
||||
qboolean radio_gender; // radiogender
|
||||
qboolean radio_power_off; // radio_power
|
||||
//---
|
||||
} client_respawn_t;
|
||||
|
||||
// this structure is cleared on each PutClientInServer(),
|
||||
|
@ -1091,6 +1099,7 @@ struct gclient_s
|
|||
int jumping;
|
||||
|
||||
int reload_attempts;
|
||||
int weapon_attempts;
|
||||
|
||||
|
||||
//FIREBLADE
|
||||
|
@ -1100,6 +1109,22 @@ struct gclient_s
|
|||
qboolean update_chase;
|
||||
int chase_mode;
|
||||
//FIREBLADE
|
||||
|
||||
//AZEROV
|
||||
// Number of team kills this game
|
||||
int team_kills;
|
||||
//AZEROV
|
||||
|
||||
//EEK
|
||||
// Number of teammate woundings this game and a "before attack" tracker
|
||||
int team_wounds;
|
||||
int team_wounds_before;
|
||||
int ff_warning;
|
||||
|
||||
// IP address of this host to be collected at Connection time.
|
||||
// (getting at it later seems to be unreliable)
|
||||
char ipaddr[100]; // changed to 100 -FB
|
||||
//EEK
|
||||
};
|
||||
|
||||
|
||||
|
@ -1266,6 +1291,7 @@ void LaserSightThink (edict_t *self);
|
|||
void SP_LaserSight(edict_t *self, gitem_t *item );
|
||||
void Cmd_Reload_f (edict_t *ent);
|
||||
void Cmd_New_Reload_f (edict_t *ent);
|
||||
void Cmd_New_Weapon_f (edict_t *ent);
|
||||
void Cmd_Weapon_f ( edict_t *ent );
|
||||
void Cmd_OpenDoor_f (edict_t *ent );
|
||||
void Cmd_Bandage_f ( edict_t *ent );
|
||||
|
@ -1315,8 +1341,8 @@ edict_t *FindEdictByClassnum (char *classname, int classnum);
|
|||
|
||||
void EjectBlooder (edict_t *self, vec3_t start, vec3_t veloc );
|
||||
void EjectShell (edict_t *self, vec3_t start, int toggle);
|
||||
void AddSplat (edict_t *self, vec3_t point, vec3_t direct);
|
||||
void AddDecal (edict_t *self, vec3_t point, vec3_t direct);
|
||||
void AddDecal (edict_t *self, trace_t* tr);
|
||||
void AddSplat (edict_t *self, vec3_t point, trace_t* tr);
|
||||
// weapon names
|
||||
/*
|
||||
bind 2 "use M3 Super 90 Assault Shotgun;"
|
||||
|
|
49
g_main.c
49
g_main.c
|
@ -23,11 +23,16 @@ cvar_t *radiolog;
|
|||
cvar_t *motd_time;
|
||||
cvar_t *actionmaps;
|
||||
cvar_t *roundtimelimit;
|
||||
cvar_t *maxteamkills;
|
||||
cvar_t *twbanrounds;
|
||||
cvar_t *tkbanrounds;
|
||||
cvar_t *limchasecam;
|
||||
cvar_t *roundlimit;
|
||||
cvar_t *skipmotd;
|
||||
cvar_t *nohud;
|
||||
cvar_t *noscore;
|
||||
cvar_t *actionversion;
|
||||
cvar_t *needpass;
|
||||
//FIREBLADE
|
||||
cvar_t *deathmatch;
|
||||
cvar_t *coop;
|
||||
|
@ -86,6 +91,7 @@ void ClientUserinfoChanged (edict_t *ent, char *userinfo);
|
|||
void ClientDisconnect (edict_t *ent);
|
||||
void ClientBegin (edict_t *ent);
|
||||
void ClientCommand (edict_t *ent);
|
||||
void CheckNeedPass (void);
|
||||
void RunEntity (edict_t *ent);
|
||||
void WriteGame (char *filename, qboolean autosave);
|
||||
void ReadGame (char *filename);
|
||||
|
@ -205,6 +211,11 @@ EndDMLevel
|
|||
The timelimit or fraglimit has been exceeded
|
||||
=================
|
||||
*/
|
||||
|
||||
//AZEROV
|
||||
extern void UnBan_TeamKillers (void);
|
||||
//AZEROV
|
||||
|
||||
void EndDMLevel (void)
|
||||
{
|
||||
edict_t *ent;
|
||||
|
@ -260,6 +271,10 @@ void EndDMLevel (void)
|
|||
|
||||
ReadMOTDFile();
|
||||
BeginIntermission (ent);
|
||||
|
||||
//AZEROV
|
||||
UnBan_TeamKillers ();
|
||||
//AZEROV
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -415,7 +430,41 @@ void G_RunFrame (void)
|
|||
// see if it is time to end a deathmatch
|
||||
CheckDMRules ();
|
||||
|
||||
//FIREBLADE
|
||||
CheckNeedPass();
|
||||
//FIREBLADE
|
||||
|
||||
// build the playerstate_t structures for all players
|
||||
ClientEndServerFrames ();
|
||||
}
|
||||
|
||||
//ADDED FROM 3.20 SOURCE -FB
|
||||
//Commented out spectator_password stuff since we don't have that now.
|
||||
/*
|
||||
=================
|
||||
CheckNeedPass
|
||||
=================
|
||||
*/
|
||||
void CheckNeedPass (void)
|
||||
{
|
||||
int need;
|
||||
|
||||
// if password or spectator_password has changed, update needpass
|
||||
// as needed
|
||||
if (password->modified /*|| spectator_password->modified*/)
|
||||
{
|
||||
password->modified = /*spectator_password->modified = */ false;
|
||||
|
||||
need = 0;
|
||||
|
||||
if (*password->string && Q_stricmp(password->string, "none"))
|
||||
need |= 1;
|
||||
/*
|
||||
if (*spectator_password->string && Q_stricmp(spectator_password->string, "none"))
|
||||
need |= 2;
|
||||
*/
|
||||
|
||||
gi.cvar_set("needpass", va("%d", need));
|
||||
}
|
||||
}
|
||||
//FROM 3.20 END
|
||||
|
|
6
g_misc.c
6
g_misc.c
|
@ -1,7 +1,7 @@
|
|||
// g_misc.c
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
#include "cgf_sfx_glass.h"
|
||||
|
||||
/*QUAKED func_group (0 0 0) ?
|
||||
Used to group brushes together just for editor convenience.
|
||||
|
@ -797,11 +797,13 @@ void func_explosive_spawn (edict_t *self, edict_t *other, edict_t *activator)
|
|||
|
||||
void SP_func_explosive (edict_t *self)
|
||||
{
|
||||
/* removed for glass fx
|
||||
if (deathmatch->value)
|
||||
{ // auto-remove for deathmatch
|
||||
G_FreeEdict (self);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
self->movetype = MOVETYPE_PUSH;
|
||||
|
||||
|
@ -837,6 +839,8 @@ void SP_func_explosive (edict_t *self)
|
|||
}
|
||||
|
||||
gi.linkentity (self);
|
||||
self->think = CGF_SFX_TestBreakableGlassAndRemoveIfNot_Think;
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
}
|
||||
|
||||
|
||||
|
|
15
g_phys.c
15
g_phys.c
|
@ -1,6 +1,7 @@
|
|||
// g_phys.c
|
||||
|
||||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
|
||||
/*
|
||||
|
||||
|
@ -36,7 +37,9 @@ edict_t *SV_TestEntityPosition (edict_t *ent)
|
|||
mask = ent->clipmask;
|
||||
else
|
||||
mask = MASK_SOLID;
|
||||
trace = do_trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask);
|
||||
PRETRACE();
|
||||
trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask);
|
||||
POSTTRACE();
|
||||
|
||||
if (trace.startsolid)
|
||||
return g_edicts;
|
||||
|
@ -191,7 +194,9 @@ int SV_FlyMove (edict_t *ent, float time, int mask)
|
|||
for (i=0 ; i<3 ; i++)
|
||||
end[i] = ent->s.origin[i] + time_left * ent->velocity[i];
|
||||
|
||||
trace = do_trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask);
|
||||
PRETRACE();
|
||||
trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask);
|
||||
POSTTRACE();
|
||||
|
||||
if (trace.allsolid)
|
||||
{ // entity is trapped in another solid
|
||||
|
@ -336,7 +341,9 @@ retry:
|
|||
else
|
||||
mask = MASK_SOLID;
|
||||
|
||||
trace = do_trace (start, ent->mins, ent->maxs, end, ent, mask);
|
||||
PRETRACE();
|
||||
trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask);
|
||||
POSTTRACE();
|
||||
|
||||
VectorCopy (trace.endpos, ent->s.origin);
|
||||
gi.linkentity (ent);
|
||||
|
@ -824,7 +831,7 @@ void SV_Physics_Toss (edict_t *ent)
|
|||
{
|
||||
if (!ent->splatted)
|
||||
{
|
||||
AddSplat (ent->owner, ent->s.origin, trace.plane.normal);
|
||||
AddSplat (ent->owner, ent->s.origin, &trace);
|
||||
ent->splatted = true;
|
||||
}
|
||||
|
||||
|
|
10
g_save.c
10
g_save.c
|
@ -1,4 +1,5 @@
|
|||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
|
||||
field_t fields[] = {
|
||||
{"classname", FOFS(classname), F_LSTRING},
|
||||
|
@ -175,6 +176,7 @@ void InitGame (void)
|
|||
password = gi.cvar ("password", "", CVAR_USERINFO);
|
||||
filterban = gi.cvar("filterban", "1", 0);
|
||||
//FIREBLADE
|
||||
needpass = gi.cvar("needpass", "0", CVAR_SERVERINFO);
|
||||
radiolog = gi.cvar("radiolog", "0", 0);
|
||||
teamplay = gi.cvar ("teamplay", "0", CVAR_SERVERINFO|CVAR_LATCH);
|
||||
motd_time = gi.cvar("motd_time", "2", 0);
|
||||
|
@ -187,8 +189,12 @@ void InitGame (void)
|
|||
}
|
||||
nohud = gi.cvar("nohud", "0", CVAR_LATCH);
|
||||
roundlimit = gi.cvar("roundlimit", "0", CVAR_SERVERINFO);
|
||||
limchasecam = gi.cvar("limchasecam", "0", CVAR_SERVERINFO|CVAR_LATCH);
|
||||
skipmotd = gi.cvar("skipmotd", "0", 0);
|
||||
roundtimelimit = gi.cvar("roundtimelimit", "0", CVAR_SERVERINFO);
|
||||
maxteamkills = gi.cvar("maxteamkills", "0", 0);
|
||||
twbanrounds = gi.cvar("twbanrounds", "2", 0);
|
||||
tkbanrounds = gi.cvar("tkbanrounds", "2", 0);
|
||||
noscore = gi.cvar("noscore", "0", CVAR_SERVERINFO|CVAR_LATCH);
|
||||
actionversion = gi.cvar("actionversion", "none set", CVAR_SERVERINFO|CVAR_LATCH);
|
||||
gi.cvar_set("actionversion", ACTION_VERSION);
|
||||
|
@ -208,11 +214,15 @@ void InitGame (void)
|
|||
allweapon = gi.cvar ("allweapon", "0", CVAR_SERVERINFO);
|
||||
allitem = gi.cvar ("allitem", "0", CVAR_SERVERINFO);
|
||||
tgren = gi.cvar ("tgren", "0", CVAR_SERVERINFO);
|
||||
|
||||
// zucc from action
|
||||
sv_shelloff = gi.cvar ("shelloff", "1", 0);
|
||||
bholelimit = gi.cvar ("bholelimit", "0", 0);
|
||||
splatlimit = gi.cvar ("splatlimit", "0", 0);
|
||||
|
||||
// william for CGF (glass fx)
|
||||
CGF_SFX_InstallGlassSupport();
|
||||
|
||||
g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE);
|
||||
|
||||
run_pitch = gi.cvar ("run_pitch", "0.002", 0);
|
||||
|
|
|
@ -1338,5 +1338,11 @@ void SP_worldspawn (edict_t *ent)
|
|||
|
||||
// 63 testing
|
||||
gi.configstring(CS_LIGHTS+63, "a");
|
||||
|
||||
//FB 6/2/99
|
||||
if (took_damage != NULL)
|
||||
gi.TagFree(took_damage);
|
||||
took_damage = (int *)gi.TagMalloc(sizeof(int) * game.maxclients, TAG_GAME);
|
||||
//FB 6/2/99
|
||||
}
|
||||
|
||||
|
|
146
g_svcmds.c
146
g_svcmds.c
|
@ -41,6 +41,10 @@ typedef struct
|
|||
{
|
||||
unsigned mask;
|
||||
unsigned compare;
|
||||
|
||||
//AZEROV
|
||||
int temp_ban_games;
|
||||
//AZEROV
|
||||
} ipfilter_t;
|
||||
|
||||
#define MAX_IPFILTERS 1024
|
||||
|
@ -53,7 +57,7 @@ int numipfilters;
|
|||
StringToFilter
|
||||
=================
|
||||
*/
|
||||
static qboolean StringToFilter (char *s, ipfilter_t *f)
|
||||
static qboolean StringToFilter (char *s, ipfilter_t *f, int temp_ban_games)
|
||||
{
|
||||
char num[128];
|
||||
int i, j;
|
||||
|
@ -92,6 +96,8 @@ static qboolean StringToFilter (char *s, ipfilter_t *f)
|
|||
f->mask = *(unsigned *)m;
|
||||
f->compare = *(unsigned *)b;
|
||||
|
||||
f->temp_ban_games = temp_ban_games;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -157,7 +163,7 @@ void SVCmd_AddIP_f (void)
|
|||
numipfilters++;
|
||||
}
|
||||
|
||||
if (!StringToFilter (gi.argv(2), &ipfilters[i]))
|
||||
if (!StringToFilter (gi.argv(2), &ipfilters[i], 0))
|
||||
ipfilters[i].compare = 0xffffffff;
|
||||
}
|
||||
|
||||
|
@ -176,7 +182,7 @@ void SVCmd_RemoveIP_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!StringToFilter (gi.argv(2), &f))
|
||||
if (!StringToFilter (gi.argv(2), &f, 0))
|
||||
return;
|
||||
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
|
@ -206,8 +212,15 @@ void SVCmd_ListIP_f (void)
|
|||
for (i=0 ; i<numipfilters ; i++)
|
||||
{
|
||||
*(unsigned *)b = ipfilters[i].compare;
|
||||
if (!ipfilters[i].temp_ban_games)
|
||||
{
|
||||
gi.cprintf (NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.cprintf (NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i (%d more game(s))\n", b[0], b[1], b[2], b[3], ipfilters[i].temp_ban_games);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -242,14 +255,39 @@ void SVCmd_WriteIP_f (void)
|
|||
fprintf(f, "set filterban %d\n", (int)filterban->value);
|
||||
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
{
|
||||
if (!ipfilters[i].temp_ban_games)
|
||||
{
|
||||
*(unsigned *)b = ipfilters[i].compare;
|
||||
fprintf (f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
|
||||
// zucc so it works under vc++
|
||||
void ExitLevel (void);
|
||||
|
||||
//Black Cross - Begin
|
||||
/*
|
||||
=================
|
||||
SV_Nextmap_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_Nextmap_f (char *arg)
|
||||
{
|
||||
// end level and go to next map in map rotation
|
||||
gi.bprintf(PRINT_HIGH, "Changing to next map in rotation.\n");
|
||||
EndDMLevel ();
|
||||
if (arg != NULL && Q_stricmp(arg, "force") == 0)
|
||||
ExitLevel ();
|
||||
return;
|
||||
}
|
||||
//Black Cross - End
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
ServerCommand
|
||||
|
@ -273,9 +311,111 @@ void ServerCommand (void)
|
|||
SVCmd_ListIP_f ();
|
||||
else if (Q_stricmp (cmd, "writeip") == 0)
|
||||
SVCmd_WriteIP_f ();
|
||||
else if (Q_stricmp (cmd, "nextmap") == 0)
|
||||
|
||||
SVCmd_Nextmap_f (gi.argv(2)); // Added by Black Cross
|
||||
else if (Q_stricmp (cmd, "reloadmotd") == 0)
|
||||
SVCmd_ReloadMOTD_f();
|
||||
else
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
Kick a client entity
|
||||
==========================
|
||||
*/
|
||||
void Kick_Client (edict_t *ent)
|
||||
{
|
||||
int i = 0;
|
||||
char ban_string[256];
|
||||
edict_t *entL;
|
||||
|
||||
if (!ent->client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We used to kick on names, but people got crafty and figured
|
||||
// out that putting in a space after their name let them get
|
||||
// around the stupid 'kick' function. So now we kick by number.
|
||||
for (i=0 ; i<game.maxclients ; i++)
|
||||
{
|
||||
entL = &g_edicts[1+i];
|
||||
if (!entL || !entL->inuse)
|
||||
continue;
|
||||
if (entL->client && ent == entL)
|
||||
{
|
||||
sprintf (ban_string, "kick %d\n", i);
|
||||
gi.AddCommandString (ban_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
Ban a client for N rounds
|
||||
==========================
|
||||
*/
|
||||
qboolean Ban_TeamKiller ( edict_t *ent, int rounds )
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!ent || !ent->client || !ent->client->ipaddr)
|
||||
{
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Unable to determine client->ipaddr for edict\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
{
|
||||
if (ipfilters[i].compare == 0xffffffff)
|
||||
break; // free spot
|
||||
}
|
||||
|
||||
if (i == numipfilters)
|
||||
{
|
||||
if (numipfilters == MAX_IPFILTERS)
|
||||
{
|
||||
gi.cprintf (NULL, PRINT_HIGH, "IP filter list is full\n");
|
||||
return false;
|
||||
}
|
||||
numipfilters++;
|
||||
}
|
||||
if (!StringToFilter (ent->client->ipaddr, &ipfilters[i], rounds))
|
||||
{
|
||||
ipfilters[i].compare = 0xffffffff;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnBan_TeamKillers (void)
|
||||
{
|
||||
// We don't directly unban them all - we subtract 1 from temp_ban_games,
|
||||
// and unban them if it's 0.
|
||||
|
||||
int i, j;
|
||||
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
{
|
||||
if (ipfilters[i].temp_ban_games > 0)
|
||||
{
|
||||
if (!--ipfilters[i].temp_ban_games)
|
||||
{
|
||||
// re-pack the filters
|
||||
for (j=i+1 ; j<numipfilters ; j++)
|
||||
ipfilters[j-1] = ipfilters[j];
|
||||
numipfilters--;
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Unbanned teamkiller.\n");
|
||||
|
||||
// since we removed the current we have to re-process the new current
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//AZEROV
|
||||
|
||||
|
|
|
@ -503,7 +503,9 @@ void target_laser_think (edict_t *self)
|
|||
VectorMA (start, 2048, self->movedir, end);
|
||||
while(1)
|
||||
{
|
||||
tr = do_trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
|
||||
PRETRACE();
|
||||
tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
|
||||
POSTTRACE();
|
||||
|
||||
if (!tr.ent)
|
||||
break;
|
||||
|
|
215
g_weapon.c
215
g_weapon.c
|
@ -1,11 +1,15 @@
|
|||
#include "g_local.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
#include "a_game.h" //zucc for KickDoor
|
||||
|
||||
|
||||
void knife_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);
|
||||
void Zylon_Grenade(edict_t *ent);
|
||||
void setFFState(edict_t *ent);
|
||||
|
||||
//FIREBLADE
|
||||
qboolean ap_already_hit[1000]; // 1000 = a number much larger than the possible max # of clients
|
||||
int *took_damage; //FB 6/2/99, to keep track of shotgun damage
|
||||
//FIREBLADE
|
||||
|
||||
/*
|
||||
|
@ -31,7 +35,9 @@ static void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed)
|
|||
return;
|
||||
}
|
||||
VectorMA (start, 8192, dir, end);
|
||||
tr = do_trace (start, NULL, NULL, end, self, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
if ((tr.ent) && (tr.ent->svflags & SVF_MONSTER) && (tr.ent->health > 0) && (tr.ent->monsterinfo.dodge) && infront(tr.ent, self))
|
||||
{
|
||||
VectorSubtract (tr.endpos, start, v);
|
||||
|
@ -72,9 +78,6 @@ void SpawnHole( trace_t *tr, vec3_t dir )
|
|||
VectorMA(tr->endpos, 0,dir,origin);
|
||||
VectorCopy(origin,lss->s.origin);
|
||||
gi.linkentity (lss);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,7 +119,9 @@ qboolean fire_hit (edict_t *self, vec3_t aim, int damage, int kick)
|
|||
|
||||
VectorMA (self->s.origin, range, dir, point);
|
||||
|
||||
tr = do_trace (self->s.origin, NULL, NULL, point, self, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (self->s.origin, NULL, NULL, point, self, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
if (tr.fraction < 1)
|
||||
{
|
||||
if (!tr.ent->takedamage)
|
||||
|
@ -132,6 +137,7 @@ qboolean fire_hit (edict_t *self, vec3_t aim, int damage, int kick)
|
|||
VectorMA (point, aim[2], up, point);
|
||||
VectorSubtract (point, self->enemy->s.origin, dir);
|
||||
|
||||
setFFState(self);
|
||||
// do the damage
|
||||
T_Damage (tr.ent, self, self, dir, point, vec3_origin, damage, kick/2, DAMAGE_NO_KNOCKBACK, MOD_HIT);
|
||||
|
||||
|
@ -168,7 +174,9 @@ static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, i
|
|||
qboolean water = false;
|
||||
int content_mask = MASK_SHOT | MASK_WATER;
|
||||
|
||||
tr = do_trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
if (!(tr.fraction < 1.0))
|
||||
{
|
||||
vectoangles (aimdir, dir);
|
||||
|
@ -187,7 +195,26 @@ static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, i
|
|||
content_mask &= ~MASK_WATER;
|
||||
}
|
||||
|
||||
tr = do_trace (start, NULL, NULL, end, self, content_mask);
|
||||
PRETRACE();
|
||||
tr = gi.trace (start, NULL, NULL, end, self, content_mask);
|
||||
POSTTRACE();
|
||||
|
||||
// glass fx
|
||||
// catch case of firing thru one or breakable glasses
|
||||
while ( (tr.fraction < 1.0)
|
||||
&& (tr.surface->flags & (SURF_TRANS33 | SURF_TRANS66))
|
||||
&& (tr.ent)
|
||||
&& (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
)
|
||||
{
|
||||
// break glass
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, self, &tr, mod);
|
||||
// continue trace from current endpos to start
|
||||
PRETRACE();
|
||||
tr = gi.trace (tr.endpos, NULL, NULL, end, tr.ent, content_mask);
|
||||
POSTTRACE();
|
||||
}
|
||||
// ---
|
||||
|
||||
// see if we hit water
|
||||
if (tr.contents & MASK_WATER)
|
||||
|
@ -236,7 +263,9 @@ static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, i
|
|||
}
|
||||
|
||||
// re-trace ignoring water this time
|
||||
tr = do_trace (water_start, NULL, NULL, end, self, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +282,7 @@ static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, i
|
|||
{
|
||||
if ( mod != MOD_M3 && mod != MOD_HC)
|
||||
{
|
||||
AddDecal (self, tr.endpos, tr.plane.normal);
|
||||
AddDecal (self, &tr);
|
||||
}
|
||||
//zucc remove spawnhole for real release
|
||||
// SpawnHole( &tr, dir );
|
||||
|
@ -283,7 +312,11 @@ static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, i
|
|||
if (gi.pointcontents (pos) & MASK_WATER)
|
||||
VectorCopy (pos, tr.endpos);
|
||||
else
|
||||
tr = do_trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);
|
||||
{
|
||||
PRETRACE();
|
||||
tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);
|
||||
POSTTRACE();
|
||||
}
|
||||
|
||||
VectorAdd (water_start, tr.endpos, pos);
|
||||
VectorScale (pos, 0.5, pos);
|
||||
|
@ -307,6 +340,7 @@ pistols, rifles, etc....
|
|||
*/
|
||||
void fire_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod)
|
||||
{
|
||||
setFFState(self);
|
||||
fire_lead (self, start, aimdir, damage, kick, TE_GUNSHOT, hspread, vspread, mod);
|
||||
}
|
||||
|
||||
|
@ -352,13 +386,33 @@ static void fire_lead_ap (edict_t *self, vec3_t start, vec3_t aimdir, int damage
|
|||
|
||||
ignore = self;
|
||||
|
||||
// tr = do_trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
|
||||
// PRETRACE();
|
||||
// tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
|
||||
// POSTTRACE();
|
||||
while (ignore)
|
||||
//if (!(tr.fraction < 1.0))
|
||||
{
|
||||
PRETRACE();
|
||||
//tr = gi.trace (from, NULL, NULL, end, ignore, mask);
|
||||
tr = gi.trace (from, NULL, NULL, end, ignore, content_mask);
|
||||
POSTTRACE();
|
||||
|
||||
//tr = do_trace (from, NULL, NULL, end, ignore, mask);
|
||||
tr = do_trace (from, NULL, NULL, end, ignore, content_mask);
|
||||
// glass fx
|
||||
// catch case of firing thru one or breakable glasses
|
||||
while ( (tr.fraction < 1.0)
|
||||
&& (tr.surface->flags & (SURF_TRANS33 | SURF_TRANS66))
|
||||
&& (tr.ent)
|
||||
&& (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
)
|
||||
{
|
||||
// break glass
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, self, &tr, mod);
|
||||
// continue trace from current endpos to start
|
||||
PRETRACE();
|
||||
tr = gi.trace (tr.endpos, NULL, NULL, end, tr.ent, content_mask);
|
||||
POSTTRACE();
|
||||
}
|
||||
// ---
|
||||
|
||||
// see if we hit water
|
||||
if (tr.contents & MASK_WATER)
|
||||
|
@ -407,7 +461,9 @@ static void fire_lead_ap (edict_t *self, vec3_t start, vec3_t aimdir, int damage
|
|||
}
|
||||
|
||||
// re-trace ignoring water this time
|
||||
tr = do_trace (water_start, NULL, NULL, end, ignore, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (water_start, NULL, NULL, end, ignore, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
|
||||
}
|
||||
|
||||
|
@ -457,7 +513,7 @@ static void fire_lead_ap (edict_t *self, vec3_t start, vec3_t aimdir, int damage
|
|||
|
||||
if (strncmp (tr.surface->name, "sky", 3) != 0)
|
||||
{
|
||||
AddDecal (self, tr.endpos, tr.plane.normal);
|
||||
AddDecal (self, &tr);
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (te_impact);
|
||||
gi.WritePosition (tr.endpos);
|
||||
|
@ -482,7 +538,11 @@ static void fire_lead_ap (edict_t *self, vec3_t start, vec3_t aimdir, int damage
|
|||
if (gi.pointcontents (pos) & MASK_WATER)
|
||||
VectorCopy (pos, tr.endpos);
|
||||
else
|
||||
tr = do_trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);
|
||||
{
|
||||
PRETRACE();
|
||||
tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);
|
||||
POSTTRACE();
|
||||
}
|
||||
|
||||
VectorAdd (water_start, tr.endpos, pos);
|
||||
VectorScale (pos, 0.5, pos);
|
||||
|
@ -501,20 +561,68 @@ static void fire_lead_ap (edict_t *self, vec3_t start, vec3_t aimdir, int damage
|
|||
// zucc - for the M4
|
||||
void fire_bullet_sparks (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod)
|
||||
{
|
||||
setFFState(self);
|
||||
fire_lead_ap (self, start, aimdir, damage, kick, TE_BULLET_SPARKS, hspread, vspread, mod);
|
||||
}
|
||||
|
||||
// zucc - for sniper
|
||||
void fire_bullet_sniper (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod)
|
||||
{
|
||||
setFFState(self);
|
||||
fire_lead_ap (self, start, aimdir, damage, kick, TE_GUNSHOT, hspread, vspread, mod);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Init and ProduceShotgunDamageReport
|
||||
*/
|
||||
|
||||
void InitShotgunDamageReport()
|
||||
{
|
||||
memset(took_damage, 0, game.maxclients * sizeof(int));
|
||||
}
|
||||
|
||||
void ProduceShotgunDamageReport(edict_t *self)
|
||||
{
|
||||
int l;
|
||||
int total_to_print = 0, printed = 0;
|
||||
static char textbuf[1024];
|
||||
|
||||
//FB 6/2/99 - shotgun/handcannon damage notification
|
||||
for (l = 1; l <= game.maxclients; l++)
|
||||
{
|
||||
if (took_damage[l - 1])
|
||||
total_to_print++;
|
||||
}
|
||||
if (total_to_print)
|
||||
{
|
||||
if (total_to_print > 10)
|
||||
total_to_print = 10;
|
||||
|
||||
strcpy(textbuf, "You hit ");
|
||||
for (l = 1; l <= game.maxclients; l++)
|
||||
{
|
||||
if (took_damage[l - 1])
|
||||
{
|
||||
if (printed == (total_to_print - 1))
|
||||
{
|
||||
if (total_to_print == 2)
|
||||
strcat(textbuf, " and ");
|
||||
else if (total_to_print != 1)
|
||||
strcat(textbuf, ", and ");
|
||||
}
|
||||
else if (printed)
|
||||
strcat(textbuf, ", ");
|
||||
strcat(textbuf, g_edicts[l].client->pers.netname);
|
||||
printed++;
|
||||
}
|
||||
if (printed == total_to_print)
|
||||
break;
|
||||
}
|
||||
gi.cprintf(self, PRINT_HIGH, "%s\n", textbuf);
|
||||
}
|
||||
//FB 6/2/99
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
|
@ -614,7 +722,9 @@ void fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage, int spee
|
|||
if (self->client)
|
||||
check_dodge (self, bolt->s.origin, dir, speed);
|
||||
|
||||
tr = do_trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
if (tr.fraction < 1.0)
|
||||
{
|
||||
VectorMA (bolt->s.origin, -10, dir, bolt->s.origin);
|
||||
|
@ -914,7 +1024,9 @@ void fire_rail (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick
|
|||
mask = MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA;
|
||||
while (ignore)
|
||||
{
|
||||
tr = do_trace (from, NULL, NULL, end, ignore, mask);
|
||||
PRETRACE();
|
||||
tr = gi.trace (from, NULL, NULL, end, ignore, mask);
|
||||
POSTTRACE();
|
||||
|
||||
if (tr.contents & (CONTENTS_SLIME|CONTENTS_LAVA))
|
||||
{
|
||||
|
@ -1089,7 +1201,9 @@ void bfg_think (edict_t *self)
|
|||
VectorMA (start, 2048, dir, end);
|
||||
while(1)
|
||||
{
|
||||
tr = do_trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
|
||||
PRETRACE();
|
||||
tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
|
||||
POSTTRACE();
|
||||
|
||||
if (!tr.ent)
|
||||
break;
|
||||
|
@ -1177,8 +1291,6 @@ void kick_attack (edict_t * ent )
|
|||
trace_t tr;
|
||||
vec3_t end;
|
||||
|
||||
|
||||
|
||||
AngleVectors (ent->client->v_angle, forward, right, NULL);
|
||||
|
||||
VectorScale (forward, 0, ent->client->kick_origin);
|
||||
|
@ -1188,14 +1300,16 @@ void kick_attack (edict_t * ent )
|
|||
|
||||
VectorMA( start, 25, forward, end );
|
||||
|
||||
tr = do_trace (ent->s.origin, NULL, NULL, end, ent, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (ent->s.origin, NULL, NULL, end, ent, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
|
||||
// don't need to check for water
|
||||
if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
|
||||
{
|
||||
if (tr.fraction < 1.0)
|
||||
{
|
||||
if (tr.ent->takedamage)
|
||||
if (tr.ent->takedamage || KickDoor(&tr, ent, forward))
|
||||
{
|
||||
if (teamplay->value)
|
||||
{
|
||||
|
@ -1213,9 +1327,15 @@ void kick_attack (edict_t * ent )
|
|||
if (((tr.ent != ent) && ((deathmatch->value && ((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value) && OnSameTeam (tr.ent, ent)))
|
||||
return;
|
||||
// zucc stop powerful upwards kicking
|
||||
forward[2] = 0;
|
||||
|
||||
//forward[2] = 0;
|
||||
|
||||
// glass fx
|
||||
if (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
{
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, ent, &tr, MOD_KICK);
|
||||
}
|
||||
else
|
||||
// ---
|
||||
T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage, kick, 0, MOD_KICK );
|
||||
gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/kick.wav"), 1, ATTN_NORM, 0);
|
||||
PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
|
||||
|
@ -1228,6 +1348,8 @@ void kick_attack (edict_t * ent )
|
|||
&& 1 ) // crandom() > .8 )
|
||||
{
|
||||
|
||||
// zucc fix this so reloading won't happen on the new gun!
|
||||
tr.ent->client->reload_attempts = 0;
|
||||
DropSpecialWeapon(tr.ent);
|
||||
if (IsFemale(tr.ent))
|
||||
{
|
||||
|
@ -1262,15 +1384,25 @@ int knife_attack ( edict_t *self, vec3_t start, vec3_t aimdir, int damage, int k
|
|||
|
||||
VectorMA (start, 45, aimdir, end);
|
||||
|
||||
tr = do_trace (self->s.origin, NULL, NULL, end, self, MASK_SHOT);
|
||||
PRETRACE();
|
||||
tr = gi.trace (self->s.origin, NULL, NULL, end, self, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
|
||||
// don't need to check for water
|
||||
if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
|
||||
{
|
||||
if (tr.fraction < 1.0)
|
||||
{
|
||||
//glass fx
|
||||
if (0 == Q_stricmp(tr.ent->classname, "func_explosive"))
|
||||
{
|
||||
CGF_SFX_ShootBreakableGlass(tr.ent, self, &tr, MOD_KNIFE);
|
||||
}
|
||||
else
|
||||
// ---
|
||||
if (tr.ent->takedamage)
|
||||
{
|
||||
setFFState(self);
|
||||
T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, 0, MOD_KNIFE );
|
||||
return -2;
|
||||
}
|
||||
|
@ -1323,6 +1455,14 @@ void knife_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *sur
|
|||
// calculate position for the explosion entity
|
||||
VectorMA (ent->s.origin, -0.02, ent->velocity, origin);
|
||||
|
||||
//glass fx
|
||||
if (0 == Q_stricmp(other->classname, "func_explosive"))
|
||||
{
|
||||
// ignore it, so it can bounce
|
||||
return;
|
||||
}
|
||||
else
|
||||
// ---
|
||||
if (other->takedamage)
|
||||
{
|
||||
T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_KNIFE_THROWN);
|
||||
|
@ -1453,7 +1593,9 @@ void knife_throw (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed
|
|||
// if (self->client)
|
||||
// check_dodge (self, rocket->s.origin, dir, speed);
|
||||
|
||||
PRETRACE();
|
||||
tr = gi.trace (self->s.origin, NULL, NULL, knife->s.origin, knife, MASK_SHOT);
|
||||
POSTTRACE();
|
||||
if (tr.fraction < 1.0)
|
||||
{
|
||||
VectorMA (knife->s.origin, -10, dir, knife->s.origin);
|
||||
|
@ -1464,3 +1606,24 @@ void knife_throw (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed
|
|||
gi.linkentity (knife);
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================================================
|
||||
setFFState: Save team wound count & warning state before an attack
|
||||
|
||||
The purpose of this is so that we can increment team_wounds by 1 for
|
||||
each real attack instead of just counting each bullet/pellet/shrapnel
|
||||
as a wound. The ff_warning flag is so that we don't overflow the
|
||||
clients from repeated FF warnings. Hopefully the overhead on this
|
||||
will be low enough to not affect things.
|
||||
=====================================================================
|
||||
*/
|
||||
void setFFState(edict_t *ent)
|
||||
{
|
||||
if (ent && ent->client)
|
||||
{
|
||||
ent->client->team_wounds_before = ent->client->team_wounds;
|
||||
ent->client->ff_warning = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
359
p_client.c
359
p_client.c
|
@ -1,5 +1,6 @@
|
|||
#include "g_local.h"
|
||||
#include "m_player.h"
|
||||
#include "cgf_sfx_glass.h"
|
||||
|
||||
void ClientUserinfoChanged (edict_t *ent, char *userinfo);
|
||||
void ClientDisconnect(edict_t *ent);
|
||||
|
@ -54,6 +55,141 @@ void Subtract_Frag( edict_t *ent )
|
|||
}
|
||||
|
||||
|
||||
// FRIENDLY FIRE functions
|
||||
extern qboolean Ban_TeamKiller ( edict_t *ent, int rounds ); // g_svcmds.c
|
||||
extern void Kick_Client ( edict_t *ent); // g_svcmds.c
|
||||
|
||||
void Add_TeamWound( edict_t *attacker, edict_t *victim, int mod)
|
||||
{
|
||||
if (!teamplay->value || !attacker->client || !victim->client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
attacker->client->team_wounds++;
|
||||
|
||||
// Warn both parties that they are teammates. Since shotguns are pellet based,
|
||||
// make sure we don't overflow the client when using MOD_HC or MOD_SHOTGUN. The
|
||||
// ff_warning flag should have been reset before each attack.
|
||||
if (attacker->client->ff_warning == 0)
|
||||
{
|
||||
attacker->client->ff_warning++;
|
||||
gi.cprintf(victim, PRINT_HIGH, "You were hit by %s, your TEAMMATE!\n",
|
||||
attacker->client->pers.netname);
|
||||
gi.cprintf(attacker, PRINT_HIGH, "You hit your TEAMMATE %s!\n",
|
||||
victim->client->pers.netname);
|
||||
}
|
||||
|
||||
// We want team_wounds to increment by one for each ATTACK, not after each
|
||||
// bullet or pellet does damage. With the HAND CANNON this means 2 attacks
|
||||
// since it is double barreled and we don't want to go into p_weapon.c...
|
||||
attacker->client->team_wounds = (attacker->client->team_wounds_before + 1);
|
||||
|
||||
// If count is less than MAX_TEAMKILLS*3, return. If count is greater than
|
||||
// MAX_TEAMKILLS*3 but less than MAX_TEAMKILLS*4, print off a ban warning. If
|
||||
// count equal (or greater than) MAX_TEAMKILLS*4, ban and kick the client.
|
||||
if ((int)maxteamkills->value < 1) //FB
|
||||
return;
|
||||
if (attacker->client->team_wounds < ((int)maxteamkills->value * 3))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (attacker->client->team_wounds < ((int)maxteamkills->value * 4))
|
||||
{
|
||||
// Print a note to console, and issue a warning to the player.
|
||||
gi.cprintf(NULL, PRINT_MEDIUM,
|
||||
"%s is in danger of being banned for wounding teammates\n",
|
||||
attacker->client->pers.netname);
|
||||
gi.cprintf(attacker, PRINT_HIGH,
|
||||
"WARNING: You'll be temporarily banned if you continue wounding teammates!\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attacker->client->ipaddr)
|
||||
{
|
||||
if (Ban_TeamKiller(attacker, (int)twbanrounds->value))
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_MEDIUM,
|
||||
"Banning %s@%s for team wounding\n",
|
||||
attacker->client->pers.netname, attacker->client->ipaddr);
|
||||
|
||||
gi.cprintf(attacker, PRINT_HIGH,
|
||||
"You've wounded teammates too many times, and are banned for %d %s.\n",
|
||||
(int)twbanrounds->value, (((int)twbanrounds->value > 1) ? "games" : "game"));
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_MEDIUM,
|
||||
"Error banning %s: unable to get ipaddr\n",
|
||||
attacker->client->pers.netname);
|
||||
}
|
||||
Kick_Client(attacker);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Add_TeamKill( edict_t *attacker )
|
||||
{
|
||||
if (!teamplay->value || !attacker->client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
attacker->client->team_kills++;
|
||||
// Because the stricter team kill was incremented, lower team_wounds
|
||||
// by amount inflicted in last attack (i.e., no double penalty).
|
||||
if (attacker->client->team_wounds > attacker->client->team_wounds_before)
|
||||
{
|
||||
attacker->client->team_wounds = attacker->client->team_wounds_before;
|
||||
}
|
||||
|
||||
// If count is less than 1/2 MAX_TEAMKILLS, print off simple warning. If
|
||||
// count is greater than 1/2 MAX_TEAMKILLS but less than MAX_TEAMKILLS,
|
||||
// print off a ban warning. If count equal or greater than MAX_TEAMKILLS,
|
||||
// ban and kick the client.
|
||||
if (((int)maxteamkills->value < 1) ||
|
||||
(attacker->client->team_kills < (((int)maxteamkills->value % 2) + (int)maxteamkills->value / 2)))
|
||||
{
|
||||
gi.cprintf(attacker, PRINT_HIGH, "You killed your TEAMMATE!\n");
|
||||
return;
|
||||
}
|
||||
else if (attacker->client->team_kills < (int)maxteamkills->value)
|
||||
{
|
||||
// Show this on the console
|
||||
gi.cprintf(NULL, PRINT_MEDIUM, "%s is in danger of being banned for killing teammates\n", attacker->client->pers.netname);
|
||||
// Issue a warning to the player
|
||||
gi.cprintf(attacker, PRINT_HIGH, "WARNING: You'll be temporarily banned if you continue killing teammates!\n" );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// They've killed too many teammates this game - kick 'em for a while
|
||||
if (attacker->client->ipaddr)
|
||||
{
|
||||
if (Ban_TeamKiller(attacker, (int)tkbanrounds->value))
|
||||
{
|
||||
gi.cprintf (NULL, PRINT_MEDIUM,
|
||||
"Banning %s@%s for team killing\n",
|
||||
attacker->client->pers.netname,
|
||||
attacker->client->ipaddr);
|
||||
gi.cprintf(attacker, PRINT_HIGH, "You've killed too many teammates, and are banned for %d %s.\n", (int)tkbanrounds->value,
|
||||
(((int)tkbanrounds->value > 1) ? "games" : "game"));
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_MEDIUM,
|
||||
"Error banning %s: unable to get ipaddr\n",
|
||||
attacker->client->pers.netname);
|
||||
}
|
||||
}
|
||||
Kick_Client(attacker);
|
||||
}
|
||||
}
|
||||
// FRIENDLY FIRE
|
||||
|
||||
|
||||
//
|
||||
// Gross, ugly, disgustuing hack section
|
||||
|
@ -283,6 +419,9 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
if (coop->value && attacker->client)
|
||||
meansOfDeath |= MOD_FRIENDLY_FIRE;
|
||||
|
||||
if (attacker && attacker != self && attacker->client && OnSameTeam (self, attacker))
|
||||
meansOfDeath |= MOD_FRIENDLY_FIRE;
|
||||
|
||||
if (deathmatch->value || coop->value)
|
||||
{
|
||||
ff = meansOfDeath & MOD_FRIENDLY_FIRE;
|
||||
|
@ -293,12 +432,15 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
|
||||
switch (mod)
|
||||
{
|
||||
case MOD_BREAKINGGLASS:
|
||||
message = "ate too much glass";
|
||||
break;
|
||||
case MOD_SUICIDE:
|
||||
message = "suicides";
|
||||
break;
|
||||
case MOD_FALLING:
|
||||
// moved falling to the end
|
||||
if (self->client->attacker)
|
||||
if (self->client->push_timeout)
|
||||
special = 1;
|
||||
//message = "hit the ground hard, real hard";
|
||||
if (IsNeutral(self))
|
||||
|
@ -394,14 +536,32 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
}
|
||||
else if ( special ) // handle falling with an attacker set
|
||||
{
|
||||
if ( self->client->attacker->client &&
|
||||
if (self->client->attacker &&
|
||||
self->client->attacker->client &&
|
||||
(self->client->attacker->client !=
|
||||
self->client))
|
||||
{
|
||||
sprintf(death_msg, "%s was taught how to fly by %s\n",
|
||||
self->client->pers.netname, self->client->attacker->client->pers.netname );
|
||||
PrintDeathMessage(death_msg, self);
|
||||
Add_Frag( self->client->attacker );//self->client->attacker->client->resp.score++;
|
||||
|
||||
//MODIFIED FOR FF -FB
|
||||
if (!((int)dmflags->value & DF_NO_FRIENDLY_FIRE) &&
|
||||
OnSameTeam(self, self->client->attacker) &&
|
||||
teamplay->value)
|
||||
{
|
||||
if (!teamplay->value || team_round_going)
|
||||
{
|
||||
Add_TeamKill(self->client->attacker);
|
||||
Subtract_Frag( self->client->attacker );//attacker->client->resp.score--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!teamplay->value || mod != MOD_TELEFRAG)
|
||||
Add_Frag(self->client->attacker );//attacker->client->resp.score++;
|
||||
}
|
||||
//END FF ADD
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -412,20 +572,31 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
else
|
||||
sprintf(death_msg, "%s plummets to his death\n", self->client->pers.netname);
|
||||
PrintDeathMessage(death_msg, self);
|
||||
if (deathmatch->value)
|
||||
Subtract_Frag( self );//self->client->resp.score--;
|
||||
self->enemy = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// handle bleeding, not used because bleeding doesn't get set
|
||||
if ( mod == MOD_BLEEDING )
|
||||
{
|
||||
sprintf(death_msg, "%s bleeds to death\n", self->client->pers.netname);
|
||||
PrintDeathMessage(death_msg, self);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
self->enemy = attacker;
|
||||
if (attacker && attacker->client)
|
||||
{
|
||||
switch (mod)
|
||||
{
|
||||
// zucc
|
||||
case MOD_MK23:
|
||||
case MOD_MK23: // zucc
|
||||
switch (loc)
|
||||
{
|
||||
|
||||
case LOC_HDAM:
|
||||
if (IsNeutral(self))
|
||||
message = " has a hole in its head from";
|
||||
|
@ -486,8 +657,6 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
message2 = "'s MP5/10 Submachinegun";
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case MOD_M4:
|
||||
switch (loc)
|
||||
{
|
||||
|
@ -515,16 +684,28 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
case MOD_M3:
|
||||
n = rand() % 2 + 1;
|
||||
if (n == 1)
|
||||
{message = " accepts"; message2 = "'s M3 Super 90 Assault Shotgun in hole-y matrimony";}
|
||||
if (n == 2)
|
||||
{message = " is full of buckshot from"; message2 = "'s M3 Super 90 Assault Shotgun";}
|
||||
{
|
||||
message = " accepts";
|
||||
message2 = "'s M3 Super 90 Assault Shotgun in hole-y matrimony";
|
||||
}
|
||||
else
|
||||
{
|
||||
message = " is full of buckshot from";
|
||||
message2 = "'s M3 Super 90 Assault Shotgun";
|
||||
}
|
||||
break;
|
||||
case MOD_HC:
|
||||
n = rand() % 2 + 1;
|
||||
if (n == 1)
|
||||
{message = " ate"; message2 = "'s sawed-off 12 gauge";}
|
||||
if (n == 2)
|
||||
{message = " is full of buckshot from"; message2 = "'s sawed off shotgun";}
|
||||
{
|
||||
message = " ate";
|
||||
message2 = "'s sawed-off 12 gauge";
|
||||
}
|
||||
else
|
||||
{
|
||||
message = " is full of buckshot from";
|
||||
message2 = "'s sawed off shotgun";
|
||||
}
|
||||
break;
|
||||
case MOD_SNIPER:
|
||||
switch (loc)
|
||||
|
@ -540,7 +721,9 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
message = " saw the sniper bullet go through his scope thanks to";
|
||||
}
|
||||
else
|
||||
{
|
||||
message = " caught a sniper bullet between the eyes from";
|
||||
}
|
||||
break;
|
||||
case LOC_CDAM:
|
||||
message = " was picked off by";
|
||||
|
@ -565,7 +748,7 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
break;
|
||||
case LOC_CDAM:
|
||||
message = " was John Woo'd by";
|
||||
// message2 = "'s .45 caliber pistol round";
|
||||
//message2 = "'s .45 caliber pistol round";
|
||||
break;
|
||||
case LOC_SDAM:
|
||||
message = " needs some new kidneys thanks to";
|
||||
|
@ -575,9 +758,6 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
message = " was shot in the legs by";
|
||||
message2 = "'s akimbo Mark 23 pistols";
|
||||
break;
|
||||
|
||||
|
||||
|
||||
default:
|
||||
message = " was shot by";
|
||||
message2 = "'s pair of Mark 23 Pistols";
|
||||
|
@ -586,8 +766,6 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
case MOD_KNIFE:
|
||||
switch (loc)
|
||||
{
|
||||
|
||||
|
||||
case LOC_HDAM:
|
||||
if (IsNeutral(self))
|
||||
message = " had its throat slit by";
|
||||
|
@ -609,7 +787,6 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
message = " was slashed apart by";
|
||||
message2 = "'s Combat Knife";
|
||||
}
|
||||
|
||||
break;
|
||||
case MOD_KNIFE_THROWN:
|
||||
switch (loc)
|
||||
|
@ -648,21 +825,15 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
default:
|
||||
message = " was hit by";
|
||||
message2 = "'s flying Combat Knife";
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case MOD_GAS:
|
||||
message = "sucks down some toxic gas thanks to";
|
||||
break;
|
||||
|
||||
case MOD_KICK:
|
||||
n = rand() % 3 + 1;
|
||||
if (n == 1)
|
||||
{
|
||||
|
||||
if (IsNeutral(self))
|
||||
message = " got its ass kicked by";
|
||||
else if (IsFemale(self))
|
||||
|
@ -700,9 +871,7 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
message = " had a Bruce Lee put on him by"; message2 = ", with a quickness";
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MOD_BLASTER:
|
||||
message = "was blasted by";
|
||||
break;
|
||||
|
@ -772,21 +941,29 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
message2 = "'s personal space";
|
||||
break;
|
||||
}
|
||||
|
||||
if (message)
|
||||
{
|
||||
//FIREBLADE
|
||||
sprintf(death_msg, "%s%s %s%s\n", self->client->pers.netname, message, attacker->client->pers.netname, message2);
|
||||
//FIREBLADE
|
||||
sprintf(death_msg, "%s%s %s%s\n", self->client->pers.netname, message,
|
||||
attacker->client->pers.netname, message2);
|
||||
PrintDeathMessage(death_msg, self);
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
if (deathmatch->value)
|
||||
{
|
||||
if (ff)
|
||||
{
|
||||
if (!teamplay->value || team_round_going)
|
||||
{
|
||||
Add_TeamKill(attacker);
|
||||
Subtract_Frag( attacker );//attacker->client->resp.score--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
if (!teamplay->value || mod != MOD_TELEFRAG)
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
Add_Frag(attacker );//attacker->client->resp.score++;
|
||||
}
|
||||
}
|
||||
|
@ -795,10 +972,10 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
|
|||
}
|
||||
}
|
||||
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
sprintf(death_msg, "%s died\n", self->client->pers.netname);
|
||||
PrintDeathMessage(death_msg, self);
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
if (deathmatch->value)
|
||||
Subtract_Frag( self );//self->client->resp.score--;
|
||||
}
|
||||
|
@ -919,7 +1096,7 @@ void TossItemsOnDeath( edict_t *ent )
|
|||
}
|
||||
// special items
|
||||
|
||||
/*
|
||||
#if 0
|
||||
item = FindItem(SIL_NAME);
|
||||
if ( ent->client->pers.inventory[ITEM_INDEX(item)] )
|
||||
EjectItem( ent, item );
|
||||
|
@ -935,7 +1112,7 @@ void TossItemsOnDeath( edict_t *ent )
|
|||
item = FindItem(LASER_NAME);
|
||||
if ( ent->client->pers.inventory[ITEM_INDEX(item)] )
|
||||
EjectItem( ent, item );
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -1066,6 +1243,9 @@ void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damag
|
|||
self->s.sound = 0;
|
||||
self->client->weapon_sound = 0;
|
||||
|
||||
self->client->reload_attempts = 0; // stop them from trying to reload
|
||||
self->client->weapon_attempts = 0;
|
||||
|
||||
self->maxs[2] = -8;
|
||||
|
||||
self->svflags |= SVF_DEADMONSTER;
|
||||
|
@ -1187,7 +1367,13 @@ but is called after each death and level change in deathmatch
|
|||
void InitClientPersistant (gclient_t *client)
|
||||
{
|
||||
gitem_t *item;
|
||||
/*
|
||||
client_persistant_t oldpers;
|
||||
|
||||
//FB 6/3/99
|
||||
memcpy(oldpers, pers, sizeof(client->pers));
|
||||
//FB 6/3/99
|
||||
*/
|
||||
memset (&client->pers, 0, sizeof(client->pers));
|
||||
// changed to mk23
|
||||
item = FindItem(MK23_NAME);
|
||||
|
@ -1583,7 +1769,16 @@ void CopyToBodyQue (edict_t *ent)
|
|||
//body->solid = ent->solid;
|
||||
body->clipmask = ent->clipmask;
|
||||
body->owner = ent->owner;
|
||||
body->movetype = ent->movetype;
|
||||
//FB 5/31/99
|
||||
body->movetype = MOVETYPE_TOSS; // just in case?
|
||||
// body->movetype = ent->movetype;
|
||||
VectorCopy (ent->velocity, body->velocity);
|
||||
body->mass = ent->mass;
|
||||
body->groundentity = NULL;
|
||||
//FB 5/31/99
|
||||
//FB 6/1/99
|
||||
body->s.renderfx = 0;
|
||||
//FB
|
||||
|
||||
body->die = body_die;
|
||||
body->takedamage = DAMAGE_YES;
|
||||
|
@ -1878,6 +2073,12 @@ void PutClientInServer (edict_t *ent)
|
|||
// zucc for ammo
|
||||
// gitem_t *item;
|
||||
|
||||
//FF
|
||||
int save_team_wounds;
|
||||
int save_team_kills;
|
||||
char save_ipaddr[100];
|
||||
//FF
|
||||
|
||||
// find a spawn point
|
||||
// do it before setting health back up, so farthest
|
||||
// ranging doesn't count this client
|
||||
|
@ -1921,8 +2122,24 @@ void PutClientInServer (edict_t *ent)
|
|||
|
||||
// clear everything but the persistant data
|
||||
saved = client->pers;
|
||||
//FF
|
||||
save_team_wounds = client->team_wounds;
|
||||
save_team_kills = client->team_kills;
|
||||
|
||||
if (client->ipaddr)
|
||||
strncpy(save_ipaddr, client->ipaddr, sizeof(save_ipaddr)-1);
|
||||
//FF
|
||||
|
||||
memset (client, 0, sizeof(*client));
|
||||
client->pers = saved;
|
||||
//FF
|
||||
client->team_wounds = save_team_wounds;
|
||||
client->team_kills = save_team_kills;
|
||||
|
||||
if (save_ipaddr && client->ipaddr)
|
||||
strncpy(client->ipaddr, save_ipaddr, sizeof(client->ipaddr));
|
||||
//FF
|
||||
|
||||
if (client->pers.health <= 0)
|
||||
InitClientPersistant(client);
|
||||
client->resp = resp;
|
||||
|
@ -2053,6 +2270,7 @@ void PutClientInServer (edict_t *ent)
|
|||
ent->lasersight = NULL;
|
||||
|
||||
//other
|
||||
client->resp.sniper_mode = SNIPER_1X;
|
||||
client->bandaging = 0;
|
||||
client->leg_damage = 0;
|
||||
client->leg_noise = 0;
|
||||
|
@ -2065,6 +2283,8 @@ void PutClientInServer (edict_t *ent)
|
|||
client->knife_sound = 0;
|
||||
client->doortoggle = 0;
|
||||
client->have_laser = 0;
|
||||
client->reload_attempts = 0;
|
||||
client->weapon_attempts = 0;
|
||||
|
||||
//FIREBLADE
|
||||
if (!going_observer)
|
||||
|
@ -2130,12 +2350,15 @@ void ClientBeginDeathmatch (edict_t *ent)
|
|||
else
|
||||
{
|
||||
// ^^^
|
||||
if (!teamplay->value)
|
||||
{ //FB 5/31/99
|
||||
// send effect
|
||||
gi.WriteByte (svc_muzzleflash);
|
||||
gi.WriteShort (ent-g_edicts);
|
||||
gi.WriteByte (MZ_LOGIN);
|
||||
gi.multicast (ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
}
|
||||
|
||||
gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
|
||||
//FIREBLADE
|
||||
|
@ -2167,15 +2390,15 @@ void ClientBegin (edict_t *ent)
|
|||
|
||||
ent->client = game.clients + (ent - g_edicts - 1);
|
||||
|
||||
|
||||
// clear modes of weapons
|
||||
/*ent->client->pers.mk23_mode = 0;
|
||||
ent->client->pers.mp5_mode = 0;
|
||||
ent->client->pers.m4_mode = 0;
|
||||
ent->client->pers.sniper_mode = 0;
|
||||
ent->client->pers.knife_mode = 0;
|
||||
ent->client->pers.grenade_mode = 0;
|
||||
*/
|
||||
/*
|
||||
ent->client->resp.mk23_mode = 0;
|
||||
ent->client->resp.mp5_mode = 0;
|
||||
ent->client->resp.m4_mode = 0;
|
||||
ent->client->resp.sniper_mode = 0;
|
||||
ent->client->resp.knife_mode = 0;
|
||||
ent->client->resp.grenade_mode = 0;
|
||||
*/
|
||||
|
||||
if (deathmatch->value)
|
||||
{
|
||||
|
@ -2328,12 +2551,15 @@ loadgames will.
|
|||
qboolean ClientConnect (edict_t *ent, char *userinfo)
|
||||
{
|
||||
char *value, *ipaddr;
|
||||
char ipaddr_buf[1000];
|
||||
char ipaddr_buf[100];
|
||||
|
||||
// check to see if they are on the banned IP list
|
||||
ipaddr = Info_ValueForKey (userinfo, "ip");
|
||||
//FIREBLADE
|
||||
strcpy(ipaddr_buf, ipaddr);
|
||||
if (strlen(ipaddr) > sizeof(ipaddr_buf)-1)
|
||||
gi.dprintf("ipaddr_buf length exceeded\n");
|
||||
strncpy(ipaddr_buf, ipaddr, 99);
|
||||
ipaddr_buf[99] = 0;
|
||||
//FIREBLADE
|
||||
|
||||
// FROM 3.20 -FB
|
||||
|
@ -2354,6 +2580,15 @@ qboolean ClientConnect (edict_t *ent, char *userinfo)
|
|||
// they can connect
|
||||
ent->client = game.clients + (ent - g_edicts - 1);
|
||||
|
||||
//AZEROV
|
||||
ent->client->team_kills = 0;
|
||||
//AZEROV
|
||||
|
||||
//EEK
|
||||
ent->client->team_wounds = 0;
|
||||
ent->client->team_wounds_before = 0;
|
||||
//EEK
|
||||
|
||||
//FIREBLADE
|
||||
// We're not going to attempt to support reconnection...
|
||||
if (ent->inuse == true)
|
||||
|
@ -2377,6 +2612,9 @@ qboolean ClientConnect (edict_t *ent, char *userinfo)
|
|||
|
||||
if (game.maxclients > 1)
|
||||
gi.dprintf ("%s@%s connected\n",ent->client->pers.netname, ipaddr_buf);
|
||||
//EEK
|
||||
strncpy(ent->client->ipaddr, ipaddr_buf, sizeof(ent->client->ipaddr));
|
||||
//EEK
|
||||
|
||||
// FROM 3.20 -FB
|
||||
ent->svflags = 0;
|
||||
|
@ -2428,11 +2666,14 @@ void ClientDisconnect (edict_t *ent)
|
|||
etemp->client->attacker = NULL;
|
||||
}
|
||||
}
|
||||
if (!teamplay->value)
|
||||
{ //FB 5/31/99
|
||||
// send effect
|
||||
gi.WriteByte (svc_muzzleflash);
|
||||
gi.WriteShort (ent-g_edicts);
|
||||
gi.WriteByte (MZ_LOGOUT);
|
||||
gi.multicast (ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
gi.unlinkentity (ent);
|
||||
ent->s.modelindex = 0;
|
||||
|
@ -2568,6 +2809,16 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
// perform a pmove
|
||||
gi.Pmove (&pm);
|
||||
|
||||
//FB 6/3/99 - info from Mikael Lindh from AQ:G
|
||||
if (pm.maxs[2] == 4)
|
||||
{
|
||||
ent->maxs[2] = CROUCHING_MAXS2;
|
||||
pm.maxs[2] = CROUCHING_MAXS2;
|
||||
ent->viewheight = CROUCHING_VIEWHEIGHT;
|
||||
pm.viewheight = (float)ent->viewheight;
|
||||
}
|
||||
//FB 6/3/99
|
||||
|
||||
// save results of pmove
|
||||
client->ps.pmove = pm.s;
|
||||
client->old_pmove = pm.s;
|
||||
|
@ -2728,7 +2979,14 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
ent->light_level = ucmd->lightlevel;
|
||||
|
||||
// fire weapon from final position if needed
|
||||
if (client->latched_buttons & BUTTON_ATTACK)
|
||||
if ((client->latched_buttons & BUTTON_ATTACK)
|
||||
//Black Cross - Begin
|
||||
|| (((limchasecam->value && !client->chase_mode) ||
|
||||
(limchasecam->value == 2 && client->chase_mode == 1)) &&
|
||||
team_round_going && (client->resp.team != NOTEAM) &&
|
||||
!(limchasecam->value == 2 && client->chase_mode == 2))
|
||||
//Black Cross - End
|
||||
)
|
||||
{
|
||||
if (ent->solid == SOLID_NOT && ent->deadflag != DEAD_DEAD)
|
||||
{
|
||||
|
@ -2869,6 +3127,7 @@ void ClientBeginServerFrame (edict_t *ent)
|
|||
ent->client->chase_mode = 0;
|
||||
ent->client->chase_target = NULL;
|
||||
ent->client->desired_fov = 90;
|
||||
ent->client->ps.fov = 90; // FB 5/31/99 added
|
||||
ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
|
||||
ent->solid = SOLID_BBOX;
|
||||
gi.linkentity(ent);
|
||||
|
|
17
p_hud.c
17
p_hud.c
|
@ -148,6 +148,23 @@ void BeginIntermission (edict_t *targ)
|
|||
continue;
|
||||
MoveClientToIntermission (client);
|
||||
}
|
||||
|
||||
// AZEROV: Clear the team kills for everyone
|
||||
//gi.cprintf(NULL,PRINT_MEDIUM,"Resetting all team kills\n");
|
||||
for (i=1; i<=maxclients->value; i++)
|
||||
{
|
||||
edict_t *temp_ent;
|
||||
temp_ent = g_edicts + i;
|
||||
|
||||
if (!temp_ent->inuse || !temp_ent->client)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
temp_ent->client->team_wounds = 0;
|
||||
temp_ent->client->team_kills = 0;
|
||||
}
|
||||
// AZEROV
|
||||
}
|
||||
|
||||
void A_ScoreboardMessage (edict_t *ent, edict_t *killer);
|
||||
|
|
137
p_view.c
137
p_view.c
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "g_local.h"
|
||||
#include "m_player.h"
|
||||
|
||||
|
@ -209,7 +208,7 @@ void SV_CalcViewOffset (edict_t *ent)
|
|||
vec3_t v;
|
||||
|
||||
|
||||
//===================================
|
||||
//===================================
|
||||
|
||||
// base angles
|
||||
angles = ent->client->ps.kick_angles;
|
||||
|
@ -270,7 +269,7 @@ void SV_CalcViewOffset (edict_t *ent)
|
|||
angles[ROLL] += delta;
|
||||
}
|
||||
|
||||
//===================================
|
||||
//===================================
|
||||
|
||||
// base origin
|
||||
|
||||
|
@ -358,7 +357,7 @@ void SV_CalcGunOffset (edict_t *ent)
|
|||
|
||||
// gun height
|
||||
VectorClear (ent->client->ps.gunoffset);
|
||||
// ent->ps->gunorigin[2] += bob;
|
||||
// ent->ps->gunorigin[2] += bob;
|
||||
|
||||
// gun_x / gun_y / gun_z are development tools
|
||||
for (i=0 ; i<3 ; i++)
|
||||
|
@ -406,7 +405,14 @@ void SV_CalcBlend (edict_t *ent)
|
|||
// enable ir vision if appropriate
|
||||
if ( ir->value )
|
||||
{
|
||||
if ( ent->client->pers.inventory[ITEM_INDEX(FindItem(BAND_NAME))] && ent->client->resp.ir == 0 )
|
||||
if ((ent->client->pers.inventory[ITEM_INDEX(FindItem(BAND_NAME))] &&
|
||||
ent->client->resp.ir == 0) ||
|
||||
(ent->client->chase_target != NULL &&
|
||||
ent->client->chase_target->client != NULL &&
|
||||
ent->client->chase_mode == 2 &&
|
||||
ent->client->chase_target->client->resp.ir == 0 &&
|
||||
ent->client->chase_target->client->pers.inventory[ITEM_INDEX(FindItem(BAND_NAME))]))
|
||||
|
||||
{
|
||||
ent->client->ps.rdflags |= RDF_IRGOGGLES;
|
||||
}
|
||||
|
@ -507,7 +513,7 @@ void P_FallingDamage (edict_t *ent)
|
|||
{
|
||||
if (lights_camera_action)
|
||||
{
|
||||
// ent->s.event = EV_FOOTSTEP;
|
||||
// ent->s.event = EV_FOOTSTEP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -768,7 +774,11 @@ void G_SetClientEffects (edict_t *ent)
|
|||
|
||||
ent->s.effects = 0;
|
||||
// zucc added RF_IR_VISIBLE
|
||||
//FB 6/1/99 - only for live players
|
||||
if (ent->deadflag != DEAD_DEAD)
|
||||
ent->s.renderfx = RF_IR_VISIBLE;
|
||||
else
|
||||
ent->s.renderfx = 0;
|
||||
|
||||
if (ent->health <= 0 || level.intermissiontime)
|
||||
return;
|
||||
|
@ -933,7 +943,7 @@ void G_SetClientFrame (edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
newanim:
|
||||
newanim:
|
||||
// return to either a running or standing frame
|
||||
client->anim_priority = ANIM_BASIC;
|
||||
client->anim_duck = duck;
|
||||
|
@ -1031,7 +1041,77 @@ void Do_Bleeding( edict_t *ent )
|
|||
}
|
||||
|
||||
|
||||
int canFire( edict_t* ent )
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
|
||||
switch ( ent->client->curr_weap )
|
||||
{
|
||||
case MK23_NUM:
|
||||
{
|
||||
|
||||
if ( ent->client->mk23_rds > 0 )
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case MP5_NUM:
|
||||
{
|
||||
if ( ent->client->mp5_rds > 0 )
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case M4_NUM:
|
||||
{
|
||||
if ( ent->client->m4_rds > 0 )
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case M3_NUM:
|
||||
{
|
||||
if ( ent->client->shot_rds > 0 )
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HC_NUM:
|
||||
{
|
||||
if ( ent->client->cannon_rds == 2 )
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SNIPER_NUM:
|
||||
{
|
||||
if ( ent->client->sniper_rds > 0 )
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DUAL_NUM:
|
||||
{
|
||||
if ( ent->client->dual_rds > 0 )
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
=================
|
||||
ClientEndServerFrame
|
||||
|
@ -1044,12 +1124,12 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
{
|
||||
float bobtime;
|
||||
int i;
|
||||
// int damage; // zucc for bleeding
|
||||
// int damage; // zucc for bleeding
|
||||
|
||||
current_player = ent;
|
||||
current_client = ent->client;
|
||||
|
||||
//FIREBLADE - Unstick avoidance stuff.
|
||||
//FIREBLADE - Unstick avoidance stuff.
|
||||
if (ent->solid == SOLID_TRIGGER && !lights_camera_action)
|
||||
{
|
||||
edict_t *overlap;
|
||||
|
@ -1073,7 +1153,7 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
} while (overlap != NULL);
|
||||
}
|
||||
}
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
|
||||
//
|
||||
// If the origin or velocity have changed since ClientThink(),
|
||||
|
@ -1126,9 +1206,9 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
xyspeed = sqrt(ent->velocity[0]*ent->velocity[0] + ent->velocity[1]*ent->velocity[1]);
|
||||
|
||||
if (xyspeed < 5 ||
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
ent->solid == SOLID_NOT)
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
{
|
||||
bobmove = 0;
|
||||
current_client->bobtime = 0; // start at beginning of cycle again
|
||||
|
@ -1175,7 +1255,7 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
|
||||
G_SetStats (ent);
|
||||
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
for (i = 1; i <= maxclients->value; i++) {
|
||||
int stats_copy;
|
||||
edict_t *e = g_edicts + i;
|
||||
|
@ -1198,10 +1278,10 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
ent->client->ps.stats[stats_copy];
|
||||
}
|
||||
|
||||
//FB e->client->ps.stats[STAT_LAYOUTS] = 1;
|
||||
//FB break;
|
||||
//FB e->client->ps.stats[STAT_LAYOUTS] = 1;
|
||||
//FB break;
|
||||
}
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
|
||||
G_SetClientEvent (ent);
|
||||
|
||||
|
@ -1223,29 +1303,40 @@ void ClientEndServerFrame (edict_t *ent)
|
|||
|
||||
if ( ent->client->push_timeout > 0 )
|
||||
ent->client->push_timeout--;
|
||||
else
|
||||
/* else
|
||||
{
|
||||
ent->client->attacker = NULL;
|
||||
ent->client->attacker_mod = MOD_BLEEDING;
|
||||
}
|
||||
|
||||
*/
|
||||
if ( ent->client->reload_attempts > 0 )
|
||||
{
|
||||
if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) && canFire(ent) )
|
||||
{
|
||||
ent->client->reload_attempts = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Cmd_Reload_f(ent);
|
||||
|
||||
}
|
||||
}
|
||||
if ( ent->client->weapon_attempts > 0 )
|
||||
Cmd_Weapon_f(ent);
|
||||
|
||||
// if the scoreboard is up, update it
|
||||
if (ent->client->showscores && !(level.framenum & 31) )
|
||||
{
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
if (ent->client->menu) {
|
||||
PMenu_Update(ent);
|
||||
} else
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
DeathmatchScoreboardMessage (ent, ent->enemy);
|
||||
gi.unicast (ent, false);
|
||||
}
|
||||
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
RadioThink(ent);
|
||||
//FIREBLADE
|
||||
//FIREBLADE
|
||||
}
|
||||
|
||||
|
|
68
p_weapon.c
68
p_weapon.c
|
@ -7,7 +7,7 @@
|
|||
static qboolean is_quad;
|
||||
static byte is_silenced;
|
||||
|
||||
|
||||
void setFFState(edict_t *ent);
|
||||
void weapon_grenade_fire (edict_t *ent, qboolean held);
|
||||
|
||||
void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
|
||||
|
@ -511,6 +511,9 @@ void ChangeWeapon (edict_t *ent)
|
|||
ent->client->grenade_time = 0;
|
||||
}
|
||||
|
||||
// zucc - prevent reloading queue for previous weapon from doing anything
|
||||
ent->client->reload_attempts = 0;
|
||||
|
||||
ent->client->pers.lastweapon = ent->client->pers.weapon;
|
||||
ent->client->pers.weapon = ent->client->newweapon;
|
||||
ent->client->newweapon = NULL;
|
||||
|
@ -1380,7 +1383,7 @@ void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST,
|
|||
{
|
||||
ent->client->pers.inventory[ent->client->ammo_index] = 0;
|
||||
}
|
||||
break;
|
||||
return;
|
||||
}
|
||||
case DUAL_NUM:
|
||||
{
|
||||
|
@ -1623,12 +1626,17 @@ void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST,
|
|||
if( ent->client->curr_weap == SNIPER_NUM )
|
||||
{
|
||||
if ( ent->client->desired_fov == 90 )
|
||||
{
|
||||
ent->client->ps.fov = 90;
|
||||
if ( !(ent->client->idle_weapon) )
|
||||
ent->client->weaponstate = WEAPON_READY;
|
||||
ent->client->idle_weapon = 0;
|
||||
}
|
||||
if ( !(ent->client->idle_weapon) && ent->client->desired_fov != 90 )
|
||||
{
|
||||
ent->client->ps.fov = ent->client->desired_fov;
|
||||
ent->client->weaponstate = WEAPON_READY;
|
||||
ent->client->ps.gunindex = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
(ent->client->idle_weapon)--;
|
||||
|
@ -2013,7 +2021,7 @@ void weapon_grenade_fire (edict_t *ent, qboolean held)
|
|||
|
||||
timer = ent->client->grenade_time - level.time;
|
||||
speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
|
||||
fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
|
||||
fire_grenade2 (ent, start, forward, GRENADE_DAMRAD, speed, timer, GRENADE_DAMRAD*2, held);
|
||||
|
||||
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
|
||||
ent->client->pers.inventory[ent->client->ammo_index]--;
|
||||
|
@ -3307,6 +3315,10 @@ void Weapon_M4 (edict_t *ent)
|
|||
Weapon_Generic (ent, 10, 12, 39, 44, 63, 71, pause_frames, fire_frames, M4_Fire);
|
||||
}
|
||||
|
||||
|
||||
void InitShotgunDamageReport();
|
||||
void ProduceShotgunDamageReport(edict_t *);
|
||||
|
||||
void M3_Fire (edict_t *ent)
|
||||
{
|
||||
vec3_t start;
|
||||
|
@ -3327,12 +3339,30 @@ void M3_Fire (edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
AngleVectors (ent->client->v_angle, forward, right, NULL);
|
||||
|
||||
VectorScale (forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -2;
|
||||
|
||||
VectorSet(offset, 0, 8, ent->viewheight-height);
|
||||
|
||||
|
||||
|
||||
if ( ent->client->ps.gunframe == 14 )
|
||||
{
|
||||
if (!sv_shelloff->value)
|
||||
{
|
||||
vec3_t result;
|
||||
Old_ProjectSource (ent->client, ent->s.origin, offset, forward, right, result);
|
||||
EjectShell(ent, result, 0);
|
||||
}
|
||||
ent->client->ps.gunframe++;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
|
||||
|
||||
/* if (is_quad)
|
||||
|
@ -3341,29 +3371,22 @@ void M3_Fire (edict_t *ent)
|
|||
kick *= 4;
|
||||
}*/
|
||||
|
||||
|
||||
setFFState(ent);
|
||||
InitShotgunDamageReport(); //FB 6/3/99
|
||||
if (deathmatch->value)
|
||||
fire_shotgun (ent, start, forward, damage, kick, 800, 800, 12/*DEFAULT_DEATHMATCH_SHOTGUN_COUNT*/, MOD_M3);
|
||||
else
|
||||
fire_shotgun (ent, start, forward, damage, kick, 800, 800, 12/*DEFAULT_SHOTGUN_COUNT*/, MOD_M3);
|
||||
|
||||
if (!sv_shelloff->value)
|
||||
{
|
||||
vec3_t result;
|
||||
Old_ProjectSource (ent->client, ent->s.origin, offset, forward, right, result);
|
||||
EjectShell(ent, result, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/shotgf1b.wav"), 1, ATTN_NORM, 0);
|
||||
|
||||
// send muzzle flash
|
||||
gi.WriteByte (svc_muzzleflash);
|
||||
gi.WriteShort (ent-g_edicts);
|
||||
gi.WriteByte (MZ_SHOTGUN | is_silenced);
|
||||
gi.multicast (ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
ProduceShotgunDamageReport(ent); //FB 6/3/99
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
|
||||
|
@ -3376,7 +3399,7 @@ void M3_Fire (edict_t *ent)
|
|||
void Weapon_M3 (edict_t *ent)
|
||||
{
|
||||
static int pause_frames[] = {22, 28, 0};
|
||||
static int fire_frames[] = {8, 9, 0};
|
||||
static int fire_frames[] = {8, 9, 14, 0};
|
||||
|
||||
Weapon_Generic (ent, 7, 15, 35, 41, 52, 60, pause_frames, fire_frames, M3_Fire);
|
||||
}
|
||||
|
@ -3416,18 +3439,19 @@ void HC_Fire (edict_t *ent)
|
|||
v[ROLL] = ent->client->v_angle[ROLL];
|
||||
AngleVectors (v, forward, NULL, NULL);
|
||||
// default hspread is 1k and default vspread is 500
|
||||
setFFState(ent);
|
||||
InitShotgunDamageReport(); //FB 6/3/99
|
||||
fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD*4, DEFAULT_SHOTGUN_VSPREAD*4, 34/2, MOD_HC);
|
||||
v[YAW] = ent->client->v_angle[YAW] + 5;
|
||||
AngleVectors (v, forward, NULL, NULL);
|
||||
fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD*4, DEFAULT_SHOTGUN_VSPREAD*5, 34/2, MOD_HC);
|
||||
|
||||
gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/cannon_fire.wav"), 1, ATTN_NORM, 0);
|
||||
|
||||
// send muzzle flash
|
||||
gi.WriteByte (svc_muzzleflash);
|
||||
gi.WriteShort (ent-g_edicts);
|
||||
gi.WriteByte (MZ_SSHOTGUN | is_silenced);
|
||||
gi.multicast (ent->s.origin, MULTICAST_PVS);
|
||||
ProduceShotgunDamageReport(ent); //FB 6/3/99
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
|
@ -4109,7 +4133,7 @@ int Knife_Fire (edict_t *ent)
|
|||
vec3_t forward, right;
|
||||
|
||||
vec3_t offset;
|
||||
int damage = 50;
|
||||
int damage = 200;
|
||||
int throwndamage = 250;
|
||||
int kick = 50; // doesn't throw them back much..
|
||||
int knife_return = 3;
|
||||
|
@ -4271,7 +4295,7 @@ void gas_fire (edict_t *ent )
|
|||
vec3_t offset;
|
||||
vec3_t forward, right;
|
||||
vec3_t start;
|
||||
int damage = 300;//GRENADE_DAMRAD;
|
||||
int damage = GRENADE_DAMRAD;
|
||||
float timer;
|
||||
int speed;
|
||||
float radius;
|
||||
|
@ -4293,7 +4317,7 @@ void gas_fire (edict_t *ent )
|
|||
else
|
||||
speed = 920;
|
||||
|
||||
fire_grenade2 (ent, start, forward, damage, speed, timer, radius, false);
|
||||
fire_grenade2 (ent, start, forward, GRENADE_DAMRAD, speed, timer, GRENADE_DAMRAD*2, false);
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue