1 
2 //**************************************************************************
3 //**
4 //** p_mobj.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile: p_mobj.c,v $
7 //** $Revision: 1.133 $
8 //** $Date: 96/01/12 12:31:43 $
9 //** $Author: bgokey $
10 //**
11 //**************************************************************************
12 
13 // HEADER FILES ------------------------------------------------------------
14 
15 #include "h2def.h"
16 #include "p_local.h"
17 #include "sounds.h"
18 #include "soundst.h"
19 
20 // MACROS ------------------------------------------------------------------
21 
22 #define MAX_TID_COUNT 200
23 
24 // TYPES -------------------------------------------------------------------
25 
26 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
27 
28 void G_PlayerReborn(int player);
29 void P_MarkAsLeaving(mobj_t *corpse);
30 
31 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
32 
33 void P_SpawnMapThing(mapthing_t *mthing);
34 
35 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
36 
37 static void PlayerLandedOnThing(mobj_t *mo, mobj_t *onmobj);
38 
39 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
40 
41 extern mobj_t LavaInflictor;
42 
43 // PUBLIC DATA DEFINITIONS -------------------------------------------------
44 
45 mobjtype_t PuffType;
46 mobj_t *MissileMobj;
47 
48 fixed_t FloatBobOffsets[64] =
49 {
50 	0, 51389, 102283, 152192,
51 	200636, 247147, 291278, 332604,
52 	370727, 405280, 435929, 462380,
53 	484378, 501712, 514213, 521763,
54 	524287, 521763, 514213, 501712,
55 	484378, 462380, 435929, 405280,
56 	370727, 332604, 291278, 247147,
57 	200636, 152192, 102283, 51389,
58 	-1, -51390, -102284, -152193,
59 	-200637, -247148, -291279, -332605,
60 	-370728, -405281, -435930, -462381,
61 	-484380, -501713, -514215, -521764,
62 	-524288, -521764, -514214, -501713,
63 	-484379, -462381, -435930, -405280,
64 	-370728, -332605, -291279, -247148,
65 	-200637, -152193, -102284, -51389
66 };
67 
68 // PRIVATE DATA DEFINITIONS ------------------------------------------------
69 
70 static int TIDList[MAX_TID_COUNT+1]; // +1 for termination marker
71 static mobj_t *TIDMobj[MAX_TID_COUNT];
72 
73 // CODE --------------------------------------------------------------------
74 
75 //==========================================================================
76 //
77 // P_SetMobjState
78 //
79 // Returns true if the mobj is still present.
80 //
81 //==========================================================================
82 
P_SetMobjState(mobj_t * mobj,statenum_t state)83 boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
84 {
85 	state_t *st;
86 
87 	if(state == S_NULL)
88 	{ // Remove mobj
89 		mobj->state = S_NULL;
90 		P_RemoveMobj(mobj);
91 		return(false);
92 	}
93 	st = &states[state];
94 	mobj->state = st;
95 	mobj->tics = st->tics;
96 	mobj->sprite = st->sprite;
97 	mobj->frame = st->frame;
98 	if(st->action)
99 	{ // Call action function
100 		st->action(mobj);
101 	}
102 	return(true);
103 }
104 
105 //==========================================================================
106 //
107 // P_SetMobjStateNF
108 //
109 // Same as P_SetMobjState, but does not call the state function.
110 //
111 //==========================================================================
112 
P_SetMobjStateNF(mobj_t * mobj,statenum_t state)113 boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state)
114 {
115 	state_t *st;
116 
117 	if(state == S_NULL)
118 	{ // Remove mobj
119 		mobj->state = S_NULL;
120 		P_RemoveMobj(mobj);
121 		return(false);
122 	}
123 	st = &states[state];
124 	mobj->state = st;
125 	mobj->tics = st->tics;
126 	mobj->sprite = st->sprite;
127 	mobj->frame = st->frame;
128 	return(true);
129 }
130 
131 //----------------------------------------------------------------------------
132 //
133 // PROC P_ExplodeMissile
134 //
135 //----------------------------------------------------------------------------
136 
P_ExplodeMissile(mobj_t * mo)137 void P_ExplodeMissile(mobj_t *mo)
138 {
139 	mo->momx = mo->momy = mo->momz = 0;
140 	P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
141 	//mo->tics -= P_Random()&3;
142 	mo->flags &= ~MF_MISSILE;
143 
144 	switch(mo->type)
145 	{
146 		case MT_SORCBALL1:
147 		case MT_SORCBALL2:
148 		case MT_SORCBALL3:
149 			S_StartSound(NULL, SFX_SORCERER_BIGBALLEXPLODE);
150 			break;
151 		case MT_SORCFX1:
152 			S_StartSound(NULL, SFX_SORCERER_HEADSCREAM);
153 			break;
154 		default:
155 			if(mo->info->deathsound)
156 			{
157 				S_StartSound(mo, mo->info->deathsound);
158 			}
159 			break;
160 	}
161 }
162 
163 //----------------------------------------------------------------------------
164 //
165 // PROC P_FloorBounceMissile
166 //
167 //----------------------------------------------------------------------------
168 
P_FloorBounceMissile(mobj_t * mo)169 void P_FloorBounceMissile(mobj_t *mo)
170 {
171 	if(P_HitFloor(mo) >= FLOOR_LIQUID)
172 	{
173 		switch(mo->type)
174 		{
175 			case MT_SORCFX1:
176 			case MT_SORCBALL1:
177 			case MT_SORCBALL2:
178 			case MT_SORCBALL3:
179 				break;
180 			default:
181 				P_RemoveMobj(mo);
182 				return;
183 		}
184 	}
185 	switch(mo->type)
186 	{
187 		case MT_SORCFX1:
188 			mo->momz = -mo->momz;		// no energy absorbed
189 			break;
190 		case MT_SGSHARD1:
191 		case MT_SGSHARD2:
192 		case MT_SGSHARD3:
193 		case MT_SGSHARD4:
194 		case MT_SGSHARD5:
195 		case MT_SGSHARD6:
196 		case MT_SGSHARD7:
197 		case MT_SGSHARD8:
198 		case MT_SGSHARD9:
199 		case MT_SGSHARD0:
200 			mo->momz = FixedMul(mo->momz, -0.3*FRACUNIT);
201 			if(abs(mo->momz) < (FRACUNIT/2))
202 			{
203 				P_SetMobjState(mo, S_NULL);
204 				return;
205 			}
206 			break;
207 		default:
208 			mo->momz = FixedMul(mo->momz, -0.7*FRACUNIT);
209 			break;
210 	}
211 	mo->momx = 2*mo->momx/3;
212 	mo->momy = 2*mo->momy/3;
213 	if(mo->info->seesound)
214 	{
215 		switch(mo->type)
216 		{
217 			case MT_SORCBALL1:
218 			case MT_SORCBALL2:
219 			case MT_SORCBALL3:
220 				if (!mo->args[0]) S_StartSound(mo, mo->info->seesound);
221 				break;
222 			default:
223 				S_StartSound(mo, mo->info->seesound);
224 				break;
225 		}
226 		S_StartSound(mo, mo->info->seesound);
227 	}
228 //	P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
229 }
230 
231 //----------------------------------------------------------------------------
232 //
233 // PROC P_ThrustMobj
234 //
235 //----------------------------------------------------------------------------
236 
P_ThrustMobj(mobj_t * mo,angle_t angle,fixed_t move)237 void P_ThrustMobj(mobj_t *mo, angle_t angle, fixed_t move)
238 {
239 	angle >>= ANGLETOFINESHIFT;
240 	mo->momx += FixedMul(move, finecosine[angle]);
241 	mo->momy += FixedMul(move, finesine[angle]);
242 }
243 
244 //----------------------------------------------------------------------------
245 //
246 // FUNC P_FaceMobj
247 //
248 // Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs
249 // to turn counter clockwise.  'delta' is set to the amount 'source'
250 // needs to turn.
251 //
252 //----------------------------------------------------------------------------
253 
P_FaceMobj(mobj_t * source,mobj_t * target,angle_t * delta)254 int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta)
255 {
256 	angle_t diff;
257 	angle_t angle1;
258 	angle_t angle2;
259 
260 	angle1 = source->angle;
261 	angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y);
262 	if(angle2 > angle1)
263 	{
264 		diff = angle2-angle1;
265 		if(diff > ANGLE_180)
266 		{
267 			*delta = ANGLE_MAX-diff;
268 			return(0);
269 		}
270 		else
271 		{
272 			*delta = diff;
273 			return(1);
274 		}
275 	}
276 	else
277 	{
278 		diff = angle1-angle2;
279 		if(diff > ANGLE_180)
280 		{
281 			*delta = ANGLE_MAX-diff;
282 			return(1);
283 		}
284 		else
285 		{
286 			*delta = diff;
287 			return(0);
288 		}
289 	}
290 }
291 
292 //----------------------------------------------------------------------------
293 //
294 //
295 // The missile special1 field must be mobj_t *target.  Returns true if
296 // target was tracked, false if not.
297 //
298 //----------------------------------------------------------------------------
299 
P_SeekerMissile(mobj_t * actor,angle_t thresh,angle_t turnMax)300 boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax)
301 {
302 	int dir;
303 	int dist;
304 	angle_t delta;
305 	angle_t angle;
306 	mobj_t *target;
307 
308 	target = (mobj_t *)actor->special1;
309 	if(target == NULL)
310 	{
311 		return(false);
312 	}
313 	if(!(target->flags&MF_SHOOTABLE))
314 	{ // Target died
315 		actor->special1 = 0;
316 		return(false);
317 	}
318 	dir = P_FaceMobj(actor, target, &delta);
319 	if(delta > thresh)
320 	{
321 		delta >>= 1;
322 		if(delta > turnMax)
323 		{
324 			delta = turnMax;
325 		}
326 	}
327 	if(dir)
328 	{ // Turn clockwise
329 		actor->angle += delta;
330 	}
331 	else
332 	{ // Turn counter clockwise
333 		actor->angle -= delta;
334 	}
335 	angle = actor->angle>>ANGLETOFINESHIFT;
336 	actor->momx = FixedMul(actor->info->speed, finecosine[angle]);
337 	actor->momy = FixedMul(actor->info->speed, finesine[angle]);
338 	if(actor->z+actor->height < target->z
339 		|| target->z+target->height < actor->z)
340 	{ // Need to seek vertically
341 		dist = P_AproxDistance(target->x-actor->x, target->y-actor->y);
342 		dist = dist/actor->info->speed;
343 		if(dist < 1)
344 		{
345 			dist = 1;
346 		}
347 		actor->momz = (target->z+(target->height>>1)
348 			-(actor->z+(actor->height>>1)))/dist;
349 	}
350 	return(true);
351 }
352 
353 //----------------------------------------------------------------------------
354 //
355 // PROC P_XYMovement
356 //
357 //----------------------------------------------------------------------------
358 
359 #define STOPSPEED			0x1000
360 #define FRICTION_NORMAL		0xe800
361 #define FRICTION_LOW		0xf900
362 #define FRICTION_FLY		0xeb00
363 
P_XYMovement(mobj_t * mo)364 void P_XYMovement(mobj_t *mo)
365 {
366 	fixed_t ptryx, ptryy;
367 	player_t *player;
368 	fixed_t xmove, ymove;
369 	int special;
370 	angle_t angle;
371 	static int windTab[3] = {2048*5, 2048*10, 2048*25};
372 
373 	if(!mo->momx && !mo->momy)
374 	{
375 		if(mo->flags&MF_SKULLFLY)
376 		{ // A flying mobj slammed into something
377 			mo->flags &= ~MF_SKULLFLY;
378 			mo->momx = mo->momy = mo->momz = 0;
379 			P_SetMobjState(mo, mo->info->seestate);
380 		}
381 		return;
382 	}
383 	special = mo->subsector->sector->special;
384 	if(mo->flags2&MF2_WINDTHRUST)
385 	{
386 		switch(special)
387 		{
388 			case 40: case 41: case 42: // Wind_East
389 				P_ThrustMobj(mo, 0, windTab[special-40]);
390 				break;
391 			case 43: case 44: case 45: // Wind_North
392 				P_ThrustMobj(mo, ANG90, windTab[special-43]);
393 				break;
394 			case 46: case 47: case 48: // Wind_South
395 				P_ThrustMobj(mo, ANG270, windTab[special-46]);
396 				break;
397 			case 49: case 50: case 51: // Wind_West
398 				P_ThrustMobj(mo, ANG180, windTab[special-49]);
399 				break;
400 		}
401 	}
402 	player = mo->player;
403 	if(mo->momx > MAXMOVE)
404 	{
405 		mo->momx = MAXMOVE;
406 	}
407 	else if(mo->momx < -MAXMOVE)
408 	{
409 		mo->momx = -MAXMOVE;
410 	}
411 	if(mo->momy > MAXMOVE)
412 	{
413 		mo->momy = MAXMOVE;
414 	}
415 	else if(mo->momy < -MAXMOVE)
416 	{
417 		mo->momy = -MAXMOVE;
418 	}
419 	xmove = mo->momx;
420 	ymove = mo->momy;
421 	do
422 	{
423 		if(xmove > MAXMOVE/2 || ymove > MAXMOVE/2)
424 		{
425 			ptryx = mo->x+xmove/2;
426 			ptryy = mo->y+ymove/2;
427 			xmove >>= 1;
428 			ymove >>= 1;
429 		}
430 		else
431 		{
432 			ptryx = mo->x + xmove;
433 			ptryy = mo->y + ymove;
434 			xmove = ymove = 0;
435 		}
436 		if(!P_TryMove(mo, ptryx, ptryy))
437 		{ // Blocked move
438 			if(mo->flags2&MF2_SLIDE)
439 			{ // Try to slide along it
440 				if(BlockingMobj == NULL)
441 				{ // Slide against wall
442 					P_SlideMove(mo);
443 				}
444 				else
445 				{ // Slide against mobj
446 					//if(P_TryMove(mo, mo->x, mo->y+mo->momy))
447 					if(P_TryMove(mo, mo->x, ptryy))
448 					{
449 						mo->momx = 0;
450 					}
451 					//else if(P_TryMove(mo, mo->x+mo->momx, mo->y))
452 					else if(P_TryMove(mo, ptryx, mo->y))
453 					{
454 						mo->momy = 0;
455 					}
456 					else
457 					{
458 						mo->momx = mo->momy = 0;
459 					}
460 				}
461 			}
462 			else if(mo->flags&MF_MISSILE)
463 			{
464 				if(mo->flags2&MF2_FLOORBOUNCE)
465 				{
466 					if(BlockingMobj)
467 					{
468 						if ((BlockingMobj->flags2&MF2_REFLECTIVE) ||
469 							((!BlockingMobj->player) &&
470 							(!(BlockingMobj->flags&MF_COUNTKILL))))
471 						{
472 							fixed_t speed;
473 
474 							angle = R_PointToAngle2(BlockingMobj->x,
475 								BlockingMobj->y, mo->x, mo->y)
476 								+ANGLE_1*((P_Random()%16)-8);
477 							speed = P_AproxDistance(mo->momx, mo->momy);
478 							speed = FixedMul(speed, 0.75*FRACUNIT);
479 							mo->angle = angle;
480 							angle >>= ANGLETOFINESHIFT;
481 							mo->momx = FixedMul(speed, finecosine[angle]);
482 							mo->momy = FixedMul(speed, finesine[angle]);
483 							if(mo->info->seesound)
484 							{
485 								S_StartSound(mo, mo->info->seesound);
486 							}
487 							return;
488 						}
489 						else
490 						{ // Struck a player/creature
491  							P_ExplodeMissile(mo);
492 						}
493 					}
494 					else
495 					{ // Struck a wall
496 						P_BounceWall(mo);
497 						switch(mo->type)
498 						{
499 							case MT_SORCBALL1:
500 							case MT_SORCBALL2:
501 							case MT_SORCBALL3:
502 							case MT_SORCFX1:
503 								break;
504 							default:
505 								if(mo->info->seesound)
506 								{
507 									S_StartSound(mo, mo->info->seesound);
508 								}
509 								break;
510 						}
511 						return;
512 					}
513 				}
514 				if(BlockingMobj &&
515 					(BlockingMobj->flags2 & MF2_REFLECTIVE))
516 				{
517 					angle = R_PointToAngle2(BlockingMobj->x,
518 													BlockingMobj->y,
519 													mo->x, mo->y);
520 
521 					// Change angle for delflection/reflection
522 					switch(BlockingMobj->type)
523 					{
524 						case MT_CENTAUR:
525 						case MT_CENTAURLEADER:
526 							if ( abs(angle-BlockingMobj->angle)>>24 > 45)
527 								goto explode;
528 							if (mo->type == MT_HOLY_FX)
529 								goto explode;
530 								// Drop through to sorcerer full reflection
531 						case MT_SORCBOSS:
532 							// Deflection
533 							if (P_Random()<128)
534 								angle += ANGLE_45;
535 							else
536 								angle -= ANGLE_45;
537 							break;
538 						default:
539 							// Reflection
540 							angle += ANGLE_1 * ((P_Random()%16)-8);
541 							break;
542 					}
543 
544 					// Reflect the missile along angle
545 					mo->angle = angle;
546 					angle >>= ANGLETOFINESHIFT;
547 					mo->momx = FixedMul(mo->info->speed>>1, finecosine[angle]);
548 					mo->momy = FixedMul(mo->info->speed>>1, finesine[angle]);
549 //					mo->momz = -mo->momz;
550 					if (mo->flags2 & MF2_SEEKERMISSILE)
551 					{
552 						mo->special1 = (int)(mo->target);
553 					}
554 					mo->target = BlockingMobj;
555 					return;
556 				}
557 explode:
558 				// Explode a missile
559 				if(ceilingline && ceilingline->backsector
560 					&& ceilingline->backsector->ceilingpic == skyflatnum)
561 				{ // Hack to prevent missiles exploding against the sky
562 					if(mo->type == MT_BLOODYSKULL)
563 					{
564 						mo->momx = mo->momy = 0;
565 						mo->momz = -FRACUNIT;
566 					}
567 					else if(mo->type == MT_HOLY_FX)
568 					{
569 						P_ExplodeMissile(mo);
570 					}
571 					else
572 					{
573 						P_RemoveMobj(mo);
574 					}
575 					return;
576 				}
577 				P_ExplodeMissile(mo);
578 			}
579 			//else if(mo->info->crashstate)
580 			//{
581 			//	mo->momx = mo->momy = 0;
582 			//	P_SetMobjState(mo, mo->info->crashstate);
583 			//	return;
584 			//}
585 			else
586 			{
587 				mo->momx = mo->momy = 0;
588 			}
589 		}
590 	} while(xmove || ymove);
591 
592 	// Friction
593 
594 	if(player && player->cheats&CF_NOMOMENTUM)
595 	{ // Debug option for no sliding at all
596 		mo->momx = mo->momy = 0;
597 		return;
598 	}
599 	if(mo->flags&(MF_MISSILE|MF_SKULLFLY))
600 	{ // No friction for missiles
601 		return;
602 	}
603 	if(mo->z > mo->floorz && !(mo->flags2&MF2_FLY) && !(mo->flags2&MF2_ONMOBJ))
604 	{ // No friction when falling
605 		if (mo->type != MT_BLASTEFFECT)
606 		return;
607 	}
608 	if(mo->flags&MF_CORPSE)
609 	{ // Don't stop sliding if halfway off a step with some momentum
610 		if(mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4
611 			|| mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4)
612 		{
613 			if(mo->floorz != mo->subsector->sector->floorheight)
614 			{
615 				return;
616 			}
617 		}
618 	}
619 	if(mo->momx > -STOPSPEED && mo->momx < STOPSPEED
620 		&& mo->momy > -STOPSPEED && mo->momy < STOPSPEED
621 		&& (!player || (player->cmd.forwardmove == 0
622 		&& player->cmd.sidemove == 0)))
623 	{ // If in a walking frame, stop moving
624 		if(player)
625 		{
626 			if((unsigned)((player->mo->state-states)
627 				-PStateRun[player->class]) < 4)
628 			{
629 				P_SetMobjState(player->mo, PStateNormal[player->class]);
630 			}
631 		}
632 		mo->momx = 0;
633 		mo->momy = 0;
634 	}
635 	else
636 	{
637 		if(mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
638 			&&!(mo->flags2&MF2_ONMOBJ))
639 		{
640 			mo->momx = FixedMul(mo->momx, FRICTION_FLY);
641 			mo->momy = FixedMul(mo->momy, FRICTION_FLY);
642 		}
643 		else if(P_GetThingFloorType(mo) == FLOOR_ICE)
644 		{
645 			mo->momx = FixedMul(mo->momx, FRICTION_LOW);
646 			mo->momy = FixedMul(mo->momy, FRICTION_LOW);
647 		}
648 		else
649 		{
650 			mo->momx = FixedMul(mo->momx, FRICTION_NORMAL);
651 			mo->momy = FixedMul(mo->momy, FRICTION_NORMAL);
652 		}
653 	}
654 }
655 
656 
657 // Move this to p_inter ***
P_MonsterFallingDamage(mobj_t * mo)658 void P_MonsterFallingDamage(mobj_t *mo)
659 {
660 	int damage;
661 	int mom;
662 
663 	mom = abs(mo->momz);
664 	if(mom > 35*FRACUNIT)
665 	{ // automatic death
666 		damage=10000;
667 	}
668 	else
669 	{
670 		damage = ((mom - (23*FRACUNIT) )*6)>>FRACBITS;
671 	}
672 	damage=10000;	// always kill 'em
673 	P_DamageMobj(mo, NULL, NULL, damage);
674 }
675 
676 
677 
678 /*
679 ===============
680 =
681 = P_ZMovement
682 =
683 ===============
684 */
685 
P_ZMovement(mobj_t * mo)686 void P_ZMovement(mobj_t *mo)
687 {
688 	int dist;
689 	int delta;
690 //
691 // check for smooth step up
692 //
693 	if (mo->player && mo->z < mo->floorz)
694 	{
695 		mo->player->viewheight -= mo->floorz-mo->z;
696 		mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3;
697 	}
698 //
699 // adjust height
700 //
701 	mo->z += mo->momz;
702 	if(mo->flags&MF_FLOAT && mo->target)
703 	{	// float down towards target if too close
704 		if(!(mo->flags&MF_SKULLFLY) && !(mo->flags&MF_INFLOAT))
705 		{
706 			dist = P_AproxDistance(mo->x-mo->target->x, mo->y-mo->target->y);
707 			delta =( mo->target->z+(mo->height>>1))-mo->z;
708 			if (delta < 0 && dist < -(delta*3))
709 				mo->z -= FLOATSPEED;
710 			else if (delta > 0 && dist < (delta*3))
711 				mo->z += FLOATSPEED;
712 		}
713 	}
714 	if(mo->player && mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
715 		&& leveltime&2)
716 	{
717 		mo->z += finesine[(FINEANGLES/20*leveltime>>2)&FINEMASK];
718 	}
719 
720 //
721 // clip movement
722 //
723 	if(mo->z <= mo->floorz)
724 	{	// Hit the floor
725 		if(mo->flags&MF_MISSILE)
726 		{
727 			mo->z = mo->floorz;
728 			if(mo->flags2&MF2_FLOORBOUNCE)
729 			{
730 				P_FloorBounceMissile(mo);
731 				return;
732 			}
733 			else if(mo->type == MT_HOLY_FX)
734 			{ // The spirit struck the ground
735 				mo->momz = 0;
736 				P_HitFloor(mo);
737 				return;
738 			}
739 			else if(mo->type == MT_MNTRFX2 || mo->type == MT_LIGHTNING_FLOOR)
740 			{ // Minotaur floor fire can go up steps
741 				return;
742 			}
743 			else
744 			{
745 				P_HitFloor(mo);
746 				P_ExplodeMissile(mo);
747 				return;
748 			}
749 		}
750 		if(mo->flags&MF_COUNTKILL)		// Blasted mobj falling
751 		{
752 			if(mo->momz < -(23*FRACUNIT))
753 			{
754 				P_MonsterFallingDamage(mo);
755 			}
756 		}
757 		if(mo->z-mo->momz > mo->floorz)
758 		{ // Spawn splashes, etc.
759 			P_HitFloor(mo);
760 		}
761 		mo->z = mo->floorz;
762 		if(mo->momz < 0)
763 		{
764 			if(mo->flags2&MF2_ICEDAMAGE && mo->momz < -GRAVITY*8)
765 			{
766 				mo->tics = 1;
767 				mo->momx = 0;
768 				mo->momy = 0;
769 				mo->momz = 0;
770 				return;
771 			}
772 			if(mo->player)
773 			{
774 				mo->player->jumpTics = 7;// delay any jumping for a short time
775 				if(mo->momz < -GRAVITY*8 && !(mo->flags2&MF2_FLY))
776 				{ // squat down
777 					mo->player->deltaviewheight = mo->momz>>3;
778 					if(mo->momz < -23*FRACUNIT)
779 					{
780 						P_FallingDamage(mo->player);
781 						P_NoiseAlert(mo, mo);
782 					}
783 					else if(mo->momz < -GRAVITY*12 && !mo->player->morphTics)
784 					{
785 						S_StartSound(mo, SFX_PLAYER_LAND);
786 						switch(mo->player->class)
787 						{
788 							case PCLASS_FIGHTER:
789 								S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT);
790 								break;
791 							case PCLASS_CLERIC:
792 								S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT);
793 								break;
794 							case PCLASS_MAGE:
795 								S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT);
796 								break;
797 							default:
798 								break;
799 						}
800 					}
801 					else if ((P_GetThingFloorType(mo) < FLOOR_LIQUID) &&
802 						(!mo->player->morphTics))
803 					{
804 						S_StartSound(mo, SFX_PLAYER_LAND);
805 					}
806 #ifdef __WATCOMC__
807 					if(!useexterndriver)
808 					{
809 						mo->player->centering = true;
810 					}
811 #else
812 					mo->player->centering = true;
813 #endif
814 				}
815 			}
816 			else if(mo->type >= MT_POTTERY1
817 				&& mo->type <= MT_POTTERY3)
818 			{
819 				P_DamageMobj(mo, NULL, NULL, 25);
820 			}
821 			else if(mo->flags&MF_COUNTKILL)
822 			{
823 				if(mo->momz < -23*FRACUNIT)
824 				{
825 					// Doesn't get here
826 				}
827 			}
828 			mo->momz = 0;
829 		}
830 		if(mo->flags&MF_SKULLFLY)
831 		{ // The skull slammed into something
832 			mo->momz = -mo->momz;
833 		}
834 		if(mo->info->crashstate &&
835 			(mo->flags&MF_CORPSE) &&
836 			!(mo->flags2&MF2_ICEDAMAGE))
837 		{
838 			P_SetMobjState(mo, mo->info->crashstate);
839 			return;
840 		}
841 	}
842 	else if(mo->flags2&MF2_LOGRAV)
843 	{
844 		if(mo->momz == 0)
845 			mo->momz = -(GRAVITY>>3)*2;
846 		else
847 			mo->momz -= GRAVITY>>3;
848 	}
849 	else if (! (mo->flags & MF_NOGRAVITY) )
850 	{
851 		if (mo->momz == 0)
852 			mo->momz = -GRAVITY*2;
853 		else
854 			mo->momz -= GRAVITY;
855 	}
856 
857 	if (mo->z + mo->height > mo->ceilingz)
858 	{	// hit the ceiling
859 		if (mo->momz > 0)
860 			mo->momz = 0;
861 		mo->z = mo->ceilingz - mo->height;
862 		if(mo->flags2&MF2_FLOORBOUNCE)
863 		{
864 			// Maybe reverse momentum here for ceiling bounce
865 			// Currently won't happen
866 
867 			if(mo->info->seesound)
868 			{
869 				S_StartSound(mo, mo->info->seesound);
870 			}
871 			return;
872 		}
873 		if (mo->flags & MF_SKULLFLY)
874 		{	// the skull slammed into something
875 			mo->momz = -mo->momz;
876 		}
877 		if(mo->flags&MF_MISSILE)
878 		{
879 			if(mo->type == MT_LIGHTNING_CEILING)
880 			{
881 				return;
882 			}
883 			if(mo->subsector->sector->ceilingpic == skyflatnum)
884 			{
885 				if(mo->type == MT_BLOODYSKULL)
886 				{
887 					mo->momx = mo->momy = 0;
888 					mo->momz = -FRACUNIT;
889 				}
890 				else if(mo->type == MT_HOLY_FX)
891 				{
892 					P_ExplodeMissile(mo);
893 				}
894 				else
895 				{
896 					P_RemoveMobj(mo);
897 				}
898 				return;
899 			}
900 			P_ExplodeMissile(mo);
901 			return;
902 		}
903 	}
904 }
905 
906 //----------------------------------------------------------------------------
907 //
908 // PROC P_BlasterMobjThinker
909 //
910 //
911 //----------------------------------------------------------------------------
912 
P_BlasterMobjThinker(mobj_t * mobj)913 void P_BlasterMobjThinker(mobj_t *mobj)
914 {
915 	int i;
916 	fixed_t xfrac;
917 	fixed_t yfrac;
918 	fixed_t zfrac;
919 	fixed_t z;
920 	boolean changexy;
921 	mobj_t *mo;
922 
923 	// Handle movement
924 	if(mobj->momx || mobj->momy ||
925 		(mobj->z != mobj->floorz) || mobj->momz)
926 	{
927 		xfrac = mobj->momx>>3;
928 		yfrac = mobj->momy>>3;
929 		zfrac = mobj->momz>>3;
930 		changexy = xfrac || yfrac;
931 		for(i = 0; i < 8; i++)
932 		{
933 			if(changexy)
934 			{
935 				if(!P_TryMove(mobj, mobj->x+xfrac, mobj->y+yfrac))
936 				{ // Blocked move
937 					P_ExplodeMissile(mobj);
938 					return;
939 				}
940 			}
941 			mobj->z += zfrac;
942 			if(mobj->z <= mobj->floorz)
943 			{ // Hit the floor
944 				mobj->z = mobj->floorz;
945 				P_HitFloor(mobj);
946 				P_ExplodeMissile(mobj);
947 				return;
948 			}
949 			if(mobj->z+mobj->height > mobj->ceilingz)
950 			{ // Hit the ceiling
951 				mobj->z = mobj->ceilingz-mobj->height;
952 				P_ExplodeMissile(mobj);
953 				return;
954 			}
955 			if(changexy)
956 			{
957 				if(mobj->type == MT_MWAND_MISSILE && (P_Random() < 128))
958 				{
959 					z = mobj->z-8*FRACUNIT;
960 					if(z < mobj->floorz)
961 					{
962 						z = mobj->floorz;
963 					}
964 					P_SpawnMobj(mobj->x, mobj->y, z, MT_MWANDSMOKE);
965 				}
966 				else if(!--mobj->special1)
967 				{
968 					mobj->special1 = 4;
969 					z = mobj->z-12*FRACUNIT;
970 					if(z < mobj->floorz)
971 					{
972 						z = mobj->floorz;
973 					}
974 					mo = P_SpawnMobj(mobj->x, mobj->y, z, MT_CFLAMEFLOOR);
975 					if(mo)
976 					{
977 						mo->angle = mobj->angle;
978 					}
979 				}
980 			}
981 		}
982 	}
983 	// Advance the state
984 	if(mobj->tics != -1)
985 	{
986 		mobj->tics--;
987 		while(!mobj->tics)
988 		{
989 			if(!P_SetMobjState(mobj, mobj->state->nextstate))
990 			{ // mobj was removed
991 				return;
992 			}
993 		}
994 	}
995 }
996 
997 //===========================================================================
998 //
999 // PlayerLandedOnThing
1000 //
1001 //===========================================================================
1002 
PlayerLandedOnThing(mobj_t * mo,mobj_t * onmobj)1003 static void PlayerLandedOnThing(mobj_t *mo, mobj_t *onmobj)
1004 {
1005 	mo->player->deltaviewheight = mo->momz>>3;
1006 	if(mo->momz < -23*FRACUNIT)
1007 	{
1008 		P_FallingDamage(mo->player);
1009 		P_NoiseAlert(mo, mo);
1010 	}
1011 	else if(mo->momz < -GRAVITY*12
1012 		&& !mo->player->morphTics)
1013 	{
1014 		S_StartSound(mo, SFX_PLAYER_LAND);
1015 		switch(mo->player->class)
1016 		{
1017 			case PCLASS_FIGHTER:
1018 				S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT);
1019 				break;
1020 			case PCLASS_CLERIC:
1021 				S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT);
1022 				break;
1023 			case PCLASS_MAGE:
1024 				S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT);
1025 				break;
1026 			default:
1027 				break;
1028 		}
1029 	}
1030 	else if(!mo->player->morphTics)
1031 	{
1032 		S_StartSound(mo, SFX_PLAYER_LAND);
1033 	}
1034 #ifdef __WATCOMC__
1035 	if(!useexterndriver)
1036 	{
1037 		mo->player->centering = true;
1038 	}
1039 #else
1040 	mo->player->centering = true;
1041 #endif
1042 }
1043 
1044 //----------------------------------------------------------------------------
1045 //
1046 // PROC P_MobjThinker
1047 //
1048 //----------------------------------------------------------------------------
1049 
P_MobjThinker(mobj_t * mobj)1050 void P_MobjThinker(mobj_t *mobj)
1051 {
1052 	mobj_t *onmo;
1053 /*
1054 	// Reset to not blasted when momentums are gone
1055 	if((mobj->flags2&MF2_BLASTED) && (!(mobj->momx)) && (!(mobj->momy)))
1056 		ResetBlasted(mobj);
1057 */
1058 	// Handle X and Y momentums
1059 	BlockingMobj = NULL;
1060 	if(mobj->momx || mobj->momy || (mobj->flags&MF_SKULLFLY))
1061 	{
1062 		P_XYMovement(mobj);
1063 		if(mobj->thinker.function == (think_t)-1)
1064 		{ // mobj was removed
1065 			return;
1066 		}
1067 	}
1068 	else if(mobj->flags2&MF2_BLASTED)
1069 	{ // Reset to not blasted when momentums are gone
1070 		ResetBlasted(mobj);
1071 	}
1072 	if(mobj->flags2&MF2_FLOATBOB)
1073 	{ // Floating item bobbing motion (special1 is height)
1074 		mobj->z = mobj->floorz +
1075 					mobj->special1 +
1076 					FloatBobOffsets[(mobj->health++)&63];
1077 	}
1078 	else if((mobj->z != mobj->floorz) || mobj->momz || BlockingMobj)
1079 	{	// Handle Z momentum and gravity
1080 		if(mobj->flags2&MF2_PASSMOBJ)
1081 		{
1082 			if(!(onmo = P_CheckOnmobj(mobj)))
1083 			{
1084 				P_ZMovement(mobj);
1085 				if(mobj->player && mobj->flags&MF2_ONMOBJ)
1086 				{
1087 					mobj->flags2 &= ~MF2_ONMOBJ;
1088 				}
1089 			}
1090 			else
1091 			{
1092 				if(mobj->player)
1093 				{
1094 					if(mobj->momz < -GRAVITY*8 && !(mobj->flags2&MF2_FLY))
1095 					{
1096 						PlayerLandedOnThing(mobj, onmo);
1097 					}
1098 					if(onmo->z+onmo->height-mobj->z <= 24*FRACUNIT)
1099 					{
1100 						mobj->player->viewheight -= onmo->z+onmo->height
1101 							-mobj->z;
1102 						mobj->player->deltaviewheight =
1103 							(VIEWHEIGHT-mobj->player->viewheight)>>3;
1104 						mobj->z = onmo->z+onmo->height;
1105 						mobj->flags2 |= MF2_ONMOBJ;
1106 						mobj->momz = 0;
1107 					}
1108 					else
1109 					{ // hit the bottom of the blocking mobj
1110 						mobj->momz = 0;
1111 					}
1112 				}
1113 /* Landing on another player, and mimicking his movements
1114 				if(mobj->player && onmo->player)
1115 				{
1116 					mobj->momx = onmo->momx;
1117 					mobj->momy = onmo->momy;
1118 					if(onmo->z < onmo->floorz)
1119 					{
1120 						mobj->z += onmo->floorz-onmo->z;
1121 						if(onmo->player)
1122 						{
1123 							onmo->player->viewheight -= onmo->floorz-onmo->z;
1124 							onmo->player->deltaviewheight = (VIEWHEIGHT-
1125 								onmo->player->viewheight)>>3;
1126 						}
1127 						onmo->z = onmo->floorz;
1128 					}
1129 				}
1130 */
1131 			}
1132 		}
1133 		else
1134 		{
1135 			P_ZMovement(mobj);
1136 		}
1137 		if(mobj->thinker.function == (think_t)-1)
1138 		{ // mobj was removed
1139 			return;
1140 		}
1141 	}
1142 
1143 	// Cycle through states, calling action functions at transitions
1144 	if(mobj->tics != -1)
1145 	{
1146 		mobj->tics--;
1147 		// you can cycle through multiple states in a tic
1148 		while(!mobj->tics)
1149 		{
1150 			if(!P_SetMobjState(mobj, mobj->state->nextstate))
1151 			{ // mobj was removed
1152 				return;
1153 			}
1154 		}
1155 	}
1156 }
1157 
1158 //==========================================================================
1159 //
1160 // P_SpawnMobj
1161 //
1162 //==========================================================================
1163 
P_SpawnMobj(fixed_t x,fixed_t y,fixed_t z,mobjtype_t type)1164 mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
1165 {
1166 	mobj_t *mobj;
1167 	state_t *st;
1168 	mobjinfo_t *info;
1169 	fixed_t space;
1170 
1171 	mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
1172 	memset(mobj, 0, sizeof(*mobj));
1173 	info = &mobjinfo[type];
1174 	mobj->type = type;
1175 	mobj->info = info;
1176 	mobj->x = x;
1177 	mobj->y = y;
1178 	mobj->radius = info->radius;
1179 	mobj->height = info->height;
1180 	mobj->flags = info->flags;
1181 	mobj->flags2 = info->flags2;
1182 	mobj->damage = info->damage;
1183 	mobj->health = info->spawnhealth;
1184 	if(gameskill != sk_nightmare)
1185 	{
1186 		mobj->reactiontime = info->reactiontime;
1187 	}
1188 	mobj->lastlook = P_Random()%MAXPLAYERS;
1189 
1190 	// Set the state, but do not use P_SetMobjState, because action
1191 	// routines can't be called yet.  If the spawnstate has an action
1192 	// routine, it will not be called.
1193 	st = &states[info->spawnstate];
1194 	mobj->state = st;
1195 	mobj->tics = st->tics;
1196 	mobj->sprite = st->sprite;
1197 	mobj->frame = st->frame;
1198 
1199 	// Set subsector and/or block links.
1200 	P_SetThingPosition(mobj);
1201 	mobj->floorz = mobj->subsector->sector->floorheight;
1202 	mobj->ceilingz = mobj->subsector->sector->ceilingheight;
1203 	if(z == ONFLOORZ)
1204 	{
1205 		mobj->z = mobj->floorz;
1206 	}
1207 	else if(z == ONCEILINGZ)
1208 	{
1209 		mobj->z = mobj->ceilingz-mobj->info->height;
1210 	}
1211 	else if(z == FLOATRANDZ)
1212 	{
1213 		space = ((mobj->ceilingz)-(mobj->info->height))-mobj->floorz;
1214 		if(space > 48*FRACUNIT)
1215 		{
1216 			space -= 40*FRACUNIT;
1217 			mobj->z = ((space*P_Random())>>8)+mobj->floorz+40*FRACUNIT;
1218 		}
1219 		else
1220 		{
1221 			mobj->z = mobj->floorz;
1222 		}
1223 	}
1224 	else if (mobj->flags2&MF2_FLOATBOB)
1225 	{
1226 		mobj->z = mobj->floorz + z;		// artifact z passed in as height
1227 	}
1228 	else
1229 	{
1230 		mobj->z = z;
1231 	}
1232 	if(mobj->flags2&MF2_FLOORCLIP && P_GetThingFloorType(mobj) >= FLOOR_LIQUID
1233 		&& mobj->z == mobj->subsector->sector->floorheight)
1234 	{
1235 		mobj->floorclip = 10*FRACUNIT;
1236 	}
1237 	else
1238 	{
1239 		mobj->floorclip = 0;
1240 	}
1241 
1242 	mobj->thinker.function = P_MobjThinker;
1243 	P_AddThinker(&mobj->thinker);
1244 	return(mobj);
1245 }
1246 
1247 //==========================================================================
1248 //
1249 // P_RemoveMobj
1250 //
1251 //==========================================================================
1252 
P_RemoveMobj(mobj_t * mobj)1253 void P_RemoveMobj(mobj_t *mobj)
1254 {
1255 	// Remove from creature queue
1256 	if(mobj->flags&MF_COUNTKILL &&
1257 		mobj->flags&MF_CORPSE)
1258 	{
1259 		A_DeQueueCorpse(mobj);
1260 	}
1261 
1262 	if(mobj->tid)
1263 	{ // Remove from TID list
1264 		P_RemoveMobjFromTIDList(mobj);
1265 	}
1266 
1267 	// Unlink from sector and block lists
1268 	P_UnsetThingPosition(mobj);
1269 
1270 	// Stop any playing sound
1271 	S_StopSound(mobj);
1272 
1273 	// Free block
1274 	P_RemoveThinker((thinker_t *)mobj);
1275 }
1276 
1277 //==========================================================================
1278 //
1279 // P_SpawnPlayer
1280 //
1281 // Called when a player is spawned on the level.  Most of the player
1282 // structure stays unchanged between levels.
1283 //
1284 //==========================================================================
1285 
P_SpawnPlayer(mapthing_t * mthing)1286 void P_SpawnPlayer(mapthing_t *mthing)
1287 {
1288 	player_t *p;
1289 	fixed_t x, y, z;
1290 	mobj_t *mobj;
1291 
1292 	if(!playeringame[mthing->type-1])
1293 	{ // Not playing
1294 		return;
1295 	}
1296 	p = &players[mthing->type-1];
1297 	if(p->playerstate == PST_REBORN)
1298 	{
1299 		G_PlayerReborn(mthing->type-1);
1300 	}
1301 	x = mthing->x << FRACBITS;
1302 	y = mthing->y << FRACBITS;
1303 	z = ONFLOORZ;
1304 	if(randomclass && deathmatch)
1305 	{
1306 		p->class = P_Random()%3;
1307 		if(p->class == PlayerClass[mthing->type-1])
1308 		{
1309 			p->class = (p->class+1)%3;
1310 		}
1311 		PlayerClass[mthing->type-1] = p->class;
1312 		SB_SetClassData();
1313 	}
1314 	else
1315 	{
1316 		p->class = PlayerClass[mthing->type-1];
1317 	}
1318 	switch(p->class)
1319 	{
1320 		case PCLASS_FIGHTER:
1321 			mobj = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER);
1322 			break;
1323 		case PCLASS_CLERIC:
1324 			mobj = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC);
1325 			break;
1326 		case PCLASS_MAGE:
1327 			mobj = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE);
1328 			break;
1329 		default:
1330 			I_Error("P_SpawnPlayer: Unknown class type");
1331 			break;
1332 	}
1333 
1334 	// Set translation table data
1335 	if(p->class == PCLASS_FIGHTER && (mthing->type == 1 || mthing->type == 3))
1336 	{
1337 		// The first type should be blue, and the third should be the
1338 		// Fighter's original gold color
1339 		if(mthing->type == 1)
1340 		{
1341 			mobj->flags |= 2<<MF_TRANSSHIFT;
1342 		}
1343 	}
1344 	else if(mthing->type > 1)
1345 	{ // Set color translation bits for player sprites
1346 		mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
1347 	}
1348 
1349 	mobj->angle = ANG45 * (mthing->angle/45);
1350 	mobj->player = p;
1351 	mobj->health = p->health;
1352 	p->mo = mobj;
1353 	p->playerstate = PST_LIVE;
1354 	p->refire = 0;
1355 	P_ClearMessage(p);
1356 	p->damagecount = 0;
1357 	p->bonuscount = 0;
1358 	p->poisoncount = 0;
1359 	p->morphTics = 0;
1360 	p->extralight = 0;
1361 	p->fixedcolormap = 0;
1362 	p->viewheight = VIEWHEIGHT;
1363 	P_SetupPsprites(p);
1364 	if(deathmatch)
1365 	{ // Give all keys in death match mode
1366 		p->keys = 2047;
1367 	}
1368 }
1369 
1370 //==========================================================================
1371 //
1372 // P_SpawnMapThing
1373 //
1374 // The fields of the mapthing should already be in host byte order.
1375 //
1376 //==========================================================================
1377 
P_SpawnMapThing(mapthing_t * mthing)1378 void P_SpawnMapThing(mapthing_t *mthing)
1379 {
1380 	int i;
1381 	unsigned int spawnMask;
1382 	mobj_t *mobj;
1383 	fixed_t x, y, z;
1384 	static unsigned int classFlags[] =
1385 	{
1386 		MTF_FIGHTER,
1387 		MTF_CLERIC,
1388 		MTF_MAGE
1389 	};
1390 
1391 	// Count deathmatch start positions
1392 	if(mthing->type == 11)
1393 	{
1394 		if(deathmatch_p < &deathmatchstarts[MAXDEATHMATCHSTARTS])
1395 		{
1396 			memcpy(deathmatch_p, mthing, sizeof(*mthing));
1397 			deathmatch_p++;
1398 		}
1399 		return;
1400 	}
1401 	if(mthing->type == PO_ANCHOR_TYPE)
1402 	{ // Polyobj Anchor Pt.
1403 		return;
1404 	}
1405 	else if(mthing->type == PO_SPAWN_TYPE
1406 		|| mthing->type == PO_SPAWNCRUSH_TYPE)
1407 	{ // Polyobj Anchor Pt.
1408 		po_NumPolyobjs++;
1409 		return;
1410 	}
1411 
1412 	// Check for player starts 1 to 4
1413 	if(mthing->type <= 4)
1414 	{
1415 		playerstarts[mthing->arg1][mthing->type-1] = *mthing;
1416 		if(!deathmatch && !mthing->arg1)
1417 		{
1418 			P_SpawnPlayer(mthing);
1419 		}
1420 		return;
1421 	}
1422 	// Check for player starts 5 to 8
1423 	if(mthing->type >= 9100 && mthing->type <= 9103)
1424 	{
1425 		mthing->type = 5+mthing->type-9100; // Translate to 5 - 8
1426 		playerstarts[mthing->arg1][mthing->type-1] = *mthing;
1427 		if(!deathmatch && !mthing->arg1)
1428 		{
1429 			P_SpawnPlayer(mthing);
1430 		}
1431 		return;
1432 	}
1433 
1434 	if(mthing->type >= 1400 && mthing->type < 1410)
1435 	{
1436 		R_PointInSubsector(mthing->x<<FRACBITS,
1437 			mthing->y<<FRACBITS)->sector->seqType = mthing->type-1400;
1438 		return;
1439 	}
1440 
1441 	// Check current game type with spawn flags
1442 	if(netgame == false)
1443 	{
1444 		spawnMask = MTF_GSINGLE;
1445 	}
1446 	else if(deathmatch)
1447 	{
1448 		spawnMask = MTF_GDEATHMATCH;
1449 	}
1450 	else
1451 	{
1452 		spawnMask = MTF_GCOOP;
1453 	}
1454 	if(!(mthing->options&spawnMask))
1455 	{
1456 		return;
1457 	}
1458 
1459 	// Check current skill with spawn flags
1460 	if(gameskill == sk_baby || gameskill == sk_easy)
1461 	{
1462 		spawnMask = MTF_EASY;
1463 	}
1464 	else if(gameskill == sk_hard || gameskill == sk_nightmare)
1465 	{
1466 		spawnMask = MTF_HARD;
1467 	}
1468 	else
1469 	{
1470 		spawnMask = MTF_NORMAL;
1471 	}
1472 	if(!(mthing->options&spawnMask))
1473 	{
1474 		return;
1475 	}
1476 
1477 	// Check current character classes with spawn flags
1478 	if(netgame == false)
1479 	{ // Single player
1480 		if((mthing->options&classFlags[PlayerClass[0]]) == 0)
1481 		{ // Not for current class
1482 			return;
1483 		}
1484 	}
1485 	else if(deathmatch == false)
1486 	{ // Cooperative
1487 		spawnMask = 0;
1488 		for(i = 0; i < MAXPLAYERS; i++)
1489 		{
1490 			if(playeringame[i])
1491 			{
1492 				spawnMask |= classFlags[PlayerClass[i]];
1493 			}
1494 		}
1495 		if((mthing->options&spawnMask) == 0)
1496 		{
1497 			return;
1498 		}
1499 	}
1500 
1501 	// Find which type to spawn
1502 	for(i = 0; i < NUMMOBJTYPES; i++)
1503 	{
1504 		if(mthing->type == mobjinfo[i].doomednum)
1505 		{
1506 			break;
1507 		}
1508 	}
1509 
1510 	if(i == NUMMOBJTYPES)
1511 	{ // Can't find thing type
1512 		I_Error("P_SpawnMapThing: Unknown type %i at (%i, %i)",
1513 			mthing->type, mthing->x, mthing->y);
1514 	}
1515 
1516 	// Don't spawn keys and players in deathmatch
1517 	if(deathmatch && mobjinfo[i].flags&MF_NOTDMATCH)
1518 	{
1519 		return;
1520 	}
1521 
1522 	// Don't spawn monsters if -nomonsters
1523 	if(nomonsters && (mobjinfo[i].flags&MF_COUNTKILL))
1524 	{
1525 		return;
1526 	}
1527 
1528 	x = mthing->x<<FRACBITS;
1529 	y = mthing->y<<FRACBITS;
1530 	if(mobjinfo[i].flags&MF_SPAWNCEILING)
1531 	{
1532 		z = ONCEILINGZ;
1533 	}
1534 	else if(mobjinfo[i].flags2&MF2_SPAWNFLOAT)
1535 	{
1536 		z = FLOATRANDZ;
1537 	}
1538 	else if(mobjinfo[i].flags2&MF2_FLOATBOB)
1539 	{
1540 		z = mthing->height<<FRACBITS;
1541 	}
1542 	else
1543 	{
1544 		z = ONFLOORZ;
1545 	}
1546 	switch(i)
1547 	{ // Special stuff
1548 		case MT_ZLYNCHED_NOHEART:
1549 			P_SpawnMobj(x, y, ONFLOORZ, MT_BLOODPOOL);
1550 			break;
1551 		default:
1552 			break;
1553 	}
1554 	mobj = P_SpawnMobj(x, y, z, i);
1555 	if(z == ONFLOORZ)
1556 	{
1557 		mobj->z += mthing->height<<FRACBITS;
1558 	}
1559 	else if(z == ONCEILINGZ)
1560 	{
1561 		mobj->z -= mthing->height<<FRACBITS;
1562 	}
1563 	mobj->tid = mthing->tid;
1564 	mobj->special = mthing->special;
1565 	mobj->args[0] = mthing->arg1;
1566 	mobj->args[1] = mthing->arg2;
1567 	mobj->args[2] = mthing->arg3;
1568 	mobj->args[3] = mthing->arg4;
1569 	mobj->args[4] = mthing->arg5;
1570 	if(mobj->flags2&MF2_FLOATBOB)
1571 	{ // Seed random starting index for bobbing motion
1572 		mobj->health = P_Random();
1573 		mobj->special1 = mthing->height<<FRACBITS;
1574 	}
1575 	if(mobj->tics > 0)
1576 	{
1577 		mobj->tics = 1+(P_Random()%mobj->tics);
1578 	}
1579 //	if(mobj->flags&MF_COUNTITEM)
1580 //	{
1581 //		totalitems++;
1582 //	}
1583 	if (mobj->flags&MF_COUNTKILL)
1584 	{
1585 		// Quantize angle to 45 degree increments
1586 		mobj->angle = ANG45*(mthing->angle/45);
1587 	}
1588 	else
1589 	{
1590 		// Scale angle correctly (source is 0..359)
1591 		mobj->angle = ((mthing->angle<<8)/360)<<24;
1592 	}
1593 	if(mthing->options&MTF_AMBUSH)
1594 	{
1595 		mobj->flags |= MF_AMBUSH;
1596 	}
1597 	if(mthing->options&MTF_DORMANT)
1598 	{
1599 		mobj->flags2 |= MF2_DORMANT;
1600 		if(mobj->type == MT_ICEGUY)
1601 		{
1602 			P_SetMobjState(mobj, S_ICEGUY_DORMANT);
1603 		}
1604 		mobj->tics = -1;
1605 	}
1606 }
1607 
1608 //==========================================================================
1609 //
1610 // P_CreateTIDList
1611 //
1612 //==========================================================================
1613 
P_CreateTIDList(void)1614 void P_CreateTIDList(void)
1615 {
1616 	int i;
1617 	mobj_t *mobj;
1618 	thinker_t *t;
1619 
1620 	i = 0;
1621 	for(t = thinkercap.next; t != &thinkercap; t = t->next)
1622 	{ // Search all current thinkers
1623 		if(t->function != P_MobjThinker)
1624 		{ // Not a mobj thinker
1625 			continue;
1626 		}
1627 		mobj = (mobj_t *)t;
1628 		if(mobj->tid != 0)
1629 		{ // Add to list
1630 			if(i == MAX_TID_COUNT)
1631 			{
1632 				I_Error("P_CreateTIDList: MAX_TID_COUNT (%d) exceeded.",
1633 					MAX_TID_COUNT);
1634 			}
1635 			TIDList[i] = mobj->tid;
1636 			TIDMobj[i++] = mobj;
1637 		}
1638 	}
1639 	// Add termination marker
1640 	TIDList[i] = 0;
1641 }
1642 
1643 //==========================================================================
1644 //
1645 // P_InsertMobjIntoTIDList
1646 //
1647 //==========================================================================
1648 
P_InsertMobjIntoTIDList(mobj_t * mobj,int tid)1649 void P_InsertMobjIntoTIDList(mobj_t *mobj, int tid)
1650 {
1651 	int i;
1652 	int index;
1653 
1654 	index = -1;
1655 	for(i = 0; TIDList[i] != 0; i++)
1656 	{
1657 		if(TIDList[i] == -1)
1658 		{ // Found empty slot
1659 			index = i;
1660 			break;
1661 		}
1662 	}
1663 	if(index == -1)
1664 	{ // Append required
1665 		if(i == MAX_TID_COUNT)
1666 		{
1667 			I_Error("P_InsertMobjIntoTIDList: MAX_TID_COUNT (%d)"
1668 				"exceeded.", MAX_TID_COUNT);
1669 		}
1670 		index = i;
1671 		TIDList[index+1] = 0;
1672 	}
1673 	mobj->tid = tid;
1674 	TIDList[index] = tid;
1675 	TIDMobj[index] = mobj;
1676 }
1677 
1678 //==========================================================================
1679 //
1680 // P_RemoveMobjFromTIDList
1681 //
1682 //==========================================================================
1683 
P_RemoveMobjFromTIDList(mobj_t * mobj)1684 void P_RemoveMobjFromTIDList(mobj_t *mobj)
1685 {
1686 	int i;
1687 
1688 	for(i = 0; TIDList[i] != 0; i++)
1689 	{
1690 		if(TIDMobj[i] == mobj)
1691 		{
1692 			TIDList[i] = -1;
1693 			TIDMobj[i] = NULL;
1694 			mobj->tid = 0;
1695 			return;
1696 		}
1697 	}
1698 	mobj->tid = 0;
1699 }
1700 
1701 //==========================================================================
1702 //
1703 // P_FindMobjFromTID
1704 //
1705 //==========================================================================
1706 
P_FindMobjFromTID(int tid,int * searchPosition)1707 mobj_t *P_FindMobjFromTID(int tid, int *searchPosition)
1708 {
1709 	int i;
1710 
1711 	for(i = *searchPosition+1; TIDList[i] != 0; i++)
1712 	{
1713 		if(TIDList[i] == tid)
1714 		{
1715 			*searchPosition = i;
1716 			return TIDMobj[i];
1717 		}
1718 	}
1719 	*searchPosition = -1;
1720 	return NULL;
1721 }
1722 
1723 /*
1724 ===============================================================================
1725 
1726 						GAME SPAWN FUNCTIONS
1727 
1728 ===============================================================================
1729 */
1730 
1731 //---------------------------------------------------------------------------
1732 //
1733 // PROC P_SpawnPuff
1734 //
1735 //---------------------------------------------------------------------------
1736 
1737 extern fixed_t attackrange;
1738 
P_SpawnPuff(fixed_t x,fixed_t y,fixed_t z)1739 void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
1740 {
1741 	mobj_t *puff;
1742 
1743 	z += ((P_Random()-P_Random())<<10);
1744 	puff = P_SpawnMobj(x, y, z, PuffType);
1745 	if(linetarget && puff->info->seesound)
1746 	{ // Hit thing sound
1747 		S_StartSound(puff, puff->info->seesound);
1748 	}
1749 	else if(puff->info->attacksound)
1750 	{
1751 		S_StartSound(puff, puff->info->attacksound);
1752 	}
1753 	switch(PuffType)
1754 	{
1755 		case MT_PUNCHPUFF:
1756 			puff->momz = FRACUNIT;
1757 			break;
1758 		case MT_HAMMERPUFF:
1759 			puff->momz = .8*FRACUNIT;
1760 			break;
1761 		default:
1762 			break;
1763 	}
1764 	PuffSpawned = puff;
1765 }
1766 
1767 /*
1768 ================
1769 =
1770 = P_SpawnBlood
1771 =
1772 ================
1773 */
1774 
1775 /*
1776 void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
1777 {
1778 	mobj_t	*th;
1779 
1780 	z += ((P_Random()-P_Random())<<10);
1781 	th = P_SpawnMobj (x,y,z, MT_BLOOD);
1782 	th->momz = FRACUNIT*2;
1783 	th->tics -= P_Random()&3;
1784 
1785 	if (damage <= 12 && damage >= 9)
1786 		P_SetMobjState (th,S_BLOOD2);
1787 	else if (damage < 9)
1788 		P_SetMobjState (th,S_BLOOD3);
1789 }
1790 */
1791 
1792 //---------------------------------------------------------------------------
1793 //
1794 // PROC P_BloodSplatter
1795 //
1796 //---------------------------------------------------------------------------
1797 
P_BloodSplatter(fixed_t x,fixed_t y,fixed_t z,mobj_t * originator)1798 void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
1799 {
1800 	mobj_t *mo;
1801 
1802 	mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER);
1803 	mo->target = originator;
1804 	mo->momx = (P_Random()-P_Random())<<10;
1805 	mo->momy = (P_Random()-P_Random())<<10;
1806 	mo->momz = 3*FRACUNIT;
1807 }
1808 
1809 //===========================================================================
1810 //
1811 //  P_BloodSplatter2
1812 //
1813 //===========================================================================
1814 
P_BloodSplatter2(fixed_t x,fixed_t y,fixed_t z,mobj_t * originator)1815 void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
1816 {
1817 	mobj_t *mo;
1818 
1819 	mo = P_SpawnMobj(x+((P_Random()-128)<<11), y+((P_Random()-128)<<11), z,
1820 		MT_AXEBLOOD);
1821 	mo->target = originator;
1822 }
1823 
1824 //---------------------------------------------------------------------------
1825 //
1826 // PROC P_RipperBlood
1827 //
1828 //---------------------------------------------------------------------------
1829 
P_RipperBlood(mobj_t * mo)1830 void P_RipperBlood(mobj_t *mo)
1831 {
1832 	mobj_t *th;
1833 	fixed_t x, y, z;
1834 
1835 	x = mo->x+((P_Random()-P_Random())<<12);
1836 	y = mo->y+((P_Random()-P_Random())<<12);
1837 	z = mo->z+((P_Random()-P_Random())<<12);
1838 	th = P_SpawnMobj(x, y, z, MT_BLOOD);
1839 //	th->flags |= MF_NOGRAVITY;
1840 	th->momx = mo->momx>>1;
1841 	th->momy = mo->momy>>1;
1842 	th->tics += P_Random()&3;
1843 }
1844 
1845 //---------------------------------------------------------------------------
1846 //
1847 // FUNC P_GetThingFloorType
1848 //
1849 //---------------------------------------------------------------------------
1850 
P_GetThingFloorType(mobj_t * thing)1851 int P_GetThingFloorType(mobj_t *thing)
1852 {
1853 	if(thing->floorpic)
1854 	{
1855 		return(TerrainTypes[thing->floorpic]);
1856 	}
1857 	else
1858 	{
1859 		return(TerrainTypes[thing->subsector->sector->floorpic]);
1860 	}
1861 /*
1862 	if(thing->subsector->sector->floorpic
1863 		== W_GetNumForName("FLTWAWA1")-firstflat)
1864 	{
1865 		return(FLOOR_WATER);
1866 	}
1867 	else
1868 	{
1869 		return(FLOOR_SOLID);
1870 	}
1871 */
1872 }
1873 
1874 //---------------------------------------------------------------------------
1875 //
1876 // FUNC P_HitFloor
1877 //
1878 //---------------------------------------------------------------------------
1879 #define SMALLSPLASHCLIP 12<<FRACBITS;
1880 
P_HitFloor(mobj_t * thing)1881 int P_HitFloor(mobj_t *thing)
1882 {
1883 	mobj_t *mo;
1884 	int smallsplash=false;
1885 
1886 	if(thing->floorz != thing->subsector->sector->floorheight)
1887 	{ // don't splash if landing on the edge above water/lava/etc....
1888 		return(FLOOR_SOLID);
1889 	}
1890 
1891 	// Things that don't splash go here
1892 	switch(thing->type)
1893 	{
1894 		case MT_LEAF1:
1895 		case MT_LEAF2:
1896 //		case MT_BLOOD:			// I set these to low mass -- pm
1897 //		case MT_BLOODSPLATTER:
1898 		case MT_SPLASH:
1899 		case MT_SLUDGECHUNK:
1900 			return(FLOOR_SOLID);
1901 		default:
1902 			break;
1903 	}
1904 
1905 	// Small splash for small masses
1906 	if (thing->info->mass < 10) smallsplash = true;
1907 
1908 	switch(P_GetThingFloorType(thing))
1909 	{
1910 		case FLOOR_WATER:
1911 			if (smallsplash)
1912 			{
1913 				mo=P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
1914 				if (mo) mo->floorclip += SMALLSPLASHCLIP;
1915 				S_StartSound(mo, SFX_AMBIENT10);	// small drip
1916 			}
1917 			else
1918 			{
1919 				mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH);
1920 				mo->target = thing;
1921 				mo->momx = (P_Random()-P_Random())<<8;
1922 				mo->momy = (P_Random()-P_Random())<<8;
1923 				mo->momz = 2*FRACUNIT+(P_Random()<<8);
1924 				mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
1925 				if (thing->player) P_NoiseAlert(thing, thing);
1926 				S_StartSound(mo, SFX_WATER_SPLASH);
1927 			}
1928 			return(FLOOR_WATER);
1929 		case FLOOR_LAVA:
1930 			if (smallsplash)
1931 			{
1932 				mo=P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
1933 				if (mo) mo->floorclip += SMALLSPLASHCLIP;
1934 			}
1935 			else
1936 			{
1937 				mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE);
1938 				mo->momz = FRACUNIT+(P_Random()<<7);
1939 				mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
1940 				if (thing->player) P_NoiseAlert(thing, thing);
1941 			}
1942 			S_StartSound(mo, SFX_LAVA_SIZZLE);
1943 			if(thing->player && leveltime&31)
1944 			{
1945 				P_DamageMobj(thing, &LavaInflictor, NULL, 5);
1946 			}
1947 			return(FLOOR_LAVA);
1948 		case FLOOR_SLUDGE:
1949 			if (smallsplash)
1950 			{
1951 				mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
1952 					MT_SLUDGESPLASH);
1953 				if (mo) mo->floorclip += SMALLSPLASHCLIP;
1954 			}
1955 			else
1956 			{
1957 				mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK);
1958 				mo->target = thing;
1959 				mo->momx = (P_Random()-P_Random())<<8;
1960 				mo->momy = (P_Random()-P_Random())<<8;
1961 				mo->momz = FRACUNIT+(P_Random()<<8);
1962 				mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
1963 					MT_SLUDGESPLASH);
1964 				if (thing->player) P_NoiseAlert(thing, thing);
1965 			}
1966 			S_StartSound(mo, SFX_SLUDGE_GLOOP);
1967 			return(FLOOR_SLUDGE);
1968 	}
1969 	return(FLOOR_SOLID);
1970 }
1971 
1972 
1973 //---------------------------------------------------------------------------
1974 //
1975 // FUNC P_CheckMissileSpawn
1976 //
1977 // Returns true if the missile is at a valid spawn point, otherwise
1978 // explodes it and returns false.
1979 //
1980 //---------------------------------------------------------------------------
1981 
P_CheckMissileSpawn(mobj_t * missile)1982 boolean P_CheckMissileSpawn(mobj_t *missile)
1983 {
1984 	//missile->tics -= P_Random()&3;
1985 
1986 	// move a little forward so an angle can be computed if it
1987 	// immediately explodes
1988 	missile->x += (missile->momx>>1);
1989 	missile->y += (missile->momy>>1);
1990 	missile->z += (missile->momz>>1);
1991 	if(!P_TryMove(missile, missile->x, missile->y))
1992 	{
1993 		P_ExplodeMissile(missile);
1994 		return(false);
1995 	}
1996 	return(true);
1997 }
1998 
1999 //---------------------------------------------------------------------------
2000 //
2001 // FUNC P_SpawnMissile
2002 //
2003 // Returns NULL if the missile exploded immediately, otherwise returns
2004 // a mobj_t pointer to the missile.
2005 //
2006 //---------------------------------------------------------------------------
2007 
P_SpawnMissile(mobj_t * source,mobj_t * dest,mobjtype_t type)2008 mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
2009 {
2010 	fixed_t z;
2011 	mobj_t *th;
2012 	angle_t an;
2013 	int dist;
2014 
2015 	switch(type)
2016 	{
2017 		case MT_MNTRFX1: // Minotaur swing attack missile
2018 			z = source->z+40*FRACUNIT;
2019 			break;
2020 		case MT_MNTRFX2: // Minotaur floor fire missile
2021 			z = ONFLOORZ+source->floorclip;
2022 			break;
2023 		case MT_CENTAUR_FX:
2024 			z = source->z+45*FRACUNIT;
2025 			break;
2026 		case MT_ICEGUY_FX:
2027 			z = source->z+40*FRACUNIT;
2028 			break;
2029 		case MT_HOLY_MISSILE:
2030 			z = source->z+40*FRACUNIT;
2031 			break;
2032 		default:
2033 			z = source->z+32*FRACUNIT;
2034 			break;
2035 	}
2036 	z -= source->floorclip;
2037 	th = P_SpawnMobj(source->x, source->y, z, type);
2038 	if(th->info->seesound)
2039 	{
2040 		S_StartSound(th, th->info->seesound);
2041 	}
2042 	th->target = source; // Originator
2043 	an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
2044 	if(dest->flags&MF_SHADOW)
2045 	{ // Invisible target
2046 		an += (P_Random()-P_Random())<<21;
2047 	}
2048 	th->angle = an;
2049 	an >>= ANGLETOFINESHIFT;
2050 	th->momx = FixedMul(th->info->speed, finecosine[an]);
2051 	th->momy = FixedMul(th->info->speed, finesine[an]);
2052 	dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
2053 	dist = dist/th->info->speed;
2054 	if(dist < 1)
2055 	{
2056 		dist = 1;
2057 	}
2058 	th->momz = (dest->z-source->z)/dist;
2059 	return(P_CheckMissileSpawn(th) ? th : NULL);
2060 }
2061 
2062 //---------------------------------------------------------------------------
2063 //
2064 // FUNC P_SpawnMissileXYZ
2065 //
2066 // Returns NULL if the missile exploded immediately, otherwise returns
2067 // a mobj_t pointer to the missile.
2068 //
2069 //---------------------------------------------------------------------------
2070 
P_SpawnMissileXYZ(fixed_t x,fixed_t y,fixed_t z,mobj_t * source,mobj_t * dest,mobjtype_t type)2071 mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z,
2072 	mobj_t *source, mobj_t *dest, mobjtype_t type)
2073 {
2074 	mobj_t *th;
2075 	angle_t an;
2076 	int dist;
2077 
2078 	z -= source->floorclip;
2079 	th = P_SpawnMobj(x, y, z, type);
2080 	if(th->info->seesound)
2081 	{
2082 		S_StartSound(th, th->info->seesound);
2083 	}
2084 	th->target = source; // Originator
2085 	an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
2086 	if(dest->flags&MF_SHADOW)
2087 	{ // Invisible target
2088 		an += (P_Random()-P_Random())<<21;
2089 	}
2090 	th->angle = an;
2091 	an >>= ANGLETOFINESHIFT;
2092 	th->momx = FixedMul(th->info->speed, finecosine[an]);
2093 	th->momy = FixedMul(th->info->speed, finesine[an]);
2094 	dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
2095 	dist = dist/th->info->speed;
2096 	if(dist < 1)
2097 	{
2098 		dist = 1;
2099 	}
2100 	th->momz = (dest->z-source->z)/dist;
2101 	return(P_CheckMissileSpawn(th) ? th : NULL);
2102 }
2103 
2104 //---------------------------------------------------------------------------
2105 //
2106 // FUNC P_SpawnMissileAngle
2107 //
2108 // Returns NULL if the missile exploded immediately, otherwise returns
2109 // a mobj_t pointer to the missile.
2110 //
2111 //---------------------------------------------------------------------------
2112 
P_SpawnMissileAngle(mobj_t * source,mobjtype_t type,angle_t angle,fixed_t momz)2113 mobj_t *P_SpawnMissileAngle(mobj_t *source, mobjtype_t type,
2114 	angle_t angle, fixed_t momz)
2115 {
2116 	fixed_t z;
2117 	mobj_t *mo;
2118 
2119 	switch(type)
2120 	{
2121 		case MT_MNTRFX1: // Minotaur swing attack missile
2122 			z = source->z+40*FRACUNIT;
2123 			break;
2124 		case MT_MNTRFX2: // Minotaur floor fire missile
2125 			z = ONFLOORZ+source->floorclip;
2126 			break;
2127 		case MT_ICEGUY_FX2: // Secondary Projectiles of the Ice Guy
2128 			z = source->z+3*FRACUNIT;
2129 			break;
2130 		case MT_MSTAFF_FX2:
2131 			z = source->z+40*FRACUNIT;
2132 			break;
2133 		default:
2134 			z = source->z+32*FRACUNIT;
2135 			break;
2136 	}
2137 	z -= source->floorclip;
2138 	mo = P_SpawnMobj(source->x, source->y, z, type);
2139 	if(mo->info->seesound)
2140 	{
2141 		S_StartSound(mo, mo->info->seesound);
2142 	}
2143 	mo->target = source; // Originator
2144 	mo->angle = angle;
2145 	angle >>= ANGLETOFINESHIFT;
2146 	mo->momx = FixedMul(mo->info->speed, finecosine[angle]);
2147 	mo->momy = FixedMul(mo->info->speed, finesine[angle]);
2148 	mo->momz = momz;
2149 	return(P_CheckMissileSpawn(mo) ? mo : NULL);
2150 }
2151 
2152 //---------------------------------------------------------------------------
2153 //
2154 // FUNC P_SpawnMissileAngleSpeed
2155 //
2156 // Returns NULL if the missile exploded immediately, otherwise returns
2157 // a mobj_t pointer to the missile.
2158 //
2159 //---------------------------------------------------------------------------
2160 
P_SpawnMissileAngleSpeed(mobj_t * source,mobjtype_t type,angle_t angle,fixed_t momz,fixed_t speed)2161 mobj_t *P_SpawnMissileAngleSpeed(mobj_t *source, mobjtype_t type,
2162 	angle_t angle, fixed_t momz, fixed_t speed)
2163 {
2164 	fixed_t z;
2165 	mobj_t *mo;
2166 
2167 	z = source->z;
2168 	z -= source->floorclip;
2169 	mo = P_SpawnMobj(source->x, source->y, z, type);
2170 	if(mo->info->seesound)
2171 	{
2172 		//S_StartSound(mo, mo->info->seesound);
2173 	}
2174 	mo->target = source; // Originator
2175 	mo->angle = angle;
2176 	angle >>= ANGLETOFINESHIFT;
2177 	mo->momx = FixedMul(speed, finecosine[angle]);
2178 	mo->momy = FixedMul(speed, finesine[angle]);
2179 	mo->momz = momz;
2180 	return(P_CheckMissileSpawn(mo) ? mo : NULL);
2181 }
2182 
2183 
2184 
2185 /*
2186 ================
2187 =
2188 = P_SpawnPlayerMissile
2189 =
2190 = Tries to aim at a nearby monster
2191 ================
2192 */
2193 
P_SpawnPlayerMissile(mobj_t * source,mobjtype_t type)2194 mobj_t *P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type)
2195 {
2196 	angle_t an;
2197 	fixed_t x, y, z, slope;
2198 
2199 	// Try to find a target
2200 	an = source->angle;
2201 	slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2202 	if(!linetarget)
2203 	{
2204 		an += 1<<26;
2205 		slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2206 		if(!linetarget)
2207 		{
2208 			an -= 2<<26;
2209 			slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2210 		}
2211 		if(!linetarget)
2212 		{
2213 			an = source->angle;
2214 			slope = ((source->player->lookdir)<<FRACBITS)/173;
2215 		}
2216 	}
2217 	x = source->x;
2218 	y = source->y;
2219 	if(type == MT_LIGHTNING_FLOOR)
2220 	{
2221 		z = ONFLOORZ;
2222 		slope = 0;
2223 	}
2224 	else if(type == MT_LIGHTNING_CEILING)
2225 	{
2226 		z = ONCEILINGZ;
2227 		slope = 0;
2228 	}
2229 	else
2230 	{
2231 		z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2232 		z -= source->floorclip;
2233 	}
2234 	MissileMobj = P_SpawnMobj(x, y, z, type);
2235 	if(MissileMobj->info->seesound)
2236 	{
2237 		//S_StartSound(MissileMobj, MissileMobj->info->seesound);
2238 	}
2239 	MissileMobj->target = source;
2240 	MissileMobj->angle = an;
2241 	MissileMobj->momx = FixedMul(MissileMobj->info->speed,
2242 		finecosine[an>>ANGLETOFINESHIFT]);
2243 	MissileMobj->momy = FixedMul(MissileMobj->info->speed,
2244 		finesine[an>>ANGLETOFINESHIFT]);
2245 	MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope);
2246 	if(MissileMobj->type == MT_MWAND_MISSILE
2247 		|| MissileMobj->type == MT_CFLAME_MISSILE)
2248 	{ // Ultra-fast ripper spawning missile
2249 		MissileMobj->x += (MissileMobj->momx>>3);
2250 		MissileMobj->y += (MissileMobj->momy>>3);
2251 		MissileMobj->z += (MissileMobj->momz>>3);
2252 	}
2253 	else
2254 	{ // Normal missile
2255 		MissileMobj->x += (MissileMobj->momx>>1);
2256 		MissileMobj->y += (MissileMobj->momy>>1);
2257 		MissileMobj->z += (MissileMobj->momz>>1);
2258 	}
2259 	if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
2260 	{ // Exploded immediately
2261 		P_ExplodeMissile(MissileMobj);
2262 		return(NULL);
2263 	}
2264 	return(MissileMobj);
2265 }
2266 
2267 
2268 //----------------------------------------------------------------------------
2269 //
2270 // P_SpawnPlayerMinotaur -
2271 //
2272 //	Special missile that has larger blocking than player
2273 //----------------------------------------------------------------------------
2274 
2275 /*
2276 mobj_t *P_SpawnPlayerMinotaur(mobj_t *source, mobjtype_t type)
2277 {
2278 	angle_t an;
2279 	fixed_t x, y, z;
2280 	fixed_t dist=0 *FRACUNIT;
2281 
2282 	an = source->angle;
2283 	x = source->x + FixedMul(dist, finecosine[an>>ANGLETOFINESHIFT]);
2284 	y = source->y + FixedMul(dist, finesine[an>>ANGLETOFINESHIFT]);
2285 	z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2286 	z -= source->floorclip;
2287 	MissileMobj = P_SpawnMobj(x, y, z, type);
2288 	if(MissileMobj->info->seesound)
2289 	{
2290 		//S_StartSound(MissileMobj, MissileMobj->info->seesound);
2291 	}
2292 	MissileMobj->target = source;
2293 	MissileMobj->angle = an;
2294 	MissileMobj->momx = FixedMul(MissileMobj->info->speed,
2295 		finecosine[an>>ANGLETOFINESHIFT]);
2296 	MissileMobj->momy = FixedMul(MissileMobj->info->speed,
2297 		finesine[an>>ANGLETOFINESHIFT]);
2298 	MissileMobj->momz = 0;
2299 
2300 //	MissileMobj->x += (MissileMobj->momx>>3);
2301 //	MissileMobj->y += (MissileMobj->momy>>3);
2302 //	MissileMobj->z += (MissileMobj->momz>>3);
2303 
2304 	if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
2305 	{ // Wouln't fit
2306 
2307 		return(NULL);
2308 	}
2309 	return(MissileMobj);
2310 }
2311 */
2312 
2313 //---------------------------------------------------------------------------
2314 //
2315 // PROC P_SPMAngle
2316 //
2317 //---------------------------------------------------------------------------
2318 
P_SPMAngle(mobj_t * source,mobjtype_t type,angle_t angle)2319 mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle)
2320 {
2321 	mobj_t *th;
2322 	angle_t an;
2323 	fixed_t x, y, z, slope;
2324 
2325 //
2326 // see which target is to be aimed at
2327 //
2328 	an = angle;
2329 	slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2330 	if (!linetarget)
2331 	{
2332 		an += 1<<26;
2333 		slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2334 		if (!linetarget)
2335 		{
2336 			an -= 2<<26;
2337 			slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2338 		}
2339 		if (!linetarget)
2340 		{
2341 			an = angle;
2342 			slope = ((source->player->lookdir)<<FRACBITS)/173;
2343 		}
2344 	}
2345 	x = source->x;
2346 	y = source->y;
2347 	z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2348 	z -= source->floorclip;
2349 	th = P_SpawnMobj(x, y, z, type);
2350 //	if(th->info->seesound)
2351 //	{
2352 //		S_StartSound(th, th->info->seesound);
2353 //	}
2354 	th->target = source;
2355 	th->angle = an;
2356 	th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
2357 	th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
2358 	th->momz = FixedMul(th->info->speed, slope);
2359 	return(P_CheckMissileSpawn(th) ? th : NULL);
2360 }
2361 
2362 //===========================================================================
2363 //
2364 // P_SPMAngleXYZ
2365 //
2366 //===========================================================================
2367 
P_SPMAngleXYZ(mobj_t * source,fixed_t x,fixed_t y,fixed_t z,mobjtype_t type,angle_t angle)2368 mobj_t *P_SPMAngleXYZ(mobj_t *source, fixed_t x, fixed_t y,
2369 	fixed_t z, mobjtype_t type, angle_t angle)
2370 {
2371 	mobj_t *th;
2372 	angle_t an;
2373 	fixed_t slope;
2374 
2375 //
2376 // see which target is to be aimed at
2377 //
2378 	an = angle;
2379 	slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2380 	if (!linetarget)
2381 	{
2382 		an += 1<<26;
2383 		slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2384 		if (!linetarget)
2385 		{
2386 			an -= 2<<26;
2387 			slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2388 		}
2389 		if (!linetarget)
2390 		{
2391 			an = angle;
2392 			slope = ((source->player->lookdir)<<FRACBITS)/173;
2393 		}
2394 	}
2395 	z += 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2396 	z -= source->floorclip;
2397 	th = P_SpawnMobj(x, y, z, type);
2398 //	if(th->info->seesound)
2399 //	{
2400 //		S_StartSound(th, th->info->seesound);
2401 //	}
2402 	th->target = source;
2403 	th->angle = an;
2404 	th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
2405 	th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
2406 	th->momz = FixedMul(th->info->speed, slope);
2407 	return(P_CheckMissileSpawn(th) ? th : NULL);
2408 }
2409 
P_SpawnKoraxMissile(fixed_t x,fixed_t y,fixed_t z,mobj_t * source,mobj_t * dest,mobjtype_t type)2410 mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z,
2411 	mobj_t *source, mobj_t *dest, mobjtype_t type)
2412 {
2413 	mobj_t *th;
2414 	angle_t an;
2415 	int dist;
2416 
2417 	z -= source->floorclip;
2418 	th = P_SpawnMobj(x, y, z, type);
2419 	if(th->info->seesound)
2420 	{
2421 		S_StartSound(th, th->info->seesound);
2422 	}
2423 	th->target = source; // Originator
2424 	an = R_PointToAngle2(x, y, dest->x, dest->y);
2425 	if(dest->flags&MF_SHADOW)
2426 	{ // Invisible target
2427 		an += (P_Random()-P_Random())<<21;
2428 	}
2429 	th->angle = an;
2430 	an >>= ANGLETOFINESHIFT;
2431 	th->momx = FixedMul(th->info->speed, finecosine[an]);
2432 	th->momy = FixedMul(th->info->speed, finesine[an]);
2433 	dist = P_AproxDistance(dest->x - x, dest->y - y);
2434 	dist = dist/th->info->speed;
2435 	if(dist < 1)
2436 	{
2437 		dist = 1;
2438 	}
2439 	th->momz = (dest->z-z+(30*FRACUNIT))/dist;
2440 	return(P_CheckMissileSpawn(th) ? th : NULL);
2441 }
2442