📄 m_medic.pas
字号:
end;
procedure medic_dead (self:edict_p);
begin
VectorSet (self^.mins, -16, -16, -24);
VectorSet (self^.maxs, 16, 16, -8);
self^.movetype := MOVETYPE_TOSS;
self^.svflags :=self^.svflags or SVF_DEADMONSTER;
self^.nextthink := 0;
gi.linkentity (self);
end;
const
medic_frames_death : Array[0..29] of mframe_t =
((aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil));
medic_move_death : mmove_t =
(firstframe:FRAME_death1; lastframe:FRAME_death30; frame:@medic_frames_death; endfunc:medic_dead);
procedure medic_die (self, inflictor, attacker:edict_p; damage:Integer; const point:vec3_t);
var n : Integer;
begin
// if we had a pending patient, free him up for another medic
if ((self^.enemy<>nil) and (self^.enemy^.owner = self)) then
self^.enemy^.owner := nil;
// check for gib
if (self^.health <= self^.gib_health) then
begin
gi.sound (self, CHAN_VOICE, gi.soundindex ('misc/udeath.wav'), 1, ATTN_NORM, 0);
for n:= 0 to 1 do
ThrowGib (self, 'models/objects/gibs/bone/tris.md2', damage, GIB_ORGANIC);
for n:= 0 to 3 do
ThrowGib (self, 'models/objects/gibs/sm_meat/tris.md2', damage, GIB_ORGANIC);
ThrowHead (self, 'models/objects/gibs/head2/tris.md2', damage, GIB_ORGANIC);
self^.deadflag := DEAD_DEAD;
exit;
end;
if (self^.deadflag = DEAD_DEAD) then
exit;
// regular death
gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
self^.deadflag := DEAD_DEAD;
self^.takedamage := DAMAGE_YES;
self^.monsterinfo.currentmove := @medic_move_death;
end;
procedure medic_duck_down (self:edict_p);
begin
if (self^.monsterinfo.aiflags and AI_DUCKED) <> 0 then
exit;
self^.monsterinfo.aiflags :=self^.monsterinfo.aiflags or AI_DUCKED;
self^.maxs[2] := self^.maxs[2] - 32;
self^.takedamage := DAMAGE_YES;
self^.monsterinfo.pausetime := level.time + 1;
gi.linkentity (self);
end;
procedure medic_duck_hold (self:edict_p);
begin
if (level.time >= self^.monsterinfo.pausetime) then
self^.monsterinfo.aiflags :=self^.monsterinfo.aiflags and ((AI_HOLD_FRAME+1)*(-1))
else
self^.monsterinfo.aiflags :=self^.monsterinfo.aiflags or AI_HOLD_FRAME;
end;
procedure medic_duck_up (self:edict_p);
begin
self^.monsterinfo.aiflags :=self^.monsterinfo.aiflags and ((AI_DUCKED+1) * (-1));
self^.maxs[2] := self^.maxs[2] - 32;
self^.takedamage := DAMAGE_AIM;
gi.linkentity (self);
end;
const
medic_frames_duck : Array[0..15] of mframe_t =
((aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:medic_duck_down),
(aifunc:ai_move; dist:-1; thinkfunc:medic_duck_hold),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:medic_duck_up),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil),
(aifunc:ai_move; dist:-1; thinkfunc:nil));
medic_move_duck : mmove_t =
(firstframe:FRAME_duck1; lastframe:FRAME_duck16; frame:@medic_frames_duck; endfunc:medic_run);
procedure medic_dodge (self , attacker : edict_p;eta : single);
begin
if (_random() > 0.25) then
exit;
if (self^.enemy=nil) then
self^.enemy := attacker;
self^.monsterinfo.currentmove := @medic_move_duck;
end;
const
medic_frames_attackHyperBlaster : Array[0..14] of mframe_t =
((aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_move; dist:0; thinkfunc:medic_fire_blaster));
medic_move_attackHyperBlaster : mmove_t =
(firstframe:FRAME_attack15; lastframe:FRAME_attack30; frame:@medic_frames_attackHyperBlaster; endfunc:medic_run);
procedure medic_continue (self:edict_p);
begin
if (visible (self, self^.enemy) ) then
if (_random() <= 0.95) then
self^.monsterinfo.currentmove := @medic_move_attackHyperBlaster;
end;
const
medic_frames_attackBlaster : Array[0..13] of mframe_t =
((aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_charge; dist:5; thinkfunc:nil),
(aifunc:ai_charge; dist:5; thinkfunc:nil),
(aifunc:ai_charge; dist:3; thinkfunc:nil),
(aifunc:ai_charge; dist:2; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:medic_fire_blaster),
(aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:medic_continue));
medic_move_attackBlaster : mmove_t =
(firstframe:FRAME_attack1; lastframe:FRAME_attack14; frame:@medic_frames_attackBlaster; endfunc:medic_run);
procedure medic_hook_launch (self:edict_p);
begin
gi.sound (self, CHAN_WEAPON, sound_hook_launch, 1, ATTN_NORM, 0);
end;
const
medic_cable_offsets : array[0..9] of vec3_t =
((45.0, -9.2, 15.5),
(48.4, -9.7, 15.2),
(47.8, -9.8, 15.8),
(47.3, -9.3, 14.3),
(45.4, -10.1, 13.1),
(41.9, -12.7, 12.0),
(37.8, -15.8, 11.2),
(34.3, -18.4, 10.7),
(32.7, -19.7, 10.4),
(32.7, -19.7, 10.4));
procedure medic_cable_attack (self:edict_p); cdecl;
var offset, start, _end, f, r : vec3_t;
dir, angles : vec3_t;
tr : trace_t;
distance : Single;
begin
if (not self^.enemy^.inuse) then
exit;
AngleVectors (self^.s.angles, @f, @r, nil);
VectorCopy (medic_cable_offsets[self^.s.frame - FRAME_attack42], offset);
G_ProjectSource (self^.s.origin, offset, f, r, start);
// check for max distance
VectorSubtract (start, self^.enemy^.s.origin, dir);
distance := VectorLength(dir);
if (distance > 256) then
exit;
// check for min/max pitch
vectoangles (dir, angles);
if (angles[0] < -180) then
angles[0] := angles[0] + 360;
if (fabs(angles[0]) > 45) then
exit;
tr := gi.trace (@start, nil, nil, @self^.enemy^.s.origin, self, MASK_SHOT);
if ((tr.fraction <> 1.0) and (tr.ent <> self^.enemy)) then
exit;
if (self^.s.frame = FRAME_attack43) then
begin
gi.sound (self^.enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
self^.enemy^.monsterinfo.aiflags :=self^.enemy^.monsterinfo.aiflags or AI_RESURRECTING;
end
else if (self^.s.frame = FRAME_attack50) then
begin
self^.enemy^.spawnflags := 0;
self^.enemy^.monsterinfo.aiflags := 0;
self^.enemy^.target := nil;
self^.enemy^.targetname := nil;
self^.enemy^.combattarget := nil;
self^.enemy^.deathtarget := nil;
self^.enemy^.owner := self;
ED_CallSpawn (self^.enemy);
self^.enemy^.owner := nil;
if (@self^.enemy^.think <> nil) then
begin
self^.enemy^.nextthink := level.time;
self^.enemy^.think (self^.enemy);
end;
self^.enemy^.monsterinfo.aiflags :=self^.enemy^.monsterinfo.aiflags or AI_RESURRECTING;
if ((self^.oldenemy<>nil) and (self^.oldenemy^.client<>nil)) then
begin
self^.enemy^.enemy := self^.oldenemy;
FoundTarget (self^.enemy);
end;
end
else
begin
if (self^.s.frame = FRAME_attack44) then
gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
end;
// adjust start for beam origin being in middle of a segment
VectorMA (start, 8, f, start);
// adjust end z for end spot since the monster is currently dead
VectorCopy (self^.enemy^.s.origin, _end);
_end[2] := self^.enemy^.absmin[2] + self^.enemy^.size[2] / 2;
gi.WriteByte (svc_temp_entity);
gi.WriteByte (Ord(TE_MEDIC_CABLE_ATTACK));
gi.WriteShort (ShortInt((Cardinal(Self) - Cardinal(g_edicts)) div SizeOf(edict_t)));
gi.WritePosition (start);
gi.WritePosition (_end);
gi.multicast (@self^.s.origin, MULTICAST_PVS);
end;
procedure medic_hook_retract (self:edict_p);
begin
gi.sound (self, CHAN_WEAPON, sound_hook_retract, 1, ATTN_NORM, 0);
self^.enemy^.monsterinfo.aiflags := self^.enemy^.monsterinfo.aiflags and (AI_RESURRECTING+1)*(-1);
end;
const
medic_frames_attackCable : Array[0..27] of mframe_t =
((aifunc:ai_move; dist:2; thinkfunc:nil),
(aifunc:ai_move; dist:3; thinkfunc:nil),
(aifunc:ai_move; dist:5; thinkfunc:nil),
(aifunc:ai_move; dist:4.4; thinkfunc:nil),
(aifunc:ai_charge; dist:4.7; thinkfunc:nil),
(aifunc:ai_charge; dist:5; thinkfunc:nil),
(aifunc:ai_charge; dist:6; thinkfunc:nil),
(aifunc:ai_charge; dist:4; thinkfunc:nil),
(aifunc:ai_charge; dist:0; thinkfunc:nil),
(aifunc:ai_move; dist:0; thinkfunc:medic_hook_launch),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:0; thinkfunc:medic_cable_attack),
(aifunc:ai_move; dist:-15; thinkfunc:medic_hook_retract),
(aifunc:ai_move; dist:-1.5; thinkfunc:nil),
(aifunc:ai_move; dist:-1.2; thinkfunc:nil),
(aifunc:ai_move; dist:-3; thinkfunc:nil),
(aifunc:ai_move; dist:-2; thinkfunc:nil),
(aifunc:ai_move; dist:0.3; thinkfunc:nil),
(aifunc:ai_move; dist:0.7; thinkfunc:nil),
(aifunc:ai_move; dist:1.2; thinkfunc:nil),
(aifunc:ai_move; dist:1.3; thinkfunc:nil));
medic_move_attackCable : mmove_t =
(firstframe:FRAME_attack33; lastframe:FRAME_attack60; frame:@medic_frames_attackCable; endfunc:medic_run);
procedure medic_attack(self:edict_p);
begin
if ((self^.monsterinfo.aiflags and AI_MEDIC) <> 0) then
self^.monsterinfo.currentmove := @medic_move_attackCable
else
self^.monsterinfo.currentmove := @medic_move_attackBlaster;
end;
function medic_checkattack (self:edict_p):qboolean;
begin
if ((self^.monsterinfo.aiflags) and (AI_MEDIC) <> 0) then
begin
medic_attack(self);
Result := True;
Exit;
end;
Result := M_CheckAttack (self);
end;
(* QUAKED monster_medic (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight *)
procedure SP_monster_medic(self:edict_p);
begin
if (deathmatch^.value<>0.0) then
begin
G_FreeEdict (self);
exit;
end;
sound_idle1 := gi.soundindex ('medic/idle.wav');
sound_pain1 := gi.soundindex ('medic/medpain1.wav');
sound_pain2 := gi.soundindex ('medic/medpain2.wav');
sound_die := gi.soundindex ('medic/meddeth1.wav');
sound_sight := gi.soundindex ('medic/medsght1.wav');
sound_search := gi.soundindex ('medic/medsrch1.wav');
sound_hook_launch := gi.soundindex ('medic/medatck2.wav');
sound_hook_hit := gi.soundindex ('medic/medatck3.wav');
sound_hook_heal := gi.soundindex ('medic/medatck4.wav');
sound_hook_retract := gi.soundindex ('medic/medatck5.wav');
gi.soundindex ('medic/medatck1.wav');
self^.movetype := MOVETYPE_STEP;
self^.solid := SOLID_BBOX;
self^.s.modelindex := gi.modelindex ('models/monsters/medic/tris.md2');
VectorSet (self^.mins, -24, -24, -24);
VectorSet (self^.maxs, 24, 24, 32);
self^.health := 300;
self^.gib_health := -130;
self^.mass := 400;
self^.pain := medic_pain;
self^.die := medic_die;
self^.monsterinfo.stand := medic_stand;
self^.monsterinfo.walk := medic_walk;
self^.monsterinfo.run := medic_run;
self^.monsterinfo.dodge := medic_dodge;
self^.monsterinfo.attack := medic_attack;
self^.monsterinfo.melee := nil;
self^.monsterinfo.sight := medic_sight;
self^.monsterinfo.idle := medic_idle;
self^.monsterinfo.search := medic_search;
self^.monsterinfo.checkattack := medic_checkattack;
gi.linkentity (self);
self^.monsterinfo.currentmove := @medic_move_stand;
self^.monsterinfo.scale := MODEL_SCALE;
walkmonster_start (self);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -