📄 g_turret.pas
字号:
//100%
{----------------------------------------------------------------------------}
{ }
{ File(s): g_turret.c }
{ }
{ Initial conversion by : Ben Watt (ben@delphigamedev.com) }
{ Initial conversion on : 12-Feb-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-May-22 }
{ Updated by : Scott Price (scott.price@totalise.co.uk) }
{ Corrected pointer dereferences, and some minor conversion }
{ errors such as excluded ~ operator effects on logic }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ }
{----------------------------------------------------------------------------}
{ * TODO: }
{ }
{----------------------------------------------------------------------------}
unit g_turret;
interface
uses
g_local,
q_shared;
procedure AnglesNormalize(var vec : vec3_t);
function SnapToEights(x : single): Single;
procedure turret_blocked(self, other : edict_p); cdecl;
procedure turret_breach_fire(self : edict_p); cdecl;
procedure turret_breach_think(self : edict_p); cdecl;
procedure turret_breach_finish_init(self : edict_p); cdecl;
procedure SP_turret_breach(self : edict_p); cdecl;
procedure SP_turret_base(self : edict_p); cdecl;
procedure turret_driver_die(self, inflictor, attacker : edict_p; damage : integer; const point : vec3_t); cdecl;
procedure turret_driver_think(self : edict_p); cdecl;
procedure turret_driver_link(self : edict_p); cdecl;
procedure SP_turret_driver(self : edict_p); cdecl;
implementation
uses math, g_local_add, g_combat, g_main, g_weapon, CPas, g_utils,
game_add, m_infantry, g_ai, GameUnit, g_monster, g_items;
procedure AnglesNormalize(var vec : vec3_t);
begin
while vec[0] > 360 do
vec[0] := vec[0] - 360;
while vec[0] < 0 do
vec[0] := vec[0] + 360;
while vec[1] > 360 do
vec[1] := vec[1] - 360;
while vec[1] < 0 do
vec[1] := vec[1] + 360;
end;
function SnapToEights(x : single): Single;
begin
x := x*8.0;
if x > 0.0 then
x := x+0.5
else
x := x-0.5;
Result := 0.125 * {TODO:Int}Trunc(x); { TODO: Should this have been left as Int()? }
end;
procedure turret_blocked(self, other : edict_p);
var
attacker : edict_p;
begin
if other^.takedamage <> DAMAGE_NO then
begin
if self^.teammaster^.owner <> nil then
attacker := self^.teammaster^.owner
else
attacker := self^.teammaster;
T_Damage(other, self, attacker, vec3_origin, other^.s.origin, vec3_origin, self^.teammaster^.dmg, 10, 0, MOD_CRUSH);
end;
end;
{QUAKED turret_breach (0 0 0) ?
This portion of the turret can change both pitch and yaw.
The model should be made with a flat pitch.
It (and the associated base) need to be oriented towards 0.
Use "angle" to set the starting angle.
"speed" default 50
"dmg" default 10
"angle" point this forward
"target" point this at an info_notnull at the muzzle tip
"minpitch" min acceptable pitch angle : default -30
"maxpitch" max acceptable pitch angle : default 30
"minyaw" min acceptable yaw angle : default 0
"maxyaw" max acceptable yaw angle : default 360
}
procedure turret_breach_fire(self : edict_p);
var
f, r, u : vec3_t;
start : vec3_t;
damage : integer;
speed : integer;
begin
AngleVectors(self^.s.angles, @f, @r, @u);
VectorMA(self^.s.origin, self^.move_origin[0], f, start);
VectorMA(start, self^.move_origin[1], r, start);
VectorMA(start, self^.move_origin[2], u, start);
damage := 100 + trunc(_random() * 50);
speed := 550 + 50 * trunc(skill^.Value);
fire_rocket(self^.teammaster^.owner, start, f, damage, speed, 150, damage);
gi.positioned_sound(@start, self, CHAN_WEAPON, gi.soundindex('weapons/rocklf1a.wav'), 1, ATTN_NORM, 0);
end;
procedure turret_breach_think(self : edict_p);
var
ent : edict_p;
current_angles : vec3_t;
delta : vec3_t;
dmin, dmax : single;
angle : single;
target_z : single;
diff : single;
target : vec3_t;
dir : vec3_t;
begin
VectorCopy(self^.s.angles, current_angles);
AnglesNormalize(current_angles);
AnglesNormalize(self^.move_angles);
if self^.move_angles[PITCH] > 180 then
self^.move_angles[PITCH] := self^.move_angles[PITCH] - 360;
// clamp angles to mins & maxs
if self^.move_angles[PITCH] > self^.pos1[PITCH] then
self^.move_angles[PITCH] := self^.pos1[PITCH]
else if self^.move_angles[PITCH] < self^.pos2[PITCH] then
self^.move_angles[PITCH] := self^.pos2[PITCH];
if (self^.move_angles[YAW] < self^.pos1[YAW]) or (self^.move_angles[YAW] > self^.pos2[YAW]) then
begin
dmin := fabs(self^.pos1[YAW] - self^.move_angles[YAW]);
if dmin < -180 then
dmin := dmin + 360
else if dmin > 180 then
dmin := dmin - 360;
dmax := fabs(self^.pos2[YAW] - self^.move_angles[YAW]);
if dmax < -180 then
dmax := dmax + 360
else if dmax > 180 then
dmax := dmax - 360;
if fabs(dmin) < fabs(dmax) then
self^.move_angles[YAW] := self^.pos1[YAW]
else
self^.move_angles[YAW] := self^.pos2[YAW];
end;
VectorSubtract(self^.move_angles, current_angles, delta);
if delta[0] < -180 then
delta[0] := delta[0] + 360
else if delta[0] > 180 then
delta[0] := delta[0] - 360;
if delta[1] < -180 then
delta[1] := delta[1] + 360
else if delta[1] > 180 then
delta[1] := delta[1] - 360;
delta[2] := 0;
if delta[0] > (self^.speed * FRAMETIME) then
delta[0] := self^.speed * FRAMETIME;
if delta[0] < (-1 * self^.speed * FRAMETIME) then
delta[0] := -1 * self^.speed * FRAMETIME;
if delta[1] > (self^.speed * FRAMETIME) then
delta[1] := self^.speed * FRAMETIME;
if delta[1] < (-1 * self^.speed * FRAMETIME) then
delta[1] := -1 * self^.speed * FRAMETIME;
VectorScale(delta, 1.0/FRAMETIME, self^.avelocity);
self^.nextthink := level.time + FRAMETIME;
ent := self^.teammaster;
while (ent <> nil) do
begin
ent^.avelocity[1] := self^.avelocity[1];
ent := ent^.teamchain;
end;
// if we have adriver, adjust his velocities
if self^.owner <> nil then
begin
// angular is easy, just copy ours
self^.owner^.avelocity[0] := self^.avelocity[0];
self^.owner^.avelocity[1] := self^.avelocity[1];
// x & y
angle := self^.s.angles[1] + self^.owner^.move_origin[1];
angle := angle * (M_PI*2 / 360);
target[0] := SnapToEights(self^.s.origin[0] + cos(angle) * self^.owner^.move_origin[0]);
target[1] := SnapToEights(self^.s.origin[1] + sin(angle) * self^.owner^.move_origin[0]);
target[2] := self^.owner^.s.origin[2];
VectorSubtract(target, self^.owner^.s.origin, dir);
self^.owner^.velocity[0] := dir[0] * 1.0 / FRAMETIME;
self^.owner^.velocity[1] := dir[1] * 1.0 / FRAMETIME;
// z
angle := self^.s.angles[PITCH] * (M_PI*2 / 360);
target_z := SnapToEights(self^.s.origin[2] + self^.owner^.move_origin[0] * tan(angle) + self^.owner^.move_origin[2]);
diff := target_z - self^.owner^.s.origin[2];
self^.owner^.velocity[2] := diff * 1.0 / FRAMETIME;
if (self^.spawnflags and 65536) <> 0 then
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -