1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_pillar.cpp 4469 2014-01-03 23:38:29Z dr_sean $
5 //
6 // Copyright (C) 1998-2006 by Randy Heit (ZDoom).
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 // [RH] p_pillar.c: New file to handle pillars
21 //
22 //-----------------------------------------------------------------------------
23
24
25 #include "z_zone.h"
26 #include "doomdef.h"
27 #include "p_local.h"
28 #include "p_spec.h"
29 #include "g_level.h"
30 #include "s_sound.h"
31
32 extern bool predicting;
33
P_SetPillarDestroy(DPillar * pillar)34 void P_SetPillarDestroy(DPillar *pillar)
35 {
36 if (!pillar)
37 return;
38
39 pillar->m_Status = DPillar::destroy;
40
41 if (clientside && pillar->m_Sector)
42 {
43 pillar->m_Sector->ceilingdata = NULL;
44 pillar->m_Sector->floordata = NULL;
45 pillar->Destroy();
46 }
47 }
48
IMPLEMENT_SERIAL(DPillar,DMover)49 IMPLEMENT_SERIAL (DPillar, DMover)
50
51 DPillar::DPillar () :
52 m_Status(init)
53 {
54 }
55
Serialize(FArchive & arc)56 void DPillar::Serialize (FArchive &arc)
57 {
58 Super::Serialize (arc);
59 if (arc.IsStoring ())
60 {
61 arc << m_Type
62 << m_Status
63 << m_FloorSpeed
64 << m_CeilingSpeed
65 << m_FloorTarget
66 << m_CeilingTarget
67 << m_Crush;
68 }
69 else
70 {
71 arc >> m_Type
72 >> m_Status
73 >> m_FloorSpeed
74 >> m_CeilingSpeed
75 >> m_FloorTarget
76 >> m_CeilingTarget
77 >> m_Crush;
78 }
79 }
80
PlayPillarSound()81 void DPillar::PlayPillarSound()
82 {
83 if (predicting || !m_Sector)
84 return;
85
86 if (m_Status == init)
87 S_Sound(m_Sector->soundorg, CHAN_BODY, "plats/pt1_mid", 1, ATTN_NORM);
88 else if (m_Status == finished)
89 S_StopSound(m_Sector->soundorg);
90 }
91
RunThink()92 void DPillar::RunThink ()
93 {
94 int r, s;
95
96 if (m_Type == pillarBuild)
97 {
98 r = MoveFloor (m_FloorSpeed, m_FloorTarget, m_Crush, 1);
99 s = MoveCeiling (m_CeilingSpeed, m_CeilingTarget, m_Crush, -1);
100 }
101 else
102 {
103 r = MoveFloor (m_FloorSpeed, m_FloorTarget, m_Crush, -1);
104 s = MoveCeiling (m_CeilingSpeed, m_CeilingTarget, m_Crush, 1);
105 }
106
107 if (r == pastdest && s == pastdest)
108 {
109 m_Status = finished;
110 PlayPillarSound();
111 P_SetPillarDestroy(this);
112 }
113 }
114
DPillar(sector_t * sector,EPillar type,fixed_t speed,fixed_t height,fixed_t height2,bool crush)115 DPillar::DPillar (sector_t *sector, EPillar type, fixed_t speed,
116 fixed_t height, fixed_t height2, bool crush)
117 : DMover (sector), m_Status(init)
118 {
119 fixed_t ceilingdist, floordist;
120
121 sector->floordata = sector->ceilingdata = this;
122
123 fixed_t floorheight = P_FloorHeight(sector);
124 fixed_t ceilingheight = P_CeilingHeight(sector);
125
126 m_Type = type;
127 m_Crush = crush;
128
129 if (type == pillarBuild)
130 {
131 // If the pillar height is 0, have the floor and ceiling meet halfway
132 if (height == 0)
133 {
134 m_FloorTarget = m_CeilingTarget =
135 (ceilingheight - floorheight) / 2 + floorheight;
136 floordist = m_FloorTarget - floorheight;
137 }
138 else
139 {
140 m_FloorTarget = m_CeilingTarget = floorheight + height;
141 floordist = height;
142 }
143 ceilingdist = ceilingheight - m_CeilingTarget;
144 }
145 else
146 {
147 // If one of the heights is 0, figure it out based on the
148 // surrounding sectors
149 if (height == 0)
150 {
151 m_FloorTarget = P_FindLowestFloorSurrounding (sector);
152 floordist = floorheight - m_FloorTarget;
153 }
154 else
155 {
156 floordist = height;
157 m_FloorTarget = floorheight - height;
158 }
159 if (height2 == 0)
160 {
161 m_CeilingTarget = P_FindHighestCeilingSurrounding (sector);
162 ceilingdist = m_CeilingTarget - ceilingheight;
163 }
164 else
165 {
166 m_CeilingTarget = ceilingheight + height2;
167 ceilingdist = height2;
168 }
169 }
170
171 // The speed parameter applies to whichever part of the pillar
172 // travels the farthest. The other part's speed is then set so
173 // that it arrives at its destination at the same time.
174 if (floordist > ceilingdist)
175 {
176 m_FloorSpeed = speed;
177 m_CeilingSpeed = FixedDiv (FixedMul (speed, ceilingdist), floordist);
178 }
179 else
180 {
181 m_CeilingSpeed = speed;
182 m_FloorSpeed = FixedDiv (FixedMul (speed, floordist), ceilingdist);
183 }
184
185 PlayPillarSound();
186 }
187
EV_DoPillar(DPillar::EPillar type,int tag,fixed_t speed,fixed_t height,fixed_t height2,bool crush)188 BOOL EV_DoPillar (DPillar::EPillar type, int tag, fixed_t speed, fixed_t height,
189 fixed_t height2, bool crush)
190 {
191 BOOL rtn = false;
192 int secnum = -1;
193
194 while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
195 {
196 sector_t *sec = §ors[secnum];
197 fixed_t floorheight = P_FloorHeight(sec);
198 fixed_t ceilingheight = P_CeilingHeight(sec);
199
200 if (sec->floordata || sec->ceilingdata)
201 continue;
202
203 if (type == DPillar::pillarBuild && floorheight == ceilingheight)
204 continue;
205
206 if (type == DPillar::pillarOpen && floorheight != ceilingheight)
207 continue;
208
209 rtn = true;
210 new DPillar (sec, type, speed, height, height2, crush);
211 P_AddMovingCeiling(sec);
212 }
213 return rtn;
214 }
215
216 VERSION_CONTROL (p_pillar_cpp, "$Id: p_pillar.cpp 4469 2014-01-03 23:38:29Z dr_sean $")
217
218