📄 m_mutant.pas
字号:
(firstframe: FRAME_run03;
lastframe: FRAME_run08;
frame: @mutant_frames_run[0]);
procedure mutant_run(self: edict_p); cdecl;
begin
if (self.monsterinfo.aiflags AND AI_STAND_GROUND)>0 then
self.monsterinfo.currentmove := @mutant_move_stand
else
self.monsterinfo.currentmove := @mutant_move_run;
end;
//
// MELEE
//
procedure mutant_hit_left(self: edict_p); cdecl;
Var aim: vec3_t;
begin
VectorSet(aim, MELEE_DISTANCE, self.mins[0], 8);
if fire_hit(Self, aim, 10 + (rand() mod 5), 100) then
gi.sound(self, CHAN_WEAPON, sound_hit, 1, ATTN_NORM, 0)
else
gi.sound(self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0);
end;
procedure mutant_hit_right(self: edict_p); cdecl;
Var aim: vec3_t;
begin
VectorSet(aim, MELEE_DISTANCE, self.maxs[0], 8);
if fire_hit(Self, aim, 10 + (rand() mod 5), 100) then
gi.sound (self, CHAN_WEAPON, sound_hit2, 1, ATTN_NORM, 0)
else
gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0);
end;
procedure mutant_check_refire(self: edict_p); cdecl;
begin
if (self.enemy=Nil) or (not self.enemy.inuse) or (self.enemy.health <= 0) then
exit;
if ((skill.value = 3) and (_random() < 0.5)) or (range(self, self.enemy) = RANGE_MELEE) then
self.monsterinfo.nextframe := FRAME_attack09;
end;
const
mutant_frames_attack: Array[0..6] of mframe_t = (
(aifunc: ai_charge; dist: 0),
(aifunc: ai_charge; dist: 0),
(aifunc: ai_charge; dist: 0; thinkfunc: mutant_hit_left),
(aifunc: ai_charge; dist: 0),
(aifunc: ai_charge; dist: 0),
(aifunc: ai_charge; dist: 0; thinkfunc: mutant_hit_right),
(aifunc: ai_charge; dist: 0; thinkfunc: mutant_check_refire)
);
mutant_move_attack: mmove_t =
(firstframe: FRAME_attack09;
lastframe: FRAME_attack15;
frame: @mutant_frames_attack[0];
endfunc: mutant_run);
procedure mutant_melee(self: edict_p); cdecl;
begin
self.monsterinfo.currentmove := @mutant_move_attack;
end;
//
// ATTACK
//
procedure mutant_jump_touch(self, other: edict_p; plane: cplane_p; surf: csurface_p); cdecl;
Var point, normal: vec3_t; damage: Integer;
begin
if self.health <= 0 then begin
self.touch := nil;
exit;
end;
if other.takedamage<>DAMAGE_NO then begin
if VectorLength(self.velocity) > 400 then begin
VectorCopy(self.velocity, normal);
VectorNormalize(normal);
VectorMA(self.s.origin, self.maxs[0], normal, point);
damage := Trunc(40 + 10 * _random());
T_Damage(other, self, self, self.velocity, point, normal, damage, damage, 0, MOD_UNKNOWN);
end;
end;
if not M_CheckBottom(self) then begin
if self.groundentity<>Nil then begin
self.monsterinfo.nextframe := FRAME_attack02;
self.touch := Nil;
end;
exit;
end;
self.touch := Nil;
end;
procedure mutant_jump_takeoff(self: edict_p); cdecl;
Var forwards: vec3_t;
begin
gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
AngleVectors(self.s.angles, @forwards, Nil, Nil);
self.s.origin[2]:= self.s.origin[2] + 1;
VectorScale(forwards, 600, self.velocity);
self.velocity[2] := 250;
self.groundentity := Nil;
self.monsterinfo.aiflags := self.monsterinfo.aiflags OR AI_DUCKED;
self.monsterinfo.attack_finished := level.time + 3;
self.touch := mutant_jump_touch;
end;
procedure mutant_check_landing(self: edict_p); cdecl;
begin
if self.groundentity<>Nil then begin
gi.sound(self, CHAN_WEAPON, sound_thud, 1, ATTN_NORM, 0);
self.monsterinfo.attack_finished := 0;
self.monsterinfo.aiflags := self.monsterinfo.aiflags and (not AI_DUCKED);
exit;
end;
if level.time > self.monsterinfo.attack_finished then
self.monsterinfo.nextframe := FRAME_attack02
else
self.monsterinfo.nextframe := FRAME_attack05;
end;
const
mutant_frames_jump: Array[0..7] of mframe_t = (
(aifunc: ai_charge; dist: 0),
(aifunc: ai_charge; dist: 17),
(aifunc: ai_charge; dist: 15; thinkfunc: mutant_jump_takeoff),
(aifunc: ai_charge; dist: 15),
(aifunc: ai_charge; dist: 15; thinkfunc: mutant_check_landing),
(aifunc: ai_charge; dist: 0),
(aifunc: ai_charge; dist: 3),
(aifunc: ai_charge; dist: 0)
);
mutant_move_jump: mmove_t =
(firstframe: FRAME_attack01;
lastframe: FRAME_attack08;
frame: @mutant_frames_jump[0];
endfunc: mutant_run);
procedure mutant_jump(self: edict_p); cdecl;
begin
self.monsterinfo.currentmove := @mutant_move_jump;
end;
//
// CHECKATTACK
//
function mutant_check_melee(self: edict_p): qboolean;
begin
if range (self, self.enemy) = RANGE_MELEE then begin
Result:=true;
exit;
end;
Result:=false;
end;
function mutant_check_jump(self: edict_p): qboolean;
Var v: vec3_t; distance: Single;
begin
if self.absmin[2] > self.enemy.absmin[2] + 0.75 * self.enemy.size[2] then begin
Result:=False;
exit;
end;
if self.absmax[2] < (self.enemy.absmin[2] + 0.25 * self.enemy.size[2]) then begin
Result:=False;
exit;
end;
v[0] := self.s.origin[0] - self.enemy.s.origin[0];
v[1] := self.s.origin[1] - self.enemy.s.origin[1];
v[2] := 0;
distance := VectorLength(v);
if distance < 100 then begin
Result:=False;
exit;
end;
if distance > 100 then begin
if _random() < 0.9 then begin
Result:=False;
exit;
end;
end;
Result:=true;
end;
function mutant_checkattack(self: edict_p): qboolean; cdecl;
begin
if (self.enemy=Nil) or (self.enemy.health <=0) then begin
Result:= false;
exit;
end;
if mutant_check_melee(self) then begin
self.monsterinfo.attack_state := AS_MELEE;
result:=true;
exit;
end;
if mutant_check_jump(self) then begin
self.monsterinfo.attack_state := AS_MISSILE;
// FIXME play a jump sound here
result:= true;
exit;
end;
Result:=false;
end;
//
// PAIN
//
Const
mutant_frames_pain1: Array[0..4] of mframe_t = (
(aifunc: ai_move; dist: 4),
(aifunc: ai_move; dist: -3),
(aifunc: ai_move; dist: -8),
(aifunc: ai_move; dist: 2),
(aifunc: ai_move; dist: 5)
);
mutant_move_pain1: mmove_t =
(firstframe: FRAME_pain101;
lastframe: FRAME_pain105;
frame: @mutant_frames_pain1[0];
endfunc: mutant_run);
mutant_frames_pain2: Array[0..5] of mframe_t = (
(aifunc: ai_move; dist: -24),
(aifunc: ai_move; dist: 11),
(aifunc: ai_move; dist: 5),
(aifunc: ai_move; dist: -2),
(aifunc: ai_move; dist: 6),
(aifunc: ai_move; dist: 4)
);
mutant_move_pain2: mmove_t =
(firstframe: FRAME_pain201;
lastframe: FRAME_pain206;
frame: @mutant_frames_pain2[0];
endfunc: mutant_run);
mutant_frames_pain3: Array[0..10] of mframe_t = (
(aifunc: ai_move; dist: -22),
(aifunc: ai_move; dist: 3),
(aifunc: ai_move; dist: 3),
(aifunc: ai_move; dist: 2),
(aifunc: ai_move; dist: 1),
(aifunc: ai_move; dist: 1),
(aifunc: ai_move; dist: 6),
(aifunc: ai_move; dist: 3),
(aifunc: ai_move; dist: 2),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 1)
);
mutant_move_pain3: mmove_t =
(firstframe: FRAME_pain301;
lastframe: FRAME_pain311;
frame: @mutant_frames_pain3[0];
endfunc: mutant_run);
procedure mutant_pain(self, other: edict_p; kick: Single; damage: Integer); cdecl;
Var r: Single;
begin
if self.health < self.max_health / 2 then
self.s.skinnum := 1;
if level.time < self.pain_debounce_time then
exit;
self.pain_debounce_time := level.time + 3;
if skill.Value = 3 then
exit; // no pain anims in nightmare
r := _random();
if r < 0.33 then begin
gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
self.monsterinfo.currentmove := @mutant_move_pain1;
end else if r < 0.66 then begin
gi.sound(self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self.monsterinfo.currentmove := @mutant_move_pain2;
end else begin
gi.sound(self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
self.monsterinfo.currentmove := @mutant_move_pain3;
end;
end;
//
// DEATH
//
procedure mutant_dead(self: edict_p); cdecl;
begin
VectorSet(self.mins, -16, -16, -24);
VectorSet(self.maxs, 16, 16, -8);
Integer(self.movetype) := Integer(MOVETYPE_TOSS);
self.svflags := self.svflags OR SVF_DEADMONSTER;
gi.linkentity(self);
M_FlyCheck(self);
end;
const
mutant_frames_death1: Array[0..8] of mframe_t = (
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0)
);
mutant_move_death1: mmove_t = (
firstframe: FRAME_death101;
lastframe: FRAME_death109;
frame: @mutant_frames_death1[0];
endfunc: mutant_dead);
mutant_frames_death2: Array[0..9] of mframe_t = (
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0),
(aifunc: ai_move; dist: 0)
);
mutant_move_death2: mmove_t =
(firstframe: FRAME_death201;
lastframe: FRAME_death210;
frame: @mutant_frames_death2[0];
endfunc: mutant_dead);
procedure mutant_die (self: edict_p; inflictor: edict_p; attacker: edict_p; damage: Integer; const point: vec3_t); cdecl;
Var n: Integer;
begin
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;
gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
self.deadflag := DEAD_DEAD;
self.takedamage := DAMAGE_YES;
self.s.skinnum := 1;
if _random() < 0.5 then
self.monsterinfo.currentmove := @mutant_move_death1
else
self.monsterinfo.currentmove := @mutant_move_death2;
end;
//
// SPAWN
//
(*QUAKED monster_mutant (1 .5 0) (-32 -32 -24) (32 32 32) Ambush Trigger_Spawn Sight
*)
procedure SP_monster_mutant(self: edict_p);
begin
if deathmatch.value<>0 then begin
G_FreeEdict(self);
exit;
end;
sound_swing := gi.soundindex('mutant/mutatck1.wav');
sound_hit := gi.soundindex('mutant/mutatck2.wav');
sound_hit2 := gi.soundindex('mutant/mutatck3.wav');
sound_death := gi.soundindex('mutant/mutdeth1.wav');
sound_idle := gi.soundindex('mutant/mutidle1.wav');
sound_pain1 := gi.soundindex('mutant/mutpain1.wav');
sound_pain2 := gi.soundindex('mutant/mutpain2.wav');
sound_sight := gi.soundindex('mutant/mutsght1.wav');
sound_search := gi.soundindex('mutant/mutsrch1.wav');
sound_step1 := gi.soundindex('mutant/step1.wav');
sound_step2 := gi.soundindex('mutant/step2.wav');
sound_step3 := gi.soundindex('mutant/step3.wav');
sound_thud := gi.soundindex('mutant/thud1.wav');
self.movetype := MOVETYPE_STEP;
self.solid := SOLID_BBOX;
self.s.modelindex := gi.modelindex ('models/monsters/mutant/tris.md2');
VectorSet(self.mins, -32, -32, -24);
VectorSet(self.maxs, 32, 32, 48);
self.health := 300;
self.gib_health := -120;
self.mass := 300;
self.pain := mutant_pain;
self.die := mutant_die;
self.monsterinfo.stand := mutant_stand;
self.monsterinfo.walk := mutant_walk;
self.monsterinfo.run := mutant_run;
self.monsterinfo.dodge := Nil;
self.monsterinfo.attack := mutant_jump;
self.monsterinfo.melee := mutant_melee;
self.monsterinfo.sight := mutant_sight;
self.monsterinfo.search := mutant_search;
self.monsterinfo.idle := mutant_idle;
self.monsterinfo.checkattack := mutant_checkattack;
gi.linkentity(self);
self.monsterinfo.currentmove := @mutant_move_stand;
self.monsterinfo.scale := MODEL_SCALE;
walkmonster_start(self);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -