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