📄 p_weapon.pas
字号:
//This is "COMMON" file for \GAME\p_weapon.pas & \CTF\p_weapon.pas
{$DEFINE CTF}
{$IFDEF CTF}
{$ELSE}
{$ENDIF}
// PLEASE, don't modify this file
// 70% complete
{----------------------------------------------------------------------------}
{ }
{ File(s): p_weapon.c }
{ }
{ Initial conversion by : YgriK (Igor Karpov) - glYgriK@hotbox.ru }
{ Initial conversion on : 24-Jan-2002 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ Copyright (C) 1997-2001 Id Software, Inc. }
{ }
{ This program is free software; you can redistribute it and/or }
{ modify it under the terms of the GNU General Public License }
{ as published by the Free Software Foundation; either version 2 }
{ of the License, or (at your option) any later version. }
{ }
{ This program is distributed in the hope that it will be useful, }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
{ }
{ See the GNU General Public License for more details. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : }
{ Updated by : }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ 1) ???../g_local.inc }
{ 2) ???../m_player.inc }
{ }
{----------------------------------------------------------------------------}
{ * TODO: }
{ 1) Do more tests }
{ }
{----------------------------------------------------------------------------}
// g_weapon.c
#include "g_local.h"
#include "m_player.h"
static qboolean is_quad;
static byte is_silenced;
void weapon_grenade_fire (edict_t *ent, qboolean held);
{ (GAME <> CTF):
GAME: static void P_ProjectSource
CTF: void P_ProjectSource }
procedure static void P_ProjectSource (gclient_t *client,
vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result);
var
_distance : vec3_t;
begin
VectorCopy (distance, _distance);
if (client.pers.hand = LEFT_HANDED)
// then _distance[1] *= -1;
then _distance[1] := - _distance[1]
else
if (client.pers.hand = CENTER_HANDED) then
_distance[1] := 0;
G_ProjectSource (point, _distance, forward, right, result);
end;//procedure (GAME <> CTF) ???
{*
===============
PlayerNoise
Each player can have two noise objects associated with it:
a personal noise (jumping, pain, weapon firing), and a weapon
target noise (bullet wall impacts)
Monsters that don't directly see the player can move
to a noise in hopes of seeing the player from there.
===============
*}
// (GAME=CTF)
procedure PlayerNoise(edict_t *who, vec3_t where, int type);
var
edict_t *noise;
begin
if (type = PNOISE_WEAPON) then
if (who.client.silencer_shots) then
begin
who.client.silencer_shots--;
Exit;
end;
if (deathmatch.value) then
Exit;
// if (who.flags & FL_NOTARGET) then
if (who.flags AND FL_NOTARGET) <> 0 then
Exit;
if (!who.mynoise) then
begin
noise := G_Spawn();
noise.classname := 'player_noise';
VectorSet (noise.mins, -8, -8, -8);
VectorSet (noise.maxs, 8, 8, 8);
noise.owner := who;
noise.svflags := SVF_NOCLIENT;
who.mynoise := noise;
noise := G_Spawn();
noise.classname := 'player_noise';
VectorSet (noise.mins, -8, -8, -8);
VectorSet (noise.maxs, 8, 8, 8);
noise.owner := who;
noise.svflags := SVF_NOCLIENT;
who.mynoise2 := noise;
end;
if (type = PNOISE_SELF) OR (type = PNOISE_WEAPON)
then begin
noise := who.mynoise;
level.sound_entity := noise;
level.sound_entity_framenum := level.framenum;
end
else begin// type == PNOISE_IMPACT
noise := who.mynoise2;
level.sound2_entity := noise;
level.sound2_entity_framenum := level.framenum;
end;
VectorCopy (where, noise.s.origin);
VectorSubtract (where, noise.maxs, noise.absmin);
VectorAdd (where, noise.maxs, noise.absmax);
noise.teleport_time := level.time;
gi.linkentity (noise);
end;//procedure (GAME=CTF)
// (GAME=CTF)
function Pickup_Weapon (edict_t *ent, edict_t *other) : qboolean;
var
index : integer;
gitem_t *ammo;
begin
index := ITEM_INDEX(ent.item);
(* if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value)
&& other->client->pers.inventory[index])
if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
return false; // leave the weapon for others to pickup*)
{Y: NB! need test}
if ( ( ((Trunc(dmflags.value) AND DF_WEAPONS_STAY) <> 0) OR coop.value ) AND
other.client.pers.inventory[index] ) then
if (ent.spawnflags AND (DROPPED_ITEM OR DROPPED_PLAYER_ITEM) = 0) then
begin
Result := false; // leave the weapon for others to pickup
Exit;
end;
other.client.pers.inventory[index]++;
// if (!(ent.spawnflags & DROPPED_ITEM) ) then
if ((ent.spawnflags AND DROPPED_ITEM) = 0) then
begin
// give them some ammo with it
ammo := FindItem (ent.item.ammo);
// if ( (int)dmflags.value & DF_INFINITE_AMMO )
{Y: NB! need test}
if ((Trunc(dmflags.value) AND DF_INFINITE_AMMO) <> 0)
then Add_Ammo (other, ammo, 1000)
else Add_Ammo (other, ammo, ammo.quantity);
// if (! (ent.spawnflags & DROPPED_PLAYER_ITEM) ) then
if ((ent.spawnflags AND DROPPED_PLAYER_ITEM) =0) then
begin
if (deathmatch.value) then
// if ((int)(dmflags.value) & DF_WEAPONS_STAY)
{Y: NB! need test}
if ((Trunc(dmflags.value) AND DF_WEAPONS_STAY) < 0)
then ent.flags := ent.flags OR FL_RESPAWN
else SetRespawn (ent, 30);
if (coop.value) then
ent.flags := ent.flags OR FL_RESPAWN;
end;
end;//if
if (other.client.pers.weapon <> ent.item) AND
(other.client.pers.inventory[index] = 1) AND
(!deathmatch.value OR other.client.pers.weapon = FindItem('blaster')) then
other.client.newweapon := ent.item;
Result := true;
end;//function (GAME=CTF)
{*
===============
ChangeWeapon
The old weapon has been dropped all the way, so make the new one
current
===============
*}
// (GAME=CTF)
procedure ChangeWeapon (edict_t *ent);
var
i : integer;
begin
if (ent.client.grenade_time) then
begin
ent.client.grenade_time := level.time;
ent.client.weapon_sound := 0;
weapon_grenade_fire (ent, false);
ent.client.grenade_time := 0;
end;
ent.client.pers.lastweapon := ent.client.pers.weapon;
ent.client.pers.weapon := ent.client.newweapon;
ent.client.newweapon := NULL;
ent.client.machinegun_shots := 0;
// set visible model
if (ent.s.modelindex = 255) then
begin
if (ent.client.pers.weapon)
then i := ((ent.client.pers.weapon.weapmodel AND $FF) SHL 8)
else i := 0;
ent.s.skinnum := (ent - g_edicts - 1) OR i;
end;
if (ent.client.pers.weapon AND ent.client.pers.weapon.ammo)
then ent.client.ammo_index := ITEM_INDEX(FindItem(ent.client.pers.weapon.ammo));
else ent.client.ammo_index := 0;
if (!ent.client.pers.weapon) then
begin
// dead
ent.client.ps.gunindex := 0;
Exit;
end;
ent.client.weaponstate := WEAPON_ACTIVATING;
ent.client.ps.gunframe := 0;
ent.client.ps.gunindex := gi.modelindex(ent.client.pers.weapon.view_model);
ent.client.anim_priority := ANIM_PAIN;
if (ent.client.ps.pmove.pm_flags AND PMF_DUCKED) <> 0
then begin
ent.s.frame := FRAME_crpain1;
ent.client.anim_end := FRAME_crpain4;
end
else begin
ent.s.frame := FRAME_pain301;
ent.client.anim_end := FRAME_pain304;
end;
end;//procedure (GAME=CTF)
{*
=================
NoAmmoWeaponChange
=================
*}
// (GAME=CTF)
procedure NoAmmoWeaponChange (edict_t *ent);
begin
if (ent.client.pers.inventory[ITEM_INDEX(FindItem('slugs'))]) AND
(ent.client.pers.inventory[ITEM_INDEX(FindItem('railgun'))]) then
begin
ent.client.newweapon := FindItem ('railgun');
Exit;
end;
if (ent.client.pers.inventory[ITEM_INDEX(FindItem('cells'))]) AND
(ent.client.pers.inventory[ITEM_INDEX(FindItem('hyperblaster'))]) then
begin
ent.client.newweapon := FindItem ('hyperblaster');
Exit;
end;
if (ent.client.pers.inventory[ITEM_INDEX(FindItem('bullets'))]) AND
(ent.client.pers.inventory[ITEM_INDEX(FindItem('chaingun'))]) then
begin
ent.client.newweapon := FindItem ('chaingun');
Exit;
end;
if (ent.client.pers.inventory[ITEM_INDEX(FindItem('bullets'))]) AND
(ent.client.pers.inventory[ITEM_INDEX(FindItem('machinegun'))]) then
begin
ent.client.newweapon = FindItem ('machinegun');
Exit;
end;
if (ent.client.pers.inventory[ITEM_INDEX(FindItem('shells'))] > 1) AND
(ent.client.pers.inventory[ITEM_INDEX(FindItem('super shotgun'))]) then
begin
ent.client.newweapon := FindItem ('super shotgun');
Exit;
end;
if (ent.client.pers.inventory[ITEM_INDEX(FindItem('shells'))]) AND
(ent.client.pers.inventory[ITEM_INDEX(FindItem('shotgun'))]) then
begin
ent.client.newweapon := FindItem ('shotgun');
Exit;
end;
ent.client.newweapon := FindItem ('blaster');
end;//procedure (GAME=CTF)
{*
=================
Think_Weapon
Called by ClientBeginServerFrame and ClientThink
=================
*}
// (GAME=CTF)
procedure Think_Weapon (edict_t *ent);
begin
// if just died, put the weapon away
if (ent.health < 1) then
begin
ent.client.newweapon := NULL;
ChangeWeapon (ent);
end;
// call active weapon think routine
if (ent.client.pers.weapon) AND (ent.client.pers.weapon.weaponthink) then
begin
is_quad := (ent.client.quad_framenum > level.framenum);
if (ent.client.silencer_shots)
then is_silenced := MZ_SILENCED
else is_silenced := 0;
ent.client.pers.weapon.weaponthink (ent);
end;
end;//procedure (GAME=CTF)
{*
================
Use_Weapon
Make the weapon ready if there is ammo
================
*}
// (GAME=CTF)
procedure Use_Weapon (edict_t *ent, gitem_t *item);
var
ammo_index : integer;
gitem_t *ammo_item;
begin
// see if we're already using it
if (item = ent.client.pers.weapon) then
Exit;
// if (item.ammo) AND (!g_select_empty.value) AND (!(item.flags & IT_AMMO)) then
if (item.ammo) AND (!g_select_empty.value) AND ((item.flags AND IT_AMMO) = 0) then
begin
ammo_item := FindItem(item.ammo);
ammo_index := ITEM_INDEX(ammo_item);
if (!ent.client.pers.inventory[ammo_index]) then
begin
gi.cprintf (ent, PRINT_HIGH, 'No %s for %s.\n', ammo_item.pickup_name, item.pickup_name);
Exit;
end;
if (ent.client.pers.inventory[ammo_index] < item.quantity) then
begin
gi.cprintf (ent, PRINT_HIGH, 'Not enough %s for %s.\n', ammo_item.pickup_name, item.pickup_name);
Exit;
end;
end;
// change to this weapon when down
ent.client.newweapon := item;
end;//procedure (GAME=CTF)
{*
================
Drop_Weapon
================
*}
// (GAME=CTF)
procedure Drop_Weapon (edict_t *ent, gitem_t *item);
var
index : integer;
begin
// if ((int)(dmflags.value) & DF_WEAPONS_STAY) then
{Y: NB! need test}
if ((Trunc(dmflags.value) AND DF_WEAPONS_STAY) <> 0) then
Exit;
index := ITEM_INDEX(item);
// see if we're already using it
if ( ((item = ent.client.pers.weapon) OR (item = ent.client.newweapon)) AND
(ent.client.pers.inventory[index] = 1) ) then
begin
gi.cprintf (ent, PRINT_HIGH, 'Can"t drop current weapon\n');
Exit;
end;//if
Drop_Item (ent, item);
ent.client.pers.inventory[index]--;
end;//procedure (GAME=CTF)
{*
================
Weapon_Generic
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -