1 #include "3dc.h"
2 #include "inline.h"
3 #include "module.h"
4 #include "stratdef.h"
5 #include "gamedef.h"
6 #include "bh_types.h"
7 
8 #include "weapons.h"
9 #include "comp_shp.h"
10 #include "inventry.h"
11 #include "triggers.h"
12 #include "huddefs.h"
13 
14 #include "dynblock.h"
15 #include "dynamics.h"
16 
17 #define UseLocalAssert Yes
18 
19 #include "ourasert.h"
20 
21 #include "pmove.h"
22 #include "pvisible.h"
23 #include "bh_swdor.h"
24 #include "load_shp.h"
25 #include "lighting.h"
26 #include "bh_lnksw.h"
27 #include "bh_binsw.h"
28 #include "bh_lift.h"
29 
30 #include "psnd.h"
31 
32 /* for win95 net game support */
33 #include "pldghost.h"
34 
35 extern int NormalFrameTime;
36 // stuff for environment changing
37 
38 extern void IntegrateNewEnvironment();
39 extern int NumActiveBlocks;
40 
41 // Globals we are going to export
42 
43 int RequestEnvChangeViaLift	= 0;
44 int RequestEnvChangeViaAirlock	= 0;
45 
46 LIFT_CONTROL_BLOCK	EC_Lift_Ctrl;
47 MODULE Old_Pos_Module;
48 
49 
50 
51 static void TeleportFloorSwitches(MODULE* dest, MODULE* src, LIFT_CONTROL_BLOCK* liftCtrl);
52 
53 
54 
55 /*********************** CLOSED TELEPORT LIFTS INIT ***************/
56 
LiftBehaveInit(void * bhdata,STRATEGYBLOCK * sbptr)57 void * LiftBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
58 {
59 
60 	LIFT_BEHAV_BLOCK *lift_bhv;
61  	LIFT_STATION* lift_stn;
62 	LIFT_TOOLS_TEMPLATE* lift_tt;
63 	MODULE * my_mod;
64 
65  	GLOBALASSERT(sbptr);
66 	lift_bhv = (LIFT_BEHAV_BLOCK*)AllocateMem(sizeof(LIFT_BEHAV_BLOCK));
67 	if(!lift_bhv)
68 	{
69 		memoryInitialisationFailure = 1;
70 		return ((void *)NULL);
71 	}
72 
73   lift_bhv->bhvr_type = I_BehaviourLift;
74 
75 	lift_stn = &lift_bhv->lift_station;
76 	lift_tt = (LIFT_TOOLS_TEMPLATE*)bhdata;
77 
78 	// Copy the name over
79 	COPY_NAME (sbptr->SBname, lift_tt->nameID);
80 
81 
82 	// Setup module ref if not external
83 	if (lift_tt->environment == (int)AvP.CurrentEnv)
84 	{
85 		{
86 			MREF mref=lift_tt->my_module;
87 			ConvertModuleNameToPointer (&mref, MainSceneArray[0]->sm_marray);
88 
89 			my_mod = mref.mref_ptr;
90 		}
91 		GLOBALASSERT (my_mod);
92 
93 		my_mod->m_sbptr = sbptr;
94 		sbptr->SBmoptr = my_mod;
95 		sbptr->SBmomptr = my_mod->m_mapptr;
96 		sbptr->SBflags.no_displayblock = 1;
97 	}
98 
99 	// loaded data - first the station
100 
101 	COPY_NAME(lift_stn->lift_call_switch_name, lift_tt->call_switch_name);
102 	COPY_NAME(lift_stn->lift_door_name, lift_tt->lift_door_name);
103 	COPY_NAME(lift_stn->lift_floor_switch_name, lift_tt->lift_floor_switch_name);
104 	COPY_NAME(lift_stn->my_sb_name, lift_tt->my_module_name);
105 
106 	lift_stn->env	= lift_tt->environment;
107 	lift_stn->num_floor =	lift_tt->num_floor;
108 	lift_stn->orient = lift_tt->orient;
109 
110 	// fill in the rest of the stn data;
111 
112 	lift_stn->lift_call_switch = NULL;
113 	lift_stn->lift_door = NULL;
114 	lift_stn->lift_floor_switch = NULL;
115 	lift_stn->lift_module = sbptr->SBmoptr;
116 	if(lift_tt->lift_flags & LiftFlag_Here)
117 		lift_stn->starting_station = 1;
118 	else
119 		lift_stn->starting_station = 0;
120 
121 	lift_stn->called = 0;
122 
123 	// fill in the behaviour block
124 
125 	lift_bhv->control_sb = NULL;
126 	lift_bhv->controller = lift_tt->controller;
127 	COPY_NAME(lift_bhv->control_sb_name, lift_tt->control_sb_name);
128 
129 	if(lift_bhv->controller)
130 	{
131 		LIFT_CONTROL_BLOCK* lcont = AllocateMem(sizeof(LIFT_CONTROL_BLOCK));
132 		if(!lcont)
133 		{
134 			memoryInitialisationFailure = 1;
135 			return ((void *)NULL);
136 		}
137 
138 		lift_bhv->lift_control = lcont;
139 
140 		// fill in the number of floors
141 
142 		lcont->num_stations	= lift_tt->num_stations;
143   	lcont->lift_stations = (LIFT_STATION**)AllocateMem(sizeof(LIFT_STATION*)*lcont->num_stations);
144 
145 		if(!lcont->lift_stations)
146 		{
147 			memoryInitialisationFailure = 1;
148 			return ((void *)NULL);
149 		}
150 
151 		//and init that array
152 		{
153 			int i=0;
154 			while(i < lcont->num_stations)
155 			{
156 				*(lcont->lift_stations + i) = NULL;
157 				i++;
158 			}
159 		}
160 		// fill in the rest of the data
161 
162 		*(lcont->lift_stations + lift_stn->num_floor) = lift_stn;
163 		lcont->dest_station = -1;
164 		lcont->delay_at_floor = 0;
165 		lcont->delay_between_floors = 0;
166 		lcont->motion = I_going_down;
167 		lcont->state = I_ls_waiting;
168 		lcont->curr_station = -1;
169 		lcont->prev_station = -1;
170 		lcont->SoundHandle = SOUND_NOACTIVEINDEX;
171 
172 
173 		if(lift_tt->lift_flags & LiftFlag_NoTel)
174 			lcont->floor_switches_fixed=1;
175 		else
176 			lcont->floor_switches_fixed=0;
177 
178 	}
179 
180 
181 	return((void*)lift_bhv);
182 }
183 
184 
185 // this function reposts anything that would prevent
186 // The palyer most be in the module and nothing
187 // else can be
188 
189 
BadGuyInModuleOrNoPlayer()190 BOOL BadGuyInModuleOrNoPlayer()
191 {
192 	return(0);
193 }
194 
195 /*************************** LIFT CONTROL *****************************/
196 
LiftBehaveFun(STRATEGYBLOCK * sbptr)197 void LiftBehaveFun(STRATEGYBLOCK* sbptr)
198 {
199 	LIFT_BEHAV_BLOCK *lift_bhv;
200 	LIFT_CONTROL_BLOCK *lift_ctrl;
201 	LIFT_STATION *curr_stn;
202 	I_AVP_ENVIRONMENTS dest_env;
203 
204  	GLOBALASSERT(sbptr);
205 	lift_bhv = (LIFT_BEHAV_BLOCK*)sbptr->SBdataptr;
206 	GLOBALASSERT((lift_bhv->bhvr_type == I_BehaviourLift));
207 
208 	curr_stn = &lift_bhv->lift_station;
209 	GLOBALASSERT(curr_stn);
210 
211 	lift_ctrl = lift_bhv->lift_control;
212 
213 
214 	/* ALL the lift modules have a Strategy block that contains inforamtion
215 		 about that particular location. Only one points to the LIFT CONTROL
216 		 BLOCK
217 	*/
218 
219 	/* the lifts will work between envs as well as on the same env
220 		 so the control of the doors in the other envs sin't actually set,
221 		 but a record of the postion is maintained
222 	*/
223 
224 
225 
226 	if(lift_bhv->controller)
227    	{
228 
229    		// HACK	- RWH - if this is true the data is broken and this fix won't always work
230 
231    		if(lift_ctrl->curr_station == -1)
232    			lift_ctrl->curr_station = 0;
233 
234    		switch(lift_ctrl->state)
235 		{
236 			case I_ls_waiting:
237 			 {
238 			 	/*** find dest and set movement direction this is always the
239 			 	same even if the lift is on a different floor ***/
240 			 	int lower_station = -1;
241 			 	int upper_station = -1;
242 			 	int i;
243 			 	LIFT_STATION *lift_stn;
244 
245 			 	/**** find the nearest floors selected ****/
246 
247 				// search up and down
248 			 	for(i = lift_ctrl->curr_station; (i >= 0) && (lower_station == -1); i --)
249 		 		{
250 		 			lift_stn = lift_ctrl->lift_stations[i];
251 
252 		 			if(lift_stn->called)
253 		 					upper_station = i;    // higher floors have lower nums
254 		 		}
255 			 	for(i = lift_ctrl->curr_station; (i < lift_ctrl->num_stations) && (upper_station == -1); i ++)
256 		 		{
257 		 			lift_stn = lift_ctrl->lift_stations[i];
258 
259 		 			if(lift_stn->called)
260 		 				lower_station = i;      // lower floors have higher nums
261 		 		}
262 
263 			 	/****** set the	destination and the motion direction ****/
264 
265 			 	if(lift_ctrl->motion == I_going_down)// higher nums
266 			 	 {
267 			 	 	if(lower_station != -1)
268 					{
269 						lift_ctrl->dest_station = lower_station;
270 					}
271 			 	 	else
272 		 	 		{
273 		 	 			lift_ctrl->dest_station = upper_station;
274 		 	 			lift_ctrl->motion =I_going_up;
275 		 	 		}
276 			 	 }
277 				else if(lift_ctrl->motion == I_going_up) // lower nums
278 				{
279 					if(upper_station != -1)
280 					{
281 						lift_ctrl->dest_station = upper_station;
282 					}
283 					else
284 					{
285 						lift_ctrl->dest_station = lower_station;
286 						lift_ctrl->motion =I_going_down;
287 					}
288 				}
289 
290 			 	// now we have a station to go to, we start the lift in motion
291 			 	// unless we have just pressed the current floor switch again
292 
293 			 	if(lift_ctrl->dest_station == lift_ctrl->curr_station)
294 		 		{
295 		 			// we have just called the lift to the same place
296 		 			lift_ctrl->dest_station = -1;
297 		 			lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
298 		 			lift_stn->called = 0;
299 		 		}
300 			 	else if(lift_ctrl->dest_station != -1)
301 		 		{
302 		 			// if there is a dest, set the lift to go
303 		 			// close current stations
304 		 			lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
305 
306 		 			lift_ctrl->prev_station = lift_ctrl->curr_station;
307 		 			if(lift_stn->lift_door)
308  					{
309  						// no door - must be on another env
310  						RequestState(lift_stn->lift_door, 0, 0);
311  					}
312 		 			lift_ctrl->state = I_ls_closing_door;
313 		 		}
314 
315 			 	break;
316 			 }
317 			case I_ls_closing_door:
318 				{
319 					// lift station for the current lift position has to
320 					// have a closed door
321 
322 					BOOL door_state;
323 					LIFT_STATION *pos_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
324 					MODULE* mptr;
325 
326 					mptr = pos_stn->lift_module;
327 
328 					// deal with the fact that the lift is in a different env
329 
330 					// same env - normal code
331 					// called from us to another env -  normal code
332 					// called from another env to us - jump the close door
333 
334 					if(pos_stn->env != AvP.CurrentEnv)
335 						{
336 	 						lift_ctrl->state = I_ls_moving;
337 							lift_ctrl->delay_between_floors = LIFT_MOVE_DELAY;
338 							break;
339 						}
340 
341 					// otherwise run normal code
342 					// close the door before we change state to moving
343 
344 					door_state = GetState(pos_stn->lift_door);
345 
346 					if(!door_state)
347 						{
348 							// turn off the current lift position station call switches
349 							// run only when pos_stn is in our own env POSSIBLE BUG -
350 							// lift wont be called to our floor if there is an Alien in it
351 
352 							if(BadGuyInModuleOrNoPlayer())
353 							{
354 								lift_ctrl->state = I_ls_opening_door;
355 								lift_ctrl->dest_station = -1;
356 								lift_ctrl->delay_between_floors = -1;
357 								RequestState(pos_stn->lift_door, 1, 0);
358 							}
359 							else
360 							{
361 
362 		 						lift_ctrl->state = I_ls_moving;
363 								lift_ctrl->delay_between_floors = LIFT_MOVE_DELAY;
364 
365 								RequestState(pos_stn->lift_call_switch, 0, 0);
366 								if(pos_stn->lift_floor_switch)
367 									RequestState(pos_stn->lift_floor_switch, 0, 0);
368 
369 								//what if there is a bad guy in the lift - if there is open the door
370 								//and reset all the switches and stations
371 
372 								if (lift_ctrl->SoundHandle==SOUND_NOACTIVEINDEX)
373 								{
374 									GLOBALASSERT(mptr);
375 									Sound_Play(SID_LIFT_START,"dh",&mptr->m_world);
376 									Sound_Play(SID_LIFT_LOOP,"delh",&mptr->m_world, &lift_ctrl->SoundHandle);
377 								}
378 							}
379 
380 						}
381 						break;
382 				 }
383 
384 			case I_ls_moving:
385 				{
386 					int curr_station_num = lift_ctrl->curr_station;
387 					LIFT_STATION *pos_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
388 					MODULE* mptr;
389 					mptr = pos_stn->lift_module;
390 
391 
392 
393 					dest_env = lift_ctrl->lift_stations[lift_ctrl->dest_station]->env;
394 
395 						lift_ctrl->delay_between_floors -= NormalFrameTime;
396 
397 					// TRAP CHANGE OF ENVIRONMENT
398 					// we need to trap it here so we don't have the delay
399 					// between floors. However. The trap should make sure it is the nex array pos
400 
401 					if(AvP.CurrentEnv != dest_env)
402 						{
403 							// have to load an env - can we do it next - is the
404 							// new env the next floor in the array??
405 
406 							if(lift_ctrl->motion == I_going_up)
407 								{
408 									curr_station_num --;
409 								}
410 							else
411 								{
412 									curr_station_num ++;
413 								}
414 							lift_ctrl->curr_station=curr_station_num;
415 							if(curr_station_num == lift_ctrl->dest_station)
416 								{
417 									// OKAY chnage Environment VIA LIFT
418 									// we need a copy of our current module pos
419 									// (for the teleport), a copy of the
420 									// SBs in our module and a copy of the lift
421 									// control block
422 
423 									LIFT_STATION *lift_stn_old;
424 									EC_Lift_Ctrl = *lift_ctrl;
425 
426 									lift_stn_old = EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.prev_station];
427 									Old_Pos_Module = *lift_stn_old->lift_module;
428 
429 									InitPreservedSBs();
430 									PreserveStBlocksInModule(&Old_Pos_Module);
431 
432 									EC_Lift_Ctrl.curr_station = curr_station_num;
433 									RequestEnvChangeViaLift = 1;
434 
435 									// we now do the rest of the SBs. before we
436 									// can chack the env - note that NOTHING can move
437 									// into the lift now.
438 
439 								}
440 
441 						}
442 
443 					// else do normal code
444 
445 					else if((lift_ctrl->delay_between_floors < 0))
446 						{
447 							if(lift_ctrl->motion == I_going_up)
448 								{
449 									lift_ctrl->curr_station --;
450 								}
451 							else
452 								{
453 									lift_ctrl->curr_station ++;
454 								}
455 
456 
457 
458 							LOCALASSERT(lift_ctrl->curr_station >= 0);
459 
460 
461 
462 							if(lift_ctrl->curr_station == lift_ctrl->dest_station)
463 							{
464 								// at destination
465 									LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
466 								LIFT_STATION *lift_stn_old = lift_ctrl->lift_stations[lift_ctrl->prev_station];
467 								MODULE *new_pos, *old_pos;
468 
469 								new_pos = lift_stn_new->lift_module;
470 								old_pos = lift_stn_old->lift_module;
471 
472 								lift_ctrl->dest_station = -1;
473 								lift_ctrl->state = I_ls_opening_door;
474 
475 								/* roxby: i have taken this out - patrick */
476 								/* GLOBALASSERT(mptr); */
477 								Sound_Play(SID_LIFT_END,"h");
478 								Sound_Stop(lift_ctrl->SoundHandle);
479 
480 								//  door open
481 
482 								RequestState(lift_stn_new->lift_door, 1, 0);
483 
484 								lift_stn_new->called = 0;
485 
486 								if(old_pos)
487 								{
488 									// if we don't have an old pos, we must
489 									// be coming from another env
490 									TeleportContents(new_pos, old_pos,lift_ctrl->floor_switches_fixed);
491 								}
492 							}
493 
494 							else
495 							{
496 							 	// interrupt monment to stop at new floor
497 							 	//this should never happen in a seperate env
498 							 	LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
499 							 	LIFT_STATION *lift_stn_old = lift_ctrl->lift_stations[lift_ctrl->prev_station];
500 							 	MODULE* old_pos, *new_pos;
501 							 	// to trap button presses when moving between floors -
502 							 	// not really ness and it complecates things
503 							 	old_pos = lift_stn_old->lift_module;
504 							 	new_pos = lift_stn_new->lift_module;
505 #if 0
506 
507 							 	if(lift_stn_new->called)
508 						 		{
509 						 			lift_ctrl->state = I_ls_opening_door;
510 						 			RequestState(lift_stn_new->lift_call_switch, 0, 0);
511 						 			if(lift_stn_new->lift_floor_switch)
512 						 				RequestState(lift_stn_new->lift_floor_switch, 0, 0);
513 						 			RequestState(lift_stn_new->lift_door, 1, 0);
514 
515 						 			if(old_pos)
516 						 				{
517 						 					// if we don't have an old pos, we must
518 						 					// be coming from another env
519 						 					TeleportContents(new_pos, old_pos,lift_ctrl->floor_switches_fixed);
520 						 				}
521 
522 						 			lift_stn_new->called = 0;
523 
524 						 		}
525 							 	else
526 #endif
527 						 		{
528 						 			// futher to go - move along now
529 						 			lift_ctrl->delay_between_floors += LIFT_MOVE_DELAY;
530 						 		}
531 							 }
532 						}
533 
534 					break;
535 				}
536 			case I_ls_opening_door:
537 				{
538 					LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
539 					BOOL door_state = GetState(lift_stn_new->lift_door);
540 
541 					if(door_state)
542 						{
543 							lift_ctrl->state = I_ls_delay_at_floor;
544 							lift_ctrl->delay_at_floor = LIFT_FLOOR_DELAY;
545 						}
546 					break;
547 				}
548 			case I_ls_delay_at_floor:
549 				{
550 					lift_ctrl->delay_at_floor -= NormalFrameTime;
551 
552 					if(lift_ctrl->delay_at_floor < 0)
553 						{
554 						 	LIFT_STATION *lift_stn;
555 
556 							// turn on the floor lights
557 							lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
558 
559 							RequestState(lift_stn->lift_call_switch, 1, 0);
560 							if(lift_stn->lift_floor_switch_name[0] ||	lift_stn->lift_floor_switch_name[4])
561 								RequestState(lift_stn->lift_floor_switch, 1, 0);
562 
563 
564 							lift_ctrl->state = I_ls_waiting;
565 							lift_ctrl->dest_station = -1;
566 
567 						}
568 					break;
569 				}
570 
571 			default:
572 
573 				GLOBALASSERT(2<1);
574 		}
575    	}
576 
577 }
578 
579 
TeleportContents(MODULE * new_pos,MODULE * old_pos,BOOL floor_switches_fixed)580 void TeleportContents(MODULE* new_pos, MODULE* old_pos,BOOL floor_switches_fixed)
581 {
582 	//	this used within level - find objects in module
583 	// all will have sbs
584 
585 	int i;
586 	int max_x, min_x, max_y, min_y, max_z, min_z;
587 	int dest_max_x, dest_min_x, dest_max_y, dest_min_y, dest_max_z, dest_min_z;
588 	VECTORCH mod_offset;
589 
590 	mod_offset.vx = new_pos->m_world.vx - old_pos->m_world.vx;
591 	mod_offset.vy = new_pos->m_world.vy - old_pos->m_world.vy;
592 	mod_offset.vz = new_pos->m_world.vz - old_pos->m_world.vz;
593 
594 	max_x = old_pos->m_maxx + old_pos->m_world.vx;
595 	min_x = old_pos->m_minx + old_pos->m_world.vx;
596 	max_y = old_pos->m_maxy + old_pos->m_world.vy;
597 	min_y = old_pos->m_miny + old_pos->m_world.vy;
598 	max_z = old_pos->m_maxz + old_pos->m_world.vz;
599 	min_z = old_pos->m_minz + old_pos->m_world.vz;
600 
601 	dest_max_x = new_pos->m_maxx + new_pos->m_world.vx -200;
602 	dest_min_x = new_pos->m_minx + new_pos->m_world.vx +200;
603 	dest_max_y = new_pos->m_maxy + new_pos->m_world.vy -200;
604 	dest_min_y = new_pos->m_miny + new_pos->m_world.vy +200;
605 	dest_max_z = new_pos->m_maxz + new_pos->m_world.vz -200;
606 	dest_min_z = new_pos->m_minz + new_pos->m_world.vz +200;
607 
608 	for(i = 0; i < NumActiveStBlocks; i++)
609 		{
610 			VECTORCH obj_world;
611 			STRATEGYBLOCK	*sbptr;
612 			DYNAMICSBLOCK	*dynptr;
613 
614 			sbptr = ActiveStBlockList[i];
615 
616 			if(!(dynptr = sbptr->DynPtr))
617 				continue;
618 
619 			if(floor_switches_fixed)
620 			{
621 			 	if(sbptr->I_SBtype==I_BehaviourBinarySwitch || sbptr->I_SBtype==I_BehaviourLinkSwitch)
622 					continue;
623 				else if(sbptr->I_SBtype==I_BehaviourInanimateObject && ((INANIMATEOBJECT_STATUSBLOCK*)sbptr->SBdataptr)->typeId==0)
624 					continue;
625 			}
626 			obj_world = dynptr->Position;
627 
628 			if(obj_world.vx < max_x)
629 				if(obj_world.vx > min_x)
630 					if(obj_world.vz < max_z)
631 						if(obj_world.vz > min_z)
632 							if(obj_world.vy < max_y)
633 								if(obj_world.vy > min_y)
634 									{
635 
636 										dynptr->Position.vx += mod_offset.vx;
637 										dynptr->Position.vy += mod_offset.vy;
638 										dynptr->Position.vz += mod_offset.vz;
639 
640 										dynptr->PrevPosition.vx += mod_offset.vx;
641 										dynptr->PrevPosition.vy += mod_offset.vy;
642 										dynptr->PrevPosition.vz += mod_offset.vz;
643 
644 										//make sure new location is inside destination module
645 										if(!dynptr->IsStatic)
646 										{
647 											if(dynptr->Position.vx<dest_min_x) dynptr->Position.vx=dest_min_x;
648 											if(dynptr->Position.vy<dest_min_y) dynptr->Position.vy=dest_min_y;
649 											if(dynptr->Position.vz<dest_min_z) dynptr->Position.vz=dest_min_z;
650 											if(dynptr->Position.vx>dest_max_x) dynptr->Position.vx=dest_max_x;
651 											if(dynptr->Position.vy>dest_max_y) dynptr->Position.vy=dest_max_y;
652 											if(dynptr->Position.vz>dest_max_z) dynptr->Position.vz=dest_max_z;
653 
654 											if(dynptr->PrevPosition.vx<dest_min_x) dynptr->PrevPosition.vx=dest_min_x;
655 											if(dynptr->PrevPosition.vy<dest_min_y) dynptr->PrevPosition.vy=dest_min_y;
656 											if(dynptr->PrevPosition.vz<dest_min_z) dynptr->PrevPosition.vz=dest_min_z;
657 											if(dynptr->PrevPosition.vx>dest_max_x) dynptr->PrevPosition.vx=dest_max_x;
658 											if(dynptr->PrevPosition.vy>dest_max_y) dynptr->PrevPosition.vy=dest_max_y;
659 											if(dynptr->PrevPosition.vz>dest_max_z) dynptr->PrevPosition.vz=dest_max_z;
660 										}
661 
662 										if(sbptr->maintainVisibility)
663 											{
664 												sbptr->containingModule = new_pos;
665 											}
666 									}
667 		}
668 }
669 
670 
CleanUpLiftControl()671 void CleanUpLiftControl()
672 {
673 	// okay - we have selected a new env AND it is the
674 	// next env in the list - lets go with the load
675 	// we need a copu list of strat blocks that WE DO NOT
676 	// DEALLOCATE the behaviour / dyn blocks for. We then
677 	// reinitialise AFTER these have been inserted into the
678 
679 
680 	// ActiveStBlockList
681 	LIFT_STATION *lift_stn = EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.dest_station];
682 
683 	char dest_mod_name[8];
684 	MODULE *new_pos_module;
685 	int orient_diff;
686 
687 	STRATEGYBLOCK* new_loc_sbptr;
688 
689 	COPY_NAME(dest_mod_name, lift_stn->my_sb_name);
690 
691 	orient_diff =  EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.dest_station]->orient
692 					- EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.prev_station]->orient;
693 
694 
695 	// DESTROYS ALL OUR OLD DATA - ONLY OUR
696 	// COPIES REMAIN
697 
698 	ChangeEnvironmentToEnv(lift_stn->env);
699 
700 	IntegrateNewEnvironment();
701 
702 	// find where we have teleported to
703 
704 	new_loc_sbptr = FindSBWithName(dest_mod_name);
705 	GLOBALASSERT(new_loc_sbptr);
706 	new_pos_module = new_loc_sbptr->SBmoptr;
707 
708 	// teleport the bastrads
709 	TeleportPreservedSBsToNewEnvModule(new_pos_module, &Old_Pos_Module,orient_diff);
710 	AddPreservedSBsToActiveList();
711 
712 	// find the new control block anc copy our preserved one in
713 	// need to recalc lift_station_new
714 
715   	{
716   		LIFT_BEHAV_BLOCK *lift_bhv;
717   		LIFT_CONTROL_BLOCK *lift_ctrl;
718   		LIFT_STATION *lift_stn_new;
719 
720   		lift_bhv = (LIFT_BEHAV_BLOCK*)new_loc_sbptr->SBdataptr;
721   		GLOBALASSERT((lift_bhv->bhvr_type == I_BehaviourLift));
722 
723   		lift_ctrl = lift_bhv->lift_control;
724 
725   		GLOBALASSERT(lift_ctrl->num_stations == EC_Lift_Ctrl.num_stations);
726 
727   		// copy over the vital bits
728 
729   		lift_ctrl->curr_station = EC_Lift_Ctrl.curr_station;
730   		lift_ctrl->prev_station = EC_Lift_Ctrl.prev_station;
731   		lift_ctrl->motion = EC_Lift_Ctrl.motion;
732 
733   		// and get into the right state
734 
735   		lift_ctrl->state = I_ls_opening_door;
736   		lift_ctrl->dest_station = -1;
737 
738   		// and get the periphs into their right states
739 		// get the new lift station
740   		lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
741 
742 		//set all the other station switches to off to overdide
743 		// the starting_station init in AssignAllSBNames
744 
745 		{
746 			int i;
747 			LIFT_STATION *liftStnPtr;
748 
749 			for(i=0; i < lift_ctrl->num_stations; i++)
750 			{
751 				liftStnPtr = lift_ctrl->lift_stations[i];
752 				if(liftStnPtr->env == AvP.CurrentEnv)
753 				{
754 					RequestState(liftStnPtr->lift_call_switch, 0, 0);
755 					RequestState(liftStnPtr->lift_floor_switch, 0, 0);
756 					RequestState(liftStnPtr->lift_door, 0, 0);
757 				}
758 			}
759 		}
760 
761 		// set our current stations periphs into the correct
762 		// state
763 
764 
765 		RequestState(lift_stn_new->lift_call_switch, 1, 0);
766 		RequestState(lift_stn_new->lift_floor_switch, 1, 0);
767    		RequestState(lift_stn_new->lift_door, 1, 0);
768 
769 		TeleportFloorSwitches
770 		(
771 			lift_stn_new->lift_module,
772 			lift_stn_new->lift_floor_switch->containingModule,
773 			lift_ctrl
774 		);
775 
776   		InitPreservedSBs();
777 
778   		UpdateWeaponShape(); // so we get the correct shape in the MSL
779   	}
780 }
781 
782 
783 
784 
785 
TeleportFloorSwitches(MODULE * dest,MODULE * src,LIFT_CONTROL_BLOCK * liftCtrl)786 static void TeleportFloorSwitches
787 (
788 	MODULE* dest,
789 	MODULE* src,
790 	LIFT_CONTROL_BLOCK * liftCtrl
791 )
792 {
793 	if(dest != src)
794 	{
795 		TeleportContents(dest, src, 0);
796 	}
797 }
798