Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

m_boss31.c (17733B)


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