1 /* KJL 16:14:35 09/09/98 - BonusAbilities.c */
2 #include "3dc.h"
3 #include "module.h"
4 #include "inline.h"
5
6 #include "stratdef.h"
7 #include "gamedef.h"
8 #include "bh_types.h"
9
10 #include "weapons.h"
11 #include "dynblock.h"
12 #include "avpview.h"
13
14 #include "load_shp.h"
15 #include "kzsort.h"
16 #include "kshape.h"
17
18 #include "pfarlocs.h"
19 #include "pvisible.h"
20
21 #define UseLocalAssert Yes
22 #include "ourasert.h"
23
24
25 extern int NormalFrameTime;
26
27
28
29 /* KJL 16:18:20 09/09/98 - Predator Grappling Hook */
30 struct GrapplingHookData
31 {
32 int IsEmbedded;
33 int IsEngaged;
34 int Tightness;
35
36 VECTORCH Position;
37 MATRIXCH Orientation;
38 int ShapeIndex;
39 DISPLAYBLOCK *DispPtr;
40 };
41
42 static struct GrapplingHookData GrapplingHook;
43
44 static DISPLAYBLOCK* CreateGrapplingHook(void);
45
46
InitialiseGrapplingHook(void)47 extern void InitialiseGrapplingHook(void)
48 {
49 GrapplingHook.IsEngaged = 0;
50 GrapplingHook.IsEmbedded = 0;
51 GrapplingHook.ShapeIndex = GetLoadedShapeMSL("spear");
52 GrapplingHook.DispPtr = 0;
53
54 }
55
56 static void FireGrapplingHook(void);
57 void DisengageGrapplingHook(void);
58
ActivateGrapplingHook(void)59 extern void ActivateGrapplingHook(void)
60 {
61 if (GrapplingHook.IsEngaged)
62 {
63 DisengageGrapplingHook();
64 }
65 else
66 {
67 FireGrapplingHook();
68 }
69 }
FireGrapplingHook(void)70 static void FireGrapplingHook(void)
71 {
72 GrapplingHook.DispPtr = CreateGrapplingHook();
73
74 if (GrapplingHook.DispPtr)
75 {
76 GrapplingHook.IsEngaged = 1;
77 GrapplingHook.IsEmbedded = 0;
78 GrapplingHook.Tightness = ONE_FIXED;
79
80 /* CDF 14/4/99 Make a sound... */
81 Sound_Play(SID_GRAPPLE_THROW,"h");
82
83 #if 0
84 /* los */
85 GrapplingHook.Position = PlayersTarget.Position;
86 GrapplingHook.Orientation = Global_VDB_Ptr->VDB_Mat;
87 TransposeMatrixCH(&GrapplingHook.Orientation);
88 #endif
89 }
90
91 }
92
CreateGrapplingHook(void)93 static DISPLAYBLOCK* CreateGrapplingHook(void)
94 {
95 STRATEGYBLOCK* sbPtr;
96
97 /* create and initialise a strategy block */
98 sbPtr = CreateActiveStrategyBlock();
99 if(!sbPtr) return NULL; /* failure */
100 InitialiseSBValues(sbPtr);
101
102 sbPtr->I_SBtype = I_BehaviourGrapplingHook;
103
104 AssignNewSBName(sbPtr);
105
106 /* create, initialise and attach a dynamics block */
107 sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_ROCKET);
108 if(sbPtr->DynPtr)
109 {
110 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
111
112 dynPtr->PrevPosition = dynPtr->Position = Global_VDB_Ptr->VDB_World;
113
114 GrapplingHook.Orientation = Global_VDB_Ptr->VDB_Mat;
115 TransposeMatrixCH(&GrapplingHook.Orientation);
116 dynPtr->OrientMat = GrapplingHook.Orientation;
117
118 dynPtr->LinVelocity.vx = dynPtr->OrientMat.mat31;
119 dynPtr->LinVelocity.vy = dynPtr->OrientMat.mat32;
120 dynPtr->LinVelocity.vz = dynPtr->OrientMat.mat33;
121 }
122 else
123 {
124 /* dynamics block allocation failed... */
125 RemoveBehaviourStrategy(sbPtr);
126 return NULL;
127 }
128
129 sbPtr->shapeIndex = GetLoadedShapeMSL("spear");
130
131 sbPtr->maintainVisibility = 0;
132 sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), 0);
133 LOCALASSERT(sbPtr->containingModule);
134 if(!(sbPtr->containingModule))
135 {
136 /* no containing module can be found... abort*/
137 RemoveBehaviourStrategy(sbPtr);
138 return NULL;
139 }
140 {
141 MODULE tempModule;
142 DISPLAYBLOCK *dPtr;
143 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
144
145 VisibilityDefaultObjectMap.MapShape = sbPtr->shapeIndex;
146 tempModule.m_mapptr = &VisibilityDefaultObjectMap;
147 tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
148 tempModule.m_numlights = 0;
149 tempModule.m_lightarray = (struct lightblock *)0;
150 tempModule.m_extraitemdata = (struct extraitemdata *)0;
151 tempModule.m_dptr = NULL; /* this is important */
152 tempModule.name = NULL; /* this is important */
153
154 AllocateModuleObject(&tempModule);
155 dPtr = tempModule.m_dptr;
156 if(dPtr==NULL)
157 {
158 RemoveBehaviourStrategy(sbPtr);
159 return NULL;
160 }
161
162 sbPtr->SBdptr = dPtr;
163 dPtr->ObStrategyBlock = sbPtr;
164 dPtr->ObMyModule = NULL;
165 dPtr->ObWorld = dynPtr->Position;
166 dPtr->ObEuler = dynPtr->OrientEuler;
167 dPtr->ObMat = dynPtr->OrientMat;
168
169 dPtr->ObRadius=10;
170 dPtr->ObMaxX=10;
171 dPtr->ObMinX=-10;
172 dPtr->ObMaxY=10;
173 dPtr->ObMinY=-10;
174 dPtr->ObMaxZ=10;
175 dPtr->ObMinZ=-10;
176 /* make displayblock a dynamic module object */
177 dPtr->ObFlags3 |= ObFlag3_DynamicModuleObject;
178
179 // sbPtr->SBDamageBlock.IsOnFire=1;
180
181 return dPtr;
182 }
183
184 }
185
GrapplingHookBehaviour(STRATEGYBLOCK * sbPtr)186 void GrapplingHookBehaviour(STRATEGYBLOCK *sbPtr)
187 {
188 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
189
190 if (!GrapplingHook.IsEmbedded)
191 {
192 COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
193
194 if(reportPtr)
195 {
196 char stickWhereYouAre = 0;
197
198 if (reportPtr->ObstacleSBPtr)
199 {
200 DISPLAYBLOCK *dispPtr = reportPtr->ObstacleSBPtr->SBdptr;
201 if (dispPtr)
202 if (dispPtr->ObMyModule && (!dispPtr->ObMorphCtrl))
203 {
204 stickWhereYouAre=1;
205 }
206 }
207 else
208 {
209 stickWhereYouAre = 1;
210 }
211
212
213 if(stickWhereYouAre)
214 {
215 dynPtr->IsStatic=1;
216 dynPtr->PrevPosition=dynPtr->Position;
217 GrapplingHook.Position=dynPtr->Position;
218 GrapplingHook.IsEmbedded=1;
219 /* CDF 14/4/99 Make a sound. */
220 Sound_Play(SID_GRAPPLE_HIT_WALL,"d",&dynPtr->Position);
221 return;
222 }
223 else
224 {
225 DisengageGrapplingHook();
226 return;
227 }
228 }
229 }
230 else
231 {
232 GrapplingHook.Tightness -= NormalFrameTime*4;
233 if (GrapplingHook.Tightness<0) GrapplingHook.Tightness=0;
234 }
235 }
236
DisengageGrapplingHook(void)237 extern void DisengageGrapplingHook(void)
238 {
239 GrapplingHook.IsEngaged = 0;
240 GrapplingHook.IsEmbedded = 0;
241 if (GrapplingHook.DispPtr)
242 {
243 RemoveBehaviourStrategy(GrapplingHook.DispPtr->ObStrategyBlock);
244 GrapplingHook.DispPtr=NULL;
245 }
246 }
247
HandleGrapplingHookForces(void)248 extern void HandleGrapplingHookForces(void)
249 {
250 if (GrapplingHook.IsEmbedded)
251 {
252 DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
253 VECTORCH direction = GrapplingHook.Position;
254 int distance;
255
256 direction.vx -= dynPtr->Position.vx;
257 direction.vy -= dynPtr->Position.vy-1000;
258 direction.vz -= dynPtr->Position.vz;
259
260 distance = Approximate3dMagnitude(&direction);
261 if (distance>4096+1024)
262 {
263 Normalise(&direction);
264 dynPtr->LinImpulse.vx += MUL_FIXED(direction.vx,NormalFrameTime);
265 dynPtr->LinImpulse.vy += MUL_FIXED(direction.vy,NormalFrameTime);
266 dynPtr->LinImpulse.vz += MUL_FIXED(direction.vz,NormalFrameTime);
267 }
268 else if (distance>1024)
269 {
270 int s = MUL_FIXED((distance-1024)*16,NormalFrameTime);
271 Normalise(&direction);
272 dynPtr->LinImpulse.vx += MUL_FIXED(direction.vx,s);
273 dynPtr->LinImpulse.vy += MUL_FIXED(direction.vy,s);
274 dynPtr->LinImpulse.vz += MUL_FIXED(direction.vz,s);
275
276 dynPtr->LinImpulse.vx -= MUL_FIXED(dynPtr->LinImpulse.vx,NormalFrameTime/2);
277 dynPtr->LinImpulse.vy -= MUL_FIXED(dynPtr->LinImpulse.vy,NormalFrameTime/2);
278 dynPtr->LinImpulse.vz -= MUL_FIXED(dynPtr->LinImpulse.vz,NormalFrameTime/2);
279 }
280
281 if (Approximate3dMagnitude(&dynPtr->LinImpulse)>ONE_FIXED)
282 {
283 Normalise(&dynPtr->LinImpulse);
284 }
285 }
286 }
287
RenderGrapplingHook(void)288 extern void RenderGrapplingHook(void)
289 {
290 if (GrapplingHook.IsEngaged && GrapplingHook.DispPtr)
291 {
292 extern void D3D_DrawCable(VECTORCH *centrePtr, MATRIXCH *orientationPtr);
293 extern int CloakingPhase;
294 VECTORCH cable[46];
295 int i;
296 {
297 MATRIXCH mat = Global_VDB_Ptr->VDB_Mat;
298 TransposeMatrixCH(&mat);
299
300 cable[0].vx = Global_VDB_Ptr->VDB_World.vx-mat.mat31/128;
301 cable[0].vy = Global_VDB_Ptr->VDB_World.vy-mat.mat32/128+500;
302 cable[0].vz = Global_VDB_Ptr->VDB_World.vz-mat.mat33/128;
303 }
304 // cable[0].vx = Global_VDB_Ptr->VDB_World.vx;
305 // cable[0].vy = Global_VDB_Ptr->VDB_World.vy+500;
306 // cable[0].vz = Global_VDB_Ptr->VDB_World.vz;
307
308 for (i=1; i<46; i++)
309 {
310 cable[i].vx = ((45-i)*cable[0].vx + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vx)/45;
311 cable[i].vy = ((45-i)*cable[0].vy + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vy)/45;
312 cable[i].vz = ((45-i)*cable[0].vz + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vz)/45;
313
314 if (GrapplingHook.Tightness!=0)
315 {
316 int x = GetSin((302*i+CloakingPhase)&4095)/256;
317 int y = GetSin((502*i+200+CloakingPhase)&4095)/256;
318 int z = GetCos((302*i+100+CloakingPhase)&4095)/256;
319 int u = GetSin( ((4096*i)/45)&4095 );
320 u = MUL_FIXED(MUL_FIXED(u,u),GrapplingHook.Tightness);
321 cable[i].vx += MUL_FIXED(u,x);
322 cable[i].vy += MUL_FIXED(u,y);
323 cable[i].vz += MUL_FIXED(u,z);
324 }
325 }
326
327 {
328 MATRIXCH mat;
329 VECTORCH dir = cable[45];
330 dir.vx -= cable[0].vx;
331 dir.vy -= cable[0].vy;
332 dir.vz -= cable[0].vz;
333 Normalise(&dir);
334 MakeMatrixFromDirection(&dir,&mat);
335 D3D_DrawCable(cable, &mat);
336 }
337 #if 0
338 DISPLAYBLOCK displayblock;
339 displayblock.ObWorld=GrapplingHook.Position;
340 displayblock.ObMat=GrapplingHook.Orientation;
341 displayblock.ObShape=GrapplingHook.ShapeIndex;
342 displayblock.ObShapeData=GetShapeData(GrapplingHook.ShapeIndex);
343
344 displayblock.name=NULL;
345 displayblock.ObEuler.EulerX=0;
346 displayblock.ObEuler.EulerY=0;
347 displayblock.ObEuler.EulerZ=0;
348 displayblock.ObFlags=0;
349 displayblock.ObFlags2=0;
350 displayblock.ObFlags3=0;
351 displayblock.ObNumLights=0;
352 displayblock.ObRadius=0;
353 displayblock.ObMaxX=0;
354 displayblock.ObMinX=0;
355 displayblock.ObMaxY=0;
356 displayblock.ObMinY=0;
357 displayblock.ObMaxZ=0;
358 displayblock.ObMinZ=0;
359 displayblock.ObTxAnimCtrlBlks=NULL;
360 displayblock.ObEIDPtr=NULL;
361 displayblock.ObMorphCtrl=NULL;
362 displayblock.ObStrategyBlock=NULL;
363 displayblock.ShapeAnimControlBlock=NULL;
364 displayblock.HModelControlBlock=NULL;
365 displayblock.ObMyModule=NULL;
366 displayblock.SpecialFXFlags = 0;
367 displayblock.SfxPtr=0;
368
369 MakeVector(&displayblock.ObWorld, &Global_VDB_Ptr->VDB_World, &displayblock.ObView);
370 RotateVector(&displayblock.ObView, &Global_VDB_Ptr->VDB_Mat);
371 RenderThisDisplayblock(&displayblock);
372 {
373 PARTICLE particle;
374 particle.Colour = 0xffffffff;
375 particle.ParticleID = PARTICLE_LASERBEAM;
376 particle.Position = Player->ObStrategyBlock->DynPtr->Position;
377 particle.Position.vy-=1000;
378 particle.Offset = GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position;
379 particle.Size = 20;
380 RenderParticle(&particle);
381 }
382 #endif
383
384 }
385 }
386
387
388 /*--------------------**
389 ** Loading and Saving **
390 **--------------------*/
391 #include "savegame.h"
392
393 typedef struct grapple_save_block
394 {
395 SAVE_BLOCK_STRATEGY_HEADER header;
396
397 int IsEmbedded;
398 int IsEngaged;
399 int Tightness;
400
401 VECTORCH Position;
402 MATRIXCH Orientation;
403 //strategy block stuff
404 DYNAMICSBLOCK dynamics;
405 }GRAPPLE_SAVE_BLOCK;
406
407 //defines for load/save macros
408 #define SAVELOAD_BLOCK block
409 #define SAVELOAD_BEHAV (&GrapplingHook)
410
LoadStrategy_Grapple(SAVE_BLOCK_STRATEGY_HEADER * header)411 void LoadStrategy_Grapple(SAVE_BLOCK_STRATEGY_HEADER* header)
412 {
413 GRAPPLE_SAVE_BLOCK* block = (GRAPPLE_SAVE_BLOCK*) header;
414
415 //check the size of the save block
416 if(header->size!=sizeof(*block)) return;
417
418 //create the grappling hook
419 GrapplingHook.DispPtr = CreateGrapplingHook();
420 if(!GrapplingHook.DispPtr) return;
421
422 //copy suff from the save block
423 COPYELEMENT_LOAD(IsEmbedded)
424 COPYELEMENT_LOAD(IsEngaged)
425 COPYELEMENT_LOAD(Tightness)
426 COPYELEMENT_LOAD(Position)
427 COPYELEMENT_LOAD(Orientation)
428
429 *GrapplingHook.DispPtr->ObStrategyBlock->DynPtr = block->dynamics;
430 }
431
SaveStrategy_Grapple(STRATEGYBLOCK * sbPtr)432 void SaveStrategy_Grapple(STRATEGYBLOCK* sbPtr)
433 {
434 GRAPPLE_SAVE_BLOCK* block;
435
436 GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
437
438 //copy stuff to the save block
439 COPYELEMENT_SAVE(IsEmbedded)
440 COPYELEMENT_SAVE(IsEngaged)
441 COPYELEMENT_SAVE(Tightness)
442 COPYELEMENT_SAVE(Position)
443 COPYELEMENT_SAVE(Orientation)
444
445 block->dynamics = *sbPtr->DynPtr;
446 block->dynamics.CollisionReportPtr=0;
447 }
448