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