1 #include "3dc.h"
2 #include "module.h"
3 #include "inline.h"
4
5 #include "stratdef.h"
6 #include "gamedef.h"
7
8 #include "bh_types.h"
9 #include "dynblock.h"
10 #include "dynamics.h"
11
12 #include "pfarlocs.h"
13
14 #include "pvisible.h"
15 #include "load_shp.h"
16 #include "particle.h"
17
18 #include "bh_rubberduck.h"
19 #include "bh_weap.h"
20 #include "sfx.h"
21
22 #define UseLocalAssert Yes
23 #include "ourasert.h"
24
25 extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
26 extern int NormalFrameTime;
27
CreateRubberDuckBot(void)28 void CreateRubberDuckBot(void)
29 {
30 CreateRubberDuck(&(Global_VDB_Ptr->VDB_World));
31 }
32
33
CreateRubberDuck(VECTORCH * positionPtr)34 void CreateRubberDuck(VECTORCH *positionPtr)
35 {
36 STRATEGYBLOCK* sbPtr;
37
38 /* create and initialise a strategy block */
39 sbPtr = CreateActiveStrategyBlock();
40 if(!sbPtr) return; /* failure */
41 InitialiseSBValues(sbPtr);
42
43 sbPtr->I_SBtype = I_BehaviourRubberDuck;
44
45 AssignNewSBName(sbPtr);
46
47 /* create, initialise and attach a dynamics block */
48 sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_GRENADE);
49 if(sbPtr->DynPtr)
50 {
51 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
52 EULER zeroEuler = {0,0,0};
53 zeroEuler.EulerY = FastRandom()&4095;
54 dynPtr->PrevPosition = dynPtr->Position = *positionPtr;
55 dynPtr->OrientEuler = zeroEuler;
56 CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
57 TransposeMatrixCH(&dynPtr->OrientMat);
58
59 dynPtr->LinVelocity.vx = 0;
60 dynPtr->LinVelocity.vy = 0;
61 dynPtr->LinVelocity.vz = 0;
62 dynPtr->LinImpulse.vy = 0;
63 dynPtr->GravityOn = 0;
64 dynPtr->Elasticity = 0;
65 dynPtr->IsFloating = 1;
66 }
67 else
68 {
69 /* dynamics block allocation failed... */
70 RemoveBehaviourStrategy(sbPtr);
71 return;
72 }
73
74 sbPtr->shapeIndex = GetLoadedShapeMSL("ciggies");//Duck");
75
76 sbPtr->maintainVisibility = 1;
77 sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), 0);
78 LOCALASSERT(sbPtr->containingModule);
79 if(!(sbPtr->containingModule))
80 {
81 /* no containing module can be found... abort*/
82 RemoveBehaviourStrategy(sbPtr);
83 return;
84 }
85
86 }
87
RubberDuckBehaviour(STRATEGYBLOCK * sbPtr)88 void RubberDuckBehaviour(STRATEGYBLOCK *sbPtr)
89 {
90 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
91 int newLevel;
92
93 if (!sbPtr->SBdptr) return;
94 #if 1
95 newLevel = EffectOfRipples(&(dynPtr->Position));
96 {
97 int minusDeltaX,plusDeltaX,minusDeltaZ,plusDeltaZ;
98 VECTORCH delta;
99 delta.vx = dynPtr->Position.vx;
100 delta.vz = dynPtr->Position.vz;
101
102
103 delta.vx -= 50;
104 minusDeltaX = EffectOfRipples(&(delta))-newLevel;
105 delta.vx += 100;
106 plusDeltaX = EffectOfRipples(&(delta))-newLevel;
107 delta.vx -= 50;
108
109 delta.vz -= 50;
110 minusDeltaZ = EffectOfRipples(&(delta))-newLevel;
111 delta.vz += 100;
112 plusDeltaZ = EffectOfRipples(&(delta))-newLevel;
113 {
114 int scale = NormalFrameTime<<1;
115 if(scale>ONE_FIXED) scale = ONE_FIXED;
116 scale = ONE_FIXED;
117 dynPtr->LinImpulse.vx -= MUL_FIXED(scale,dynPtr->LinImpulse.vx);
118 dynPtr->LinImpulse.vz -= MUL_FIXED(scale,dynPtr->LinImpulse.vz);
119 }
120 if (minusDeltaX > plusDeltaX)
121 {
122 if (minusDeltaX>0) dynPtr->LinImpulse.vx = -minusDeltaX*256;
123 }
124 else
125 {
126 if (plusDeltaX>0) dynPtr->LinImpulse.vx = plusDeltaX*256;
127 }
128
129 if (minusDeltaZ > plusDeltaZ)
130 {
131 if (minusDeltaZ>0) dynPtr->LinImpulse.vz = -minusDeltaZ*256;
132 }
133 else
134 {
135 if (plusDeltaZ>0) dynPtr->LinImpulse.vz = plusDeltaZ*256;
136 }
137
138 }
139 dynPtr->LinImpulse.vy = 0;
140 {
141 int level = 0;
142 extern char LevelName[];
143 {
144 if (!strcmp(LevelName,"e3demosp")||!strcmp(LevelName,"e3demo"))
145 {
146 level = 3300;
147 }
148 else if (!strcmp(LevelName,"invasion_a"))
149 {
150 level = -35800;
151 }
152 else if (!strcmp(LevelName,"genshd1"))
153 {
154 level = 2656;
155 }
156 else if (!strcmp(LevelName,"fall")||!strcmp(LevelName,"fall_m"))
157 {
158 level = 12925;
159 }
160 else if (!strcmp(LevelName,"derelict"))
161 {
162 level = 32000;
163 }
164 dynPtr->Position.vy = newLevel+level;
165 }
166 }
167
168 dynPtr->AngVelocity.EulerY -= MUL_FIXED(dynPtr->AngVelocity.EulerY,NormalFrameTime);
169
170 dynPtr->AngVelocity.EulerY += (dynPtr->LinImpulse.vz + dynPtr->LinImpulse.vx+(FastRandom()&255)-128)/16;
171
172 dynPtr->AngVelocity.EulerZ = (dynPtr->LinImpulse.vz/256);
173 dynPtr->AngVelocity.EulerX = (dynPtr->LinImpulse.vx/256);
174
175 if (dynPtr->AngVelocity.EulerY > 8192) dynPtr->AngVelocity.EulerY = 8192;
176 else if (dynPtr->AngVelocity.EulerY < -8192) dynPtr->AngVelocity.EulerY = -8192;
177 DynamicallyRotateObject(dynPtr);
178 #else
179 {
180 VECTORCH dir;
181 dynPtr->GravityOn = 1;
182 dynPtr->IsFloating = 0;
183 dynPtr->CanClimbStairs = 0;
184 sbPtr->SBdptr->ObFlags3 |= ObFlag3_DynamicModuleObject;
185
186 if (BestDirectionOfTravel(&(Player->ObStrategyBlock->DynPtr->Position), &(dynPtr->Position), &dir))
187 {
188 dynPtr->LinVelocity.vx = MUL_FIXED(4000,dir.vx);
189 dynPtr->LinVelocity.vy = 0;
190 dynPtr->LinVelocity.vz = MUL_FIXED(4000,dir.vz);
191 }
192 else
193 {
194 dynPtr->LinVelocity.vx = 0;
195 dynPtr->LinVelocity.vy = 0;
196 dynPtr->LinVelocity.vz = 0;
197 }
198 }
199 #endif
200
201 }
202
CreateFlamingDebris(VECTORCH * positionPtr,VECTORCH * dirPtr)203 extern void CreateFlamingDebris(VECTORCH *positionPtr, VECTORCH *dirPtr)
204 {
205 STRATEGYBLOCK* sbPtr;
206
207 /* create and initialise a strategy block */
208 sbPtr = CreateActiveStrategyBlock();
209 if(!sbPtr) return; /* failure */
210 InitialiseSBValues(sbPtr);
211
212 sbPtr->I_SBtype = I_BehaviourFragment;
213
214 AssignNewSBName(sbPtr);
215
216 sbPtr->SBdataptr = (void*)AllocateMem(sizeof(ONE_SHOT_BEHAV_BLOCK));
217
218 if (sbPtr->SBdataptr == 0)
219 {
220 // Failed to allocate a strategy block data pointer
221 RemoveBehaviourStrategy(sbPtr);
222 return;
223 }
224 ((ONE_SHOT_BEHAV_BLOCK * ) sbPtr->SBdataptr)->counter = ((FastRandom()&32768)<<2) + 65535*2;
225
226 /* create, initialise and attach a dynamics block */
227 sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_ALIEN_DEBRIS);
228 if(sbPtr->DynPtr)
229 {
230 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
231 dynPtr->PrevPosition = dynPtr->Position = *positionPtr;
232 dynPtr->OrientEuler.EulerX = 0;
233 dynPtr->OrientEuler.EulerY = FastRandom()&4095;
234 dynPtr->OrientEuler.EulerZ = 0;
235 CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
236 TransposeMatrixCH(&dynPtr->OrientMat);
237
238 dynPtr->LinImpulse.vx = dirPtr->vx/4;
239 dynPtr->LinImpulse.vy = dirPtr->vy/4;
240 if (dynPtr->LinImpulse.vy>0) dynPtr->LinImpulse.vy=-dynPtr->LinImpulse.vy;
241 dynPtr->LinImpulse.vy += -4000;
242 dynPtr->LinImpulse.vz = dirPtr->vz/4;
243 dynPtr->AngVelocity.EulerX = (((FastRandom()&2047)-1023))<<2;
244 dynPtr->AngVelocity.EulerY = (((FastRandom()&2047)-1023))<<2;
245 dynPtr->AngVelocity.EulerZ = (((FastRandom()&2047)-1023))<<2;
246
247 dynPtr->Elasticity = ONE_FIXED/4;
248 }
249 else
250 {
251 /* dynamics block allocation failed... */
252 RemoveBehaviourStrategy(sbPtr);
253 return;
254 }
255
256 sbPtr->shapeIndex = GetLoadedShapeMSL("Shell");
257
258 sbPtr->maintainVisibility = 0;
259 sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), 0);
260 LOCALASSERT(sbPtr->containingModule);
261 if(!(sbPtr->containingModule))
262 {
263 /* no containing module can be found... abort*/
264 RemoveBehaviourStrategy(sbPtr);
265 return;
266 }
267
268 {
269 MODULE tempModule;
270 DISPLAYBLOCK *dPtr;
271 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
272
273 VisibilityDefaultObjectMap.MapShape = sbPtr->shapeIndex;
274 tempModule.m_mapptr = &VisibilityDefaultObjectMap;
275 tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
276 tempModule.m_numlights = 0;
277 tempModule.m_lightarray = (struct lightblock *)0;
278 tempModule.m_extraitemdata = (struct extraitemdata *)0;
279 tempModule.m_dptr = NULL; /* this is important */
280 tempModule.name = NULL; /* this is important */
281
282 AllocateModuleObject(&tempModule);
283 dPtr = tempModule.m_dptr;
284 if(dPtr==NULL)
285 {
286 RemoveBehaviourStrategy(sbPtr);
287 return;
288 }
289
290 sbPtr->SBdptr = dPtr;
291 dPtr->ObStrategyBlock = sbPtr;
292 dPtr->ObMyModule = NULL;
293 dPtr->ObWorld = dynPtr->Position;
294 dPtr->ObEuler = dynPtr->OrientEuler;
295 dPtr->ObMat = dynPtr->OrientMat;
296
297 /* make displayblock a dynamic module object */
298 dPtr->ObFlags3 |= ObFlag3_DynamicModuleObject;
299
300 sbPtr->SBDamageBlock.IsOnFire=1;
301
302 }
303 }
304
CreateRubberDucks(void)305 void CreateRubberDucks(void)
306 {
307 extern char LevelName[];
308 #if 0
309 if ( (!stricmp(LevelName,"e3demo")) || (!stricmp(LevelName,"e3demosp")) )
310 {
311 int i = 6;
312
313 do
314 {
315 VECTORCH pos = {1023,3400,27536};
316 pos.vx += (FastRandom()&4095)-2048;
317 pos.vz += (FastRandom()&4095)-2048;
318 CreateRubberDuck(&pos);
319 }
320 while(--i);
321 }
322 else
323 #endif
324 if ( (!stricmp(LevelName,"invasion_a")) )
325 {
326 int i = 6;
327
328 do
329 {
330 VECTORCH pos = {21803,-35491,40607};
331 pos.vx += FastRandom()&8191;
332 pos.vz -= FastRandom()&8191;
333 CreateRubberDuck(&pos);
334 }
335 while(--i);
336 }
337 }
338