-
Notifications
You must be signed in to change notification settings - Fork 3
/
p_change.c
145 lines (113 loc) · 3.12 KB
/
p_change.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* p_change.c */
#include "doomdef.h"
#include "p_local.h"
/*
==============================================================================
SECTOR HEIGHT CHANGING
= After modifying a sectors floor or ceiling height, call this
= routine to adjust the positions of all things that touch the
= sector.
=
= If anything doesn't fit anymore, true will be returned.
= If crunch is true, they will take damage as they are being crushed
= If Crunch is false, you should set the sector height back the way it
= was and call P_ChangeSector again to undo the changes
==============================================================================
*/
boolean crushchange;
boolean nofit;
/*
==================
=
= P_ThingHeightClip
=
= Takes a valid thing and adjusts the thing->floorz, thing->ceilingz,
= anf possibly thing->z
=
= This is called for all nearby monsters whenever a sector changes height
=
= If the thing doesn't fit, the z will be set to the lowest value and
= false will be returned
==================
*/
boolean P_ThingHeightClip (mobj_t *thing)
{
boolean onfloor;
onfloor = (thing->z == thing->floorz);
P_CheckPosition (thing, thing->x, thing->y);
/* what about stranding a monster partially off an edge? */
thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz;
if (onfloor)
/* walking monsters rise and fall with the floor */
thing->z = thing->floorz;
else
{ /* don't adjust a floating monster unless forced to */
if (thing->z+thing->height > thing->ceilingz)
thing->z = thing->ceilingz - thing->height;
}
if (thing->ceilingz - thing->floorz < thing->height)
return false;
return true;
}
/*
===============
=
= PIT_ChangeSector
=
===============
*/
boolean PIT_ChangeSector (mobj_t *thing)
{
mobj_t *mo;
if (P_ThingHeightClip (thing))
return true; /* keep checking */
/* crunch bodies to giblets */
if (thing->health <= 0)
{
P_SetMobjState (thing, S_GIBS);
thing->height = 0;
thing->radius = 0;
return true; /* keep checking */
}
/* crunch dropped items */
if (thing->flags & MF_DROPPED)
{
P_RemoveMobj (thing);
return true; /* keep checking */
}
if (! (thing->flags & MF_SHOOTABLE) )
return true; /* assume it is bloody gibs or something */
nofit = true;
if (crushchange && !(gametic&3) )
{
P_DamageMobj(thing,NULL,NULL,10);
/* spray blood in a random direction */
mo = P_SpawnMobj (thing->x, thing->y, thing->z + thing->height/2, MT_BLOOD);
mo->momx = (P_Random() - P_Random ())<<12;
mo->momy = (P_Random() - P_Random ())<<12;
}
return true; /* keep checking (crush other things) */
}
/*
===============
=
= P_ChangeSector
=
===============
*/
boolean P_ChangeSector (sector_t *sector, boolean crunch)
{
int x,y;
int i;
/* force next sound to reflood */
for (i=0 ; i<MAXPLAYERS ; i++)
players[i].lastsoundsector = NULL;
nofit = false;
crushchange = crunch;
/* recheck heights for all things near the moving sector */
for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
P_BlockThingsIterator (x, y, PIT_ChangeSector);
return nofit;
}