1 /*
2 MAP_CONSTRUCTORS.C
3 
4 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 	and the "Aleph One" developers.
6 
7 	This program is free software; you can redistribute it and/or modify
8 	it under the terms of the GNU General Public License as published by
9 	the Free Software Foundation; either version 3 of the License, or
10 	(at your option) any later version.
11 
12 	This program is distributed in the hope that it will be useful,
13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 	GNU General Public License for more details.
16 
17 	This license is contained in the file "COPYING",
18 	which is included with this source code; it is available online at
19 	http://www.gnu.org/licenses/gpl.html
20 
21 Friday, June 3, 1994 1:06:31 PM
22 
23 Thursday, March 23, 1995 8:53:35 PM  (Jason')
24 	added guess_side_lightsource_indexes().
25 
26 Jan 30, 2000 (Loren Petrich):
27 	Added some typecasts
28 
29 Feb. 4, 2000 (Loren Petrich):
30 	Changed halt() to assert(false) for better debugging
31 
32 Feb 15, 2000 (Loren Petrich):
33 	Suppressed some assertions designed to check for map consistency;
34 	this is to get around some Pfhorte bugs.
35 
36 April 16, 2000 (Loren Petrich):
37 	Made the incorrect-count vwarns optional
38 
39 Aug 29, 2000 (Loren Petrich):
40 	Created packing and unpacking functions for all the
41 		externally-accessible data types defined here
42 
43 Dec 14, 2000 (Loren Petrich):
44 	Added growable lists for lists of intersecting endpoints, lines, and polygons
45 */
46 
47 #if defined(NEW_AND_BROKEN) || defined(WITH_ORIGINAL_DATA_STRUCTURES)
48 const bool DoIncorrectCountVWarn = true;
49 #endif
50 
51 
52 #include "cseries.h"
53 #include "map.h"
54 #include "flood_map.h"
55 #include "platforms.h"
56 #include "Packing.h"
57 
58 #include <limits.h>
59 #include <vector>
60 
61 /*
62 maps of one polygon don�t have their impassability information computed
63 
64 //detached polygons (i.e., shadows) and their twins will not have their neighbor polygon lists correctly computed
65 //adjacent polygons should be precalculated in the polygon structure
66 //intersecting_flood_proc can�t store side information (using sign) with line index zero
67 //keep_line_segment_out_of_walls() can�t use precalculated height information and should do weird things next to elevators and doors
68 */
69 
70 /* ---------- structures */
71 
72 #define MAXIMUM_INTERSECTING_INDEXES 64
73 
74 struct intersecting_flood_data
75 {
76 	// This stuff now global:
77 	/*
78 	short *line_indexes;
79 	short line_count;
80 
81 	short *endpoint_indexes;
82 	short endpoint_count;
83 
84 	short *polygon_indexes;
85 	short polygon_count;
86 	*/
87 
88 	short original_polygon_index;
89 	world_point2d center;
90 
91 	int32 minimum_separation_squared;
92 };
93 
94 /* ---------- globals */
95 static int32 map_index_buffer_count= 0l; /* Added due to the dynamic nature of maps */
96 
97 // LP: Temporary areas for nearby endpoint/line/polygon finding;
98 // OK for this to be global since they replace only single instances.
99 static vector<short> LineIndices(MAXIMUM_INTERSECTING_INDEXES);
100 static vector<short> EndpointIndices(MAXIMUM_INTERSECTING_INDEXES);
101 static vector<short> PolygonIndices(MAXIMUM_INTERSECTING_INDEXES);
102 
103 
104 /* ---------- private prototypes */
105 
106 static short calculate_clockwise_endpoints(short polygon_index, short *buffer);
107 static void calculate_adjacent_polygons(short polygon_index, short *polygon_indexes);
108 static void calculate_adjacent_sides(short polygon_index, short *side_indexes);
109 static int32 calculate_polygon_area(short polygon_index);
110 
111 static void add_map_index(short index, short *count);
112 static void find_intersecting_endpoints_and_lines(short polygon_index, world_distance minimum_separation);
113 static int32 intersecting_flood_proc(short source_polygon_index, short line_index,
114 	short destination_polygon_index, void *data);
115 
116 static void precalculate_polygon_sound_sources(void);
117 
118 /* ---------- code */
119 
recalculate_side_type(short side_index)120 void recalculate_side_type(short side_index)
121 {
122 	side_data *side = get_side_data(side_index);
123 	short opposite_index = find_adjacent_polygon(side->polygon_index, side->line_index);
124 	polygon_data *polygon = get_polygon_data(side->polygon_index);
125 	if (opposite_index != NONE)
126 	{
127 		polygon_data *opposite = get_polygon_data(opposite_index);
128 		int ceiling_height, floor_height, opposite_ceiling_height, opposite_floor_height;
129 		if (polygon->type == _polygon_is_platform)
130 		{
131 			platform_data *platform = get_platform_data(polygon->permutation);
132 			ceiling_height = platform->maximum_ceiling_height;
133 			floor_height = platform->minimum_floor_height;
134 		}
135 		else
136 		{
137 			ceiling_height = polygon->ceiling_height;
138 			floor_height = polygon->floor_height;
139 		}
140 
141 		if (opposite->type == _polygon_is_platform)
142 		{
143 			platform_data *platform = get_platform_data(opposite->permutation);
144 			opposite_ceiling_height = platform->minimum_ceiling_height;
145 			opposite_floor_height = platform->maximum_floor_height;
146 		}
147 		else
148 		{
149 			opposite_ceiling_height = opposite->ceiling_height;
150 			opposite_floor_height = opposite->floor_height;
151 		}
152 
153 		if (opposite_ceiling_height < ceiling_height && opposite_floor_height > floor_height)
154 		{
155 			side->type = _split_side;
156 		}
157 		else if (opposite_floor_height > floor_height)
158 		{
159 			side->type = _low_side;
160 		}
161 		else if (opposite_ceiling_height < ceiling_height)
162 		{
163 			side->type = _high_side;
164 		}
165 		else
166 			side->type = _full_side;
167 
168 	}
169 	else
170 	{
171 		side->type = _full_side;
172 	}
173 }
174 
new_side(short polygon_index,short line_index)175 short new_side(short polygon_index, short line_index)
176 {
177 	line_data *line = get_line_data(line_index);
178 	polygon_data *polygon = get_polygon_data(polygon_index);
179 
180 	assert((line->clockwise_polygon_owner == polygon_index && line->clockwise_polygon_side_index == NONE )|| (line->counterclockwise_polygon_owner == polygon_index && line->counterclockwise_polygon_side_index == NONE));
181 
182 	side_data side;
183 	obj_clear(side);
184 	side.primary_texture.texture = UNONE;
185 	side.secondary_texture.texture = UNONE;
186 	side.transparent_texture.texture = UNONE;
187 
188 	short side_index = SideList.size();
189 	SideList.push_back(side);
190 	dynamic_world->side_count++;
191 
192 	if (line->clockwise_polygon_owner == polygon_index)
193 		line->clockwise_polygon_side_index = side_index;
194 	else
195 		line->counterclockwise_polygon_side_index = side_index;
196 	recalculate_redundant_side_data(side_index, line_index);
197 	calculate_adjacent_sides(polygon_index, polygon->side_indexes);
198 
199 	recalculate_side_type(side_index);
200 	return side_index;
201 }
202 
203 
204 /* calculates area, clockwise endpoint list, adjacent polygons */
recalculate_redundant_polygon_data(short polygon_index)205 void recalculate_redundant_polygon_data(
206 	short polygon_index)
207 {
208 	struct polygon_data *polygon= get_polygon_data(polygon_index);
209 
210 	if (!POLYGON_IS_DETACHED(polygon))
211 	{
212 		calculate_clockwise_endpoints(polygon_index, polygon->endpoint_indexes);
213 		calculate_adjacent_polygons(polygon_index, polygon->adjacent_polygon_indexes);
214 		polygon->area= calculate_polygon_area(polygon_index);
215 
216 		find_center_of_polygon(polygon_index, &polygon->center);
217 		calculate_adjacent_sides(polygon_index, polygon->side_indexes);
218 	}
219 
220 	// TEMPORARY UNTIL THE EDITOR SETS THESE FIELDS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
221 //	polygon->media_lightsource_index= polygon->floor_lightsource_index;
222 //	polygon->ambient_sound_image_index= NONE;
223 //	polygon->random_sound_image_index= NONE;
224 }
225 
226 /* calculates solidity, highest adjacent floor and lowest adjacent ceiling; not to be called
227 	at runtime. */
recalculate_redundant_endpoint_data(short endpoint_index)228 void recalculate_redundant_endpoint_data(
229 	short endpoint_index)
230 {
231 	struct endpoint_data *endpoint= get_endpoint_data(endpoint_index);
232 	world_distance highest_adjacent_floor_height= INT16_MIN;
233 	world_distance lowest_adjacent_ceiling_height= INT16_MAX;
234 	short supporting_polygon_index= NONE;
235 	struct line_data *line;
236 	short line_index;
237 	bool solid= false;
238 	bool elevation= false;
239 	bool transparent= true;
240 
241 	for (line_index= 0, line= map_lines; line_index<dynamic_world->line_count; ++line_index, ++line)
242 	{
243 		/* does this line contain our endpoint? */
244 		if (line->endpoint_indexes[0]==endpoint_index||line->endpoint_indexes[1]==endpoint_index)
245 		{
246 			short polygon_index;
247 			struct polygon_data *polygon;
248 
249 			/* if this line is solid, so is the endpoint */
250 			if (LINE_IS_SOLID(line)) solid= true;
251 			if (!LINE_IS_TRANSPARENT(line)) transparent= false;
252 			if (LINE_IS_ELEVATION(line)) elevation= true;
253 
254 			/* look at adjacent polygons to determine highest floor and lowest ceiling */
255 			polygon_index= line->clockwise_polygon_owner;
256 			if (polygon_index!=NONE)
257 			{
258 				polygon= get_polygon_data(polygon_index);
259 				if (highest_adjacent_floor_height<polygon->floor_height)
260                     {
261                         highest_adjacent_floor_height= polygon->floor_height;
262                         supporting_polygon_index= polygon_index;
263                     }
264 				if (lowest_adjacent_ceiling_height>polygon->ceiling_height) lowest_adjacent_ceiling_height= polygon->ceiling_height;
265 			}
266 			polygon_index= line->counterclockwise_polygon_owner;
267 			if (polygon_index!=NONE)
268 			{
269 				polygon= get_polygon_data(polygon_index);
270                    if (highest_adjacent_floor_height<polygon->floor_height)
271                    {
272                        highest_adjacent_floor_height= polygon->floor_height;
273                        supporting_polygon_index= polygon_index;
274                    }
275 				if (lowest_adjacent_ceiling_height>polygon->ceiling_height) lowest_adjacent_ceiling_height= polygon->ceiling_height;
276 			}
277 		}
278 	}
279 
280 	SET_ENDPOINT_SOLIDITY(endpoint, solid);
281 	SET_ENDPOINT_TRANSPARENCY(endpoint, transparent);
282 	SET_ENDPOINT_ELEVATION(endpoint, elevation);
283 	endpoint->highest_adjacent_floor_height= highest_adjacent_floor_height;
284 	endpoint->lowest_adjacent_ceiling_height= lowest_adjacent_ceiling_height;
285 	endpoint->supporting_polygon_index= supporting_polygon_index;
286 }
287 
288 /* calculates line length, highest adjacent floor and lowest adjacent ceiling and calls
289 	recalculate_redundant_side_data() on the line�s sides */
recalculate_redundant_line_data(short line_index)290 void recalculate_redundant_line_data(
291 	short line_index)
292 {
293 	struct line_data *line= get_line_data(line_index);
294 	struct side_data *clockwise_side= NULL, *counterclockwise_side= NULL;
295 	bool elevation= false;
296 	bool landscaped= false;
297 	bool variable_elevation= false;
298 	bool transparent_texture= false;
299 
300 	/* recalculate line length */
301 	line->length= distance2d(&(get_endpoint_data(line->endpoint_indexes[0])->vertex),
302 		&(get_endpoint_data(line->endpoint_indexes[1])->vertex));
303 
304 	/* find highest adjacent floor and lowest adjacent ceiling */
305 	{
306 		struct polygon_data *polygon1, *polygon2;
307 
308 		polygon1= (line->clockwise_polygon_owner == NONE) ? (struct polygon_data *) NULL : get_polygon_data(line->clockwise_polygon_owner);
309 		polygon2= (line->counterclockwise_polygon_owner == NONE) ? (struct polygon_data *) NULL : get_polygon_data(line->counterclockwise_polygon_owner);
310 
311 		if ((polygon1&&polygon1->type==_polygon_is_platform) || (polygon2&&polygon2->type==_polygon_is_platform)) variable_elevation= true;
312 
313 		if (polygon1&&polygon2)
314 		{
315 			line->highest_adjacent_floor= MAX(polygon1->floor_height, polygon2->floor_height);
316 			line->lowest_adjacent_ceiling= MIN(polygon1->ceiling_height, polygon2->ceiling_height);
317 			if (polygon1->floor_height != polygon2->floor_height) elevation= true;
318 		}
319 		else
320 		{
321 			elevation= true;
322 
323 			if (polygon1)
324 			{
325 				line->highest_adjacent_floor= polygon1->floor_height;
326 				line->lowest_adjacent_ceiling= polygon1->ceiling_height;
327 			}
328 			else
329 			{
330 				if (polygon2)
331 				{
332 					line->highest_adjacent_floor= polygon2->floor_height;
333 					line->lowest_adjacent_ceiling= polygon2->ceiling_height;
334 				}
335 				else
336 				{
337 					line->highest_adjacent_floor= line->lowest_adjacent_ceiling= 0;
338 				}
339 			}
340 		}
341 	}
342 
343 	if (line->clockwise_polygon_side_index!=NONE)
344 	{
345 		recalculate_redundant_side_data(line->clockwise_polygon_side_index, line_index);
346 		clockwise_side= get_side_data(line->clockwise_polygon_side_index);
347 	}
348 	if (line->counterclockwise_polygon_side_index!=NONE)
349 	{
350 		recalculate_redundant_side_data(line->counterclockwise_polygon_side_index, line_index);
351 		counterclockwise_side= get_side_data(line->counterclockwise_polygon_side_index);
352 	}
353 
354 	if ((clockwise_side&&clockwise_side->primary_transfer_mode==_xfer_landscape) ||
355 		(counterclockwise_side&&counterclockwise_side->primary_transfer_mode==_xfer_landscape))
356 	{
357 		landscaped= true;
358 	}
359 
360 	if ((clockwise_side && clockwise_side->transparent_texture.texture!=UNONE) ||
361 		(counterclockwise_side && counterclockwise_side->transparent_texture.texture!=UNONE))
362 	{
363 		transparent_texture= true;
364 	}
365 
366 	SET_LINE_ELEVATION(line, elevation);
367 	SET_LINE_VARIABLE_ELEVATION(line, variable_elevation && !LINE_IS_SOLID(line));
368 	SET_LINE_LANDSCAPE_STATUS(line, landscaped);
369 	SET_LINE_HAS_TRANSPARENT_SIDE(line, transparent_texture);
370 }
371 
recalculate_redundant_side_data(short side_index,short line_index)372 void recalculate_redundant_side_data(
373 	short side_index,
374 	short line_index)
375 {
376 	struct side_data *side= get_side_data(side_index);
377 	struct line_data *line= get_line_data(line_index);
378 	world_point2d *e0 = NULL , *e1 = NULL;
379 
380 	// TEMPORARY UNTIL THE EDITOR SETS THESE FIELDS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
381 //	side->transparent_texture.texture= NONE; // no transparent texture
382 //	side->ambient_delta= 0;
383 
384 	if (line->clockwise_polygon_side_index==side_index)
385 	{
386 		e0= &get_endpoint_data(line->endpoint_indexes[0])->vertex;
387 		e1= &get_endpoint_data(line->endpoint_indexes[1])->vertex;
388 		side->polygon_index= line->clockwise_polygon_owner;
389 	}
390 	else
391 	{
392 		assert(side_index==line->counterclockwise_polygon_side_index);
393 
394 		e0= &(get_endpoint_data(line->endpoint_indexes[1])->vertex);
395 		e1= &(get_endpoint_data(line->endpoint_indexes[0])->vertex);
396 		side->polygon_index= line->counterclockwise_polygon_owner;
397 	}
398 
399 //	if (line_index==98) dprintf("line sides: %d,%d side_index==%d", line->clockwise_polygon_side_index, line->counterclockwise_polygon_side_index, side_index);
400 
401 	side->exclusion_zone.e0= side->exclusion_zone.e2= *e0;
402 	side->exclusion_zone.e1= side->exclusion_zone.e3= *e1;
403 	push_out_line(&side->exclusion_zone.e0, &side->exclusion_zone.e1, MINIMUM_SEPARATION_FROM_WALL, line->length);
404 
405 	side->line_index= line_index;
406 //	side->direction= arctangent(e0->x - e1->x, e0->y - e1->y);
407 
408 //	if (line_index==98||line_index==64)
409 //		dprintf("e0(%d,%d) e1(%d,%d) e2(%d,%d) e3(%d,%d)", impassable_side->e0.x, impassable_side->e0.y,
410 //		 impassable_side->e1.x, impassable_side->e1.y, impassable_side->e2.x, impassable_side->e2.y,
411 //		 impassable_side->e3.x, impassable_side->e3.y);
412 
413 	// TEMPORARY UNTIL THE EDITOR SETS THESE FIELDS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
414 //	guess_side_lightsource_indexes(side_index);
415 }
416 
calculate_endpoint_polygon_owners(short endpoint_index,short * first_index,short * index_count)417 void calculate_endpoint_polygon_owners(
418 	short endpoint_index,
419 	short *first_index,
420 	short *index_count)
421 {
422 	struct polygon_data *polygon = map_polygons;
423 	short polygon_index = 0;
424 
425 	*first_index= dynamic_world->map_index_count;
426 	*index_count= 0;
427 
428 	for (; polygon_index<dynamic_world->polygon_count ; ++polygon_index, ++polygon)
429 	{
430 		for (unsigned short i= 0; i<polygon->vertex_count; ++i)
431 		{
432 			if (endpoint_index==polygon->endpoint_indexes[i])
433 			{
434 				add_map_index(polygon_index, index_count);
435 			}
436 		}
437 	}
438 }
439 
calculate_endpoint_line_owners(short endpoint_index,short * first_index,short * index_count)440 void calculate_endpoint_line_owners(
441 	short endpoint_index,
442 	short *first_index,
443 	short *index_count)
444 {
445 	short line_index = 0;
446 	struct line_data *line = map_lines;
447 
448 	*first_index= dynamic_world->map_index_count;
449 	*index_count= 0;
450 
451 	for (; line_index<dynamic_world->line_count; ++line_index, ++line)
452 	{
453 		if (line->endpoint_indexes[0]==endpoint_index||line->endpoint_indexes[1]==endpoint_index)
454 		{
455 			add_map_index(line_index, index_count);
456 		}
457 	}
458 }
459 
460 #define CONTINUOUS_SPLIT_SIDE_HEIGHT WORLD_ONE
461 
guess_side_lightsource_indexes(short side_index)462 void guess_side_lightsource_indexes(
463 	short side_index)
464 {
465 	struct side_data *side= get_side_data(side_index);
466 	struct line_data *line= get_line_data(side->line_index);
467 	struct polygon_data *polygon= get_polygon_data(side->polygon_index);
468 
469 	short ceiling_index = polygon->ceiling_lightsource_index;
470 	short floor_index = polygon->floor_lightsource_index;
471 	// change floor lighting if poly is a flooded platform
472 	if (polygon->type == _polygon_is_platform)
473 	{
474 		struct platform_data *platform= get_platform_data(polygon->permutation);
475 		if (platform && PLATFORM_IS_FLOODED(platform))
476 		{
477 			short adj_index = find_flooding_polygon(side->polygon_index);
478 			if (adj_index != NONE)
479 			{
480 				struct polygon_data *adj_polygon= get_polygon_data(adj_index);
481 				floor_index = adj_polygon->floor_lightsource_index;
482 			}
483 		}
484 	}
485 
486 	switch (side->type)
487 	{
488 		case _full_side:
489 			side->primary_lightsource_index= ceiling_index;
490 			break;
491 		case _split_side:
492 			side->secondary_lightsource_index= (line->lowest_adjacent_ceiling-line->highest_adjacent_floor>CONTINUOUS_SPLIT_SIDE_HEIGHT) ?
493 				floor_index : ceiling_index;
494 			/* fall through to high side */
495 		case _high_side:
496 			side->primary_lightsource_index= ceiling_index;
497 			break;
498 		case _low_side:
499 			side->primary_lightsource_index= floor_index;
500 			break;
501 
502 		default:
503 			assert(false);
504 			break;
505 	}
506 
507 	side->transparent_lightsource_index= ceiling_index;
508 }
509 
510 /* Since the map_index buffer is no longer statically sized. */
set_map_index_buffer_size(int32 length)511 void set_map_index_buffer_size(
512 	int32 length)
513 {
514 	map_index_buffer_count= length/sizeof(short);
515 }
516 
517 /* ---------- private code */
518 
519 /* given a polygon, return its endpoints in clockwise order; always returns polygon->vertex_count */
calculate_clockwise_endpoints(short polygon_index,short * buffer)520 static short calculate_clockwise_endpoints(
521 	short polygon_index,
522 	short *buffer)
523 {
524 	struct polygon_data *polygon = get_polygon_data(polygon_index);
525 
526 	for (unsigned short i=0;i<polygon->vertex_count;++i)
527 	{
528 		*buffer++ = clockwise_endpoint_in_line(polygon_index, polygon->line_indexes[i], 0);
529 	}
530 
531 	return polygon->vertex_count;
532 }
533 
calculate_adjacent_sides(short polygon_index,short * side_indexes)534 static void calculate_adjacent_sides(
535 	short polygon_index,
536 	short *side_indexes)
537 {
538 	struct polygon_data *polygon= get_polygon_data(polygon_index);
539 
540 	for (unsigned short i=0;i<polygon->vertex_count;++i)
541 	{
542 		struct line_data *line= get_line_data(polygon->line_indexes[i]);
543 		short side_index;
544 
545 		if (line->clockwise_polygon_owner==polygon_index)
546 		{
547 			side_index= line->clockwise_polygon_side_index;
548 		}
549 		else
550 		{
551 			// LP change: get around some Pfhorte bugs
552 			side_index= line->counterclockwise_polygon_side_index;
553 		}
554 
555 		*side_indexes++= side_index;
556 	}
557 }
558 
calculate_adjacent_polygons(short polygon_index,short * polygon_indexes)559 static void calculate_adjacent_polygons(
560 	short polygon_index,
561 	short *polygon_indexes)
562 {
563 	struct polygon_data *polygon = get_polygon_data(polygon_index);
564 
565      for (unsigned short i=0;i<polygon->vertex_count;++i)
566 	{
567 		struct line_data *line= get_line_data(polygon->line_indexes[i]);
568 		short adjacent_polygon_index= NONE;
569 
570 		if (polygon_index==line->clockwise_polygon_owner)
571 		{
572 			adjacent_polygon_index= line->counterclockwise_polygon_owner;
573 		}
574 		else
575 		{
576 			// LP change: get around some Pfhorte bugs
577 			adjacent_polygon_index= line->clockwise_polygon_owner;
578 		}
579 
580 		*polygon_indexes++= adjacent_polygon_index;
581 	}
582 }
583 
584 /* returns area of the given polygon */
calculate_polygon_area(short polygon_index)585 static int32 calculate_polygon_area(
586 	short polygon_index)
587 {
588 	int32 area= 0;
589 	world_point2d *first_point, *point, *next_point;
590 	struct polygon_data *polygon= get_polygon_data(polygon_index);
591 
592 	first_point= &(get_endpoint_data(polygon->endpoint_indexes[0])->vertex);
593 	for (unsigned short vertex=1;vertex<polygon->vertex_count-1;++vertex)
594 	{
595 		point= &(get_endpoint_data(polygon->endpoint_indexes[vertex])->vertex);
596 		next_point= &(get_endpoint_data(polygon->endpoint_indexes[vertex+1])->vertex);
597 
598 		area+= (((first_point->x) * (point->y)) - ((point->x) * (first_point->y))) +
599 			(((point->x) * (next_point->y)) - ((next_point->x) * (point->y))) +
600 			(((next_point->x) * (first_point->y)) - ((first_point->x) * (next_point->y)));
601 	}
602 
603 	/* real area is absolute value of calculated area divided by two */
604      area= (ABS(area) >> 1);
605 
606 	return area;
607 }
608 
609 /* ---------- precalculate map indexes */
610 
precalculate_map_indexes(void)611 void precalculate_map_indexes(
612 	void)
613 {
614 	short polygon_index = 0;
615 	struct polygon_data *polygon = map_polygons;
616 
617 	for (;polygon_index< dynamic_world->polygon_count;++polygon,++polygon_index)
618 	{
619 		if (!POLYGON_IS_DETACHED(polygon)) /* we�ll handle detached polygons during the second pass */
620 		{
621 			// short line_indexes[MAXIMUM_INTERSECTING_INDEXES], endpoint_indexes[MAXIMUM_INTERSECTING_INDEXES],
622 			// 	polygon_indexes[MAXIMUM_INTERSECTING_INDEXES];
623 			// short line_count, endpoint_count, polygon_count;
624 
625 //			if (polygon_index==17) dprintf("polygon #%d at %p", polygon_index, polygon);
626 
627 			polygon->first_exclusion_zone_index= dynamic_world->map_index_count;
628 			polygon->line_exclusion_zone_count= polygon->point_exclusion_zone_count= 0;
629 			find_intersecting_endpoints_and_lines(polygon_index, MINIMUM_SEPARATION_FROM_WALL);
630 			//	line_indexes, &line_count, endpoint_indexes, &endpoint_count, polygon_indexes,
631 			//	&polygon_count);
632 
633 			size_t line_count = LineIndices.size();
634 			size_t endpoint_count = EndpointIndices.size();
635 
636 			for (size_t i=0;i<line_count;++i)
637 			{
638 				add_map_index(LineIndices[i], &polygon->line_exclusion_zone_count);
639 			}
640 
641 			for (size_t i=0;i<endpoint_count;++i)
642 			{
643 				add_map_index(EndpointIndices[i], &polygon->point_exclusion_zone_count);
644 			}
645 
646 			polygon->first_neighbor_index= dynamic_world->map_index_count;
647 			polygon->neighbor_count= 0;
648 			find_intersecting_endpoints_and_lines(polygon_index, MINIMUM_SEPARATION_FROM_PROJECTILE);
649 			//	line_indexes, &line_count, endpoint_indexes, &endpoint_count, polygon_indexes,
650 			//	&polygon_count);
651 
652 //			if (polygon_index==155) dprintf("polygon index #%d has %d neighbors:;dm %x %x;", polygon_index, polygon_count, polygon_indexes, sizeof(short)*polygon_count);
653 
654 			size_t polygon_count = PolygonIndices.size();
655 
656 			for (size_t i=0;i<polygon_count;++i)
657 			{
658 				add_map_index(PolygonIndices[i], &polygon->neighbor_count);
659 			}
660 		}
661 	}
662 
663 	precalculate_polygon_sound_sources();
664 }
665 
find_intersecting_endpoints_and_lines(short polygon_index,world_distance minimum_separation)666 static void find_intersecting_endpoints_and_lines(
667 	short polygon_index,
668 	world_distance minimum_separation)
669 {
670 	struct intersecting_flood_data data;
671 
672 	data.original_polygon_index= polygon_index;
673 	LineIndices.clear();
674 	EndpointIndices.clear();
675 	PolygonIndices.clear();
676 
677 	data.minimum_separation_squared= minimum_separation*minimum_separation;
678 	find_center_of_polygon(polygon_index, &data.center);
679 
680 	if (film_profile.adjacent_polygons_always_intersect)
681 	{
682 		polygon_data* polygon = get_polygon_data(polygon_index);
683 		for (int i = 0; i < polygon->vertex_count; ++i)
684 		{
685 			short adjacent_polygon_index = find_adjacent_polygon(polygon_index, polygon->line_indexes[i]);
686 			if (adjacent_polygon_index != NONE)
687 			{
688 				PolygonIndices.push_back(adjacent_polygon_index);
689 			}
690 		}
691 	}
692 
693 	polygon_index= flood_map(polygon_index, INT32_MAX, intersecting_flood_proc, _breadth_first, &data);
694 	while (polygon_index!=NONE)
695 	{
696 		polygon_index= flood_map(NONE, INT32_MAX, intersecting_flood_proc, _breadth_first, &data);
697 	}
698 }
699 
700 #ifdef NEW_AND_BROKEN
701 //AS: this confuses PB, so comment it out for now
702 /*
703 static long intersecting_flood_proc(
704 	short source_polygon_index,
705 	short line_index,
706 	short destination_polygon_index,
707 	void *vdata)
708 {
709 	struct intersecting_flood_data *data=vdata;
710 	struct polygon_data *polygon= get_polygon_data(source_polygon_index);
711 	struct polygon_data *original_polygon= get_polygon_data(data->original_polygon_index);
712 	bool keep_searching= false; // don�t flood any deeper unless we find something close enough
713 	short i = 0, j = 0;
714      unsigned long new_broken_note;
715 	//(void) (line_index,destination_polygon_index);
716 #pragma unused (line_index,destination_polygon_index)
717 	// we only care about this polygon if it intersects us in z
718 	if ((polygon->floor_height<=original_polygon->ceiling_height)&&(polygon->ceiling_height>=original_polygon->floor_height))
719 	{
720 		// check each endpoint to see if it is within the critical distance of any line within our original polygon
721 		for (i= 0; i<polygon->vertex_count; ++i)
722 		{
723 			short endpoint_index= polygon->endpoint_indexes[i];
724 			world_point2d *p= &(get_endpoint_data(endpoint_index)->vertex);
725 
726 			for (j= 0; j<original_polygon->vertex_count; ++j)
727 			{
728 				short line_index= polygon->line_indexes[i];
729 				struct line_data *line= get_line_data(line_index);
730 
731 				if (point_to_line_segment_distance_squared(p, a, b)<data->minimum_separation_squared)
732 				{
733 					keep_searching |= try_and_add_endpoint(endpoint_index);
734 					keep_searching |= try_and_add_line(polygon->line_indexes[i]);
735 					keep_searching |= try_and_add_line(polygon->line_indexes[i ? i-1 : polygon->vertex_count-1);
736 					break;
737 				}
738 			}
739 		}
740 	}
741 
742 	// if any part of this polygon is close enough to our original polygon, remember it�s index
743 	if (keep_searching)
744 	{
745 		for (j=0;j<data->polygon_count;++j)
746 		{
747 			if (data->polygon_indexes[j]==source_polygon_index)
748 			{
749 				break; // found duplicate, ignore
750 			}
751 		}
752 		if (j==data->polygon_count && data->polygon_count<MAXIMUM_INTERSECTING_INDEXES)
753 		{
754 			short detached_twin_index= NONE; //find_undetached_polygons_twin(source_polygon_index);
755 
756 			if (DoIncorrectCountVWarn)
757                {
758                    vwarn(data->polygon_count!=MAXIMUM_INTERSECTING_INDEXES-1,
759                    csprintf(temporary, "incomplete neighbor list for polygon#%d", data->original_polygon_index));
760                }
761 			data->polygon_indexes[data->polygon_count++]= source_polygon_index;
762 
763 			// if this polygon has a detached twin, add it too
764 			if ((detached_twin_index!=NONE) && (data->polygon_count<MAXIMUM_INTERSECTING_INDEXES))
765 			{
766 				if (DoIncorrectCountVWarn)
767                     {
768                         vwarn(data->polygon_count!=MAXIMUM_INTERSECTING_INDEXES-1,
769                         csprintf(temporary, "incomplete neighbor list for polygon#%d", data->original_polygon_index));
770                     }
771 				data->polygon_indexes[data->polygon_count++]= detached_twin_index;
772 			}
773 		}
774 	}
775 
776 	// return area of source polygon as cost
777 	return keep_searching ? 1 : -1;
778 }
779 
780 void try_and_add_line(
781 	struct intersecting_flood_data *data,
782 	short line_index)
783 {
784 	struct polygon_data *original_polygon= get_polygon_data(data->original_polygon_index);
785 	struct line_data *line= get_line_data(line_index);
786 	bool keep_searching= false;
787 	short i = 0;
788 
789 	if ((LINE_IS_SOLID(line)) ||
790 		(line_has_variable_height(line_index)) ||
791 		(line->lowest_adjacent_ceiling<original_polygon->ceiling_height) ||
792      (line->highest_adjacent_floor>original_polygon->floor_height))
793 	{
794 		// make sure this line isn�t already in the line list
795 		for (i=0; i<data->line_count; ++i)
796 		{
797 			if (data->line_indexes[i]==line_index)
798 			{
799 				keep_searching= true;
800 				break; // found duplicate, ignore (but keep looking for others)
801 			}
802 		}
803 		if (i==data->line_count && data->line_count<MAXIMUM_INTERSECTING_INDEXES)
804 		{
805               bool clockwise= !!((((b->x-a->x)*(data->center.y-b->y)) - ((b->y-a->y)*(data->center.x-b->x)))>0);
806 
807 			if (DoIncorrectCountVWarn)
808                {
809                    vwarn(data->line_count!=MAXIMUM_INTERSECTING_INDEXES-1,
810                          csprintf(temporary, "incomplete line list for polygon#%d", data->original_polygon_index));
811                }
812 			data->line_indexes[data->line_count++]= clockwise ? polygon->line_indexes[i] : (-polygon->line_indexes[i]-1);
813 //			if (data->original_polygon_index==23) dprintf("found line %d (%s)", polygon->line_indexes[i], clockwise ? "clockwise" : "counterclockwise");
814 			keep_searching= true;
815 			break;
816 		}
817 	}
818 
819 	return keep_searching;
820 }
821 			// add this endpoint if it isn�t already in the intersecting endpoint list
822 			for (j=0;j<data->endpoint_count;++j)
823 			{
824 				if (data->endpoint_indexes[j]==polygon->endpoint_indexes[i])
825 				{
826 					keep_searching= true;
827 					break; // found duplicate, ignore (but keep looking for others)
828 				}
829 			}
830 			if (j==data->endpoint_count && data->endpoint_count<MAXIMUM_INTERSECTING_INDEXES)
831 			{
832 				world_point2d *p= &get_endpoint_data(polygon->endpoint_indexes[i])->vertex;
833 
834 				// check and see if this endpoint is close enough to any line in our original polygon to care about; if it is, add it to our list
835 				for (j=0;j<original_polygon->vertex_count;++j)
836 				{
837 					struct line_data *line= get_line_data(original_polygon->line_indexes[j]);
838 					world_point2d *a= &get_endpoint_data(line->endpoint_indexes[0])->vertex;
839 					world_point2d *b= &get_endpoint_data(line->endpoint_indexes[1])->vertex;
840 
841 					if (point_to_line_segment_distance_squared(p, a, b)<data->minimum_separation_squared)
842 					{
843 						if (DoIncorrectCountVWarn)
844 							vwarn(data->endpoint_count!=MAXIMUM_INTERSECTING_INDEXES-1, csprintf(temporary, "incomplete endpoint list for polygon#%d", data->original_polygon_index));
845 						data->endpoint_indexes[data->endpoint_count++]= polygon->endpoint_indexes[i];
846 //						if (data->original_polygon_index==23) dprintf("found endpoint %d", data->endpoint_indexes[data->endpoint_count-1]);
847 //						switch (data->endpoint_indexes[data->endpoint_count-1])
848 //						{
849 //							case 34:
850 //							case 35:
851 //								dprintf("found endpoint#%d from polygon#%d", data->endpoint_indexes[data->endpoint_count-1], data->original_polygon_index);
852 //						}
853 						break;
854 					}
855 				}
856 			}
857 		}
858 	}
859 */
860 #endif
861 
intersecting_flood_proc(short source_polygon_index,short line_index,short destination_polygon_index,void * vdata)862 static int32 intersecting_flood_proc(
863 	short source_polygon_index,
864 	short line_index,
865 	short destination_polygon_index,
866 	void *vdata)
867 {
868 	struct intersecting_flood_data *data=(struct intersecting_flood_data *)vdata;
869 	struct polygon_data *polygon= get_polygon_data(source_polygon_index);
870 	struct polygon_data *original_polygon= get_polygon_data(data->original_polygon_index);
871 	bool keep_searching= false; /* don�t flood any deeper unless we find something close enough */
872 	unsigned short i, j;
873 	(void) (line_index);
874 	(void) (destination_polygon_index);
875 
876 	/* we only care about this polygon if it intersects us in z */
877 	if ((polygon->floor_height<=original_polygon->ceiling_height)&&(polygon->ceiling_height>=original_polygon->floor_height))
878 	{
879 		/* update our running line and endpoint lists */
880 		for (i=0;i<polygon->vertex_count;++i)
881 		{
882 			/* add this line if it isn�t already in the intersecting line list */
883 			for (j=0;j<LineIndices.size();++j)
884 			{
885 				if (LineIndices[j]==polygon->line_indexes[i] ||
886 					-LineIndices[j]-1==polygon->line_indexes[i])
887 				{
888 					keep_searching= true;
889 					break; /* found duplicate, stop */
890 				}
891 			}
892 			if (j==LineIndices.size())
893 			{
894 				short line_index= polygon->line_indexes[i];
895 				struct line_data *line= get_line_data(line_index);
896 
897 				if (LINE_IS_SOLID(line) ||
898 					line_has_variable_height(line_index) ||
899 					line->lowest_adjacent_ceiling<original_polygon->ceiling_height ||
900 					line->highest_adjacent_floor>original_polygon->floor_height)
901 				{
902 					world_point2d *a= &(get_endpoint_data(line->endpoint_indexes[0])->vertex);
903 					world_point2d *b= &(get_endpoint_data(line->endpoint_indexes[1])->vertex);
904 
905 					/* check and see if this line is close enough to any point in our original polygon
906 						to care about; if it is, add it to our list */
907 					for (j=0;j<original_polygon->vertex_count;++j)
908 					{
909 						world_point2d *p= &(get_endpoint_data(original_polygon->endpoint_indexes[j])->vertex);
910 
911 						if (point_to_line_segment_distance_squared(p, a, b)<data->minimum_separation_squared)
912 						{
913 							bool clockwise= !!((((b->x-a->x)*(data->center.y-b->y)) - ((b->y-a->y)*(data->center.x-b->x)))>0);
914 
915 							LineIndices.push_back(clockwise ? polygon->line_indexes[i] : (-polygon->line_indexes[i]-1));
916 							keep_searching= true;
917 							break;
918 						}
919 					}
920 				}
921 			}
922 
923 			/* add this endpoint if it isn�t already in the intersecting endpoint list */
924 			for (j=0;j<EndpointIndices.size();++j)
925 			{
926 				if (EndpointIndices[j]==polygon->endpoint_indexes[i])
927 				{
928 					keep_searching= true;
929 					break; /* found duplicate, ignore (but keep looking for others) */
930 				}
931 			}
932 			if (j==EndpointIndices.size())
933 			{
934 				world_point2d *p= &(get_endpoint_data(polygon->endpoint_indexes[i])->vertex);
935 
936 				/* check and see if this endpoint is close enough to any line in our original polygon
937 					to care about; if it is, add it to our list */
938 				for (j=0;j<original_polygon->vertex_count;++j)
939 				{
940 					struct line_data *line= get_line_data(original_polygon->line_indexes[j]);
941 					world_point2d *a= &get_endpoint_data(line->endpoint_indexes[0])->vertex;
942 					world_point2d *b= &get_endpoint_data(line->endpoint_indexes[1])->vertex;
943 
944 					if (point_to_line_segment_distance_squared(p, a, b)<data->minimum_separation_squared)
945 					{
946 						EndpointIndices.push_back(polygon->endpoint_indexes[i]);
947 						break;
948 					}
949 				}
950 			}
951 		}
952 	}
953 
954 	/* if any part of this polygon is close enough to our original polygon, remember it�s index */
955 	if (keep_searching)
956 	{
957 		for (j=0;j<PolygonIndices.size();++j)
958 		{
959 			if (PolygonIndices[j]==source_polygon_index)
960 			{
961 				break; /* found duplicate, ignore */
962 			}
963 		}
964 		if (j==PolygonIndices.size())
965 		{
966 			short detached_twin_index= NONE; //find_undetached_polygons_twin(source_polygon_index);
967 
968 			PolygonIndices.push_back(source_polygon_index);
969 
970 			/* if this polygon has a detached twin, add it too */
971 			if (detached_twin_index!=NONE)
972 			{
973 				PolygonIndices.push_back(detached_twin_index);
974 			}
975 		}
976 	}
977 
978 	/* return area of source polygon as cost */
979 	return keep_searching ? 1 : -1;
980 }
981 
982 
983 #ifdef WITH_ORIGINAL_DATA_STRUCTURES
984 /*
985 static long intersecting_flood_proc(
986 	short source_polygon_index,
987 	short line_index,
988 	short destination_polygon_index,
989 	void *vdata)
990 {
991 	struct intersecting_flood_data *data=(struct intersecting_flood_data *)vdata;
992 	struct polygon_data *polygon= get_polygon_data(source_polygon_index);
993 	struct polygon_data *original_polygon= get_polygon_data(data->original_polygon_index);
994 	bool keep_searching= false; // don�t flood any deeper unless we find something close enough
995      short i, j;
996 	(void) (line_index);
997 	(void) (destination_polygon_index);
998 
999 	// we only care about this polygon if it intersects us in z
1000 	if (polygon->floor_height<=original_polygon->ceiling_height&&polygon->ceiling_height>=original_polygon->floor_height)
1001 	{
1002 		// update our running line and endpoint lists
1003 		for (i=0;i<polygon->vertex_count;++i)
1004 		{
1005 			// add this line if it isn�t already in the intersecting line list
1006 			for (j=0;j<data->line_count;++j)
1007 			{
1008 				if (data->line_indexes[j]==polygon->line_indexes[i] ||
1009 					-data->line_indexes[j]-1==polygon->line_indexes[i])
1010 				{
1011 					keep_searching= true;
1012 					break; // found duplicate, stop
1013 				}
1014 			}
1015 			if (j==data->line_count && data->endpoint_count<MAXIMUM_INTERSECTING_INDEXES)
1016 			{
1017 				short line_index= polygon->line_indexes[i];
1018 				struct line_data *line= get_line_data(line_index);
1019 
1020 //				if (data->original_polygon_index==23&&line_index==104) dprintf("line#%d @ %p", line_index, line);
1021 
1022 				if (LINE_IS_SOLID(line) ||
1023 					line_has_variable_height(line_index) ||
1024 					line->lowest_adjacent_ceiling<original_polygon->ceiling_height ||
1025 					line->highest_adjacent_floor>original_polygon->floor_height)
1026 				{
1027 					world_point2d *a= &get_endpoint_data(line->endpoint_indexes[0])->vertex;
1028 					world_point2d *b= &get_endpoint_data(line->endpoint_indexes[1])->vertex;
1029 
1030 					// check and see if this line is close enough to any point in our original polygon to care about; if it is, add it to our list
1031 					for (j=0;j<original_polygon->vertex_count;++j)
1032 					{
1033 						world_point2d *p= &get_endpoint_data(original_polygon->endpoint_indexes[j])->vertex;
1034 
1035 						if (point_to_line_segment_distance_squared(p, a, b)<data->minimum_separation_squared)
1036 						{
1037 							bool clockwise= ((b->x-a->x)*(data->center.y-b->y) - (b->y-a->y)*(data->center.x-b->x)>0) ? true : false;
1038 
1039 							if (DoIncorrectCountVWarn)
1040 								vwarn(data->line_count!=MAXIMUM_INTERSECTING_INDEXES-1, csprintf(temporary, "incomplete line list for polygon#%d", data->original_polygon_index));
1041 							data->line_indexes[data->line_count++]= clockwise ? polygon->line_indexes[i] : (-polygon->line_indexes[i]-1);
1042 //							if (data->original_polygon_index==23) dprintf("found line %d (%s)", polygon->line_indexes[i], clockwise ? "clockwise" : "counterclockwise");
1043 							keep_searching= true;
1044 							break;
1045 						}
1046 					}
1047 				}
1048 			}
1049 
1050 			// add this endpoint if it isn�t already in the intersecting endpoint list
1051 			for (j=0;j<data->endpoint_count;++j)
1052 			{
1053 				if (data->endpoint_indexes[j]==polygon->endpoint_indexes[i])
1054 				{
1055 					keep_searching= true;
1056 					break; // found duplicate, ignore (but keep looking for others)
1057 				}
1058 			}
1059 			if (j==data->endpoint_count && data->endpoint_count<MAXIMUM_INTERSECTING_INDEXES)
1060 			{
1061 				world_point2d *p= &get_endpoint_data(polygon->endpoint_indexes[i])->vertex;
1062 
1063 				// check and see if this endpoint is close enough to any line in our original polygon to care about; if it is, add it to our list
1064 				for (j=0;j<original_polygon->vertex_count;++j)
1065 				{
1066 					struct line_data *line= get_line_data(original_polygon->line_indexes[j]);
1067 					world_point2d *a= &get_endpoint_data(line->endpoint_indexes[0])->vertex;
1068 					world_point2d *b= &get_endpoint_data(line->endpoint_indexes[1])->vertex;
1069 
1070 					if (point_to_line_segment_distance_squared(p, a, b)<data->minimum_separation_squared)
1071 					{
1072 						if (DoIncorrectCountVWarn)
1073 							vwarn(data->endpoint_count!=MAXIMUM_INTERSECTING_INDEXES-1, csprintf(temporary, "incomplete endpoint list for polygon#%d", data->original_polygon_index));
1074 						data->endpoint_indexes[data->endpoint_count++]= polygon->endpoint_indexes[i];
1075 //						if (data->original_polygon_index==23) dprintf("found endpoint %d", data->endpoint_indexes[data->endpoint_count-1]);
1076 //						switch (data->endpoint_indexes[data->endpoint_count-1])
1077 //						{
1078 //							case 34:
1079 //							case 35:
1080 //								dprintf("found endpoint#%d from polygon#%d", data->endpoint_indexes[data->endpoint_count-1], data->original_polygon_index);
1081 //						}
1082 						break;
1083 					}
1084 				}
1085 			}
1086 		}
1087 	}
1088 
1089 	// if any part of this polygon is close enough to our original polygon, remember it�s index
1090 	if (keep_searching)
1091 	{
1092 		for (j=0;j<data->polygon_count;++j)
1093 		{
1094 			if (data->polygon_indexes[j]==source_polygon_index)
1095 			{
1096 				break; // found duplicate, ignore
1097 			}
1098 		}
1099 		if (j==data->polygon_count && data->polygon_count<MAXIMUM_INTERSECTING_INDEXES)
1100 		{
1101 			short detached_twin_index= NONE; //find_undetached_polygons_twin(source_polygon_index);
1102 
1103 			if (DoIncorrectCountVWarn)
1104 				vwarn(data->polygon_count!=MAXIMUM_INTERSECTING_INDEXES-1, csprintf(temporary, "incomplete neighbor list for polygon#%d", data->original_polygon_index));
1105 			data->polygon_indexes[data->polygon_count++]= source_polygon_index;
1106 
1107 			// if this polygon has a detached twin, add it too
1108 			if (detached_twin_index!=NONE && data->polygon_count<MAXIMUM_INTERSECTING_INDEXES)
1109 			{
1110 				if (DoIncorrectCountVWarn)
1111 					vwarn(data->polygon_count!=MAXIMUM_INTERSECTING_INDEXES-1, csprintf(temporary, "incomplete neighbor list for polygon#%d", data->original_polygon_index));
1112 				data->polygon_indexes[data->polygon_count++]= detached_twin_index;
1113 			}
1114 		}
1115 	}
1116 
1117 	// return area of source polygon as cost
1118 	return keep_searching ? 1 : -1;
1119 }
1120 */
1121 #endif
1122 
add_map_index(short index,short * count)1123 static void add_map_index(
1124 	short index,
1125 	short *count)
1126 {
1127 	assert(MapIndexList.size() < UINT16_MAX);
1128 	MapIndexList.push_back(index);
1129 	dynamic_world->map_index_count++;
1130 	*count += 1;
1131 }
1132 
1133 #define ZERO_VOLUME_DISTANCE (10*WORLD_ONE)
1134 
precalculate_polygon_sound_sources(void)1135 static void precalculate_polygon_sound_sources(
1136 	void)
1137 {
1138 	short polygon_index;
1139 	struct polygon_data *polygon;
1140 
1141 	for (polygon_index= 0, polygon= map_polygons; polygon_index<dynamic_world->polygon_count; ++polygon_index, ++polygon)
1142 	{
1143 		short object_index;
1144 		struct map_object *object;
1145 		short sound_sources= 0;
1146 
1147 		polygon->sound_source_indexes= dynamic_world->map_index_count;
1148 
1149 		for (object_index= 0, object= saved_objects; object_index<dynamic_world->initial_objects_count; ++object, ++object_index)
1150 		{
1151 			if (object->type==_saved_sound_source)
1152 			{
1153 				short i;
1154 				bool close= false;
1155 
1156 				for (i= 0; i<polygon->vertex_count; ++i)
1157 				{
1158 					struct endpoint_data *endpoint= get_endpoint_data(polygon->endpoint_indexes[i]);
1159 					struct line_data *line= get_line_data(polygon->line_indexes[i]);
1160 
1161 					if (guess_distance2d((world_point2d *)&object->location, &endpoint->vertex)<ZERO_VOLUME_DISTANCE ||
1162 						point_to_line_segment_distance_squared((world_point2d *)&object->location,
1163 							&get_endpoint_data(line->endpoint_indexes[0])->vertex,
1164 							&get_endpoint_data(line->endpoint_indexes[1])->vertex)<ZERO_VOLUME_DISTANCE)
1165 					{
1166 						close= true;
1167 						break;
1168 					}
1169 				}
1170 
1171 				if (close) add_map_index(object_index, &sound_sources);
1172 			}
1173 		}
1174 
1175 		add_map_index(NONE, &sound_sources);
1176 	}
1177 }
1178 
unpack_endpoint_data(uint8 * Stream,endpoint_data * Objects,size_t Count)1179 uint8 *unpack_endpoint_data(uint8 *Stream, endpoint_data *Objects, size_t Count)
1180 {
1181 	uint8* S = Stream;
1182 	endpoint_data* ObjPtr = Objects;
1183 
1184      for (size_t k = 0; k < Count; k++, ObjPtr++)
1185 	{
1186 		StreamToValue(S,ObjPtr->flags);
1187 		StreamToValue(S,ObjPtr->highest_adjacent_floor_height);
1188 		StreamToValue(S,ObjPtr->lowest_adjacent_ceiling_height);
1189 
1190 		StreamToValue(S,ObjPtr->vertex.x);
1191 		StreamToValue(S,ObjPtr->vertex.y);
1192 		StreamToValue(S,ObjPtr->transformed.x);
1193 		StreamToValue(S,ObjPtr->transformed.y);
1194 
1195 		StreamToValue(S,ObjPtr->supporting_polygon_index);
1196 	}
1197 
1198 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_endpoint_data));
1199 	return S;
1200 }
1201 
pack_endpoint_data(uint8 * Stream,endpoint_data * Objects,size_t Count)1202 uint8 *pack_endpoint_data(uint8 *Stream, endpoint_data *Objects, size_t Count)
1203 {
1204 	uint8* S = Stream;
1205 	endpoint_data* ObjPtr = Objects;
1206 
1207 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1208 	{
1209 		ValueToStream(S,ObjPtr->flags);
1210 		ValueToStream(S,ObjPtr->highest_adjacent_floor_height);
1211 		ValueToStream(S,ObjPtr->lowest_adjacent_ceiling_height);
1212 
1213 		ValueToStream(S,ObjPtr->vertex.x);
1214 		ValueToStream(S,ObjPtr->vertex.y);
1215 		ValueToStream(S,ObjPtr->transformed.x);
1216 		ValueToStream(S,ObjPtr->transformed.y);
1217 
1218 		ValueToStream(S,ObjPtr->supporting_polygon_index);
1219 	}
1220 
1221 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_endpoint_data));
1222 	return S;
1223 }
1224 
1225 
unpack_line_data(uint8 * Stream,line_data * Objects,size_t Count)1226 uint8 *unpack_line_data(uint8 *Stream, line_data *Objects, size_t Count)
1227 {
1228 	uint8* S = Stream;
1229 	line_data* ObjPtr = Objects;
1230 
1231 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1232 	{
1233 		StreamToList(S,ObjPtr->endpoint_indexes,2);
1234 		StreamToValue(S,ObjPtr->flags);
1235 
1236 		StreamToValue(S,ObjPtr->length);
1237 		StreamToValue(S,ObjPtr->highest_adjacent_floor);
1238 		StreamToValue(S,ObjPtr->lowest_adjacent_ceiling);
1239 
1240 		StreamToValue(S,ObjPtr->clockwise_polygon_side_index);
1241 		StreamToValue(S,ObjPtr->counterclockwise_polygon_side_index);
1242 
1243 		StreamToValue(S,ObjPtr->clockwise_polygon_owner);
1244 		StreamToValue(S,ObjPtr->counterclockwise_polygon_owner);
1245 
1246 		S += 6*2;
1247 	}
1248 
1249 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_line_data));
1250 	return S;
1251 }
1252 
pack_line_data(uint8 * Stream,line_data * Objects,size_t Count)1253 uint8 *pack_line_data(uint8 *Stream, line_data *Objects, size_t Count)
1254 {
1255 	uint8* S = Stream;
1256 	line_data* ObjPtr = Objects;
1257 
1258 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1259 	{
1260 		ListToStream(S,ObjPtr->endpoint_indexes,2);
1261 		ValueToStream(S,ObjPtr->flags);
1262 
1263 		ValueToStream(S,ObjPtr->length);
1264 		ValueToStream(S,ObjPtr->highest_adjacent_floor);
1265 		ValueToStream(S,ObjPtr->lowest_adjacent_ceiling);
1266 
1267 		ValueToStream(S,ObjPtr->clockwise_polygon_side_index);
1268 		ValueToStream(S,ObjPtr->counterclockwise_polygon_side_index);
1269 
1270 		ValueToStream(S,ObjPtr->clockwise_polygon_owner);
1271 		ValueToStream(S,ObjPtr->counterclockwise_polygon_owner);
1272 
1273 		S += 6*2;
1274 	}
1275 
1276 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_line_data));
1277 	return S;
1278 }
1279 
1280 
StreamToSideTxtr(uint8 * & S,side_texture_definition & Object)1281 inline void StreamToSideTxtr(uint8* &S, side_texture_definition& Object)
1282 {
1283 	StreamToValue(S,Object.x0);
1284 	StreamToValue(S,Object.y0);
1285 	StreamToValue(S,Object.texture);
1286 }
1287 
SideTxtrToStream(uint8 * & S,side_texture_definition & Object)1288 inline void SideTxtrToStream(uint8* &S, side_texture_definition& Object)
1289 {
1290 	ValueToStream(S,Object.x0);
1291 	ValueToStream(S,Object.y0);
1292 	ValueToStream(S,Object.texture);
1293 }
1294 
1295 
StreamToSideExclZone(uint8 * & S,side_exclusion_zone & Object)1296 void StreamToSideExclZone(uint8* &S, side_exclusion_zone& Object)
1297 {
1298 	StreamToValue(S,Object.e0.x);
1299 	StreamToValue(S,Object.e0.y);
1300 	StreamToValue(S,Object.e1.x);
1301 	StreamToValue(S,Object.e1.y);
1302 	StreamToValue(S,Object.e2.x);
1303 	StreamToValue(S,Object.e2.y);
1304 	StreamToValue(S,Object.e3.x);
1305 	StreamToValue(S,Object.e3.y);
1306 }
1307 
SideExclZoneToStream(uint8 * & S,side_exclusion_zone & Object)1308 void SideExclZoneToStream(uint8* &S, side_exclusion_zone& Object)
1309 {
1310 	ValueToStream(S,Object.e0.x);
1311 	ValueToStream(S,Object.e0.y);
1312 	ValueToStream(S,Object.e1.x);
1313 	ValueToStream(S,Object.e1.y);
1314 	ValueToStream(S,Object.e2.x);
1315 	ValueToStream(S,Object.e2.y);
1316 	ValueToStream(S,Object.e3.x);
1317 	ValueToStream(S,Object.e3.y);
1318 }
1319 
1320 
unpack_side_data(uint8 * Stream,side_data * Objects,size_t Count)1321 uint8 *unpack_side_data(uint8 *Stream, side_data *Objects, size_t Count)
1322 {
1323 	uint8* S = Stream;
1324 	side_data* ObjPtr = Objects;
1325 
1326 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1327 	{
1328 		StreamToValue(S,ObjPtr->type);
1329 		StreamToValue(S,ObjPtr->flags);
1330 
1331 		StreamToSideTxtr(S,ObjPtr->primary_texture);
1332 		StreamToSideTxtr(S,ObjPtr->secondary_texture);
1333 		StreamToSideTxtr(S,ObjPtr->transparent_texture);
1334 
1335 		StreamToSideExclZone(S,ObjPtr->exclusion_zone);
1336 
1337 		StreamToValue(S,ObjPtr->control_panel_type);
1338 		StreamToValue(S,ObjPtr->control_panel_permutation);
1339 
1340 		StreamToValue(S,ObjPtr->primary_transfer_mode);
1341 		StreamToValue(S,ObjPtr->secondary_transfer_mode);
1342 		StreamToValue(S,ObjPtr->transparent_transfer_mode);
1343 
1344 		StreamToValue(S,ObjPtr->polygon_index);
1345 		StreamToValue(S,ObjPtr->line_index);
1346 
1347 		StreamToValue(S,ObjPtr->primary_lightsource_index);
1348 		StreamToValue(S,ObjPtr->secondary_lightsource_index);
1349 		StreamToValue(S,ObjPtr->transparent_lightsource_index);
1350 
1351 		StreamToValue(S,ObjPtr->ambient_delta);
1352 
1353 		S += 1*2;
1354 	}
1355 
1356 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_side_data));
1357 	return S;
1358 }
1359 
pack_side_data(uint8 * Stream,side_data * Objects,size_t Count)1360 uint8 *pack_side_data(uint8 *Stream, side_data *Objects, size_t Count)
1361 {
1362 	uint8* S = Stream;
1363 	side_data* ObjPtr = Objects;
1364 
1365 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1366 	{
1367 		ValueToStream(S,ObjPtr->type);
1368 		ValueToStream(S,ObjPtr->flags);
1369 
1370 		SideTxtrToStream(S,ObjPtr->primary_texture);
1371 		SideTxtrToStream(S,ObjPtr->secondary_texture);
1372 		SideTxtrToStream(S,ObjPtr->transparent_texture);
1373 
1374 		SideExclZoneToStream(S,ObjPtr->exclusion_zone);
1375 
1376 		ValueToStream(S,ObjPtr->control_panel_type);
1377 		ValueToStream(S,ObjPtr->control_panel_permutation);
1378 
1379 		ValueToStream(S,ObjPtr->primary_transfer_mode);
1380 		ValueToStream(S,ObjPtr->secondary_transfer_mode);
1381 		ValueToStream(S,ObjPtr->transparent_transfer_mode);
1382 
1383 		ValueToStream(S,ObjPtr->polygon_index);
1384 		ValueToStream(S,ObjPtr->line_index);
1385 
1386 		ValueToStream(S,ObjPtr->primary_lightsource_index);
1387 		ValueToStream(S,ObjPtr->secondary_lightsource_index);
1388 		ValueToStream(S,ObjPtr->transparent_lightsource_index);
1389 
1390 		ValueToStream(S,ObjPtr->ambient_delta);
1391 
1392 		S += 1*2;
1393 	}
1394 
1395 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_side_data));
1396 	return S;
1397 }
1398 
1399 
unpack_polygon_data(uint8 * Stream,polygon_data * Objects,size_t Count)1400 uint8 *unpack_polygon_data(uint8 *Stream, polygon_data *Objects, size_t Count)
1401 {
1402 	uint8* S = Stream;
1403 	polygon_data* ObjPtr = Objects;
1404 
1405 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1406 	{
1407 		StreamToValue(S,ObjPtr->type);
1408 		StreamToValue(S,ObjPtr->flags);
1409 		StreamToValue(S,ObjPtr->permutation);
1410 
1411 		StreamToValue(S,ObjPtr->vertex_count);
1412 		StreamToList(S,ObjPtr->endpoint_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1413 		StreamToList(S,ObjPtr->line_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1414 
1415 		StreamToValue(S,ObjPtr->floor_texture);
1416 		StreamToValue(S,ObjPtr->ceiling_texture);
1417 		StreamToValue(S,ObjPtr->floor_height);
1418 		StreamToValue(S,ObjPtr->ceiling_height);
1419 		StreamToValue(S,ObjPtr->floor_lightsource_index);
1420 		StreamToValue(S,ObjPtr->ceiling_lightsource_index);
1421 
1422 		StreamToValue(S,ObjPtr->area);
1423 
1424 		StreamToValue(S,ObjPtr->first_object);
1425 
1426 		StreamToValue(S,ObjPtr->first_exclusion_zone_index);
1427 		StreamToValue(S,ObjPtr->line_exclusion_zone_count);
1428 		StreamToValue(S,ObjPtr->point_exclusion_zone_count);
1429 
1430 		StreamToValue(S,ObjPtr->floor_transfer_mode);
1431 		StreamToValue(S,ObjPtr->ceiling_transfer_mode);
1432 
1433 		StreamToList(S,ObjPtr->adjacent_polygon_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1434 
1435 		StreamToValue(S,ObjPtr->first_neighbor_index);
1436 		StreamToValue(S,ObjPtr->neighbor_count);
1437 
1438 		StreamToValue(S,ObjPtr->center.x);
1439 		StreamToValue(S,ObjPtr->center.y);
1440 
1441 		StreamToList(S,ObjPtr->side_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1442 
1443 		StreamToValue(S,ObjPtr->floor_origin.x);
1444 		StreamToValue(S,ObjPtr->floor_origin.y);
1445 		StreamToValue(S,ObjPtr->ceiling_origin.x);
1446 		StreamToValue(S,ObjPtr->ceiling_origin.y);
1447 
1448 		StreamToValue(S,ObjPtr->media_index);
1449 		StreamToValue(S,ObjPtr->media_lightsource_index);
1450 
1451 		StreamToValue(S,ObjPtr->sound_source_indexes);
1452 
1453 		StreamToValue(S,ObjPtr->ambient_sound_image_index);
1454 		StreamToValue(S,ObjPtr->random_sound_image_index);
1455 
1456 		S += 1*2;
1457 	}
1458 
1459 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_polygon_data));
1460 	return S;
1461 }
1462 
pack_polygon_data(uint8 * Stream,polygon_data * Objects,size_t Count)1463 uint8 *pack_polygon_data(uint8 *Stream, polygon_data *Objects, size_t Count)
1464 {
1465 	uint8* S = Stream;
1466 	polygon_data* ObjPtr = Objects;
1467 
1468 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1469 	{
1470 		ValueToStream(S,ObjPtr->type);
1471 		ValueToStream(S,ObjPtr->flags);
1472 		ValueToStream(S,ObjPtr->permutation);
1473 
1474 		ValueToStream(S,ObjPtr->vertex_count);
1475 		ListToStream(S,ObjPtr->endpoint_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1476 		ListToStream(S,ObjPtr->line_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1477 
1478 		ValueToStream(S,ObjPtr->floor_texture);
1479 		ValueToStream(S,ObjPtr->ceiling_texture);
1480 		ValueToStream(S,ObjPtr->floor_height);
1481 		ValueToStream(S,ObjPtr->ceiling_height);
1482 		ValueToStream(S,ObjPtr->floor_lightsource_index);
1483 		ValueToStream(S,ObjPtr->ceiling_lightsource_index);
1484 
1485 		ValueToStream(S,ObjPtr->area);
1486 
1487 		ValueToStream(S,ObjPtr->first_object);
1488 
1489 		ValueToStream(S,ObjPtr->first_exclusion_zone_index);
1490 		ValueToStream(S,ObjPtr->line_exclusion_zone_count);
1491 		ValueToStream(S,ObjPtr->point_exclusion_zone_count);
1492 
1493 		ValueToStream(S,ObjPtr->floor_transfer_mode);
1494 		ValueToStream(S,ObjPtr->ceiling_transfer_mode);
1495 
1496 		ListToStream(S,ObjPtr->adjacent_polygon_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1497 
1498 		ValueToStream(S,ObjPtr->first_neighbor_index);
1499 		ValueToStream(S,ObjPtr->neighbor_count);
1500 
1501 		ValueToStream(S,ObjPtr->center.x);
1502 		ValueToStream(S,ObjPtr->center.y);
1503 
1504 		ListToStream(S,ObjPtr->side_indexes,MAXIMUM_VERTICES_PER_POLYGON);
1505 
1506 		ValueToStream(S,ObjPtr->floor_origin.x);
1507 		ValueToStream(S,ObjPtr->floor_origin.y);
1508 		ValueToStream(S,ObjPtr->ceiling_origin.x);
1509 		ValueToStream(S,ObjPtr->ceiling_origin.y);
1510 
1511 		ValueToStream(S,ObjPtr->media_index);
1512 		ValueToStream(S,ObjPtr->media_lightsource_index);
1513 
1514 		ValueToStream(S,ObjPtr->sound_source_indexes);
1515 
1516 		ValueToStream(S,ObjPtr->ambient_sound_image_index);
1517 		ValueToStream(S,ObjPtr->random_sound_image_index);
1518 
1519 		S += 1*2;
1520 	}
1521 
1522 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_polygon_data));
1523 	return S;
1524 }
1525 
1526 
unpack_map_annotation(uint8 * Stream,map_annotation * Objects,size_t Count)1527 uint8 *unpack_map_annotation(uint8 *Stream, map_annotation* Objects, size_t Count)
1528 {
1529 	uint8* S = Stream;
1530 	map_annotation* ObjPtr = Objects;
1531 
1532 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1533 	{
1534 		StreamToValue(S,ObjPtr->type);
1535 
1536 		StreamToValue(S,ObjPtr->location.x);
1537 		StreamToValue(S,ObjPtr->location.y);
1538 		StreamToValue(S,ObjPtr->polygon_index);
1539 
1540 		StreamToBytes(S,ObjPtr->text,MAXIMUM_ANNOTATION_TEXT_LENGTH);
1541 	}
1542 
1543 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_map_annotation));
1544 	return S;
1545 }
1546 
pack_map_annotation(uint8 * Stream,map_annotation * Objects,size_t Count)1547 uint8 *pack_map_annotation(uint8 *Stream, map_annotation* Objects, size_t Count)
1548 {
1549 	uint8* S = Stream;
1550 	map_annotation* ObjPtr = Objects;
1551 
1552 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1553 	{
1554 		ValueToStream(S,ObjPtr->type);
1555 
1556 		ValueToStream(S,ObjPtr->location.x);
1557 		ValueToStream(S,ObjPtr->location.y);
1558 		ValueToStream(S,ObjPtr->polygon_index);
1559 
1560 		BytesToStream(S,ObjPtr->text,MAXIMUM_ANNOTATION_TEXT_LENGTH);
1561 	}
1562 
1563 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_map_annotation));
1564 	return S;
1565 }
1566 
1567 
unpack_map_object(uint8 * Stream,map_object * Objects,size_t Count)1568 uint8 *unpack_map_object(uint8 *Stream, map_object* Objects, size_t Count)
1569 {
1570 	uint8* S = Stream;
1571 	map_object* ObjPtr = Objects;
1572 
1573 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1574 	{
1575 		StreamToValue(S,ObjPtr->type);
1576 		StreamToValue(S,ObjPtr->index);
1577 		StreamToValue(S,ObjPtr->facing);
1578 		StreamToValue(S,ObjPtr->polygon_index);
1579 		StreamToValue(S,ObjPtr->location.x);
1580 		StreamToValue(S,ObjPtr->location.y);
1581 		StreamToValue(S,ObjPtr->location.z);
1582 
1583 		StreamToValue(S,ObjPtr->flags);
1584 	}
1585 
1586 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_map_object));
1587 	return S;
1588 }
1589 
pack_map_object(uint8 * Stream,map_object * Objects,size_t Count)1590 uint8 *pack_map_object(uint8 *Stream, map_object* Objects, size_t Count)
1591 {
1592 	uint8* S = Stream;
1593 	map_object* ObjPtr = Objects;
1594 
1595 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1596 	{
1597 		ValueToStream(S,ObjPtr->type);
1598 		ValueToStream(S,ObjPtr->index);
1599 		ValueToStream(S,ObjPtr->facing);
1600 		ValueToStream(S,ObjPtr->polygon_index);
1601 		ValueToStream(S,ObjPtr->location.x);
1602 		ValueToStream(S,ObjPtr->location.y);
1603 		ValueToStream(S,ObjPtr->location.z);
1604 
1605 		ValueToStream(S,ObjPtr->flags);
1606 	}
1607 
1608 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_map_object));
1609 	return S;
1610 }
1611 
1612 
unpack_object_frequency_definition(uint8 * Stream,object_frequency_definition * Objects,size_t Count)1613 uint8 *unpack_object_frequency_definition(uint8 *Stream, object_frequency_definition* Objects, size_t Count)
1614 {
1615 	uint8* S = Stream;
1616 	object_frequency_definition* ObjPtr = Objects;
1617 
1618 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1619 	{
1620 		StreamToValue(S,ObjPtr->flags);
1621 
1622 		StreamToValue(S,ObjPtr->initial_count);
1623 		StreamToValue(S,ObjPtr->minimum_count);
1624 		StreamToValue(S,ObjPtr->maximum_count);
1625 
1626 		StreamToValue(S,ObjPtr->random_count);
1627 		StreamToValue(S,ObjPtr->random_chance);
1628 	}
1629 
1630 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_object_frequency_definition));
1631 	return S;
1632 }
1633 
pack_object_frequency_definition(uint8 * Stream,object_frequency_definition * Objects,size_t Count)1634 uint8 *pack_object_frequency_definition(uint8 *Stream, object_frequency_definition* Objects, size_t Count)
1635 {
1636 	uint8* S = Stream;
1637 	object_frequency_definition* ObjPtr = Objects;
1638 
1639 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1640 	{
1641 		ValueToStream(S,ObjPtr->flags);
1642 
1643 		ValueToStream(S,ObjPtr->initial_count);
1644 		ValueToStream(S,ObjPtr->minimum_count);
1645 		ValueToStream(S,ObjPtr->maximum_count);
1646 
1647 		ValueToStream(S,ObjPtr->random_count);
1648 		ValueToStream(S,ObjPtr->random_chance);
1649 	}
1650 
1651 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_object_frequency_definition));
1652 	return S;
1653 }
1654 
1655 
unpack_static_data(uint8 * Stream,static_data * Objects,size_t Count)1656 uint8 *unpack_static_data(uint8 *Stream, static_data* Objects, size_t Count)
1657 {
1658 	uint8* S = Stream;
1659 	static_data* ObjPtr = Objects;
1660 
1661 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1662 	{
1663 		StreamToValue(S,ObjPtr->environment_code);
1664 
1665 		StreamToValue(S,ObjPtr->physics_model);
1666 		StreamToValue(S,ObjPtr->song_index);
1667 		StreamToValue(S,ObjPtr->mission_flags);
1668 		StreamToValue(S,ObjPtr->environment_flags);
1669 
1670 		S += 4*2;
1671 
1672 		StreamToBytes(S,ObjPtr->level_name,LEVEL_NAME_LENGTH);
1673 		StreamToValue(S,ObjPtr->entry_point_flags);
1674 	}
1675 
1676 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_static_data));
1677 	return S;
1678 }
1679 
pack_static_data(uint8 * Stream,static_data * Objects,size_t Count)1680 uint8 *pack_static_data(uint8 *Stream, static_data* Objects, size_t Count)
1681 {
1682 	uint8* S = Stream;
1683 	static_data* ObjPtr = Objects;
1684 
1685 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1686 	{
1687 		ValueToStream(S,ObjPtr->environment_code);
1688 
1689 		ValueToStream(S,ObjPtr->physics_model);
1690 		ValueToStream(S,ObjPtr->song_index);
1691 		ValueToStream(S,ObjPtr->mission_flags);
1692 		ValueToStream(S,ObjPtr->environment_flags);
1693 
1694 		S += 4*2;
1695 
1696 		BytesToStream(S,ObjPtr->level_name,LEVEL_NAME_LENGTH);
1697 		ValueToStream(S,ObjPtr->entry_point_flags);
1698 	}
1699 
1700 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_static_data));
1701 	return S;
1702 }
1703 
1704 
unpack_ambient_sound_image_data(uint8 * Stream,ambient_sound_image_data * Objects,size_t Count)1705 uint8 *unpack_ambient_sound_image_data(uint8 *Stream, ambient_sound_image_data* Objects, size_t Count)
1706 {
1707 	uint8* S = Stream;
1708 	ambient_sound_image_data* ObjPtr = Objects;
1709 
1710 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1711 	{
1712 		StreamToValue(S,ObjPtr->flags);
1713 
1714 		StreamToValue(S,ObjPtr->sound_index);
1715 		StreamToValue(S,ObjPtr->volume);
1716 
1717 		S += 5*2;
1718 	}
1719 
1720 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_ambient_sound_image_data));
1721 	return S;
1722 }
1723 
pack_ambient_sound_image_data(uint8 * Stream,ambient_sound_image_data * Objects,size_t Count)1724 uint8 *pack_ambient_sound_image_data(uint8 *Stream, ambient_sound_image_data* Objects, size_t Count)
1725 {
1726 	uint8* S = Stream;
1727 	ambient_sound_image_data* ObjPtr = Objects;
1728 
1729 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1730 	{
1731 		ValueToStream(S,ObjPtr->flags);
1732 
1733 		ValueToStream(S,ObjPtr->sound_index);
1734 		ValueToStream(S,ObjPtr->volume);
1735 
1736 		S += 5*2;
1737 	}
1738 
1739 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_ambient_sound_image_data));
1740 	return S;
1741 }
1742 
1743 
unpack_random_sound_image_data(uint8 * Stream,random_sound_image_data * Objects,size_t Count)1744 uint8 *unpack_random_sound_image_data(uint8 *Stream, random_sound_image_data* Objects, size_t Count)
1745 {
1746 	uint8* S = Stream;
1747 	random_sound_image_data* ObjPtr = Objects;
1748 
1749 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1750 	{
1751 		StreamToValue(S,ObjPtr->flags);
1752 
1753 		StreamToValue(S,ObjPtr->sound_index);
1754 
1755 		StreamToValue(S,ObjPtr->volume);
1756 		StreamToValue(S,ObjPtr->delta_volume);
1757 		StreamToValue(S,ObjPtr->period);
1758 		StreamToValue(S,ObjPtr->delta_period);
1759 		StreamToValue(S,ObjPtr->direction);
1760 		StreamToValue(S,ObjPtr->delta_direction);
1761 		StreamToValue(S,ObjPtr->pitch);
1762 		StreamToValue(S,ObjPtr->delta_pitch);
1763 
1764 		StreamToValue(S,ObjPtr->phase);
1765 
1766 		S += 3*2;
1767 	}
1768 
1769 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_random_sound_image_data));
1770 	return S;
1771 }
1772 
pack_random_sound_image_data(uint8 * Stream,random_sound_image_data * Objects,size_t Count)1773 uint8 *pack_random_sound_image_data(uint8 *Stream, random_sound_image_data* Objects, size_t Count)
1774 {
1775 	uint8* S = Stream;
1776 	random_sound_image_data* ObjPtr = Objects;
1777 
1778 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1779 	{
1780 		ValueToStream(S,ObjPtr->flags);
1781 
1782 		ValueToStream(S,ObjPtr->sound_index);
1783 
1784 		ValueToStream(S,ObjPtr->volume);
1785 		ValueToStream(S,ObjPtr->delta_volume);
1786 		ValueToStream(S,ObjPtr->period);
1787 		ValueToStream(S,ObjPtr->delta_period);
1788 		ValueToStream(S,ObjPtr->direction);
1789 		ValueToStream(S,ObjPtr->delta_direction);
1790 		ValueToStream(S,ObjPtr->pitch);
1791 		ValueToStream(S,ObjPtr->delta_pitch);
1792 
1793 		ValueToStream(S,ObjPtr->phase);
1794 
1795 		S += 3*2;
1796 	}
1797 
1798 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_random_sound_image_data));
1799 	return S;
1800 }
1801 
1802 
StreamToGameData(uint8 * & S,game_data & Object)1803 static void StreamToGameData(uint8* &S, game_data& Object)
1804 {
1805 	StreamToValue(S,Object.game_time_remaining);
1806 	StreamToValue(S,Object.game_type);
1807 	StreamToValue(S,Object.game_options);
1808 	StreamToValue(S,Object.kill_limit);
1809 	StreamToValue(S,Object.initial_random_seed);
1810 	StreamToValue(S,Object.difficulty_level);
1811 	StreamToList(S,Object.parameters,2);
1812 }
1813 
GameDataToStream(uint8 * & S,game_data & Object)1814 static void GameDataToStream(uint8* &S, game_data& Object)
1815 {
1816 	ValueToStream(S,Object.game_time_remaining);
1817 	ValueToStream(S,Object.game_type);
1818 	ValueToStream(S,Object.game_options);
1819 	ValueToStream(S,Object.kill_limit);
1820 	ValueToStream(S,Object.initial_random_seed);
1821 	ValueToStream(S,Object.difficulty_level);
1822 	ListToStream(S,Object.parameters,2);
1823 }
1824 
1825 
unpack_dynamic_data(uint8 * Stream,dynamic_data * Objects,size_t Count)1826 uint8 *unpack_dynamic_data(uint8 *Stream, dynamic_data* Objects, size_t Count)
1827 {
1828 	uint8* S = Stream;
1829 	dynamic_data* ObjPtr = Objects;
1830 
1831 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1832 	{
1833 		StreamToValue(S,ObjPtr->tick_count);
1834 
1835 		StreamToValue(S,ObjPtr->random_seed);
1836 
1837 		StreamToGameData(S,ObjPtr->game_information);
1838 
1839 		StreamToValue(S,ObjPtr->player_count);
1840 		StreamToValue(S,ObjPtr->speaking_player_index);
1841 
1842 		S += 2;
1843 		StreamToValue(S,ObjPtr->platform_count);
1844 		StreamToValue(S,ObjPtr->endpoint_count);
1845 		StreamToValue(S,ObjPtr->line_count);
1846 		StreamToValue(S,ObjPtr->side_count);
1847 		StreamToValue(S,ObjPtr->polygon_count);
1848 		StreamToValue(S,ObjPtr->lightsource_count);
1849 		StreamToValue(S,ObjPtr->map_index_count);
1850 		StreamToValue(S,ObjPtr->ambient_sound_image_count);
1851 		StreamToValue(S,ObjPtr->random_sound_image_count);
1852 
1853 		StreamToValue(S,ObjPtr->object_count);
1854 		StreamToValue(S,ObjPtr->monster_count);
1855 		StreamToValue(S,ObjPtr->projectile_count);
1856 		StreamToValue(S,ObjPtr->effect_count);
1857 		StreamToValue(S,ObjPtr->light_count);
1858 
1859 		StreamToValue(S,ObjPtr->default_annotation_count);
1860 		StreamToValue(S,ObjPtr->personal_annotation_count);
1861 
1862 		StreamToValue(S,ObjPtr->initial_objects_count);
1863 
1864 		StreamToValue(S,ObjPtr->garbage_object_count);
1865 
1866 		StreamToValue(S,ObjPtr->last_monster_index_to_get_time);
1867 		StreamToValue(S,ObjPtr->last_monster_index_to_build_path);
1868 
1869 		StreamToValue(S,ObjPtr->new_monster_mangler_cookie);
1870 		StreamToValue(S,ObjPtr->new_monster_vanishing_cookie);
1871 
1872 		StreamToValue(S,ObjPtr->civilians_killed_by_players);
1873 
1874 		StreamToList(S,ObjPtr->random_monsters_left,MAXIMUM_OBJECT_TYPES);
1875 		StreamToList(S,ObjPtr->current_monster_count,MAXIMUM_OBJECT_TYPES);
1876 		StreamToList(S,ObjPtr->random_items_left,MAXIMUM_OBJECT_TYPES);
1877 		StreamToList(S,ObjPtr->current_item_count,MAXIMUM_OBJECT_TYPES);
1878 
1879 		StreamToValue(S,ObjPtr->current_level_number);
1880 
1881 		StreamToValue(S,ObjPtr->current_civilian_causalties);
1882 		StreamToValue(S,ObjPtr->current_civilian_count);
1883 		StreamToValue(S,ObjPtr->total_civilian_causalties);
1884 		StreamToValue(S,ObjPtr->total_civilian_count);
1885 
1886 		StreamToValue(S,ObjPtr->game_beacon.x);
1887 		StreamToValue(S,ObjPtr->game_beacon.y);
1888 		StreamToValue(S,ObjPtr->game_player_index);
1889 	}
1890 
1891 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_dynamic_data));
1892 	return S;
1893 }
1894 
pack_dynamic_data(uint8 * Stream,dynamic_data * Objects,size_t Count)1895 uint8 *pack_dynamic_data(uint8 *Stream, dynamic_data* Objects, size_t Count)
1896 {
1897 	uint8* S = Stream;
1898 	dynamic_data* ObjPtr = Objects;
1899 
1900 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1901 	{
1902 		ValueToStream(S,ObjPtr->tick_count);
1903 
1904 		ValueToStream(S,ObjPtr->random_seed);
1905 
1906 		GameDataToStream(S,ObjPtr->game_information);
1907 
1908 		ValueToStream(S,ObjPtr->player_count);
1909 		ValueToStream(S,ObjPtr->speaking_player_index);
1910 
1911 		S += 2;
1912 		ValueToStream(S,ObjPtr->platform_count);
1913 		ValueToStream(S,ObjPtr->endpoint_count);
1914 		ValueToStream(S,ObjPtr->line_count);
1915 		ValueToStream(S,ObjPtr->side_count);
1916 		ValueToStream(S,ObjPtr->polygon_count);
1917 		ValueToStream(S,ObjPtr->lightsource_count);
1918 		ValueToStream(S,ObjPtr->map_index_count);
1919 		ValueToStream(S,ObjPtr->ambient_sound_image_count);
1920 		ValueToStream(S,ObjPtr->random_sound_image_count);
1921 
1922 		ValueToStream(S,ObjPtr->object_count);
1923 		ValueToStream(S,ObjPtr->monster_count);
1924 		ValueToStream(S,ObjPtr->projectile_count);
1925 		ValueToStream(S,ObjPtr->effect_count);
1926 		ValueToStream(S,ObjPtr->light_count);
1927 
1928 		ValueToStream(S,ObjPtr->default_annotation_count);
1929 		ValueToStream(S,ObjPtr->personal_annotation_count);
1930 
1931 		ValueToStream(S,ObjPtr->initial_objects_count);
1932 
1933 		ValueToStream(S,ObjPtr->garbage_object_count);
1934 
1935 		ValueToStream(S,ObjPtr->last_monster_index_to_get_time);
1936 		ValueToStream(S,ObjPtr->last_monster_index_to_build_path);
1937 
1938 		ValueToStream(S,ObjPtr->new_monster_mangler_cookie);
1939 		ValueToStream(S,ObjPtr->new_monster_vanishing_cookie);
1940 
1941 		ValueToStream(S,ObjPtr->civilians_killed_by_players);
1942 
1943 		ListToStream(S,ObjPtr->random_monsters_left,MAXIMUM_OBJECT_TYPES);
1944 		ListToStream(S,ObjPtr->current_monster_count,MAXIMUM_OBJECT_TYPES);
1945 		ListToStream(S,ObjPtr->random_items_left,MAXIMUM_OBJECT_TYPES);
1946 		ListToStream(S,ObjPtr->current_item_count,MAXIMUM_OBJECT_TYPES);
1947 
1948 		ValueToStream(S,ObjPtr->current_level_number);
1949 
1950 		ValueToStream(S,ObjPtr->current_civilian_causalties);
1951 		ValueToStream(S,ObjPtr->current_civilian_count);
1952 		ValueToStream(S,ObjPtr->total_civilian_causalties);
1953 		ValueToStream(S,ObjPtr->total_civilian_count);
1954 
1955 		ValueToStream(S,ObjPtr->game_beacon.x);
1956 		ValueToStream(S,ObjPtr->game_beacon.y);
1957 		ValueToStream(S,ObjPtr->game_player_index);
1958 	}
1959 
1960 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_dynamic_data));
1961 	return S;
1962 }
1963 
1964 
unpack_object_data(uint8 * Stream,object_data * Objects,size_t Count)1965 uint8 *unpack_object_data(uint8 *Stream, object_data* Objects, size_t Count)
1966 {
1967 	uint8* S = Stream;
1968 	object_data* ObjPtr = Objects;
1969 
1970 	for (size_t k = 0; k < Count; k++, ObjPtr++)
1971 	{
1972 		StreamToValue(S,ObjPtr->location.x);
1973 		StreamToValue(S,ObjPtr->location.y);
1974 		StreamToValue(S,ObjPtr->location.z);
1975 		StreamToValue(S,ObjPtr->polygon);
1976 
1977 		StreamToValue(S,ObjPtr->facing);
1978 
1979 		StreamToValue(S,ObjPtr->shape);
1980 
1981 		StreamToValue(S,ObjPtr->sequence);
1982 		StreamToValue(S,ObjPtr->flags);
1983 		StreamToValue(S,ObjPtr->transfer_mode);
1984 		StreamToValue(S,ObjPtr->transfer_period);
1985 		StreamToValue(S,ObjPtr->transfer_phase);
1986 		StreamToValue(S,ObjPtr->permutation);
1987 
1988 		StreamToValue(S,ObjPtr->next_object);
1989 		StreamToValue(S,ObjPtr->parasitic_object);
1990 
1991 		StreamToValue(S,ObjPtr->sound_pitch);
1992 	}
1993 
1994 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_object_data));
1995 	return S;
1996 }
1997 
pack_object_data(uint8 * Stream,object_data * Objects,size_t Count)1998 uint8 *pack_object_data(uint8 *Stream, object_data* Objects, size_t Count)
1999 {
2000 	uint8* S = Stream;
2001 	object_data* ObjPtr = Objects;
2002 
2003 	for (size_t k = 0; k < Count; k++, ObjPtr++)
2004 	{
2005 		ValueToStream(S,ObjPtr->location.x);
2006 		ValueToStream(S,ObjPtr->location.y);
2007 		ValueToStream(S,ObjPtr->location.z);
2008 		ValueToStream(S,ObjPtr->polygon);
2009 
2010 		ValueToStream(S,ObjPtr->facing);
2011 
2012 		ValueToStream(S,ObjPtr->shape);
2013 
2014 		ValueToStream(S,ObjPtr->sequence);
2015 		ValueToStream(S,ObjPtr->flags);
2016 		ValueToStream(S,ObjPtr->transfer_mode);
2017 		ValueToStream(S,ObjPtr->transfer_period);
2018 		ValueToStream(S,ObjPtr->transfer_phase);
2019 		ValueToStream(S,ObjPtr->permutation);
2020 
2021 		ValueToStream(S,ObjPtr->next_object);
2022 		ValueToStream(S,ObjPtr->parasitic_object);
2023 
2024 		ValueToStream(S,ObjPtr->sound_pitch);
2025 	}
2026 
2027 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_object_data));
2028 	return S;
2029 }
2030 
2031 
unpack_damage_definition(uint8 * Stream,damage_definition * Objects,size_t Count)2032 uint8 *unpack_damage_definition(uint8 *Stream, damage_definition* Objects, size_t Count)
2033 {
2034 	uint8* S = Stream;
2035 	damage_definition* ObjPtr = Objects;
2036 
2037 	for (size_t k = 0; k < Count; k++, ObjPtr++)
2038 	{
2039 		StreamToValue(S,ObjPtr->type);
2040 		StreamToValue(S,ObjPtr->flags);
2041 
2042 		StreamToValue(S,ObjPtr->base);
2043 		StreamToValue(S,ObjPtr->random);
2044 		StreamToValue(S,ObjPtr->scale);
2045 	}
2046 
2047 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_damage_definition));
2048 	return S;
2049 }
2050 
pack_damage_definition(uint8 * Stream,damage_definition * Objects,size_t Count)2051 uint8 *pack_damage_definition(uint8 *Stream, damage_definition* Objects, size_t Count)
2052 {
2053 	uint8* S = Stream;
2054 	damage_definition* ObjPtr = Objects;
2055 
2056 	for (size_t k = 0; k < Count; k++, ObjPtr++)
2057 	{
2058 		ValueToStream(S,ObjPtr->type);
2059 		ValueToStream(S,ObjPtr->flags);
2060 
2061 		ValueToStream(S,ObjPtr->base);
2062 		ValueToStream(S,ObjPtr->random);
2063 		ValueToStream(S,ObjPtr->scale);
2064 	}
2065 
2066 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_damage_definition));
2067 	return S;
2068 }
2069