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