2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* Functions to dump text description of mine .
* An editor - only function , called at mine load time .
* To be read by a human to verify the correctness and completeness of a mine .
*
*/
2014-10-02 03:02:34 +00:00
# include <bitset>
2006-03-20 17:12:09 +00:00
# include <stdio.h>
2019-05-04 18:27:37 +00:00
# include <cinttypes>
2006-03-20 17:12:09 +00:00
# include <string.h>
# include <stdarg.h>
# include <errno.h>
# include "pstypes.h"
2008-04-06 20:23:28 +00:00
# include "console.h"
2014-07-20 01:09:55 +00:00
# include "physfsx.h"
2006-03-20 17:12:09 +00:00
# include "key.h"
# include "gr.h"
# include "palette.h"
2013-12-08 23:37:40 +00:00
# include "fmtcheck.h"
2006-03-20 17:12:09 +00:00
# include "inferno.h"
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
# include "editor/editor.h"
# endif
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "object.h"
# include "wall.h"
# include "gamemine.h"
2013-12-26 04:18:28 +00:00
# include "gameseg.h"
2006-03-20 17:12:09 +00:00
# include "robot.h"
# include "player.h"
# include "newmenu.h"
# include "textures.h"
# include "bm.h"
# include "menu.h"
# include "switch.h"
# include "fuelcen.h"
# include "powerup.h"
# include "gameseq.h"
# include "polyobj.h"
# include "gamesave.h"
2012-11-11 00:14:30 +00:00
# include "piggy.h"
2006-03-20 17:12:09 +00:00
2014-07-30 02:52:33 +00:00
# include "compiler-range_for.h"
2019-05-04 18:27:36 +00:00
# include "d_enumerate.h"
2019-05-04 18:27:37 +00:00
# include "d_range.h"
2019-05-04 18:27:36 +00:00
# include "d_zip.h"
2014-07-30 02:52:33 +00:00
# include "segiter.h"
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2016-05-22 17:49:30 +00:00
namespace dsx {
namespace {
# if defined(DXX_BUILD_DESCENT_I)
2020-05-02 21:18:42 +00:00
using perm_tmap_buffer_type = std : : array < int , MAX_TEXTURES > ;
using level_tmap_buffer_type = std : : array < int8_t , MAX_TEXTURES > ;
using wall_buffer_type = std : : array < int , MAX_WALL_ANIMS > ;
2016-05-22 17:49:30 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2020-05-02 21:18:42 +00:00
using perm_tmap_buffer_type = std : : array < int , MAX_BITMAP_FILES > ;
using level_tmap_buffer_type = std : : array < int8_t , MAX_BITMAP_FILES > ;
using wall_buffer_type = std : : array < int , MAX_BITMAP_FILES > ;
2016-05-22 17:49:30 +00:00
# endif
}
}
namespace dcx {
2020-05-02 21:18:42 +00:00
const std : : array < char [ 10 ] , 7 > Wall_names { {
2015-04-02 02:36:56 +00:00
" NORMAL " ,
" BLASTABLE " ,
" DOOR " ,
" ILLUSION " ,
" OPEN " ,
" CLOSED " ,
" EXTERNAL "
} } ;
2016-05-22 17:49:30 +00:00
}
2015-04-02 02:36:56 +00:00
2019-08-06 02:59:40 +00:00
static void dump_used_textures_level ( PHYSFS_File * my_file , int level_num , const char * Gamesave_current_filename ) ;
2017-07-26 03:15:59 +00:00
static void say_totals ( fvcobjptridx & vcobjptridx , PHYSFS_File * my_file , const char * level_name ) ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
namespace dsx {
2020-05-02 21:18:42 +00:00
const std : : array < char [ 9 ] , MAX_OBJECT_TYPES > Object_type_names { {
2015-03-22 18:49:21 +00:00
" WALL " ,
" FIREBALL " ,
" ROBOT " ,
" HOSTAGE " ,
" PLAYER " ,
" WEAPON " ,
" CAMERA " ,
" POWERUP " ,
" DEBRIS " ,
" CNTRLCEN " ,
" FLARE " ,
" CLUTTER " ,
" GHOST " ,
" LIGHT " ,
" COOP " ,
# if defined(DXX_BUILD_DESCENT_II)
" MARKER " ,
# endif
} } ;
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-05-22 17:49:30 +00:00
static const char * object_types ( const object_base & objp )
2006-03-20 17:12:09 +00:00
{
2016-05-22 17:49:30 +00:00
const auto type = objp . type ;
2015-05-28 03:08:39 +00:00
assert ( type = = OBJ_NONE | | type < MAX_OBJECT_TYPES ) ;
2014-11-23 04:36:58 +00:00
return & Object_type_names [ type ] [ 0 ] ;
2006-03-20 17:12:09 +00:00
}
2016-05-22 17:49:30 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-28 22:41:48 +00:00
static const char * object_ids ( const object_base & objp )
2006-03-20 17:12:09 +00:00
{
2016-08-28 22:41:48 +00:00
switch ( objp . type )
2015-05-28 03:08:39 +00:00
{
2006-03-20 17:12:09 +00:00
case OBJ_ROBOT :
2016-07-09 17:58:34 +00:00
return Robot_names [ get_robot_id ( objp ) ] . data ( ) ;
2006-03-20 17:12:09 +00:00
case OBJ_POWERUP :
2016-07-09 17:58:34 +00:00
return Powerup_names [ get_powerup_id ( objp ) ] . data ( ) ;
2016-11-20 23:12:00 +00:00
default :
return nullptr ;
2006-03-20 17:12:09 +00:00
}
}
2016-01-09 16:38:14 +00:00
static void err_puts ( PHYSFS_File * f , const char * str , size_t len ) __attribute_nonnull ( ) ;
static void err_puts ( PHYSFS_File * f , const char * str , size_t len )
2013-12-19 22:55:34 +00:00
# define err_puts(A1,S,...) (err_puts(A1,S, _dxx_call_puts_parameter2(1, ## __VA_ARGS__, strlen(S))))
2013-12-08 23:37:40 +00:00
{
2013-12-19 22:55:34 +00:00
con_puts ( CON_CRITICAL , str , len ) ;
PHYSFSX_puts ( f , str ) ;
2013-12-08 23:37:40 +00:00
Errors_in_mine + + ;
}
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void err_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] ) __attribute_nonnull ( ) ;
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void err_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] )
2013-12-19 22:55:34 +00:00
{
err_puts ( f , str , len ) ;
}
2016-01-09 16:38:14 +00:00
static void err_printf ( PHYSFS_File * my_file , const char * format , . . . ) __attribute_format_printf ( 2 , 3 ) ;
static void err_printf ( PHYSFS_File * my_file , const char * format , . . . )
2013-12-19 22:55:34 +00:00
# define err_printf(A1,F,...) dxx_call_printf_checked(err_printf,err_puts_literal,(A1),(F),##__VA_ARGS__)
2006-03-20 17:12:09 +00:00
{
va_list args ;
char message [ 256 ] ;
va_start ( args , format ) ;
2013-12-19 22:55:34 +00:00
size_t len = vsnprintf ( message , sizeof ( message ) , format , args ) ;
2006-03-20 17:12:09 +00:00
va_end ( args ) ;
2013-12-19 22:55:34 +00:00
err_puts ( my_file , message , len ) ;
2006-03-20 17:12:09 +00:00
}
2016-01-09 16:38:14 +00:00
static void warning_puts ( PHYSFS_File * f , const char * str , size_t len ) __attribute_nonnull ( ) ;
static void warning_puts ( PHYSFS_File * f , const char * str , size_t len )
2013-12-19 22:55:34 +00:00
# define warning_puts(A1,S,...) (warning_puts(A1,S, _dxx_call_puts_parameter2(1, ## __VA_ARGS__, strlen(S))))
2013-12-08 23:37:40 +00:00
{
2013-12-19 22:55:34 +00:00
con_puts ( CON_URGENT , str , len ) ;
2013-12-08 23:37:40 +00:00
PHYSFSX_puts ( f , str ) ;
}
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void warning_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] ) __attribute_nonnull ( ) ;
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void warning_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] )
2013-12-19 22:55:34 +00:00
{
warning_puts ( f , str , len ) ;
}
2016-01-09 16:38:14 +00:00
static void warning_printf ( PHYSFS_File * my_file , const char * format , . . . ) __attribute_format_printf ( 2 , 3 ) ;
static void warning_printf ( PHYSFS_File * my_file , const char * format , . . . )
2013-12-19 22:55:34 +00:00
# define warning_printf(A1,F,...) dxx_call_printf_checked(warning_printf,warning_puts_literal,(A1),(F),##__VA_ARGS__)
2006-03-20 17:12:09 +00:00
{
va_list args ;
char message [ 256 ] ;
va_start ( args , format ) ;
2012-06-30 05:05:33 +00:00
vsnprintf ( message , sizeof ( message ) , format , args ) ;
2006-03-20 17:12:09 +00:00
va_end ( args ) ;
2013-12-08 23:37:40 +00:00
warning_puts ( my_file , message ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2017-07-26 03:15:59 +00:00
static void write_exit_text ( fvcsegptridx & vcsegptridx , fvcwallptridx & vcwallptridx , PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2019-05-04 18:27:37 +00:00
int count ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Exit stuff \n " ) ;
2006-03-20 17:12:09 +00:00
// ---------- Find exit triggers ----------
count = 0 ;
2018-12-30 00:43:58 +00:00
auto & Triggers = LevelUniqueWallSubsystemState . Triggers ;
auto & vctrgptridx = Triggers . vcptridx ;
2017-07-08 18:17:48 +00:00
range_for ( const auto & & t , vctrgptridx )
2016-02-06 22:12:54 +00:00
{
if ( trigger_is_exit ( t ) )
{
2006-03-20 17:12:09 +00:00
int count2 ;
2017-07-08 18:17:48 +00:00
const auto i = t . get_unchecked_index ( ) ;
2016-02-06 22:12:54 +00:00
PHYSFSX_printf ( my_file , " Trigger %2i, is an exit trigger with %i links. \n " , i , t - > num_links ) ;
2006-03-20 17:12:09 +00:00
count + + ;
2016-02-06 22:12:54 +00:00
if ( t - > num_links ! = 0 )
err_printf ( my_file , " Error: Exit triggers must have 0 links, this one has %i links. " , t - > num_links ) ;
2006-03-20 17:12:09 +00:00
// Find wall pointing to this trigger.
count2 = 0 ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & w , vcwallptridx )
{
if ( w - > trigger = = i )
{
2006-03-20 17:12:09 +00:00
count2 + + ;
2016-02-12 04:02:28 +00:00
PHYSFSX_printf ( my_file , " Exit trigger %i is in segment %i, on side %i, bound to wall %i \n " , i , w - > segnum , w - > sidenum , static_cast < wallnum_t > ( w ) ) ;
2006-03-20 17:12:09 +00:00
}
2016-02-12 04:02:28 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count2 = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Trigger %i is not bound to any wall. " , i ) ;
2006-03-20 17:12:09 +00:00
else if ( count2 > 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Trigger %i is bound to %i walls. " , i , count2 ) ;
2006-03-20 17:12:09 +00:00
}
2016-02-06 22:12:54 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: No exit trigger in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else if ( count ! = 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: More than one exit trigger in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
// ---------- Find exit doors ----------
count = 0 ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2015-06-13 22:42:16 +00:00
{
2019-05-04 18:27:37 +00:00
range_for ( const auto & & es , enumerate ( segp - > children ) )
{
if ( es . value = = segment_exit )
2015-05-28 03:08:39 +00:00
{
2019-05-04 18:27:37 +00:00
PHYSFSX_printf ( my_file , " Segment %3hu, side % " PRIuFAST32 " is an exit door. \n " , segp . get_unchecked_index ( ) , es . idx ) ;
2006-03-20 17:12:09 +00:00
count + + ;
}
2019-05-04 18:27:37 +00:00
}
2015-06-13 22:42:16 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: No external wall in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else if ( count ! = 1 ) {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: %i external walls in this mine. " , count ) ;
warning_printf ( my_file , " (If %i are secret exits, then no problem.) " , count - 1 ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
} else
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2016-10-26 01:58:04 +00:00
namespace {
2006-03-20 17:12:09 +00:00
2016-10-26 01:58:04 +00:00
class key_stat
{
const char * const label ;
unsigned wall_count = 0 , powerup_count = 0 ;
segnum_t seg = segment_none ;
uint8_t side = 0 ;
public :
key_stat ( const char * const p ) :
label ( p )
2016-10-15 00:53:16 +00:00
{
2016-10-26 01:58:04 +00:00
}
2017-07-26 03:15:59 +00:00
void check_wall ( const segment_array & segments , PHYSFS_File * const fp , const vcwallptridx_t wpi , const wall_key_t key )
2016-10-26 01:58:04 +00:00
{
auto & w = * wpi ;
if ( ! ( w . keys & key ) )
return ;
PHYSFSX_printf ( fp , " Wall %i (seg=%i, side=%i) is keyed to the %s key. \n " , static_cast < wallnum_t > ( wpi ) , w . segnum , w . sidenum , label ) ;
if ( seg = = segment_none )
{
seg = w . segnum ;
side = w . sidenum ;
2006-03-20 17:12:09 +00:00
}
2016-10-26 01:58:04 +00:00
else
{
2017-07-26 03:15:59 +00:00
const auto & & connect_side = find_connect_side ( segments . vcptridx ( w . segnum ) , segments . vcptr ( seg ) ) ;
2016-10-26 01:58:04 +00:00
if ( connect_side = = side )
return ;
warning_printf ( fp , " Warning: This door at seg %i, is different than the one at seg %i, side %i " , w . segnum , seg , side ) ;
2006-03-20 17:12:09 +00:00
}
2016-10-26 01:58:04 +00:00
+ + wall_count ;
}
void report_walls ( PHYSFS_File * const fp ) const
{
if ( wall_count > 1 )
warning_printf ( fp , " Warning: %i doors are keyed to the %s key. " , wall_count , label ) ;
}
void found_powerup ( const unsigned amount = 1 )
{
powerup_count + = amount ;
}
void report_keys ( PHYSFS_File * const fp ) const
{
if ( ! powerup_count )
{
if ( wall_count )
err_printf ( fp , " Error: There is a door keyed to the %s key, but no %s key! " , label , label ) ;
2006-03-20 17:12:09 +00:00
}
2016-10-26 01:58:04 +00:00
else if ( powerup_count > 1 )
err_printf ( fp , " Error: There are %i %s keys! " , powerup_count , label ) ;
2006-03-20 17:12:09 +00:00
}
2016-10-26 01:58:04 +00:00
} ;
}
2006-03-20 17:12:09 +00:00
2016-10-26 01:58:04 +00:00
// ----------------------------------------------------------------------------
2017-07-26 03:15:59 +00:00
static void write_key_text ( fvcobjptridx & vcobjptridx , segment_array & segments , fvcwallptridx & vcwallptridx , PHYSFS_File * my_file )
2016-10-26 01:58:04 +00:00
{
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Key stuff: \n " ) ;
2006-03-20 17:12:09 +00:00
2016-10-26 01:58:04 +00:00
key_stat blue ( " blue " ) , gold ( " gold " ) , red ( " red " ) ;
2006-03-20 17:12:09 +00:00
2016-10-26 01:58:04 +00:00
range_for ( const auto & & w , vcwallptridx )
{
2017-07-26 03:15:59 +00:00
blue . check_wall ( segments , my_file , w , KEY_BLUE ) ;
gold . check_wall ( segments , my_file , w , KEY_GOLD ) ;
red . check_wall ( segments , my_file , w , KEY_RED ) ;
2016-10-26 01:58:04 +00:00
}
2006-03-20 17:12:09 +00:00
2016-10-26 01:58:04 +00:00
blue . report_walls ( my_file ) ;
gold . report_walls ( my_file ) ;
red . report_walls ( my_file ) ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-06-13 22:42:16 +00:00
if ( objp - > type = = OBJ_POWERUP )
2016-09-04 19:10:42 +00:00
{
const char * color ;
const auto id = get_powerup_id ( objp ) ;
if (
2016-10-26 01:58:04 +00:00
( id = = POW_KEY_BLUE & & ( blue . found_powerup ( ) , color = " BLUE " , true ) ) | |
( id = = POW_KEY_RED & & ( red . found_powerup ( ) , color = " RED " , true ) ) | |
( id = = POW_KEY_GOLD & & ( gold . found_powerup ( ) , color = " GOLD " , true ) )
2016-09-04 19:10:42 +00:00
)
{
PHYSFSX_printf ( my_file , " The %s key is object %hu in segment %i \n " , color , static_cast < objnum_t > ( objp ) , objp - > segnum ) ;
2006-03-20 17:12:09 +00:00
}
2016-09-04 19:10:42 +00:00
}
2006-03-20 17:12:09 +00:00
2016-09-04 19:10:42 +00:00
if ( const auto contains_count = objp - > contains_count )
2015-06-13 22:42:16 +00:00
{
if ( objp - > contains_type = = OBJ_POWERUP )
{
2016-09-04 19:10:42 +00:00
const char * color ;
const auto id = objp - > contains_id ;
if (
2016-10-26 01:58:04 +00:00
( id = = POW_KEY_BLUE & & ( blue . found_powerup ( contains_count ) , color = " BLUE " , true ) ) | |
( id = = POW_KEY_RED & & ( red . found_powerup ( contains_count ) , color = " RED " , true ) ) | |
( id = = POW_KEY_GOLD & & ( gold . found_powerup ( contains_count ) , color = " GOLD " , true ) )
2016-09-04 19:10:42 +00:00
)
PHYSFSX_printf ( my_file , " The %s key is contained in object %hu (a %s %s) in segment %hu \n " , color , static_cast < objnum_t > ( objp ) , object_types ( objp ) , Robot_names [ get_robot_id ( objp ) ] . data ( ) , objp - > segnum ) ;
2006-03-20 17:12:09 +00:00
}
}
}
2016-10-26 01:58:04 +00:00
blue . report_keys ( my_file ) ;
gold . report_keys ( my_file ) ;
red . report_keys ( my_file ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2017-07-26 03:15:59 +00:00
static void write_control_center_text ( fvcsegptridx & vcsegptridx , PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptridx = Objects . vcptridx ;
2014-10-12 23:10:05 +00:00
int count , count2 ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Control Center stuff: \n " ) ;
2006-03-20 17:12:09 +00:00
count = 0 ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2015-06-13 22:42:16 +00:00
{
if ( segp - > special = = SEGMENT_IS_CONTROLCEN )
{
2006-03-20 17:12:09 +00:00
count + + ;
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Segment %3hu is a control center. \n " , static_cast < uint16_t > ( segp ) ) ;
2006-03-20 17:12:09 +00:00
count2 = 0 ;
2019-12-22 05:34:08 +00:00
range_for ( const object & objp , objects_in ( segp , vcobjptridx , vcsegptr ) )
2014-07-30 02:52:33 +00:00
{
2019-12-22 05:34:08 +00:00
if ( objp . type = = OBJ_CNTRLCEN )
2006-03-20 17:12:09 +00:00
count2 + + ;
}
if ( count2 = = 0 )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " No control center object in control center segment. \n " ) ;
2006-03-20 17:12:09 +00:00
else if ( count2 ! = 1 )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " %i control center objects in control center segment. \n " , count2 ) ;
2006-03-20 17:12:09 +00:00
}
2015-06-13 22:42:16 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: No control center in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else if ( count ! = 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: More than one control center in this mine. " ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2016-01-09 16:38:14 +00:00
static void write_fuelcen_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2019-02-02 18:36:39 +00:00
auto & Station = LevelUniqueFuelcenterState . Station ;
2006-03-20 17:12:09 +00:00
int i ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Fuel Center stuff: (Note: This means fuel, repair, materialize, control centers!) \n " ) ;
2006-03-20 17:12:09 +00:00
2019-02-02 18:36:39 +00:00
const auto Num_fuelcenters = LevelUniqueFuelcenterState . Num_fuelcenters ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < Num_fuelcenters ; i + + ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Fuelcenter %i: Type=%i (%s), segment = %3i \n " , i , Station [ i ] . Type , Special_names [ Station [ i ] . Type ] , Station [ i ] . segnum ) ;
2013-10-06 16:20:00 +00:00
if ( Segments [ Station [ i ] . segnum ] . special ! = Station [ i ] . Type )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Conflicting data: Segment %i has special type %i (%s), expected to be %i " , Station [ i ] . segnum , Segments [ Station [ i ] . segnum ] . special , Special_names [ Segments [ Station [ i ] . segnum ] . special ] , Station [ i ] . Type ) ;
2006-03-20 17:12:09 +00:00
}
}
// ----------------------------------------------------------------------------
2017-07-26 03:15:59 +00:00
static void write_segment_text ( fvcsegptridx & vcsegptridx , PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptridx = Objects . vcptridx ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Segment stuff: \n " ) ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2014-10-12 23:10:05 +00:00
{
2017-07-08 18:17:49 +00:00
PHYSFSX_printf ( my_file , " Segment %4hu: " , static_cast < uint16_t > ( segp ) ) ;
2015-06-13 22:42:16 +00:00
if ( segp - > special ! = 0 )
2017-07-08 18:17:49 +00:00
PHYSFSX_printf ( my_file , " special = %3i (%s), station_idx=%3i " , segp - > special , Special_names [ segp - > special ] , segp - > station_idx ) ;
2015-06-13 22:42:16 +00:00
if ( segp - > matcen_num ! = - 1 )
2017-07-08 18:17:49 +00:00
PHYSFSX_printf ( my_file , " matcen = %3i " , segp - > matcen_num ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
}
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2014-10-12 23:10:05 +00:00
{
2006-03-20 17:12:09 +00:00
int depth ;
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Segment %4hu: " , static_cast < uint16_t > ( segp ) ) ;
2006-03-20 17:12:09 +00:00
depth = 0 ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Objects: " ) ;
2017-08-13 20:38:31 +00:00
range_for ( const auto objp , objects_in ( segp , vcobjptridx , vcsegptr ) )
2014-07-30 02:52:33 +00:00
{
short objnum = objp ;
2015-05-28 03:08:39 +00:00
PHYSFSX_printf ( my_file , " [%8s %8s %3i] " , object_types ( objp ) , object_ids ( objp ) , objnum ) ;
2006-03-20 17:12:09 +00:00
if ( depth + + > 30 ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Aborted after %i links \n " , depth ) ;
2006-03-20 17:12:09 +00:00
break ;
}
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
}
}
// ----------------------------------------------------------------------------
// This routine is bogus. It assumes that all centers are matcens,
// which is not true. The setting of segnum is bogus.
2016-01-09 16:38:14 +00:00
static void write_matcen_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2016-02-06 22:12:54 +00:00
int i ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Materialization centers: \n " ) ;
2019-02-02 18:36:39 +00:00
auto & RobotCenters = LevelSharedRobotcenterState . RobotCenters ;
2019-02-02 18:36:39 +00:00
auto & Station = LevelUniqueFuelcenterState . Station ;
2018-12-30 00:43:58 +00:00
auto & Triggers = LevelUniqueWallSubsystemState . Triggers ;
auto & vctrgptridx = Triggers . vcptridx ;
2019-03-12 04:01:07 +00:00
const auto Num_robot_centers = LevelSharedRobotcenterState . Num_robot_centers ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < Num_robot_centers ; i + + ) {
2013-12-29 04:28:07 +00:00
int trigger_count = 0 , fuelcen_num ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " FuelCenter[%02i].Segment = %04i " , i , Station [ i ] . segnum ) ;
2013-10-06 16:20:00 +00:00
PHYSFSX_printf ( my_file , " Segment[%04i].matcen_num = %02i " , Station [ i ] . segnum , Segments [ Station [ i ] . segnum ] . matcen_num ) ;
2006-03-20 17:12:09 +00:00
fuelcen_num = RobotCenters [ i ] . fuelcen_num ;
if ( Station [ fuelcen_num ] . Type ! = SEGMENT_IS_ROBOTMAKER )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Matcen %i corresponds to Station %i, which has type %i (%s). " , i , fuelcen_num , Station [ fuelcen_num ] . Type , Special_names [ Station [ fuelcen_num ] . Type ] ) ;
2006-03-20 17:12:09 +00:00
2014-11-20 03:00:36 +00:00
auto segnum = Station [ fuelcen_num ] . segnum ;
2006-03-20 17:12:09 +00:00
// Find trigger for this materialization center.
2017-07-08 18:17:48 +00:00
range_for ( auto & & t , vctrgptridx )
2016-02-06 22:12:54 +00:00
{
if ( trigger_is_matcen ( t ) )
2014-12-14 21:02:40 +00:00
{
2016-02-12 04:02:28 +00:00
range_for ( auto & k , partial_const_range ( t - > seg , t - > num_links ) )
2014-12-14 21:02:40 +00:00
if ( k = = segnum )
{
2017-07-08 18:17:48 +00:00
PHYSFSX_printf ( my_file , " Trigger = %2i " , t . get_unchecked_index ( ) ) ;
2006-03-20 17:12:09 +00:00
trigger_count + + ;
}
}
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
if ( trigger_count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Matcen %i in segment %i has no trigger! " , i , segnum ) ;
2006-03-20 17:12:09 +00:00
}
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2017-07-26 03:15:59 +00:00
static void write_wall_text ( fvcsegptridx & vcsegptridx , fvcwallptridx & vcwallptridx , PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2020-05-02 21:18:42 +00:00
std : : array < int8_t , MAX_WALLS > wall_flags ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Walls: \n " ) ;
2018-12-30 00:43:58 +00:00
# if defined(DXX_BUILD_DESCENT_II)
auto & Triggers = LevelUniqueWallSubsystemState . Triggers ;
# endif
2016-10-15 00:53:16 +00:00
range_for ( auto & & wp , vcwallptridx )
{
auto & w = * wp ;
2013-12-29 04:28:07 +00:00
int sidenum ;
2006-03-20 17:12:09 +00:00
2016-10-15 00:53:16 +00:00
const auto i = static_cast < wallnum_t > ( wp ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Wall %03i: seg=%3i, side=%2i, linked_wall=%3i, type=%s, flags=%4x, hps=%3i, trigger=%2i, clip_num=%2i, keys=%2i, state=%i \n " , i ,
2016-10-15 00:53:16 +00:00
w . segnum , w . sidenum , w . linked_wall , Wall_names [ w . type ] , w . flags , w . hps > > 16 , w . trigger , w . clip_num , w . keys , w . state ) ;
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2018-12-13 02:31:39 +00:00
if ( w . trigger > = Triggers . get_count ( ) )
2016-10-15 00:53:16 +00:00
PHYSFSX_printf ( my_file , " Wall %03d points to invalid trigger %d \n " , i , w . trigger ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-10-15 00:53:16 +00:00
auto segnum = w . segnum ;
sidenum = w . sidenum ;
2006-03-20 17:12:09 +00:00
2018-12-13 02:31:38 +00:00
if ( Segments [ segnum ] . shared_segment : : sides [ sidenum ] . wall_num ! = wp )
err_printf ( my_file , " Error: Wall %u points at segment %i, side %i, but that segment doesn't point back (it's wall_num = %hi) " , i , segnum , sidenum , static_cast < int16_t > ( Segments [ segnum ] . shared_segment : : sides [ sidenum ] . wall_num ) ) ;
2006-03-20 17:12:09 +00:00
}
2016-05-22 17:49:30 +00:00
wall_flags = { } ;
2006-03-20 17:12:09 +00:00
2016-10-15 00:53:16 +00:00
range_for ( const auto & & segp , vcsegptridx )
2014-10-12 23:10:05 +00:00
{
2019-05-04 18:27:37 +00:00
range_for ( const auto & & es , enumerate ( segp - > shared_segment : : sides ) )
{
const auto sidep = & es . value ;
2014-10-04 15:04:44 +00:00
if ( sidep - > wall_num ! = wall_none )
2006-03-20 17:12:09 +00:00
{
if ( wall_flags [ sidep - > wall_num ] )
2019-05-04 18:27:37 +00:00
err_printf ( my_file , " Error: Wall %hu appears in two or more segments, including segment %hu, side % " PRIuFAST32 " . " , static_cast < int16_t > ( sidep - > wall_num ) , static_cast < segnum_t > ( segp ) , es . idx ) ;
2006-03-20 17:12:09 +00:00
else
wall_flags [ sidep - > wall_num ] = 1 ;
}
}
}
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2017-07-26 03:15:59 +00:00
static void write_player_text ( fvcobjptridx & vcobjptridx , PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2014-10-12 23:05:46 +00:00
int num_players = 0 ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Players: \n " ) ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-06-13 22:42:16 +00:00
if ( objp - > type = = OBJ_PLAYER )
{
2006-03-20 17:12:09 +00:00
num_players + + ;
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Player %2i is object #%3hu in segment #%3i. \n " , get_player_id ( objp ) , static_cast < uint16_t > ( objp ) , objp - > segnum ) ;
2006-03-20 17:12:09 +00:00
}
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
if ( num_players ! = MAX_PLAYERS )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: %i player objects. %i are required. " , num_players , MAX_PLAYERS ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
if ( num_players > MAX_MULTI_PLAYERS )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: %i player objects. %i are required. " , num_players , MAX_PLAYERS ) ;
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
static void write_trigger_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Triggers: \n " ) ;
2018-12-30 00:43:58 +00:00
auto & Triggers = LevelUniqueWallSubsystemState . Triggers ;
auto & vctrgptridx = Triggers . vcptridx ;
2018-12-30 00:43:58 +00:00
auto & Walls = LevelUniqueWallSubsystemState . Walls ;
auto & vcwallptr = Walls . vcptr ;
2016-10-15 00:53:16 +00:00
range_for ( auto & & t , vctrgptridx )
2016-02-06 22:12:54 +00:00
{
2016-10-15 00:53:16 +00:00
const auto i = static_cast < trgnum_t > ( t ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2018-12-30 00:43:58 +00:00
PHYSFSX_printf ( my_file , " Trigger %03i: flags=%04x, value=%08x, time=%8x, num_links=%i " , i , t - > flags , static_cast < unsigned > ( t - > value ) , 0 , t - > num_links ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Trigger %03i: type=%02x flags=%04x, value=%08x, time=%8x, num_links=%i " , i ,
Tighten type for trigger behavior flags
Use an enum class to prevent implicit conversion between trigger
behavior flags and other integers. Fix up various resulting breaks,
which look like bugs:
- Descent 2 editor mode could modify trigger::flags, but used
TRIGGER_FLAG_* values, which specify the actions for a Descent 1
trigger when it executes, not the behavior properties for a trigger.
- Adding a trigger set its flags to 0, then cleared all flags except
TRIGGER_ON. Since the flags were just set to 0, the mask operation is
useless. Remove it.
- trigger_turn_all_ON cleared all flags except TRIGGER_ON. This seems
to be completely wrong. Change it to remove
trigger_behavior_flags::disabled. Descent 1 has no (working) support
for disabling triggers, so make trigger_turn_all_ON exclusive to
Descent 2.
- wall_restore_all would enable TRIGGER_ON in both games. Descent 1
never reads TRIGGER_ON. Descent 2 uses this field for trigger
behavior flags, and TRIGGER_ON is not a behavior flag.
- For Descent 1 builds, remove the modification of the field.
- For Descent 2 builds, change it to clear
trigger_behavior_flags::disabled.
2020-07-05 23:34:32 +00:00
t - > type , static_cast < uint8_t > ( t - > flags ) , t - > value , 0 , t - > num_links ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-02-06 22:12:54 +00:00
for ( unsigned j = 0 ; j < t - > num_links ; + + j )
PHYSFSX_printf ( my_file , " [%03i:%i] " , t - > seg [ j ] , t - > side [ j ] ) ;
2006-03-20 17:12:09 +00:00
// Find which wall this trigger is connected to.
2016-10-15 00:53:16 +00:00
const auto & & we = vcwallptr . end ( ) ;
2018-06-06 04:53:45 +00:00
const auto & & wi = std : : find_if ( vcwallptr . begin ( ) , we , [ i ] ( const wall * const p ) { return p - > trigger = = i ; } ) ;
if ( wi = = we )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Trigger %i is not connected to any wall, so it can never be triggered. " , i ) ;
2006-03-20 17:12:09 +00:00
else
2018-06-06 04:53:45 +00:00
{
const auto & & w = * wi ;
2018-12-13 02:31:38 +00:00
PHYSFSX_printf ( my_file , " Attached to seg:side = %i:%i, wall %hi \n " , w - > segnum , w - > sidenum , static_cast < int16_t > ( vcsegptr ( w - > segnum ) - > shared_segment : : sides [ w - > sidenum ] . wall_num ) ) ;
2018-06-06 04:53:45 +00:00
}
2006-03-20 17:12:09 +00:00
}
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2013-06-08 22:24:17 +00:00
void write_game_text_file ( const char * filename )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptridx = Objects . vcptridx ;
2006-03-20 17:12:09 +00:00
char my_filename [ 128 ] ;
int namelen ;
Errors_in_mine = 0 ;
namelen = strlen ( filename ) ;
Assert ( namelen > 4 ) ;
Assert ( filename [ namelen - 4 ] = = ' . ' ) ;
strcpy ( my_filename , filename ) ;
strcpy ( & my_filename [ namelen - 4 ] , " .txm " ) ;
2015-01-17 18:31:42 +00:00
auto my_file = PHYSFSX_openWriteBuffered ( my_filename ) ;
2006-03-20 17:12:09 +00:00
if ( ! my_file ) {
gr_palette_load ( gr_palette ) ;
2013-12-04 22:19:04 +00:00
nm_messagebox ( NULL , 1 , " Ok " , " ERROR: Unable to open %s \n Errno = %i " , my_filename , errno ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2019-08-06 02:59:40 +00:00
dump_used_textures_level ( my_file , 0 , filename ) ;
say_totals ( vcobjptridx , my_file , filename ) ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Number of segments: %4i \n " , Highest_segment_index + 1 ) ;
PHYSFSX_printf ( my_file , " Number of objects: %4i \n " , Highest_object_index + 1 ) ;
2018-12-30 00:43:58 +00:00
auto & Walls = LevelUniqueWallSubsystemState . Walls ;
auto & vcwallptridx = Walls . vcptridx ;
2018-12-13 02:31:39 +00:00
PHYSFSX_printf ( my_file , " Number of walls: %4i \n " , Walls . get_count ( ) ) ;
2018-12-30 00:43:58 +00:00
auto & ActiveDoors = LevelUniqueWallSubsystemState . ActiveDoors ;
2016-12-10 17:51:08 +00:00
PHYSFSX_printf ( my_file , " Number of open doors: %4i \n " , ActiveDoors . get_count ( ) ) ;
2018-12-30 00:43:58 +00:00
{
auto & Triggers = LevelUniqueWallSubsystemState . Triggers ;
2018-12-13 02:31:39 +00:00
PHYSFSX_printf ( my_file , " Number of triggers: %4i \n " , Triggers . get_count ( ) ) ;
2018-12-30 00:43:58 +00:00
}
2019-03-12 04:01:07 +00:00
PHYSFSX_printf ( my_file , " Number of matcens: %4i \n " , LevelSharedRobotcenterState . Num_robot_centers ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
2017-07-26 03:15:59 +00:00
write_segment_text ( vcsegptridx , my_file ) ;
2006-03-20 17:12:09 +00:00
write_fuelcen_text ( my_file ) ;
write_matcen_text ( my_file ) ;
2017-07-26 03:15:59 +00:00
write_player_text ( vcobjptridx , my_file ) ;
2006-03-20 17:12:09 +00:00
2017-07-26 03:15:59 +00:00
write_wall_text ( vcsegptridx , vcwallptridx , my_file ) ;
2006-03-20 17:12:09 +00:00
write_trigger_text ( my_file ) ;
2017-07-26 03:15:59 +00:00
write_exit_text ( vcsegptridx , vcwallptridx , my_file ) ;
2006-03-20 17:12:09 +00:00
// ---------- Find control center segment ----------
2017-07-26 03:15:59 +00:00
write_control_center_text ( vcsegptridx , my_file ) ;
2006-03-20 17:12:09 +00:00
// ---------- Show keyed walls ----------
2017-07-26 03:15:59 +00:00
write_key_text ( vcobjptridx , Segments , vcwallptridx , my_file ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
// Adam: Change NUM_ADAM_LEVELS to the number of levels.
# define NUM_ADAM_LEVELS 30
// Adam: Stick the names here.
2016-07-16 16:52:04 +00:00
constexpr char Adam_level_names [ NUM_ADAM_LEVELS ] [ 13 ] = {
2006-03-20 17:12:09 +00:00
" D2LEVA-1.LVL " ,
" D2LEVA-2.LVL " ,
" D2LEVA-3.LVL " ,
" D2LEVA-4.LVL " ,
" D2LEVA-S.LVL " ,
" D2LEVB-1.LVL " ,
" D2LEVB-2.LVL " ,
" D2LEVB-3.LVL " ,
" D2LEVB-4.LVL " ,
" D2LEVB-S.LVL " ,
" D2LEVC-1.LVL " ,
" D2LEVC-2.LVL " ,
" D2LEVC-3.LVL " ,
" D2LEVC-4.LVL " ,
" D2LEVC-S.LVL " ,
" D2LEVD-1.LVL " ,
" D2LEVD-2.LVL " ,
" D2LEVD-3.LVL " ,
" D2LEVD-4.LVL " ,
" D2LEVD-S.LVL " ,
" D2LEVE-1.LVL " ,
" D2LEVE-2.LVL " ,
" D2LEVE-3.LVL " ,
" D2LEVE-4.LVL " ,
" D2LEVE-S.LVL " ,
" D2LEVF-1.LVL " ,
" D2LEVF-2.LVL " ,
" D2LEVF-3.LVL " ,
" D2LEVF-4.LVL " ,
" D2LEVF-S.LVL " ,
} ;
2015-05-05 03:20:42 +00:00
static int Ignore_tmap_num2_error ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2018-12-30 00:43:57 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2018-12-30 00:43:58 +00:00
# define determine_used_textures_level(LevelSharedDestructibleLightState,load_level_flag,shareware_flag,level_num,tmap_buf,wall_buffer_type,level_tmap_buf,max_tmap) determine_used_textures_level(load_level_flag,shareware_flag,level_num,tmap_buf,wall_buffer_type,level_tmap_buf,max_tmap)
2018-12-30 00:43:57 +00:00
# endif
2018-12-30 00:43:58 +00:00
static void determine_used_textures_level ( d_level_shared_destructible_light_state & LevelSharedDestructibleLightState , int load_level_flag , int shareware_flag , int level_num , perm_tmap_buffer_type & tmap_buf , wall_buffer_type & wall_buf , level_tmap_buffer_type & level_tmap_buf , int max_tmap )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
# if defined(DXX_BUILD_DESCENT_II)
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptr = Objects . vcptr ;
# endif
2016-05-22 17:49:30 +00:00
int j ;
2006-03-20 17:12:09 +00:00
2018-12-30 00:43:58 +00:00
auto & Walls = LevelUniqueWallSubsystemState . Walls ;
2020-04-04 19:30:22 +00:00
auto & WallAnims = GameSharedState . WallAnims ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-05-22 17:49:30 +00:00
tmap_buf = { } ;
2013-03-03 01:03:33 +00:00
if ( load_level_flag ) {
2016-05-22 17:49:30 +00:00
load_level ( shareware_flag ? Shareware_level_names [ level_num ] : Registered_level_names [ level_num ] ) ;
2013-03-03 01:03:33 +00:00
}
2019-12-27 02:02:23 +00:00
range_for ( const cscusegment segp , vcsegptr )
2019-05-04 18:27:36 +00:00
{
2019-12-27 02:02:23 +00:00
range_for ( const auto & & z , zip ( segp . s . sides , segp . u . sides ) )
2019-05-04 18:27:36 +00:00
{
auto & sside = std : : get < 0 > ( z ) ;
2018-12-13 02:31:38 +00:00
if ( sside . wall_num ! = wall_none )
{
const auto clip_num = Walls . vcptr ( sside . wall_num ) - > clip_num ;
2013-03-03 01:03:33 +00:00
if ( clip_num ! = - 1 ) {
2017-06-17 23:05:16 +00:00
const auto num_frames = WallAnims [ clip_num ] . num_frames ;
2013-03-03 01:03:33 +00:00
wall_buf [ clip_num ] = 1 ;
for ( j = 0 ; j < num_frames ; j + + ) {
int tmap_num ;
tmap_num = WallAnims [ clip_num ] . frames [ j ] ;
tmap_buf [ tmap_num ] + + ;
if ( level_tmap_buf [ tmap_num ] = = - 1 )
level_tmap_buf [ tmap_num ] = level_num + ( ! shareware_flag ) * NUM_SHAREWARE_LEVELS ;
}
}
}
2019-05-04 18:27:36 +00:00
auto & uside = std : : get < 1 > ( z ) ;
2018-12-13 02:31:38 +00:00
if ( uside . tmap_num > = 0 )
2013-03-03 01:03:33 +00:00
{
2018-12-13 02:31:38 +00:00
if ( uside . tmap_num < max_tmap )
2013-03-03 01:03:33 +00:00
{
2018-12-13 02:31:38 +00:00
tmap_buf [ uside . tmap_num ] + + ;
if ( level_tmap_buf [ uside . tmap_num ] = = - 1 )
level_tmap_buf [ uside . tmap_num ] = level_num + ( ! shareware_flag ) * NUM_SHAREWARE_LEVELS ;
2013-03-03 01:03:33 +00:00
}
else
{
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
}
}
2018-12-13 02:31:38 +00:00
if ( const auto tmap_num2 = uside . tmap_num2 & 0x3fff )
2013-03-03 01:03:33 +00:00
{
2018-12-13 02:31:38 +00:00
if ( tmap_num2 < max_tmap ) {
+ + tmap_buf [ tmap_num2 ] ;
if ( level_tmap_buf [ tmap_num2 ] = = - 1 )
level_tmap_buf [ tmap_num2 ] = level_num + ( ! shareware_flag ) * NUM_SHAREWARE_LEVELS ;
2013-03-03 01:03:33 +00:00
} else
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
}
}
}
# elif defined(DXX_BUILD_DESCENT_II)
2015-01-18 01:58:33 +00:00
( void ) max_tmap ;
2015-05-05 03:20:42 +00:00
( void ) shareware_flag ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
tmap_buf = { } ;
2006-03-20 17:12:09 +00:00
if ( load_level_flag ) {
2018-12-30 00:43:58 +00:00
load_level ( LevelSharedDestructibleLightState , Adam_level_names [ level_num ] ) ;
2006-03-20 17:12:09 +00:00
}
2018-12-30 00:43:59 +00:00
auto & Polygon_models = LevelSharedPolygonModelState . Polygon_models ;
2006-03-20 17:12:09 +00:00
// Process robots.
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptr )
2014-10-12 23:05:46 +00:00
{
2006-03-20 17:12:09 +00:00
if ( objp - > render_type = = RT_POLYOBJ ) {
polymodel * po = & Polygon_models [ objp - > rtype . pobj_info . model_num ] ;
2016-05-22 17:49:30 +00:00
for ( unsigned i = 0 ; i < po - > n_textures ; + + i )
{
2016-07-14 01:59:05 +00:00
unsigned tli = ObjBitmaps [ ObjBitmapPtrs [ po - > first_texture + i ] ] . index ;
2006-03-20 17:12:09 +00:00
2016-07-14 01:59:05 +00:00
if ( tli < tmap_buf . size ( ) )
{
2006-03-20 17:12:09 +00:00
tmap_buf [ tli ] + + ;
if ( level_tmap_buf [ tli ] = = - 1 )
level_tmap_buf [ tli ] = level_num ;
} else
Int3 ( ) ; // Hmm, It seems this texture is bogus!
}
}
}
Ignore_tmap_num2_error = 0 ;
// Process walls and segment sides.
2019-12-27 02:02:23 +00:00
range_for ( const csmusegment segp , vmsegptr )
2014-10-12 23:10:05 +00:00
{
2019-12-27 02:02:23 +00:00
range_for ( const auto & & z , zip ( segp . s . sides , segp . u . sides , segp . s . children ) )
2019-05-04 18:27:36 +00:00
{
auto & sside = std : : get < 0 > ( z ) ;
auto & uside = std : : get < 1 > ( z ) ;
const auto child = std : : get < 2 > ( z ) ;
2018-12-13 02:31:38 +00:00
if ( sside . wall_num ! = wall_none ) {
const auto clip_num = Walls . vcptr ( sside . wall_num ) - > clip_num ;
2006-03-20 17:12:09 +00:00
if ( clip_num ! = - 1 ) {
// -- int num_frames = WallAnims[clip_num].num_frames;
wall_buf [ clip_num ] = 1 ;
for ( j = 0 ; j < 1 ; j + + ) { // Used to do through num_frames, but don't really want all the door01#3 stuff.
2016-07-14 01:59:05 +00:00
unsigned tmap_num = Textures [ WallAnims [ clip_num ] . frames [ j ] ] . index ;
Assert ( tmap_num < tmap_buf . size ( ) ) ;
2006-03-20 17:12:09 +00:00
tmap_buf [ tmap_num ] + + ;
if ( level_tmap_buf [ tmap_num ] = = - 1 )
level_tmap_buf [ tmap_num ] = level_num ;
}
}
2019-05-04 18:27:36 +00:00
} else if ( child = = segment_none ) {
2006-03-20 17:12:09 +00:00
2018-12-13 02:31:38 +00:00
if ( uside . tmap_num > = 0 )
2006-03-20 17:12:09 +00:00
{
2018-12-13 02:31:38 +00:00
if ( uside . tmap_num < Textures . size ( ) ) {
const auto ti = Textures [ uside . tmap_num ] . index ;
2016-07-14 01:59:05 +00:00
assert ( ti < tmap_buf . size ( ) ) ;
+ + tmap_buf [ ti ] ;
if ( level_tmap_buf [ ti ] = = - 1 )
level_tmap_buf [ ti ] = level_num ;
2006-03-20 17:12:09 +00:00
} else
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
}
2018-12-13 02:31:38 +00:00
if ( const auto masked_tmap_num2 = ( uside . tmap_num2 & 0x3fff ) )
2006-03-20 17:12:09 +00:00
{
2016-07-14 01:59:05 +00:00
if ( masked_tmap_num2 < Textures . size ( ) )
{
const auto ti = Textures [ masked_tmap_num2 ] . index ;
assert ( ti < tmap_buf . size ( ) ) ;
+ + tmap_buf [ ti ] ;
if ( level_tmap_buf [ ti ] = = - 1 )
level_tmap_buf [ ti ] = level_num ;
2006-03-20 17:12:09 +00:00
} else {
if ( ! Ignore_tmap_num2_error )
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
Ignore_tmap_num2_error = 1 ;
2018-12-13 02:31:38 +00:00
uside . tmap_num2 = 0 ;
2006-03-20 17:12:09 +00:00
}
}
}
}
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-05-22 17:49:30 +00:00
template < std : : size_t N >
2020-05-02 21:18:42 +00:00
static void merge_buffers ( std : : array < int , N > & dest , const std : : array < int , N > & src )
2006-03-20 17:12:09 +00:00
{
2016-05-22 17:49:30 +00:00
std : : transform ( dest . begin ( ) , dest . end ( ) , src . begin ( ) , dest . begin ( ) , std : : plus < int > ( ) ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-05-22 17:49:30 +00:00
static void say_used_tmaps ( PHYSFS_File * const my_file , const perm_tmap_buffer_type & tb )
2006-03-20 17:12:09 +00:00
{
int i ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
int count = 0 ;
2006-03-20 17:12:09 +00:00
2018-12-30 00:43:59 +00:00
auto & TmapInfo = LevelUniqueTmapInfoState . TmapInfo ;
2018-12-30 00:43:59 +00:00
const auto Num_tmaps = LevelUniqueTmapInfoState . Num_tmaps ;
2013-03-03 01:03:33 +00:00
for ( i = 0 ; i < Num_tmaps ; i + + )
if ( tb [ i ] ) {
2014-07-26 22:45:01 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s (%4i)] " , i , static_cast < const char * > ( TmapInfo [ i ] . filename ) , tb [ i ] ) ;
2013-03-03 01:03:33 +00:00
if ( count + + > = 4 ) {
PHYSFSX_printf ( my_file , " \n " ) ;
count = 0 ;
}
}
# elif defined(DXX_BUILD_DESCENT_II)
2016-07-14 01:59:05 +00:00
for ( i = 0 ; i < tb . size ( ) ; + + i )
2006-03-20 17:12:09 +00:00
if ( tb [ i ] ) {
2018-08-26 18:10:36 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s (%4i)] \n " , i , AllBitmaps [ i ] . name . data ( ) , tb [ i ] ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
// -----------------------------------------------------------------------------
2016-05-22 17:49:30 +00:00
static void say_used_once_tmaps ( PHYSFS_File * const my_file , const perm_tmap_buffer_type & tb , const level_tmap_buffer_type & tb_lnum )
2013-03-03 01:03:33 +00:00
{
int i ;
const char * level_name ;
2018-12-30 00:43:59 +00:00
auto & TmapInfo = LevelUniqueTmapInfoState . TmapInfo ;
2018-12-30 00:43:59 +00:00
const auto Num_tmaps = LevelUniqueTmapInfoState . Num_tmaps ;
2013-03-03 01:03:33 +00:00
for ( i = 0 ; i < Num_tmaps ; i + + )
if ( tb [ i ] = = 1 ) {
int level_num = tb_lnum [ i ] ;
if ( level_num > = NUM_SHAREWARE_LEVELS ) {
Assert ( ( level_num - NUM_SHAREWARE_LEVELS > = 0 ) & & ( level_num - NUM_SHAREWARE_LEVELS < NUM_REGISTERED_LEVELS ) ) ;
level_name = Registered_level_names [ level_num - NUM_SHAREWARE_LEVELS ] ;
} else {
Assert ( ( level_num > = 0 ) & & ( level_num < NUM_SHAREWARE_LEVELS ) ) ;
level_name = Shareware_level_names [ level_num ] ;
}
2014-07-26 22:45:01 +00:00
PHYSFSX_printf ( my_file , " Texture %3i %8s used only once on level %s \n " , i , static_cast < const char * > ( TmapInfo [ i ] . filename ) , level_name ) ;
2013-03-03 01:03:33 +00:00
}
}
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-05-22 17:49:30 +00:00
static void say_unused_tmaps ( PHYSFS_File * my_file , perm_tmap_buffer_type & tb )
2006-03-20 17:12:09 +00:00
{
int i ;
int count = 0 ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2018-12-30 00:43:59 +00:00
const unsigned bound = LevelUniqueTmapInfoState . Num_tmaps ;
2018-12-30 00:43:59 +00:00
auto & TmapInfo = LevelUniqueTmapInfoState . TmapInfo ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2014-05-03 22:08:51 +00:00
const unsigned bound = MAX_BITMAP_FILES ;
2013-03-03 01:03:33 +00:00
# endif
2014-05-03 22:08:51 +00:00
for ( i = 0 ; i < bound ; i + + )
2006-03-20 17:12:09 +00:00
if ( ! tb [ i ] ) {
2015-02-28 19:36:01 +00:00
if ( GameBitmaps [ Textures [ i ] . index ] . bm_data = = bogus_data . data ( ) )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " U " ) ;
2006-03-20 17:12:09 +00:00
else
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " " ) ;
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-07-26 22:45:01 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s] " , i , static_cast < const char * > ( TmapInfo [ i ] . filename ) ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2018-08-26 18:10:36 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s] " , i , AllBitmaps [ i ] . name . data ( ) ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
if ( count + + > = 4 ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
count = 0 ;
}
}
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-05-22 17:49:30 +00:00
static void say_unused_walls ( PHYSFS_File * my_file , const wall_buffer_type & tb )
2013-03-03 01:03:33 +00:00
{
int i ;
for ( i = 0 ; i < Num_wall_anims ; i + + )
if ( ! tb [ i ] )
PHYSFSX_printf ( my_file , " Wall %3i is unused. \n " , i ) ;
}
# endif
2017-07-26 03:15:59 +00:00
static void say_totals ( fvcobjptridx & vcobjptridx , PHYSFS_File * my_file , const char * level_name )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
2006-03-20 17:12:09 +00:00
int total_robots = 0 ;
int objects_processed = 0 ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Level %s \n " , level_name ) ;
2014-10-02 03:02:34 +00:00
std : : bitset < MAX_OBJECTS > used_objects ;
2006-03-20 17:12:09 +00:00
while ( objects_processed < Highest_object_index + 1 ) {
2016-08-28 22:41:48 +00:00
int objtype , objid , objcount , min_obj_val ;
2006-03-20 17:12:09 +00:00
// Find new min objnum.
min_obj_val = 0x7fff0000 ;
2016-08-28 22:41:48 +00:00
const object_base * min_objp = nullptr ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-12-22 04:18:51 +00:00
if ( ! used_objects [ objp ] & & objp - > type ! = OBJ_NONE )
2015-06-13 22:42:16 +00:00
{
2016-08-28 22:41:48 +00:00
const auto cur_obj_val = ( objp - > type < < 10 ) + objp - > id ;
2006-03-20 17:12:09 +00:00
if ( cur_obj_val < min_obj_val ) {
2016-08-28 22:41:48 +00:00
min_objp = & * objp ;
2006-03-20 17:12:09 +00:00
min_obj_val = cur_obj_val ;
}
}
}
2016-08-28 22:41:48 +00:00
if ( ! min_objp | | min_objp - > type = = OBJ_NONE )
2006-03-20 17:12:09 +00:00
break ;
objcount = 0 ;
2016-08-28 22:41:48 +00:00
objtype = min_objp - > type ;
objid = min_objp - > id ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2017-09-30 18:00:15 +00:00
if ( auto & & uo = used_objects [ objp ] )
{
}
else
{
2015-06-13 22:42:16 +00:00
if ( ( objp - > type = = objtype & & objp - > id = = objid ) | |
( objp - > type = = objtype & & objtype = = OBJ_PLAYER ) | |
( objp - > type = = objtype & & objtype = = OBJ_COOP ) | |
( objp - > type = = objtype & & objtype = = OBJ_HOSTAGE ) ) {
if ( objp - > type = = OBJ_ROBOT )
2006-03-20 17:12:09 +00:00
total_robots + + ;
2017-09-30 18:00:15 +00:00
uo = true ;
2006-03-20 17:12:09 +00:00
objcount + + ;
objects_processed + + ;
}
}
}
if ( objcount ) {
2016-08-28 22:41:48 +00:00
PHYSFSX_printf ( my_file , " Object: %8s %8s %3i \n " , object_types ( * min_objp ) , object_ids ( * min_objp ) , objcount ) ;
2006-03-20 17:12:09 +00:00
}
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Total robots = %3i \n " , total_robots ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
int First_dump_level = 0 ;
int Last_dump_level = NUM_ADAM_LEVELS - 1 ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2013-10-27 22:00:14 +00:00
static void say_totals_all ( void )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:08 +00:00
auto & Objects = LevelUniqueObjectState . Objects ;
auto & vcobjptridx = Objects . vcptridx ;
2006-03-20 17:12:09 +00:00
int i ;
2015-01-17 18:31:42 +00:00
auto my_file = PHYSFSX_openWriteBuffered ( " levels.all " ) ;
2006-03-20 17:12:09 +00:00
if ( ! my_file ) {
gr_palette_load ( gr_palette ) ;
2013-12-04 22:19:04 +00:00
nm_messagebox ( NULL , 1 , " Ok " , " ERROR: Unable to open levels.all \n Errno=%i " , errno ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
for ( i = 0 ; i < NUM_SHAREWARE_LEVELS ; i + + ) {
load_level ( Shareware_level_names [ i ] ) ;
2017-07-26 03:15:59 +00:00
say_totals ( vcobjptridx , my_file , Shareware_level_names [ i ] ) ;
2013-03-03 01:03:33 +00:00
}
for ( i = 0 ; i < NUM_REGISTERED_LEVELS ; i + + ) {
load_level ( Registered_level_names [ i ] ) ;
2017-07-26 03:15:59 +00:00
say_totals ( vcobjptridx , my_file , Registered_level_names [ i ] ) ;
2013-03-03 01:03:33 +00:00
}
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
for ( i = First_dump_level ; i < = Last_dump_level ; i + + ) {
2018-12-30 00:43:58 +00:00
load_level ( LevelSharedSegmentState . DestructibleLights , Adam_level_names [ i ] ) ;
2017-07-26 03:15:59 +00:00
say_totals ( vcobjptridx , my_file , Adam_level_names [ i ] ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2019-08-06 02:59:40 +00:00
static void dump_used_textures_level ( PHYSFS_File * my_file , int level_num , const char * const Gamesave_current_filename )
2006-03-20 17:12:09 +00:00
{
2016-05-22 17:49:30 +00:00
perm_tmap_buffer_type temp_tmap_buf ;
level_tmap_buffer_type level_tmap_buf ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
level_tmap_buf . fill ( - 1 ) ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
wall_buffer_type temp_wall_buf ;
2018-12-30 00:43:58 +00:00
determine_used_textures_level ( LevelSharedSegmentState . DestructibleLights , 0 , 1 , level_num , temp_tmap_buf , temp_wall_buf , level_tmap_buf , sizeof ( level_tmap_buf ) / sizeof ( level_tmap_buf [ 0 ] ) ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Gamesave_current_filename ) ;
2006-03-20 17:12:09 +00:00
say_used_tmaps ( my_file , temp_tmap_buf ) ;
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2006-03-20 17:12:09 +00:00
void dump_used_textures_all ( void )
{
int i ;
say_totals_all ( ) ;
2015-01-17 18:31:42 +00:00
auto my_file = PHYSFSX_openWriteBuffered ( " textures.dmp " ) ;
2006-03-20 17:12:09 +00:00
if ( ! my_file ) {
gr_palette_load ( gr_palette ) ;
2013-12-04 22:19:04 +00:00
nm_messagebox ( NULL , 1 , " Ok " , " ERROR: Can't open textures.dmp \n Errno=%i " , errno ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2016-05-22 17:49:30 +00:00
perm_tmap_buffer_type perm_tmap_buf { } ;
level_tmap_buffer_type level_tmap_buf ;
level_tmap_buf . fill ( - 1 ) ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
perm_tmap_buffer_type temp_tmap_buf ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-05-22 17:49:30 +00:00
wall_buffer_type perm_wall_buf { } ;
2013-03-03 01:03:33 +00:00
for ( i = 0 ; i < NUM_SHAREWARE_LEVELS ; i + + ) {
2016-05-22 17:49:30 +00:00
wall_buffer_type temp_wall_buf ;
2018-12-30 00:43:58 +00:00
determine_used_textures_level ( LevelSharedDestructibleLightState , 1 , 1 , i , temp_tmap_buf , temp_wall_buf , level_tmap_buf , sizeof ( level_tmap_buf ) / sizeof ( level_tmap_buf [ 0 ] ) ) ;
2013-03-03 01:03:33 +00:00
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Shareware_level_names [ i ] ) ;
say_used_tmaps ( my_file , temp_tmap_buf ) ;
2016-05-22 17:49:30 +00:00
merge_buffers ( perm_tmap_buf , temp_tmap_buf ) ;
merge_buffers ( perm_wall_buf , temp_wall_buf ) ;
2013-03-03 01:03:33 +00:00
}
PHYSFSX_printf ( my_file , " \n \n Used textures in all shareware mines: \n " ) ;
say_used_tmaps ( my_file , perm_tmap_buf ) ;
PHYSFSX_printf ( my_file , " \n Unused textures in all shareware mines: \n " ) ;
say_unused_tmaps ( my_file , perm_tmap_buf ) ;
PHYSFSX_printf ( my_file , " \n Textures used exactly once in all shareware mines: \n " ) ;
say_used_once_tmaps ( my_file , perm_tmap_buf , level_tmap_buf ) ;
PHYSFSX_printf ( my_file , " \n Wall anims (eg, doors) unused in all shareware mines: \n " ) ;
say_unused_walls ( my_file , perm_wall_buf ) ;
for ( i = 0 ; i < NUM_REGISTERED_LEVELS ; i + + )
# elif defined(DXX_BUILD_DESCENT_II)
2013-10-06 16:20:00 +00:00
for ( i = First_dump_level ; i < = Last_dump_level ; i + + )
2013-03-03 01:03:33 +00:00
# endif
2013-10-06 16:20:00 +00:00
{
2016-05-22 17:49:30 +00:00
wall_buffer_type temp_wall_buf ;
2018-12-30 00:43:58 +00:00
determine_used_textures_level ( LevelSharedSegmentState . DestructibleLights , 1 , 0 , i , temp_tmap_buf , temp_wall_buf , level_tmap_buf , sizeof ( level_tmap_buf ) / sizeof ( level_tmap_buf [ 0 ] ) ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Registered_level_names [ i ] ) ;
# elif defined(DXX_BUILD_DESCENT_II)
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Adam_level_names [ i ] ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
say_used_tmaps ( my_file , temp_tmap_buf ) ;
2016-05-22 17:49:30 +00:00
merge_buffers ( perm_tmap_buf , temp_tmap_buf ) ;
2006-03-20 17:12:09 +00:00
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n \n Used textures in all (including registered) mines: \n " ) ;
2006-03-20 17:12:09 +00:00
say_used_tmaps ( my_file , perm_tmap_buf ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Unused textures in all (including registered) mines: \n " ) ;
2006-03-20 17:12:09 +00:00
say_unused_tmaps ( my_file , perm_tmap_buf ) ;
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
# endif