1 
2 /* P_plats.c */
3 
4 #include "doomdef.h"
5 #include "p_local.h"
6 #include "soundst.h"
7 
8 #ifdef GL_HERETIC
9 #include "gl_struct.h"
10 #endif
11 
12 plat_t	*activeplats[MAXPLATS];
13 
14 /*
15   //==================================================================
16   //
17   //	Move a plat up and down
18   //
19   //==================================================================
20 */
T_PlatRaise(plat_t * plat)21 void	T_PlatRaise(plat_t	*plat)
22 {
23   result_e res;
24 
25   switch(plat->status)
26     {
27     case up:
28       res = T_MovePlane(plat->sector,plat->speed,
29 			plat->high,plat->crush,0,1);
30       if(!(leveltime&31))
31 	{
32 	  S_StartSound((mobj_t *)&plat->sector->soundorg,
33 		       sfx_stnmov);
34 	}
35       if(plat->type == raiseAndChange
36 	 || plat->type == raiseToNearestAndChange)
37 	{
38 	  if(!(leveltime&7))
39 	    {
40 	      S_StartSound((mobj_t *)&plat->sector->soundorg,
41 			   sfx_stnmov);
42 	    }
43 	}
44       if (res == crushed && (!plat->crush))
45 	{
46 	  plat->count = plat->wait;
47 	  plat->status = down;
48 	  S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstart);
49 	}
50       else
51 	if (res == pastdest)
52 	  {
53 	    plat->count = plat->wait;
54 	    plat->status = waiting;
55 	    S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstop);
56 	    switch(plat->type)
57 	      {
58 	      case downWaitUpStay:
59 		P_RemoveActivePlat(plat);
60 		break;
61 	      case raiseAndChange:
62 		P_RemoveActivePlat(plat);
63 		break;
64 	      default:
65 		break;
66 	      }
67 	  }
68       break;
69     case	down:
70       res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
71       if (res == pastdest)
72 	{
73 	  plat->count = plat->wait;
74 	  plat->status = waiting;
75 	  S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstop);
76 	}
77       else
78 	{
79 	  if(!(leveltime&31))
80 	    {
81 	      S_StartSound((mobj_t *)&plat->sector->soundorg,
82 			   sfx_stnmov);
83 	    }
84 	}
85       break;
86     case	waiting:
87       if (!--plat->count)
88 	{
89 	  if (plat->sector->floorheight == plat->low)
90 	    plat->status = up;
91 	  else
92 	    plat->status = down;
93 	  S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstart);
94 	}
95     case	in_stasis:
96       break;
97     }
98 }
99 
100 /*
101   //==================================================================
102   //
103   //	Do Platforms
104   //	"amount" is only used for SOME platforms.
105   //
106   //==================================================================
107 */
EV_DoPlat(line_t * line,plattype_e type,int amount)108 int	EV_DoPlat(line_t *line,plattype_e type,int amount)
109 {
110   plat_t	*plat;
111   int		secnum;
112   int		rtn;
113   sector_t	*sec;
114 
115   secnum = -1;
116   rtn = 0;
117 
118   /*
119    *	Activate all <type> plats that are in_stasis
120    */
121   switch(type)
122     {
123     case perpetualRaise:
124       P_ActivateInStasis(line->tag);
125       break;
126     default:
127       break;
128     }
129 
130   while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
131     {
132       sec = &sectors[secnum];
133       if (sec->specialdata)
134 	continue;
135 
136       /*
137        * Find lowest & highest floors around sector
138        */
139       rtn = 1;
140       plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
141       P_AddThinker(&plat->thinker);
142 
143       plat->type = type;
144       plat->sector = sec;
145       plat->sector->specialdata = plat;
146       plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
147       plat->crush = false;
148       plat->tag = line->tag;
149       switch(type)
150 	{
151 	case raiseToNearestAndChange:
152 	  plat->speed = PLATSPEED/2;
153 	  sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
154 #ifdef GL_HERETIC
155 	  GL_vSetFloorTexture(sec->iSectorID,sec->floorpic);
156 #endif
157 	  plat->high = P_FindNextHighestFloor(sec,sec->floorheight);
158 	  plat->wait = 0;
159 	  plat->status = up;
160 	  sec->special = 0;		/* NO MORE DAMAGE, IF APPLICABLE */
161 	  S_StartSound((mobj_t *)&sec->soundorg, sfx_stnmov);
162 	  break;
163 	case raiseAndChange:
164 	  plat->speed = PLATSPEED/2;
165 	  sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
166 #ifdef GL_HERETIC
167 	  GL_vSetFloorTexture(sec->iSectorID,sec->floorpic);
168 #endif
169 	  plat->high = sec->floorheight + amount*FRACUNIT;
170 	  plat->wait = 0;
171 	  plat->status = up;
172 	  S_StartSound((mobj_t *)&sec->soundorg, sfx_stnmov);
173 	  break;
174 	case downWaitUpStay:
175 	  plat->speed = PLATSPEED * 4;
176 	  plat->low = P_FindLowestFloorSurrounding(sec);
177 	  if (plat->low > sec->floorheight)
178 	    plat->low = sec->floorheight;
179 	  plat->high = sec->floorheight;
180 	  plat->wait = 35*PLATWAIT;
181 	  plat->status = down;
182 	  S_StartSound((mobj_t *)&sec->soundorg, sfx_pstart);
183 	  break;
184 	case perpetualRaise:
185 	  plat->speed = PLATSPEED;
186 	  plat->low = P_FindLowestFloorSurrounding(sec);
187 	  if (plat->low > sec->floorheight)
188 	    plat->low = sec->floorheight;
189 	  plat->high = P_FindHighestFloorSurrounding(sec);
190 	  if (plat->high < sec->floorheight)
191 	    plat->high = sec->floorheight;
192 	  plat->wait = 35*PLATWAIT;
193 	  plat->status = P_Random()&1;
194 	  S_StartSound((mobj_t *)&sec->soundorg, sfx_pstart);
195 	  break;
196 	}
197       P_AddActivePlat(plat);
198     }
199   return rtn;
200 }
201 
P_ActivateInStasis(int tag)202 void P_ActivateInStasis(int tag)
203 {
204   int		i;
205 
206   for (i = 0;i < MAXPLATS;i++)
207     if (activeplats[i] &&
208 	(activeplats[i])->tag == tag &&
209 	(activeplats[i])->status == in_stasis)
210       {
211 	(activeplats[i])->status = (activeplats[i])->oldstatus;
212 	(activeplats[i])->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
213       }
214 }
215 
EV_StopPlat(line_t * line)216 void EV_StopPlat(line_t *line)
217 {
218   int		j;
219 
220   for (j = 0;j < MAXPLATS;j++)
221     if (activeplats[j] && ((activeplats[j])->status != in_stasis) &&
222 	((activeplats[j])->tag == line->tag))
223       {
224 	(activeplats[j])->oldstatus = (activeplats[j])->status;
225 	(activeplats[j])->status = in_stasis;
226 	(activeplats[j])->thinker.function.acv = (actionf_v)NULL;
227       }
228 }
229 
P_AddActivePlat(plat_t * plat)230 void P_AddActivePlat(plat_t *plat)
231 {
232   int		i;
233   for (i = 0;i < MAXPLATS;i++)
234     if (activeplats[i] == NULL)
235       {
236 	activeplats[i] = plat;
237 	return;
238       }
239   I_Error ("P_AddActivePlat: no more plats!");
240 }
241 
P_RemoveActivePlat(plat_t * plat)242 void P_RemoveActivePlat(plat_t *plat)
243 {
244   int		i;
245   for (i = 0;i < MAXPLATS;i++)
246     if (plat == activeplats[i])
247       {
248 	(activeplats[i])->sector->specialdata = NULL;
249 	P_RemoveThinker(&(activeplats[i])->thinker);
250 	activeplats[i] = NULL;
251 	return;
252       }
253   I_Error ("P_RemoveActivePlat: can't find plat!");
254 }
255 
256