1 /*
2 ==============================================================================
3 
4 jorg
5 
6 ==============================================================================
7 */
8 
9 #include "g_local.h"
10 #include "m_boss31.h"
11 
12 extern SP_monster_makron (edict_t *self);
13 qboolean visible (edict_t *self, edict_t *other);
14 
15 static int	sound_pain1;
16 static int	sound_pain2;
17 static int	sound_pain3;
18 static int	sound_idle;
19 static int	sound_death;
20 static int	sound_search1;
21 static int	sound_search2;
22 static int	sound_search3;
23 static int	sound_attack1;
24 static int	sound_attack2;
25 static int	sound_firegun;
26 static int	sound_step_left;
27 static int	sound_step_right;
28 static int	sound_death_hit;
29 
30 void BossExplode (edict_t *self);
31 void MakronToss (edict_t *self);
32 
33 
jorg_search(edict_t * self)34 void jorg_search (edict_t *self)
35 {
36 	float r;
37 
38 	r = random();
39 
40 	if (r <= 0.3)
41 		gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0);
42 	else if (r <= 0.6)
43 		gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0);
44 	else
45 		gi.sound (self, CHAN_VOICE, sound_search3, 1, ATTN_NORM, 0);
46 }
47 
48 
49 void jorg_dead (edict_t *self);
50 void jorgBFG (edict_t *self);
51 void jorgMachineGun (edict_t *self);
52 void jorg_firebullet (edict_t *self);
53 void jorg_reattack1(edict_t *self);
54 void jorg_attack1(edict_t *self);
55 void jorg_idle(edict_t *self);
56 void jorg_step_left(edict_t *self);
57 void jorg_step_right(edict_t *self);
58 void jorg_death_hit(edict_t *self);
59 
60 //
61 // stand
62 //
63 
64 mframe_t jorg_frames_stand []=
65 {
66 	ai_stand, 0, jorg_idle,
67 	ai_stand, 0, NULL,
68 	ai_stand, 0, NULL,
69 	ai_stand, 0, NULL,
70 	ai_stand, 0, NULL,
71 	ai_stand, 0, NULL,
72 	ai_stand, 0, NULL,
73 	ai_stand, 0, NULL,
74 	ai_stand, 0, NULL,
75 	ai_stand, 0, NULL,		// 10
76 	ai_stand, 0, NULL,
77 	ai_stand, 0, NULL,
78 	ai_stand, 0, NULL,
79 	ai_stand, 0, NULL,
80 	ai_stand, 0, NULL,
81 	ai_stand, 0, NULL,
82 	ai_stand, 0, NULL,
83 	ai_stand, 0, NULL,
84 	ai_stand, 0, NULL,
85 	ai_stand, 0, NULL,		// 20
86 	ai_stand, 0, NULL,
87 	ai_stand, 0, NULL,
88 	ai_stand, 0, NULL,
89 	ai_stand, 0, NULL,
90 	ai_stand, 0, NULL,
91 	ai_stand, 0, NULL,
92 	ai_stand, 0, NULL,
93 	ai_stand, 0, NULL,
94 	ai_stand, 0, NULL,
95 	ai_stand, 0, NULL,		// 30
96 	ai_stand, 0, NULL,
97 	ai_stand, 0, NULL,
98 	ai_stand, 0, NULL,
99 	ai_stand, 19, NULL,
100 	ai_stand, 11, jorg_step_left,
101 	ai_stand, 0, NULL,
102 	ai_stand, 0, NULL,
103 	ai_stand, 6, NULL,
104 	ai_stand, 9, jorg_step_right,
105 	ai_stand, 0, NULL,		// 40
106 	ai_stand, 0, NULL,
107 	ai_stand, 0, NULL,
108 	ai_stand, 0, NULL,
109 	ai_stand, 0, NULL,
110 	ai_stand, 0, NULL,
111 	ai_stand, 0, NULL,
112 	ai_stand, -2, NULL,
113 	ai_stand, -17, jorg_step_left,
114 	ai_stand, 0, NULL,
115 	ai_stand, -12, NULL,		// 50
116 	ai_stand, -14, jorg_step_right	// 51
117 };
118 mmove_t	jorg_move_stand = {FRAME_stand01, FRAME_stand51, jorg_frames_stand, NULL};
119 
jorg_idle(edict_t * self)120 void jorg_idle (edict_t *self)
121 {
122 	gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_NORM,0);
123 }
124 
jorg_death_hit(edict_t * self)125 void jorg_death_hit (edict_t *self)
126 {
127 	gi.sound (self, CHAN_BODY, sound_death_hit, 1, ATTN_NORM,0);
128 }
129 
130 
jorg_step_left(edict_t * self)131 void jorg_step_left (edict_t *self)
132 {
133 	gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0);
134 }
135 
jorg_step_right(edict_t * self)136 void jorg_step_right (edict_t *self)
137 {
138 	gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0);
139 }
140 
141 
jorg_stand(edict_t * self)142 void jorg_stand (edict_t *self)
143 {
144 	self->monsterinfo.currentmove = &jorg_move_stand;
145 }
146 
147 mframe_t jorg_frames_run [] =
148 {
149 	ai_run, 17,	jorg_step_left,
150 	ai_run, 0,	NULL,
151 	ai_run, 0,	NULL,
152 	ai_run, 0,	NULL,
153 	ai_run, 12,	NULL,
154 	ai_run, 8,	NULL,
155 	ai_run, 10,	NULL,
156 	ai_run, 33,	jorg_step_right,
157 	ai_run, 0,	NULL,
158 	ai_run, 0,	NULL,
159 	ai_run, 0,	NULL,
160 	ai_run, 9,	NULL,
161 	ai_run, 9,	NULL,
162 	ai_run, 9,	NULL
163 };
164 mmove_t	jorg_move_run = {FRAME_walk06, FRAME_walk19, jorg_frames_run, NULL};
165 
166 //
167 // walk
168 //
169 
170 mframe_t jorg_frames_start_walk [] =
171 {
172 	ai_walk,	5,	NULL,
173 	ai_walk,	6,	NULL,
174 	ai_walk,	7,	NULL,
175 	ai_walk,	9,	NULL,
176 	ai_walk,	15,	NULL
177 };
178 mmove_t jorg_move_start_walk = {FRAME_walk01, FRAME_walk05, jorg_frames_start_walk, NULL};
179 
180 mframe_t jorg_frames_walk [] =
181 {
182 	ai_walk, 17,	NULL,
183 	ai_walk, 0,	NULL,
184 	ai_walk, 0,	NULL,
185 	ai_walk, 0,	NULL,
186 	ai_walk, 12,	NULL,
187 	ai_walk, 8,	NULL,
188 	ai_walk, 10,	NULL,
189 	ai_walk, 33,	NULL,
190 	ai_walk, 0,	NULL,
191 	ai_walk, 0,	NULL,
192 	ai_walk, 0,	NULL,
193 	ai_walk, 9,	NULL,
194 	ai_walk, 9,	NULL,
195 	ai_walk, 9,	NULL
196 };
197 mmove_t	jorg_move_walk = {FRAME_walk06, FRAME_walk19, jorg_frames_walk, NULL};
198 
199 mframe_t jorg_frames_end_walk [] =
200 {
201 	ai_walk,	11,	NULL,
202 	ai_walk,	0,	NULL,
203 	ai_walk,	0,	NULL,
204 	ai_walk,	0,	NULL,
205 	ai_walk,	8,	NULL,
206 	ai_walk,	-8,	NULL
207 };
208 mmove_t jorg_move_end_walk = {FRAME_walk20, FRAME_walk25, jorg_frames_end_walk, NULL};
209 
jorg_walk(edict_t * self)210 void jorg_walk (edict_t *self)
211 {
212 		self->monsterinfo.currentmove = &jorg_move_walk;
213 }
214 
jorg_run(edict_t * self)215 void jorg_run (edict_t *self)
216 {
217 	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
218 		self->monsterinfo.currentmove = &jorg_move_stand;
219 	else
220 		self->monsterinfo.currentmove = &jorg_move_run;
221 }
222 
223 mframe_t jorg_frames_pain3 [] =
224 {
225 	ai_move,	-28,	NULL,
226 	ai_move,	-6,	NULL,
227 	ai_move,	-3,	jorg_step_left,
228 	ai_move,	-9,	NULL,
229 	ai_move,	0,	jorg_step_right,
230 	ai_move,	0,	NULL,
231 	ai_move,	0,	NULL,
232 	ai_move,	0,	NULL,
233 	ai_move,	-7,	NULL,
234 	ai_move,	1,	NULL,
235 	ai_move,	-11,	NULL,
236 	ai_move,	-4,	NULL,
237 	ai_move,	0,	NULL,
238 	ai_move,	0,	NULL,
239 	ai_move,	10,	NULL,
240 	ai_move,	11,	NULL,
241 	ai_move,	0,	NULL,
242 	ai_move,	10,	NULL,
243 	ai_move,	3,	NULL,
244 	ai_move,	10,	NULL,
245 	ai_move,	7,	jorg_step_left,
246 	ai_move,	17,	NULL,
247 	ai_move,	0,	NULL,
248 	ai_move,	0,	NULL,
249 	ai_move,	0,	jorg_step_right
250 };
251 mmove_t jorg_move_pain3 = {FRAME_pain301, FRAME_pain325, jorg_frames_pain3, jorg_run};
252 
253 mframe_t jorg_frames_pain2 [] =
254 {
255 	ai_move,	0,	NULL,
256 	ai_move,	0,	NULL,
257 	ai_move,	0,	NULL
258 };
259 mmove_t jorg_move_pain2 = {FRAME_pain201, FRAME_pain203, jorg_frames_pain2, jorg_run};
260 
261 mframe_t jorg_frames_pain1 [] =
262 {
263 	ai_move,	0,	NULL,
264 	ai_move,	0,	NULL,
265 	ai_move,	0,	NULL
266 };
267 mmove_t jorg_move_pain1 = {FRAME_pain101, FRAME_pain103, jorg_frames_pain1, jorg_run};
268 
269 mframe_t jorg_frames_death1 [] =
270 {
271 	ai_move,	0,	NULL,
272 	ai_move,	0,	NULL,
273 	ai_move,	0,	NULL,
274 	ai_move,	0,	NULL,
275 	ai_move,	0,	NULL,
276 	ai_move,	0,	NULL,
277 	ai_move,	0,	NULL,
278 	ai_move,	0,	NULL,
279 	ai_move,	0,	NULL,
280 	ai_move,	0,	NULL,		// 10
281 	ai_move,	0,	NULL,
282 	ai_move,	0,	NULL,
283 	ai_move,	0,	NULL,
284 	ai_move,	0,	NULL,
285 	ai_move,	0,	NULL,
286 	ai_move,	0,	NULL,
287 	ai_move,	0,	NULL,
288 	ai_move,	0,	NULL,
289 	ai_move,	0,	NULL,
290 	ai_move,	0,	NULL,		// 20
291 	ai_move,	0,	NULL,
292 	ai_move,	0,	NULL,
293 	ai_move,	0,	NULL,
294 	ai_move,	0,	NULL,
295 	ai_move,	0,	NULL,
296 	ai_move,	0,	NULL,
297 	ai_move,	0,	NULL,
298 	ai_move,	0,	NULL,
299 	ai_move,	0,	NULL,
300 	ai_move,	0,	NULL,		// 30
301 	ai_move,	0,	NULL,
302 	ai_move,	0,	NULL,
303 	ai_move,	0,	NULL,
304 	ai_move,	0,	NULL,
305 	ai_move,	0,	NULL,
306 	ai_move,	0,	NULL,
307 	ai_move,	0,	NULL,
308 	ai_move,	0,	NULL,
309 	ai_move,	0,	NULL,
310 	ai_move,	0,	NULL,		// 40
311 	ai_move,	0,	NULL,
312 	ai_move,	0,	NULL,
313 	ai_move,	0,	NULL,
314 	ai_move,	0,	NULL,
315 	ai_move,	0,	NULL,
316 	ai_move,	0,	NULL,
317 	ai_move,	0,	NULL,
318 	ai_move,	0,	NULL,
319 	ai_move,	0,	MakronToss,
320 	ai_move,	0,	BossExplode		// 50
321 };
322 mmove_t jorg_move_death = {FRAME_death01, FRAME_death50, jorg_frames_death1, jorg_dead};
323 
324 mframe_t jorg_frames_attack2 []=
325 {
326 	ai_charge,	0,	NULL,
327 	ai_charge,	0,	NULL,
328 	ai_charge,	0,	NULL,
329 	ai_charge,	0,	NULL,
330 	ai_charge,	0,	NULL,
331 	ai_charge,	0,	NULL,
332 	ai_charge,	0,	jorgBFG,
333 	ai_move,	0,	NULL,
334 	ai_move,	0,	NULL,
335 	ai_move,	0,	NULL,
336 	ai_move,	0,	NULL,
337 	ai_move,	0,	NULL,
338 	ai_move,	0,	NULL
339 };
340 mmove_t jorg_move_attack2 = {FRAME_attak201, FRAME_attak213, jorg_frames_attack2, jorg_run};
341 
342 mframe_t jorg_frames_start_attack1 [] =
343 {
344 	ai_charge,	0,	NULL,
345 	ai_charge,	0,	NULL,
346 	ai_charge,	0,	NULL,
347 	ai_charge,	0,	NULL,
348 	ai_charge,	0,	NULL,
349 	ai_charge,	0,	NULL,
350 	ai_charge,	0,	NULL,
351 	ai_charge,	0,	NULL
352 };
353 mmove_t jorg_move_start_attack1 = {FRAME_attak101, FRAME_attak108, jorg_frames_start_attack1, jorg_attack1};
354 
355 mframe_t jorg_frames_attack1[]=
356 {
357 	ai_charge,	0,	jorg_firebullet,
358 	ai_charge,	0,	jorg_firebullet,
359 	ai_charge,	0,	jorg_firebullet,
360 	ai_charge,	0,	jorg_firebullet,
361 	ai_charge,	0,	jorg_firebullet,
362 	ai_charge,	0,	jorg_firebullet
363 };
364 mmove_t jorg_move_attack1 = {FRAME_attak109, FRAME_attak114, jorg_frames_attack1, jorg_reattack1};
365 
366 mframe_t jorg_frames_end_attack1[]=
367 {
368 	ai_move,	0,	NULL,
369 	ai_move,	0,	NULL,
370 	ai_move,	0,	NULL,
371 	ai_move,	0,	NULL
372 };
373 mmove_t jorg_move_end_attack1 = {FRAME_attak115, FRAME_attak118, jorg_frames_end_attack1, jorg_run};
374 
jorg_reattack1(edict_t * self)375 void jorg_reattack1(edict_t *self)
376 {
377 	if (visible(self, self->enemy))
378 		if (random() < 0.9)
379 			self->monsterinfo.currentmove = &jorg_move_attack1;
380 		else
381 		{
382 			self->s.sound = 0;
383 			self->monsterinfo.currentmove = &jorg_move_end_attack1;
384 		}
385 	else
386 	{
387 		self->s.sound = 0;
388 		self->monsterinfo.currentmove = &jorg_move_end_attack1;
389 	}
390 }
391 
jorg_attack1(edict_t * self)392 void jorg_attack1(edict_t *self)
393 {
394 	self->monsterinfo.currentmove = &jorg_move_attack1;
395 }
396 
jorg_pain(edict_t * self,edict_t * other,float kick,int damage)397 void jorg_pain (edict_t *self, edict_t *other, float kick, int damage)
398 {
399 
400 	if (self->health < (self->max_health / 2))
401 			self->s.skinnum = 1;
402 
403 	self->s.sound = 0;
404 
405 	if (level.time < self->pain_debounce_time)
406 			return;
407 
408 	// Lessen the chance of him going into his pain frames if he takes little damage
409 	if (damage <= 40)
410 		if (random()<=0.6)
411 			return;
412 
413 	/*
414 	If he's entering his attack1 or using attack1, lessen the chance of him
415 	going into pain
416 	*/
417 
418 	if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak108) )
419 		if (random() <= 0.005)
420 			return;
421 
422 	if ( (self->s.frame >= FRAME_attak109) && (self->s.frame <= FRAME_attak114) )
423 		if (random() <= 0.00005)
424 			return;
425 
426 
427 	if ( (self->s.frame >= FRAME_attak201) && (self->s.frame <= FRAME_attak208) )
428 		if (random() <= 0.005)
429 			return;
430 
431 
432 	self->pain_debounce_time = level.time + 3;
433 	if (skill->value == 3)
434 		return;		// no pain anims in nightmare
435 
436 	if (damage <= 50)
437 	{
438 		gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM,0);
439 		self->monsterinfo.currentmove = &jorg_move_pain1;
440 	}
441 	else if (damage <= 100)
442 	{
443 		gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM,0);
444 		self->monsterinfo.currentmove = &jorg_move_pain2;
445 	}
446 	else
447 	{
448 		if (random() <= 0.3)
449 		{
450 			gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM,0);
451 			self->monsterinfo.currentmove = &jorg_move_pain3;
452 		}
453 	}
454 };
455 
jorgBFG(edict_t * self)456 void jorgBFG (edict_t *self)
457 {
458 	vec3_t	forward, right;
459 	vec3_t	start;
460 	vec3_t	dir;
461 	vec3_t	vec;
462 
463 	AngleVectors (self->s.angles, forward, right, NULL);
464 	G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_BFG_1], forward, right, start);
465 
466 	VectorCopy (self->enemy->s.origin, vec);
467 	vec[2] += self->enemy->viewheight;
468 	VectorSubtract (vec, start, dir);
469 	VectorNormalize (dir);
470 	gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM, 0);
471 	/*void monster_fire_bfg (edict_t *self,
472 							 vec3_t start,
473 							 vec3_t aimdir,
474 							 int damage,
475 							 int speed,
476 							 int kick,
477 							 float damage_radius,
478 							 int flashtype)*/
479 	monster_fire_bfg (self, start, dir, 50, 300, 100, 200, MZ2_JORG_BFG_1);
480 }
481 
jorg_firebullet_right(edict_t * self)482 void jorg_firebullet_right (edict_t *self)
483 {
484 	vec3_t	forward, right, target;
485 	vec3_t	start;
486 
487 	AngleVectors (self->s.angles, forward, right, NULL);
488 	G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_R1], forward, right, start);
489 
490 	VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
491 	target[2] += self->enemy->viewheight;
492 	VectorSubtract (target, start, forward);
493 	VectorNormalize (forward);
494 
495 	monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_R1);
496 }
497 
jorg_firebullet_left(edict_t * self)498 void jorg_firebullet_left (edict_t *self)
499 {
500 	vec3_t	forward, right, target;
501 	vec3_t	start;
502 
503 	AngleVectors (self->s.angles, forward, right, NULL);
504 	G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_L1], forward, right, start);
505 
506 	VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
507 	target[2] += self->enemy->viewheight;
508 	VectorSubtract (target, start, forward);
509 	VectorNormalize (forward);
510 
511 	monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_L1);
512 }
513 
jorg_firebullet(edict_t * self)514 void jorg_firebullet (edict_t *self)
515 {
516 	jorg_firebullet_left(self);
517 	jorg_firebullet_right(self);
518 };
519 
jorg_attack(edict_t * self)520 void jorg_attack(edict_t *self)
521 {
522 	vec3_t	vec;
523 	float	range;
524 
525 	VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
526 	range = VectorLength (vec);
527 
528 	if (random() <= 0.75)
529 	{
530 		gi.sound (self, CHAN_VOICE, sound_attack1, 1, ATTN_NORM,0);
531 		self->s.sound = gi.soundindex ("boss3/w_loop.wav");
532 		self->monsterinfo.currentmove = &jorg_move_start_attack1;
533 	}
534 	else
535 	{
536 		gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM,0);
537 		self->monsterinfo.currentmove = &jorg_move_attack2;
538 	}
539 }
540 
jorg_dead(edict_t * self)541 void jorg_dead (edict_t *self)
542 {
543 #if 0
544 	edict_t	*tempent;
545 	/*
546 	VectorSet (self->mins, -16, -16, -24);
547 	VectorSet (self->maxs, 16, 16, -8);
548 	*/
549 
550 	// Jorg is on modelindex2. Do not clear him.
551 	VectorSet (self->mins, -60, -60, 0);
552 	VectorSet (self->maxs, 60, 60, 72);
553 	self->movetype = MOVETYPE_TOSS;
554 	self->nextthink = 0;
555 	gi.linkentity (self);
556 
557 	tempent = G_Spawn();
558 	VectorCopy (self->s.origin, tempent->s.origin);
559 	VectorCopy (self->s.angles, tempent->s.angles);
560 	tempent->killtarget = self->killtarget;
561 	tempent->target = self->target;
562 	tempent->activator = self->enemy;
563 	self->killtarget = 0;
564 	self->target = 0;
565 	SP_monster_makron (tempent);
566 #endif
567 }
568 
569 
jorg_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)570 void jorg_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
571 {
572 	gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
573 	self->deadflag = DEAD_DEAD;
574 	self->takedamage = DAMAGE_NO;
575 	self->s.sound = 0;
576 	self->count = 0;
577 	self->monsterinfo.currentmove = &jorg_move_death;
578 }
579 
Jorg_CheckAttack(edict_t * self)580 qboolean Jorg_CheckAttack (edict_t *self)
581 {
582 	vec3_t	spot1, spot2;
583 	vec3_t	temp;
584 	float	chance;
585 	trace_t	tr;
586 	qboolean	enemy_infront;
587 	int			enemy_range;
588 	float		enemy_yaw;
589 
590 	if (self->enemy->health > 0)
591 	{
592 	// see if any entities are in the way of the shot
593 		VectorCopy (self->s.origin, spot1);
594 		spot1[2] += self->viewheight;
595 		VectorCopy (self->enemy->s.origin, spot2);
596 		spot2[2] += self->enemy->viewheight;
597 
598 		tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);
599 
600 		// do we have a clear shot?
601 		if (tr.ent != self->enemy)
602 			return false;
603 	}
604 
605 	enemy_infront = infront(self, self->enemy);
606 	enemy_range = range(self, self->enemy);
607 	VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
608 	enemy_yaw = vectoyaw(temp);
609 
610 	self->ideal_yaw = enemy_yaw;
611 
612 
613 	// melee attack
614 	if (enemy_range == RANGE_MELEE)
615 	{
616 		if (self->monsterinfo.melee)
617 			self->monsterinfo.attack_state = AS_MELEE;
618 		else
619 			self->monsterinfo.attack_state = AS_MISSILE;
620 		return true;
621 	}
622 
623 // missile attack
624 	if (!self->monsterinfo.attack)
625 		return false;
626 
627 	if (level.time < self->monsterinfo.attack_finished)
628 		return false;
629 
630 	if (enemy_range == RANGE_FAR)
631 		return false;
632 
633 	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
634 	{
635 		chance = 0.4;
636 	}
637 	else if (enemy_range == RANGE_MELEE)
638 	{
639 		chance = 0.8;
640 	}
641 	else if (enemy_range == RANGE_NEAR)
642 	{
643 		chance = 0.4;
644 	}
645 	else if (enemy_range == RANGE_MID)
646 	{
647 		chance = 0.2;
648 	}
649 	else
650 	{
651 		return false;
652 	}
653 
654 	if (random () < chance)
655 	{
656 		self->monsterinfo.attack_state = AS_MISSILE;
657 		self->monsterinfo.attack_finished = level.time + 2*random();
658 		return true;
659 	}
660 
661 	if (self->flags & FL_FLY)
662 	{
663 		if (random() < 0.3)
664 			self->monsterinfo.attack_state = AS_SLIDING;
665 		else
666 			self->monsterinfo.attack_state = AS_STRAIGHT;
667 	}
668 
669 	return false;
670 }
671 
672 
673 void MakronPrecache (void);
674 
675 /*QUAKED monster_jorg (1 .5 0) (-80 -80 0) (90 90 140) Ambush Trigger_Spawn Sight
676 */
SP_monster_jorg(edict_t * self)677 void SP_monster_jorg (edict_t *self)
678 {
679 	if (deathmatch->value)
680 	{
681 		G_FreeEdict (self);
682 		return;
683 	}
684 
685 	sound_pain1 = gi.soundindex ("boss3/bs3pain1.wav");
686 	sound_pain2 = gi.soundindex ("boss3/bs3pain2.wav");
687 	sound_pain3 = gi.soundindex ("boss3/bs3pain3.wav");
688 	sound_death = gi.soundindex ("boss3/bs3deth1.wav");
689 	sound_attack1 = gi.soundindex ("boss3/bs3atck1.wav");
690 	sound_attack2 = gi.soundindex ("boss3/bs3atck2.wav");
691 	sound_search1 = gi.soundindex ("boss3/bs3srch1.wav");
692 	sound_search2 = gi.soundindex ("boss3/bs3srch2.wav");
693 	sound_search3 = gi.soundindex ("boss3/bs3srch3.wav");
694 	sound_idle = gi.soundindex ("boss3/bs3idle1.wav");
695 	sound_step_left = gi.soundindex ("boss3/step1.wav");
696 	sound_step_right = gi.soundindex ("boss3/step2.wav");
697 	sound_firegun = gi.soundindex ("boss3/xfire.wav");
698 	sound_death_hit = gi.soundindex ("boss3/d_hit.wav");
699 
700 	MakronPrecache ();
701 
702 	self->movetype = MOVETYPE_STEP;
703 	self->solid = SOLID_BBOX;
704 	self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2");
705 	self->s.modelindex2 = gi.modelindex ("models/monsters/boss3/jorg/tris.md2");
706 	VectorSet (self->mins, -80, -80, 0);
707 	VectorSet (self->maxs, 80, 80, 140);
708 
709 	self->health = 3000;
710 	self->gib_health = -2000;
711 	self->mass = 1000;
712 
713 	self->pain = jorg_pain;
714 	self->die = jorg_die;
715 	self->monsterinfo.stand = jorg_stand;
716 	self->monsterinfo.walk = jorg_walk;
717 	self->monsterinfo.run = jorg_run;
718 	self->monsterinfo.dodge = NULL;
719 	self->monsterinfo.attack = jorg_attack;
720 	self->monsterinfo.search = jorg_search;
721 	self->monsterinfo.melee = NULL;
722 	self->monsterinfo.sight = NULL;
723 	self->monsterinfo.checkattack = Jorg_CheckAttack;
724 	gi.linkentity (self);
725 
726 	self->monsterinfo.currentmove = &jorg_move_stand;
727 	self->monsterinfo.scale = MODEL_SCALE;
728 
729 	walkmonster_start(self);
730 	//PMM
731 	self->monsterinfo.aiflags |= AI_IGNORE_SHOTS;
732 	//pmm
733 
734 }
735