📄 p_weapon.pas
字号:
//99%
{----------------------------------------------------------------------------}
{ }
{ 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 : 2003-03-24 }
{ Updated by : Scott Price }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ x) }
{----------------------------------------------------------------------------}
{ NOTES: }
{ 1) Whilst mostly complete, there are certain elements of this which }
{ relate to the CTF define that have NOT been tidied or checked. ONLY }
{ items relating to game have been checked/reviewed. }
{ }
{----------------------------------------------------------------------------}
{ * TODO: }
{ 1) Do more tests }
{ 2) <SP> Tried to make sections more like the original C code. }
{ Optomisations can occur later to the code. }
{ }
{----------------------------------------------------------------------------}
// p_weapon.c
unit p_weapon;
interface
uses
q_shared,
q_shared_add,
GameUnit,
g_local,
g_local_add;
{$IFDEF CTF}
procedure P_ProjectSource (client : gclient_p; var point, distance, forward_, right, result : vec3_t); //only for CTF\g_ctf.c
{$ENDIF}
procedure PlayerNoise (who : edict_p; const where : vec3_t; type_ : integer); //a few files
function Pickup_Weapon (ent, other : edict_p) : qboolean; cdecl; //for g_items
procedure ChangeWeapon (ent : edict_p); //for p_client
procedure Think_Weapon (ent : edict_p); //for p_client
procedure Use_Weapon (ent : edict_p; item : gitem_p); cdecl; //for g_items
procedure Drop_Weapon (ent : edict_p; item : gitem_p); cdecl; //for g_items
procedure Weapon_Blaster (ent: edict_p); cdecl;
procedure Weapon_Shotgun (ent: edict_p); cdecl;
procedure Weapon_SuperShotgun (ent: edict_p); cdecl;
procedure Weapon_Machinegun (ent: edict_p); cdecl;
procedure Weapon_Chaingun (ent: edict_p); cdecl;
procedure Weapon_GrenadeLauncher (ent: edict_p); cdecl;
procedure Weapon_RocketLauncher (ent: edict_p); cdecl;
procedure Weapon_Hyperblaster (ent: edict_p); cdecl;
procedure Weapon_Railgun (ent: edict_p); cdecl;
procedure Weapon_BFG(ent: edict_p); cdecl;
procedure Weapon_Grenade (ent: edict_p); cdecl;
implementation
uses g_weapon,
g_utils,
g_items,
m_player,
g_main,
CPas;
var
is_quad : qboolean;
is_silenced : byte;
procedure weapon_grenade_fire (ent : edict_p; held : qboolean); cdecl; forward;
{ (GAME <> CTF):
GAME: static void P_ProjectSource
CTF: void P_ProjectSource }
//only for CTF\g_ctf.c
procedure P_ProjectSource (client : gclient_p; var point, distance, forward_, right, result : vec3_t);
var
_distance : vec3_t;
begin
VectorCopy (distance, _distance);
if (client^.pers.hand = LEFT_HANDED) then
_distance[1] := _distance[1] * -1
else if (client^.pers.hand = CENTER_HANDED) then
_distance[1] := 0;
G_ProjectSource (point, _distance, forward_, right, result);
end;
{*
===============
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 (who : edict_p; const where : vec3_t; type_ : integer); //a few files
var
noise : edict_p;
begin
if (type_ = PNOISE_WEAPON) then
if (who^.client^.silencer_shots <> 0) then
begin
Dec(who^.client^.silencer_shots);
Exit;
end;
if (deathmatch^.value <> 0) then
Exit;
if (who^.flags AND FL_NOTARGET) <> 0 then
Exit;
if (who^.mynoise = Nil) 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(); // by FAB
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 // type == PNOISE_IMPACT
begin
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;
// (GAME=CTF)
function Pickup_Weapon (ent, other : edict_p) : qboolean; //for g_items
var
index : integer;
ammo : gitem_p;
begin
index := ITEM_INDEX(ent^.item); // by FAB
if ( ( ((Trunc(dmflags^.value) AND DF_WEAPONS_STAY) <> 0) OR (coop^.value <> 0) ) AND
(other^.client^.pers.inventory[index] <> 0) ) 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;
Inc(other^.client^.pers.inventory[index]);
if ((ent^.spawnflags AND DROPPED_ITEM) = 0) then
begin
// give them some ammo with it
ammo := FindItem (ent^.item^.ammo); // by FAB
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 AND DROPPED_PLAYER_ITEM) = 0) then
begin
if (deathmatch^.value <> 0) then
begin
if ((Trunc(dmflags^.value) AND DF_WEAPONS_STAY) <> 0) then
ent^.flags := ent^.flags OR FL_RESPAWN
else
SetRespawn (ent, 30); // by FAB
end;
if (coop^.value <> 0) then
ent^.flags := ent^.flags OR FL_RESPAWN;
end;
end;
{ 2003-03-14-SP: The Deathmatch and next boolean result were supposed to have
an additional set of brackets around them. Added. }
if (other^.client^.pers.weapon <> ent^.item) AND (other^.client^.pers.inventory[index] = 1)
AND ((deathmatch^.value = 0) OR (other^.client^.pers.weapon = FindItem('blaster')) ) then
other^.client^.newweapon := ent^.item;
Result := true;
end;
{*
===============
ChangeWeapon
The old weapon has been dropped all the way, so make the new one
current
===============
*}
// (GAME=CTF)
procedure ChangeWeapon (ent : edict_p);
var
i : integer;
begin
if (ent^.client^.grenade_time <> 0) 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 := Nil;
ent^.client^.machinegun_shots := 0;
// set visible model
if (ent^.s.modelindex = 255) then
begin
if (ent^.client^.pers.weapon <> Nil) then
i := ((ent^.client^.pers.weapon^.weapmodel AND $FF) SHL 8)
else
i := 0;
ent^.s.skinnum := (Cardinal(ent) - Cardinal(g_edicts) - 1 * SizeOf(edict_t)) OR i;
end;
if (ent^.client^.pers.weapon <> Nil) 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 = Nil) 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; // by FAB
ent^.client^.anim_end := FRAME_crpain4; // by FAB
end
else begin
ent^.s.frame := FRAME_pain301; // by FAB
ent^.client^.anim_end := FRAME_pain304; // by FAB
end;
end;
{*
=================
NoAmmoWeaponChange
=================
*}
// (GAME=CTF)
procedure NoAmmoWeaponChange (ent : edict_p); //???only imp
begin
if (ent^.client^.pers.inventory[ITEM_INDEX(FindItem('slugs'))] AND
ent^.client^.pers.inventory[ITEM_INDEX(FindItem('railgun'))]) <> 0 then // check this ..by FAB
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'))]) <> 0 then // check this ..by FAB
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'))]) <> 0 then // check this ..by FAB
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'))]) <> 0 then // check this ..by FAB
begin
ent^.client^.newweapon := FindItem ('machinegun');
Exit;
end;
if (ent^.client^.pers.inventory[ITEM_INDEX(FindItem('shells'))] AND
ent^.client^.pers.inventory[ITEM_INDEX(FindItem('super shotgun'))]) <> 0 then // check this ..by FAB
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'))]) <> 0 then // check this ..by FAB
begin
ent^.client^.newweapon := FindItem ('shotgun');
Exit;
end;
ent^.client^.newweapon := FindItem ('blaster');
end;
{*
=================
Think_Weapon
Called by ClientBeginServerFrame and ClientThink
=================
*}
// (GAME=CTF)
procedure Think_Weapon (ent : edict_p);
begin
// if just died, put the weapon away
if (ent^.health < 1) then
begin
ent^.client^.newweapon := Nil;
ChangeWeapon (ent);
end;
// call active weapon think routine
if (ent^.client^.pers.weapon <> Nil) AND Assigned(ent^.client^.pers.weapon^.weaponthink) then
begin
is_quad := (ent^.client^.quad_framenum > level.framenum);
if (ent^.client^.silencer_shots <> 0) then
is_silenced := MZ_SILENCED
else
is_silenced := 0;
ent^.client^.pers.weapon^.weaponthink (ent);
end;
end;
{*
================
Use_Weapon
Make the weapon ready if there is ammo
================
*}
// (GAME=CTF)
procedure Use_Weapon (ent : edict_p; item : gitem_p);
var
ammo_index : integer;
ammo_item : gitem_p;
begin
// see if we're already using it
if (item = ent^.client^.pers.weapon) then
Exit;
if ( (item^.ammo <> nil) AND (g_select_empty^.Value = 0) 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]) = 0 then
begin
gi.cprintf (ent, PRINT_HIGH, 'No %s for %s.'#10 , 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.'#10 , ammo_item^.pickup_name, item^.pickup_name );
Exit;
end;
end;
// change to this weapon when down
ent^.client^.newweapon := item;
end;
{*
================
Drop_Weapon
================
*}
// (GAME=CTF)
procedure Drop_Weapon (ent : edict_p; item : gitem_p);
var
index : integer;
begin
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -