2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2014 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file dehacked.c
/// \brief Load dehacked file and change tables and text
# include "doomdef.h"
# include "g_game.h"
# include "sounds.h"
# include "info.h"
# include "d_think.h"
# include "m_argv.h"
# include "z_zone.h"
# include "w_wad.h"
# include "m_menu.h"
# include "m_misc.h"
# include "f_finale.h"
# include "dehacked.h"
# include "st_stuff.h"
# include "i_system.h"
# include "p_local.h" // for var1 and var2, and some constants
# include "p_setup.h"
# include "r_data.h"
# include "fastcmp.h"
# include "lua_script.h"
# include "lua_hook.h"
# include "m_cond.h"
# ifdef HAVE_BLUA
# include "v_video.h" // video flags (for lua)
# endif
# ifdef HWRENDER
# include "hardware/hw_light.h"
# endif
# ifdef PC_DOS
# include <stdio.h> // for snprintf
//int snprintf(char *str, size_t n, const char *fmt, ...);
int vsnprintf ( char * str , size_t n , const char * fmt , va_list ap ) ;
# endif
// Free slot names
// The crazy word-reading stuff uses these.
static char * FREE_STATES [ NUMSTATEFREESLOTS ] ;
static char * FREE_MOBJS [ NUMMOBJFREESLOTS ] ;
static UINT8 used_spr [ ( NUMSPRITEFREESLOTS / 8 ) + 1 ] ; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
# define initfreeslots() {\
memset ( FREE_STATES , 0 , sizeof ( char * ) * NUMSTATEFREESLOTS ) ; \
memset ( FREE_MOBJS , 0 , sizeof ( char * ) * NUMMOBJFREESLOTS ) ; \
memset ( used_spr , 0 , sizeof ( UINT8 ) * ( ( NUMSPRITEFREESLOTS / 8 ) + 1 ) ) ; \
}
// Crazy word-reading stuff
/// \todo Put these in a seperate file or something.
static mobjtype_t get_mobjtype ( const char * word ) ;
static statenum_t get_state ( const char * word ) ;
static spritenum_t get_sprite ( const char * word ) ;
static sfxenum_t get_sfx ( const char * word ) ;
static UINT16 get_mus ( const char * word ) ;
static hudnum_t get_huditem ( const char * word ) ;
# ifndef HAVE_BLUA
static powertype_t get_power ( const char * word ) ;
# endif
boolean deh_loaded = false ;
boolean modcredits = false ; // Whether a mod creator's name will show in the credits.
char modcreditname [ 32 ] ;
static int dbg_line ;
static boolean gamedataadded = false ;
# ifdef DELFILE
typedef struct undehacked_s
{
char * undata ;
struct undehacked_s * next ;
} undehacked_t ;
static UINT16 unsocwad ;
static undehacked_t * unsocdata [ MAX_WADFILES ] ;
static boolean disableundo = false ;
void DEH_WriteUndoline ( const char * value , const char * data , undotype_f flags )
{
const char * eqstr = " = " ;
const char * space = " " ;
const char * pader = eqstr ;
undehacked_t * newdata ;
if ( disableundo | | ! unsocwad )
return ;
if ( ( newdata = malloc ( sizeof ( * newdata ) ) ) = = NULL )
I_Error ( " Out of memory for unsoc line " ) ;
if ( flags & UNDO_SPACE )
pader = space ;
if ( flags & UNDO_ENDTEXT & & ! data )
data = space ;
if ( value )
{
const size_t plen = strlen ( pader ) ;
const char * pound = " # " ;
char * undata = NULL ;
const size_t elen = strlen ( pound ) ;
size_t vlen = strlen ( value ) , dlen = 0 , len = 1 ;
if ( * ( value + vlen - 1 ) = = ' \n ' )
vlen - - ; // lnet not copy the ending \n
if ( flags & UNDO_ENDTEXT )
len + = elen ; // let malloc more space
if ( flags & UNDO_NEWLINE )
len + + ; // more space for the beginning \n
if ( data )
{
dlen = strlen ( data ) ;
if ( flags & UNDO_CUTLINE & & * ( data + dlen - 1 ) = = ' \n ' )
dlen - - ; // let not copy the ending \n
newdata - > undata = malloc ( vlen + plen + dlen + len ) ;
newdata - > undata [ vlen + plen + dlen + len - 1 ] = ' \0 ' ;
}
else
{
newdata - > undata = malloc ( vlen + len ) ;
newdata - > undata [ vlen + len - 1 ] = ' \0 ' ;
}
if ( newdata - > undata )
{
undata = newdata - > undata ;
* undata = ' \0 ' ;
}
else
{
free ( newdata ) ;
I_Error ( " Out of memory for unsoc data " ) ;
}
if ( flags & UNDO_NEWLINE ) // let start with \n
strcat ( undata , " \n " ) ;
strncat ( undata , value , vlen ) ;
if ( data ) // value+pader+data
strncat ( strncat ( undata , pader , plen ) , data , dlen ) ;
if ( flags & UNDO_ENDTEXT ) // let end the text
strncat ( undata , pound , elen ) ;
}
else
newdata - > undata = NULL ;
newdata - > next = unsocdata [ unsocwad ] ;
unsocdata [ unsocwad ] = newdata ;
}
# endif
ATTRINLINE static FUNCINLINE char myfget_color ( MYFILE * f )
{
char c = * f - > curpos + + ;
if ( c = = ' ^ ' ) // oh, nevermind then.
return ' ^ ' ;
if ( c > = ' 0 ' & & c < = ' 9 ' )
return 0x80 + ( c - ' 0 ' ) ;
return 0x80 ; // Unhandled -- default to no color
}
ATTRINLINE static FUNCINLINE char myfget_hex ( MYFILE * f )
{
char c = * f - > curpos + + , endchr = 0 ;
if ( c = = ' \\ ' ) // oh, nevermind then.
return ' \\ ' ;
if ( c > = ' 0 ' & & c < = ' 9 ' )
endchr + = ( c - ' 0 ' ) < < 4 ;
else if ( c > = ' A ' & & c < = ' F ' )
endchr + = ( ( c - ' A ' ) + 10 ) < < 4 ;
else if ( c > = ' a ' & & c < = ' f ' )
endchr + = ( ( c - ' a ' ) + 10 ) < < 4 ;
else // invalid. stop and return a question mark.
return ' ? ' ;
c = * f - > curpos + + ;
if ( c > = ' 0 ' & & c < = ' 9 ' )
endchr + = ( c - ' 0 ' ) ;
else if ( c > = ' A ' & & c < = ' F ' )
endchr + = ( ( c - ' A ' ) + 10 ) ;
else if ( c > = ' a ' & & c < = ' f ' )
endchr + = ( ( c - ' a ' ) + 10 ) ;
else // invalid. stop and return a question mark.
return ' ? ' ;
return endchr ;
}
char * myfgets ( char * buf , size_t bufsize , MYFILE * f )
{
size_t i = 0 ;
if ( myfeof ( f ) )
return NULL ;
// we need one byte for a null terminated string
bufsize - - ;
while ( i < bufsize & & ! myfeof ( f ) )
{
char c = * f - > curpos + + ;
if ( c = = ' ^ ' )
buf [ i + + ] = myfget_color ( f ) ;
else if ( c = = ' \\ ' )
buf [ i + + ] = myfget_hex ( f ) ;
else if ( c ! = ' \r ' )
buf [ i + + ] = c ;
if ( c = = ' \n ' )
break ;
}
buf [ i ] = ' \0 ' ;
dbg_line + + ;
return buf ;
}
static char * myhashfgets ( char * buf , size_t bufsize , MYFILE * f )
{
size_t i = 0 ;
if ( myfeof ( f ) )
return NULL ;
// we need one byte for a null terminated string
bufsize - - ;
while ( i < bufsize & & ! myfeof ( f ) )
{
char c = * f - > curpos + + ;
if ( c = = ' ^ ' )
buf [ i + + ] = myfget_color ( f ) ;
else if ( c = = ' \\ ' )
buf [ i + + ] = myfget_hex ( f ) ;
else if ( c ! = ' \r ' )
buf [ i + + ] = c ;
if ( c = = ' \n ' ) // Ensure debug line is right...
dbg_line + + ;
if ( c = = ' # ' )
break ;
}
i + + ;
buf [ i ] = ' \0 ' ;
return buf ;
}
static INT32 deh_num_warning = 0 ;
FUNCPRINTF static void deh_warning ( const char * first , . . . )
{
va_list argptr ;
char * buf = Z_Malloc ( 1000 , PU_STATIC , NULL ) ;
va_start ( argptr , first ) ;
vsnprintf ( buf , 1000 , first , argptr ) ; // sizeof only returned 4 here. it didn't like that pointer.
va_end ( argptr ) ;
if ( dbg_line = = - 1 ) // Not in a SOC, line number unknown.
CONS_Alert ( CONS_WARNING , " %s \n " , buf ) ;
else
CONS_Alert ( CONS_WARNING , " Line %u: %s \n " , dbg_line , buf ) ;
deh_num_warning + + ;
Z_Free ( buf ) ;
}
static void deh_strlcpy ( char * dst , const char * src , size_t size , const char * warntext )
{
size_t len = strlen ( src ) + 1 ; // Used to determine if truncation has been done
if ( len > size )
deh_warning ( " %s exceeds max length of %s " , warntext , sizeu1 ( size - 1 ) ) ;
strlcpy ( dst , src , size ) ;
}
/* ======================================================================== */
// Load a dehacked file format
/* ======================================================================== */
/* a sample to see
Thing 1 ( Player ) { // MT_PLAYER
INT32 doomednum ; ID # = 3232 - 1 , // doomednum
INT32 spawnstate ; Initial frame = 32 " PLAY " , // spawnstate
INT32 spawnhealth ; Hit points = 3232 100 , // spawnhealth
INT32 seestate ; First moving frame = 32 " PLAY_RUN1 " , // seestate
INT32 seesound ; Alert sound = 32 sfx_None , // seesound
INT32 reactiontime ; Reaction time = 3232 0 , // reactiontime
INT32 attacksound ; Attack sound = 32 sfx_None , // attacksound
INT32 painstate ; Injury frame = 32 " PLAY_PAIN " , // painstate
INT32 painchance ; Pain chance = 3232 255 , // painchance
INT32 painsound ; Pain sound = 32 sfx_plpain , // painsound
INT32 meleestate ; Close attack frame = 32 " NULL " , // meleestate
INT32 missilestate ; Far attack frame = 32 " PLAY_ATK1 " , // missilestate
INT32 deathstate ; Death frame = 32 " PLAY_DIE1 " , // deathstate
INT32 xdeathstate ; Exploding frame = 32 " PLAY_XDIE1 " , // xdeathstate
INT32 deathsound ; Death sound = 32 sfx_pldeth , // deathsound
INT32 speed ; Speed = 3232 0 , // speed
INT32 radius ; Width = 211812352 16 * FRACUNIT , // radius
INT32 height ; Height = 211812352 56 * FRACUNIT , // height
INT32 dispoffset ; DispOffset = 0 0 , // dispoffset
INT32 mass ; Mass = 3232 100 , // mass
INT32 damage ; Missile damage = 3232 0 , // damage
INT32 activesound ; Action sound = 32 sfx_None , // activesound
INT32 flags ; Bits = 3232 MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH ,
INT32 raisestate ; Respawn frame = 32 S_NULL // raisestate
} , */
static INT32 searchvalue ( const char * s )
{
while ( s [ 0 ] ! = ' = ' & & s [ 0 ] )
s + + ;
if ( s [ 0 ] = = ' = ' )
return atoi ( & s [ 1 ] ) ;
else
{
deh_warning ( " No value found " ) ;
return 0 ;
}
}
# ifdef HWRENDER
static float searchfvalue ( const char * s )
{
while ( s [ 0 ] ! = ' = ' & & s [ 0 ] )
s + + ;
if ( s [ 0 ] = = ' = ' )
return ( float ) atof ( & s [ 1 ] ) ;
else
{
deh_warning ( " No value found " ) ;
return 0 ;
}
}
# endif
// These are for clearing all of various things
static void clear_conditionsets ( void )
{
UINT8 i ;
for ( i = 0 ; i < MAXCONDITIONSETS ; + + i )
M_ClearConditionSet ( i ) ;
}
static void clear_levels ( void )
{
INT16 i ;
// This is potentially dangerous but if we're resetting these headers,
// we may as well try to save some memory, right?
for ( i = 0 ; i < NUMMAPS ; + + i )
{
if ( ! mapheaderinfo [ i ] )
continue ;
P_DeleteGrades ( i ) ;
Z_Free ( mapheaderinfo [ i ] ) ;
mapheaderinfo [ i ] = NULL ;
}
// Realloc the one for the current gamemap as a safeguard
P_AllocMapHeader ( gamemap - 1 ) ;
}
/*
// Edits an animated texture slot on the array
// Tails 12-27-2003
static void readAnimTex ( MYFILE * f , INT32 num )
{
char s [ MAXLINELEN ] ;
char * word ;
char * word2 ;
INT32 i ;
do {
if ( myfgets ( s , sizeof s , f ) ! = NULL )
{
if ( s [ 0 ] = = ' \n ' ) break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
// set the value in the appropriate field
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
word2 = strtok ( NULL , " = " ) ;
if ( word2 )
strupr ( word2 ) ;
else
break ;
if ( word2 [ strlen ( word2 ) - 1 ] = = ' \n ' )
word2 [ strlen ( word2 ) - 1 ] = ' \0 ' ;
i = atoi ( word2 ) ;
if ( fastcmp ( word , " START " ) )
strncpy ( harddefs [ num ] . startname , word2 , 8 ) ;
if ( fastcmp ( word , " END " ) )
strncpy ( harddefs [ num ] . endname , word2 , 8 ) ;
else if ( fastcmp ( word , " SPEED " ) ) harddefs [ num ] . speed = i ;
else if ( fastcmp ( word , " ISTEXTURE " ) ) harddefs [ num ] . istexture = i ;
else deh_warning ( " readAnimTex %d: unknown word '%s' " , num , word ) ;
}
} while ( s [ 0 ] ! = ' \n ' & & ! myfeof ( f ) ) ; //finish when the line is empty
}
*/
static boolean findFreeSlot ( INT32 * num )
{
// Send the character select entry to a free slot.
while ( * num < 32 & & PlayerMenu [ * num ] . status ! = IT_DISABLED )
* num = * num + 1 ;
// No more free slots. :(
if ( * num > = 32 )
return false ;
// Found one! ^_^
return true ;
}
// Reads a player.
// For modifying the character select screen
static void readPlayer ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * word2 ;
INT32 i ;
boolean slotfound = false ;
DEH_WriteUndoline ( " PLAYERTEXT " , description [ num ] . notes , UNDO_ENDTEXT ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
if ( fastcmp ( word , " PLAYERTEXT " ) )
{
char * playertext = NULL ;
if ( ! slotfound & & ( slotfound = findFreeSlot ( & num ) ) = = false )
goto done ;
for ( i = 0 ; i < MAXLINELEN - 3 ; i + + )
{
if ( s [ i ] = = ' = ' )
{
playertext = & s [ i + 2 ] ;
break ;
}
}
if ( playertext )
{
strcpy ( description [ num ] . notes , playertext ) ;
strcat ( description [ num ] . notes , myhashfgets ( playertext , sizeof ( description [ num ] . notes ) , f ) ) ;
}
else
strcpy ( description [ num ] . notes , " " ) ;
// For some reason, cutting the string did not work above. Most likely due to strcpy or strcat...
// It works down here, though.
{
INT32 numline = 0 ;
for ( i = 0 ; i < MAXLINELEN - 1 ; i + + )
{
if ( numline < 20 & & description [ num ] . notes [ i ] = = ' \n ' )
numline + + ;
if ( numline > = 20 | | description [ num ] . notes [ i ] = = ' \0 ' | | description [ num ] . notes [ i ] = = ' # ' )
break ;
}
}
description [ num ] . notes [ strlen ( description [ num ] . notes ) - 1 ] = ' \0 ' ;
description [ num ] . notes [ i ] = ' \0 ' ;
continue ;
}
word2 = strtok ( NULL , " = " ) ;
if ( word2 )
strupr ( word2 ) ;
else
break ;
if ( word2 [ strlen ( word2 ) - 1 ] = = ' \n ' )
word2 [ strlen ( word2 ) - 1 ] = ' \0 ' ;
i = atoi ( word2 ) ;
/*if (fastcmp(word, "PLAYERNAME"))
{
if ( ! slotfound & & ( slotfound = findFreeSlot ( & num ) ) = = false )
goto done ;
DEH_WriteUndoline ( word , description [ num ] . text , UNDO_NONE ) ;
strlcpy ( description [ num ] . text , word2 , sizeof ( description [ num ] . text ) ) ;
for ( word2 = description [ num ] . text ; * word2 ; word2 + + )
if ( * word2 = = ' _ ' )
* word2 = ' ' ;
PlayerMenu [ num ] . text = description [ num ] . text ;
} */
/* else if (fastcmp(word, "MENUPOSITION"))
{ // Make sure you make MENUPOSITION the first thing under CHARACTER if you're using it!
// This is to manually choose a slot and overwrite existing characters! It is NOT necessary for most individual character wads!!
# ifdef DELFILE
if ( disableundo )
# endif
{
slotfound = true ;
num = i ;
}
} */
/*else*/ if ( fastcmp ( word , " PICNAME " ) )
{
if ( ! slotfound & & ( slotfound = findFreeSlot ( & num ) ) = = false )
goto done ;
DEH_WriteUndoline ( word , & description [ num ] . picname [ 0 ] , UNDO_NONE ) ;
strncpy ( description [ num ] . picname , word2 , 8 ) ;
}
else if ( fastcmp ( word , " STATUS " ) )
{
// Limit the status to only IT_DISABLED and IT_CALL
if ( i )
i = IT_CALL ;
else
i = IT_DISABLED ;
/*
You MAY disable previous entries if you so desire . . .
But try to enable something that ' s already enabled and you will be sent to a free slot .
Because of this , you are allowed to edit any previous entrys you like , but only if you
signal that you are purposely doing so by disabling and then reenabling the slot .
. . . Or use MENUPOSITION first , that works too . Hell , you could edit multiple character
slots in a single section that way , due to how SOC editing works .
*/
if ( i ! = IT_DISABLED & & ! slotfound & & ( slotfound = findFreeSlot ( & num ) ) = = false )
goto done ;
DEH_WriteUndoline ( word , va ( " %d " , PlayerMenu [ num ] . status ) , UNDO_NONE ) ;
PlayerMenu [ num ] . status = ( INT16 ) i ;
}
else if ( fastcmp ( word , " SKINNAME " ) )
{
// Send to free slot.
if ( ! slotfound & & ( slotfound = findFreeSlot ( & num ) ) = = false )
goto done ;
DEH_WriteUndoline ( word , description [ num ] . skinname , UNDO_NONE ) ;
strlcpy ( description [ num ] . skinname , word2 , sizeof description [ num ] . skinname ) ;
strlwr ( description [ num ] . skinname ) ;
}
else
deh_warning ( " readPlayer %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
# ifdef DELFILE
if ( slotfound )
DEH_WriteUndoline ( " MENUPOSITION " , va ( " %d " , num ) , UNDO_NONE ) ;
# endif
done :
Z_Free ( s ) ;
}
// TODO: Figure out how to do undolines for this....
// TODO: Warnings for running out of freeslots
static void readfreeslots ( MYFILE * f )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word , * type ;
char * tmp ;
int i ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
type = strtok ( s , " _ " ) ;
if ( type )
strupr ( type ) ;
else
break ;
word = strtok ( NULL , " \n " ) ;
if ( word )
strupr ( word ) ;
else
break ;
// TODO: Check for existing freeslot mobjs/states/etc. and make errors.
// TODO: Out-of-slots warnings/errors.
// TODO: Name too long (truncated) warnings.
if ( fastcmp ( type , " SFX " ) )
2014-03-18 17:56:54 +00:00
S_AddSoundFx ( word , false , 0 , false ) ;
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( type , " SPR " ) )
{
for ( i = SPR_FIRSTFREESLOT ; i < = SPR_LASTFREESLOT ; i + + )
{
if ( used_spr [ ( i - SPR_FIRSTFREESLOT ) / 8 ] & ( 1 < < ( i % 8 ) ) )
{
if ( ! sprnames [ i ] [ 4 ] & & memcmp ( sprnames [ i ] , word , 4 ) = = 0 )
sprnames [ i ] [ 4 ] = ( char ) f - > wad ;
continue ; // Already allocated, next.
}
// Found a free slot!
strncpy ( sprnames [ i ] , word , 4 ) ;
//sprnames[i][4] = 0;
used_spr [ ( i - SPR_FIRSTFREESLOT ) / 8 ] | = 1 < < ( i % 8 ) ; // Okay, this sprite slot has been named now.
break ;
}
}
else if ( fastcmp ( type , " S " ) )
{
for ( i = 0 ; i < NUMSTATEFREESLOTS ; i + + )
if ( ! FREE_STATES [ i ] ) {
FREE_STATES [ i ] = Z_Malloc ( strlen ( word ) + 1 , PU_STATIC , NULL ) ;
strcpy ( FREE_STATES [ i ] , word ) ;
break ;
}
}
else if ( fastcmp ( type , " MT " ) )
{
for ( i = 0 ; i < NUMMOBJFREESLOTS ; i + + )
if ( ! FREE_MOBJS [ i ] ) {
FREE_MOBJS [ i ] = Z_Malloc ( strlen ( word ) + 1 , PU_STATIC , NULL ) ;
strcpy ( FREE_MOBJS [ i ] , word ) ;
break ;
}
}
else
deh_warning ( " Freeslots: unknown enum class '%s' for '%s_%s' " , type , type , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
static void readthing ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word , * word2 ;
char * tmp ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
word2 = strtok ( NULL , " = " ) ;
if ( word2 )
strupr ( word2 ) ;
else
break ;
if ( word2 [ strlen ( word2 ) - 1 ] = = ' \n ' )
word2 [ strlen ( word2 ) - 1 ] = ' \0 ' ;
if ( fastcmp ( word , " MAPTHINGNUM " ) | | fastcmp ( word , " DOOMEDNUM " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . doomednum ) , UNDO_NONE ) ;
mobjinfo [ num ] . doomednum = ( INT32 ) atoi ( word2 ) ;
}
else if ( fastcmp ( word , " SPAWNSTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . spawnstate ) , UNDO_NONE ) ;
mobjinfo [ num ] . spawnstate = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " SPAWNHEALTH " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . spawnhealth ) , UNDO_NONE ) ;
mobjinfo [ num ] . spawnhealth = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " SEESTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . seestate ) , UNDO_NONE ) ;
mobjinfo [ num ] . seestate = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " SEESOUND " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . seesound ) , UNDO_NONE ) ;
mobjinfo [ num ] . seesound = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " REACTIONTIME " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . reactiontime ) , UNDO_NONE ) ;
mobjinfo [ num ] . reactiontime = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " ATTACKSOUND " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . attacksound ) , UNDO_NONE ) ;
mobjinfo [ num ] . attacksound = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " PAINSTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . painstate ) , UNDO_NONE ) ;
mobjinfo [ num ] . painstate = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " PAINCHANCE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . painchance ) , UNDO_NONE ) ;
mobjinfo [ num ] . painchance = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " PAINSOUND " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . painsound ) , UNDO_NONE ) ;
mobjinfo [ num ] . painsound = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " MELEESTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . meleestate ) , UNDO_NONE ) ;
mobjinfo [ num ] . meleestate = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " MISSILESTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . missilestate ) , UNDO_NONE ) ;
mobjinfo [ num ] . missilestate = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " DEATHSTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . deathstate ) , UNDO_NONE ) ;
mobjinfo [ num ] . deathstate = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " DEATHSOUND " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . deathsound ) , UNDO_NONE ) ;
mobjinfo [ num ] . deathsound = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " XDEATHSTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . xdeathstate ) , UNDO_NONE ) ;
mobjinfo [ num ] . xdeathstate = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " SPEED " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . speed ) , UNDO_NONE ) ;
mobjinfo [ num ] . speed = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " RADIUS " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . radius ) , UNDO_NONE ) ;
mobjinfo [ num ] . radius = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " HEIGHT " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . height ) , UNDO_NONE ) ;
mobjinfo [ num ] . height = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " DISPOFFSET " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . dispoffset ) , UNDO_NONE ) ;
mobjinfo [ num ] . dispoffset = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " MASS " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . mass ) , UNDO_NONE ) ;
mobjinfo [ num ] . mass = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " DAMAGE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . damage ) , UNDO_NONE ) ;
mobjinfo [ num ] . damage = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " ACTIVESOUND " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . activesound ) , UNDO_NONE ) ;
mobjinfo [ num ] . activesound = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " FLAGS " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . flags ) , UNDO_NONE ) ;
mobjinfo [ num ] . flags = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " RAISESTATE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , mobjinfo [ num ] . raisestate ) , UNDO_NONE ) ;
mobjinfo [ num ] . raisestate = get_number ( word2 ) ;
}
else
deh_warning ( " Thing %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
# ifdef HWRENDER
static void readlight ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * tmp ;
INT32 value ;
float fvalue ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
fvalue = searchfvalue ( s ) ;
value = searchvalue ( s ) ;
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
if ( fastcmp ( word , " TYPE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , lspr [ num ] . type ) , UNDO_NONE ) ;
lspr [ num ] . type = ( UINT16 ) value ;
}
else if ( fastcmp ( word , " OFFSETX " ) )
{
DEH_WriteUndoline ( word , va ( " %f " , lspr [ num ] . light_xoffset ) , UNDO_NONE ) ;
lspr [ num ] . light_xoffset = fvalue ;
}
else if ( fastcmp ( word , " OFFSETY " ) )
{
DEH_WriteUndoline ( word , va ( " %f " , lspr [ num ] . light_yoffset ) , UNDO_NONE ) ;
lspr [ num ] . light_yoffset = fvalue ;
}
else if ( fastcmp ( word , " CORONACOLOR " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , lspr [ num ] . corona_color ) , UNDO_NONE ) ;
lspr [ num ] . corona_color = value ;
}
else if ( fastcmp ( word , " CORONARADIUS " ) )
{
DEH_WriteUndoline ( word , va ( " %f " , lspr [ num ] . corona_radius ) , UNDO_NONE ) ;
lspr [ num ] . corona_radius = fvalue ;
}
else if ( fastcmp ( word , " DYNAMICCOLOR " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , lspr [ num ] . dynamic_color ) , UNDO_NONE ) ;
lspr [ num ] . dynamic_color = value ;
}
else if ( fastcmp ( word , " DYNAMICRADIUS " ) )
{
DEH_WriteUndoline ( word , va ( " %f " , lspr [ num ] . dynamic_radius ) , UNDO_NONE ) ;
lspr [ num ] . dynamic_radius = fvalue ;
/// \note Update the sqrradius! unnecessary?
lspr [ num ] . dynamic_sqrradius = fvalue * fvalue ;
}
else
deh_warning ( " Light %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
static void readspritelight ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * tmp ;
INT32 value ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
value = searchvalue ( s ) ;
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
if ( fastcmp ( word , " LIGHTTYPE " ) )
{
INT32 oldvar ;
for ( oldvar = 0 ; t_lspr [ num ] ! = & lspr [ oldvar ] ; oldvar + + )
;
DEH_WriteUndoline ( word , va ( " %d " , oldvar ) , UNDO_NONE ) ;
t_lspr [ num ] = & lspr [ value ] ;
}
else
deh_warning ( " Sprite %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
# endif // HWRENDER
static const struct {
const char * name ;
const UINT16 flag ;
} TYPEOFLEVEL [ ] = {
{ " SOLO " , TOL_SP } ,
{ " SP " , TOL_SP } ,
{ " SINGLEPLAYER " , TOL_SP } ,
{ " SINGLE " , TOL_SP } ,
{ " COOP " , TOL_COOP } ,
{ " CO-OP " , TOL_COOP } ,
{ " COMPETITION " , TOL_COMPETITION } ,
{ " RACE " , TOL_RACE } ,
{ " MATCH " , TOL_MATCH } ,
{ " TAG " , TOL_TAG } ,
{ " CTF " , TOL_CTF } ,
{ " CUSTOM " , TOL_CUSTOM } ,
{ " 2D " , TOL_2D } ,
{ " MARIO " , TOL_MARIO } ,
{ " NIGHTS " , TOL_NIGHTS } ,
{ " OLDBRAK " , TOL_ERZ3 } ,
{ " XMAS " , TOL_XMAS } ,
{ " CHRISTMAS " , TOL_XMAS } ,
{ " WINTER " , TOL_XMAS } ,
{ NULL , 0 }
} ;
static void readlevelheader ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * word2 ;
char * tmp ;
INT32 i ;
// Reset all previous map header information
// This call automatically saves all previous information when DELFILE is defined.
// We don't need to do it ourselves.
P_AllocMapHeader ( ( INT16 ) ( num - 1 ) ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
i = atoi ( word2 ) ; // used for numerical settings
// CHEAP HACK: move this over here for lowercase subtitles
if ( fastcmp ( word , " SUBTITLE " ) )
{
deh_strlcpy ( mapheaderinfo [ num - 1 ] - > subttl , word2 ,
sizeof ( mapheaderinfo [ num - 1 ] - > subttl ) , va ( " Level header %d: subtitle " , num ) ) ;
continue ;
}
// Now go to uppercase
strupr ( word2 ) ;
// NiGHTS grades
if ( fastncmp ( word , " GRADES " , 6 ) )
{
UINT8 mare = ( UINT8 ) atoi ( word + 6 ) ;
if ( mare < = 0 | | mare > 8 )
{
deh_warning ( " Level header %d: unknown word '%s' " , num , word ) ;
continue ;
}
P_AddGradesForMare ( ( INT16 ) ( num - 1 ) , mare - 1 , word2 ) ;
}
// Strings that can be truncated
else if ( fastcmp ( word , " LEVELNAME " ) )
deh_strlcpy ( mapheaderinfo [ num - 1 ] - > lvlttl , word2 ,
sizeof ( mapheaderinfo [ num - 1 ] - > lvlttl ) , va ( " Level header %d: levelname " , num ) ) ;
else if ( fastcmp ( word , " SCRIPTNAME " ) )
deh_strlcpy ( mapheaderinfo [ num - 1 ] - > scriptname , word2 ,
sizeof ( mapheaderinfo [ num - 1 ] - > scriptname ) , va ( " Level header %d: scriptname " , num ) ) ;
else if ( fastcmp ( word , " RUNSOC " ) )
deh_strlcpy ( mapheaderinfo [ num - 1 ] - > runsoc , word2 ,
sizeof ( mapheaderinfo [ num - 1 ] - > runsoc ) , va ( " Level header %d: runsoc " , num ) ) ;
else if ( fastcmp ( word , " ACT " ) )
{
if ( i > = 0 & & i < 20 ) // 0 for no act number, TTL1 through TTL19
mapheaderinfo [ num - 1 ] - > actnum = ( UINT8 ) i ;
else
deh_warning ( " Level header %d: invalid act number %d " , num , i ) ;
}
else if ( fastcmp ( word , " NEXTLEVEL " ) )
{
// Support using the actual map name,
// i.e., Nextlevel = AB, Nextlevel = FZ, etc.
// Convert to map number
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' & & word2 [ 2 ] = = ' \0 ' )
i = M_MapNumber ( word2 [ 0 ] , word2 [ 1 ] ) ;
mapheaderinfo [ num - 1 ] - > nextlevel = ( INT16 ) i ;
}
else if ( fastcmp ( word , " TYPEOFLEVEL " ) )
{
if ( i ) // it's just a number
mapheaderinfo [ num - 1 ] - > typeoflevel = ( UINT16 ) i ;
else
{
UINT16 tol = 0 ;
tmp = strtok ( word2 , " , " ) ;
do {
for ( i = 0 ; TYPEOFLEVEL [ i ] . name ; i + + )
if ( fastcmp ( tmp , TYPEOFLEVEL [ i ] . name ) )
break ;
if ( ! TYPEOFLEVEL [ i ] . name )
deh_warning ( " Level header %d: unknown typeoflevel flag %s \n " , num , tmp ) ;
tol | = TYPEOFLEVEL [ i ] . flag ;
} while ( ( tmp = strtok ( NULL , " , " ) ) ! = NULL ) ;
mapheaderinfo [ num - 1 ] - > typeoflevel = tol ;
}
}
else if ( fastcmp ( word , " MUSICSLOT " ) )
{
// Convert to map number
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' & & word2 [ 2 ] = = ' \0 ' )
i = M_MapNumber ( word2 [ 0 ] , word2 [ 1 ] ) ;
if ( i ) // it's just a number
mapheaderinfo [ num - 1 ] - > musicslot = ( UINT16 ) i ;
else // No? Okay, now we'll get technical.
mapheaderinfo [ num - 1 ] - > musicslot = get_mus ( word2 ) ; // accepts all of O_CHRSEL, mus_chrsel, or just plain ChrSel
}
else if ( fastcmp ( word , " MUSICSLOTTRACK " ) )
mapheaderinfo [ num - 1 ] - > musicslottrack = ( ( UINT16 ) i - 1 ) ;
else if ( fastcmp ( word , " FORCECHARACTER " ) )
{
strlcpy ( mapheaderinfo [ num - 1 ] - > forcecharacter , word2 , SKINNAMESIZE + 1 ) ;
strlwr ( mapheaderinfo [ num - 1 ] - > forcecharacter ) ; // skin names are lowercase
}
else if ( fastcmp ( word , " WEATHER " ) )
mapheaderinfo [ num - 1 ] - > weather = ( UINT8 ) get_number ( word2 ) ;
else if ( fastcmp ( word , " SKYNUM " ) )
mapheaderinfo [ num - 1 ] - > skynum = ( INT16 ) i ;
else if ( fastcmp ( word , " INTERSCREEN " ) )
strncpy ( mapheaderinfo [ num - 1 ] - > interscreen , word2 , 8 ) ;
else if ( fastcmp ( word , " PRECUTSCENENUM " ) )
mapheaderinfo [ num - 1 ] - > precutscenenum = ( UINT8 ) i ;
else if ( fastcmp ( word , " CUTSCENENUM " ) )
mapheaderinfo [ num - 1 ] - > cutscenenum = ( UINT8 ) i ;
else if ( fastcmp ( word , " COUNTDOWN " ) )
mapheaderinfo [ num - 1 ] - > countdown = ( INT16 ) i ;
else if ( fastcmp ( word , " PALETTE " ) )
mapheaderinfo [ num - 1 ] - > palette = ( UINT16 ) i ;
else if ( fastcmp ( word , " NUMLAPS " ) )
2014-03-21 18:42:55 +00:00
mapheaderinfo [ num - 1 ] - > numlaps = ( UINT8 ) i ;
2014-03-15 16:59:03 +00:00
else if ( fastcmp ( word , " UNLOCKABLE " ) )
{
if ( i > = 0 & & i < = MAXUNLOCKABLES ) // 0 for no unlock required, anything else requires something
mapheaderinfo [ num - 1 ] - > unlockrequired = ( SINT8 ) i - 1 ;
else
deh_warning ( " Level header %d: invalid unlockable number %d " , num , i ) ;
}
else if ( fastcmp ( word , " LEVELSELECT " ) )
mapheaderinfo [ num - 1 ] - > levelselect = ( UINT8 ) i ;
else if ( fastcmp ( word , " SKYBOXSCALE " ) )
mapheaderinfo [ num - 1 ] - > skybox_scalex = mapheaderinfo [ num - 1 ] - > skybox_scaley = mapheaderinfo [ num - 1 ] - > skybox_scalez = ( INT16 ) i ;
else if ( fastcmp ( word , " SKYBOXSCALEX " ) )
mapheaderinfo [ num - 1 ] - > skybox_scalex = ( INT16 ) i ;
else if ( fastcmp ( word , " SKYBOXSCALEY " ) )
mapheaderinfo [ num - 1 ] - > skybox_scaley = ( INT16 ) i ;
else if ( fastcmp ( word , " SKYBOXSCALEZ " ) )
mapheaderinfo [ num - 1 ] - > skybox_scalez = ( INT16 ) i ;
else if ( fastcmp ( word , " BONUSTYPE " ) )
{
if ( fastcmp ( word2 , " NONE " ) ) i = - 1 ;
else if ( fastcmp ( word2 , " NORMAL " ) ) i = 0 ;
else if ( fastcmp ( word2 , " BOSS " ) ) i = 1 ;
else if ( fastcmp ( word2 , " ERZ3 " ) ) i = 2 ;
if ( i > = - 1 & & i < = 2 ) // -1 for no bonus. Max is 2.
mapheaderinfo [ num - 1 ] - > bonustype = ( SINT8 ) i ;
else
deh_warning ( " Level header %d: invalid bonus type number %d " , num , i ) ;
}
else if ( fastcmp ( word , " LEVELFLAGS " ) )
mapheaderinfo [ num - 1 ] - > levelflags = ( UINT8 ) i ;
else if ( fastcmp ( word , " MENUFLAGS " ) )
mapheaderinfo [ num - 1 ] - > menuflags = ( UINT8 ) i ;
// Individual triggers for level flags, for ease of use (and 2.0 compatibility)
else if ( fastcmp ( word , " SCRIPTISFILE " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > levelflags | = LF_SCRIPTISFILE ;
else
mapheaderinfo [ num - 1 ] - > levelflags & = ~ LF_SCRIPTISFILE ;
}
else if ( fastcmp ( word , " SPEEDMUSIC " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > levelflags | = LF_SPEEDMUSIC ;
else
mapheaderinfo [ num - 1 ] - > levelflags & = ~ LF_SPEEDMUSIC ;
}
else if ( fastcmp ( word , " NOSSMUSIC " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > levelflags | = LF_NOSSMUSIC ;
else
mapheaderinfo [ num - 1 ] - > levelflags & = ~ LF_NOSSMUSIC ;
}
else if ( fastcmp ( word , " NORELOAD " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > levelflags | = LF_NORELOAD ;
else
mapheaderinfo [ num - 1 ] - > levelflags & = ~ LF_NORELOAD ;
}
else if ( fastcmp ( word , " NOZONE " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > levelflags | = LF_NOZONE ;
else
mapheaderinfo [ num - 1 ] - > levelflags & = ~ LF_NOZONE ;
}
// Individual triggers for menu flags
else if ( fastcmp ( word , " HIDDEN " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > menuflags | = LF2_HIDEINMENU ;
else
mapheaderinfo [ num - 1 ] - > menuflags & = ~ LF2_HIDEINMENU ;
}
else if ( fastcmp ( word , " HIDEINSTATS " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > menuflags | = LF2_HIDEINSTATS ;
else
mapheaderinfo [ num - 1 ] - > menuflags & = ~ LF2_HIDEINSTATS ;
}
else if ( fastcmp ( word , " RECORDATTACK " ) | | fastcmp ( word , " TIMEATTACK " ) )
{ // TIMEATTACK is an accepted alias
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > menuflags | = LF2_RECORDATTACK ;
else
mapheaderinfo [ num - 1 ] - > menuflags & = ~ LF2_RECORDATTACK ;
}
else if ( fastcmp ( word , " NIGHTSATTACK " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > menuflags | = LF2_NIGHTSATTACK ;
else
mapheaderinfo [ num - 1 ] - > menuflags & = LF2_NIGHTSATTACK ;
}
else if ( fastcmp ( word , " NOVISITNEEDED " ) )
{
if ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' )
mapheaderinfo [ num - 1 ] - > menuflags | = LF2_NOVISITNEEDED ;
else
mapheaderinfo [ num - 1 ] - > menuflags & = ~ LF2_NOVISITNEEDED ;
}
else
deh_warning ( " Level header %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
static void readcutscenescene ( MYFILE * f , INT32 num , INT32 scenenum )
{
char * s = Z_Calloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * word2 ;
INT32 i ;
UINT16 usi ;
UINT8 picid ;
DEH_WriteUndoline ( " SCENETEXT " , cutscenes [ num ] - > scene [ scenenum ] . text , UNDO_ENDTEXT ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
if ( fastcmp ( word , " SCENETEXT " ) )
{
char * scenetext = NULL ;
char * buffer ;
const int bufferlen = 4096 ;
for ( i = 0 ; i < MAXLINELEN ; i + + )
{
if ( s [ i ] = = ' = ' )
{
scenetext = & s [ i + 2 ] ;
break ;
}
}
if ( ! scenetext )
{
Z_Free ( cutscenes [ num ] - > scene [ scenenum ] . text ) ;
cutscenes [ num ] - > scene [ scenenum ] . text = NULL ;
continue ;
}
for ( i = 0 ; i < MAXLINELEN ; i + + )
{
if ( s [ i ] = = ' \0 ' )
{
s [ i ] = ' \n ' ;
s [ i + 1 ] = ' \0 ' ;
break ;
}
}
buffer = Z_Malloc ( 4096 , PU_STATIC , NULL ) ;
strcpy ( buffer , scenetext ) ;
strcat ( buffer ,
myhashfgets ( scenetext , bufferlen
- strlen ( buffer ) - 1 , f ) ) ;
// A cutscene overwriting another one...
Z_Free ( cutscenes [ num ] - > scene [ scenenum ] . text ) ;
cutscenes [ num ] - > scene [ scenenum ] . text = Z_StrDup ( buffer ) ;
Z_Free ( buffer ) ;
continue ;
}
word2 = strtok ( NULL , " = " ) ;
if ( word2 )
strupr ( word2 ) ;
else
break ;
if ( word2 [ strlen ( word2 ) - 1 ] = = ' \n ' )
word2 [ strlen ( word2 ) - 1 ] = ' \0 ' ;
i = atoi ( word2 ) ;
usi = ( UINT16 ) i ;
if ( fastcmp ( word , " NUMBEROFPICS " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , cutscenes [ num ] - > scene [ scenenum ] . numpics ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . numpics = ( UINT8 ) i ;
}
else if ( fastncmp ( word , " PIC " , 3 ) )
{
picid = ( UINT8 ) atoi ( word + 3 ) ;
if ( picid > 8 | | picid = = 0 )
{
deh_warning ( " CutSceneScene %d: unknown word '%s' " , num , word ) ;
continue ;
}
- - picid ;
if ( fastcmp ( word + 4 , " NAME " ) )
{
DEH_WriteUndoline ( word , cutscenes [ num ] - > scene [ scenenum ] . picname [ picid ] , UNDO_NONE ) ;
strncpy ( cutscenes [ num ] - > scene [ scenenum ] . picname [ picid ] , word2 , 8 ) ;
}
else if ( fastcmp ( word + 4 , " HIRES " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , cutscenes [ num ] - > scene [ scenenum ] . pichires [ picid ] ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . pichires [ picid ] = ( UINT8 ) ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' ) ;
}
else if ( fastcmp ( word + 4 , " DURATION " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . picduration [ picid ] ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . picduration [ picid ] = usi ;
}
else if ( fastcmp ( word + 4 , " XCOORD " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . xcoord [ picid ] ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . xcoord [ picid ] = usi ;
}
else if ( fastcmp ( word + 4 , " YCOORD " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . ycoord [ picid ] ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . ycoord [ picid ] = usi ;
}
else
deh_warning ( " CutSceneScene %d: unknown word '%s' " , num , word ) ;
}
else if ( fastcmp ( word , " MUSICSLOT " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . musicslot ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . musicslot = get_mus ( word2 ) ; // accepts all of O_MAP01M, mus_map01m, or just plain MAP01M
}
else if ( fastcmp ( word , " MUSICLOOP " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . musicloop ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . musicloop = ( UINT8 ) ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' ) ;
}
else if ( fastcmp ( word , " TEXTXPOS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . textxpos ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . textxpos = usi ;
}
else if ( fastcmp ( word , " TEXTYPOS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . textypos ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . textypos = usi ;
}
else if ( fastcmp ( word , " FADEINID " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . fadenum ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . fadeinid = ( UINT8 ) i ;
}
else if ( fastcmp ( word , " FADEOUTID " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . fadenum ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . fadeoutid = ( UINT8 ) i ;
}
else if ( fastcmp ( word , " FADECOLOR " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , cutscenes [ num ] - > scene [ scenenum ] . fadenum ) , UNDO_NONE ) ;
cutscenes [ num ] - > scene [ scenenum ] . fadecolor = ( UINT8 ) i ;
}
else
deh_warning ( " CutSceneScene %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
static void readcutscene ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * word2 ;
char * tmp ;
INT32 value ;
# ifdef DELFILE
const INT32 oldnumscenes = cutscenes [ num ] - > numscenes ;
# endif
// Allocate memory for this cutscene if we don't yet have any
if ( ! cutscenes [ num ] )
cutscenes [ num ] = Z_Calloc ( sizeof ( cutscene_t ) , PU_STATIC , NULL ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
word2 = strtok ( NULL , " " ) ;
if ( word2 )
value = atoi ( word2 ) ;
else
{
deh_warning ( " No value for token %s " , word ) ;
continue ;
}
if ( fastcmp ( word , " NUMSCENES " ) )
{
cutscenes [ num ] - > numscenes = value ;
}
else if ( fastcmp ( word , " SCENE " ) )
{
if ( 1 < = value & & value < = 128 )
{
readcutscenescene ( f , num , value - 1 ) ;
DEH_WriteUndoline ( word , word2 , UNDO_SPACE | UNDO_CUTLINE ) ;
DEH_WriteUndoline ( " NUMSCENES " , va ( " %d " , oldnumscenes ) , UNDO_SPACE ) ;
}
else
deh_warning ( " Scene number %d out of range (1 - 128) " , value ) ;
}
else
deh_warning ( " Cutscene %d: unknown word '%s', Scene <num> expected. " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
static void readhuditem ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * word2 ;
char * tmp ;
INT32 i ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
strupr ( word2 ) ;
i = atoi ( word2 ) ; // used for numerical settings
if ( fastcmp ( word , " X " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , hudinfo [ num ] . x ) , UNDO_NONE ) ;
hudinfo [ num ] . x = i ;
}
else if ( fastcmp ( word , " Y " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , hudinfo [ num ] . y ) , UNDO_NONE ) ;
hudinfo [ num ] . y = i ;
}
else
deh_warning ( " Level header %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
/*
Sprite number = 10
Sprite subnumber = 32968
Duration = 200
Next frame = 200
*/
/** Action pointer for reading actions from Dehacked lumps.
*/
typedef struct
{
actionf_t action ; ///< Function pointer corresponding to the actual action.
const char * name ; ///< Name of the action in ALL CAPS.
} actionpointer_t ;
/** Array mapping action names to action functions.
* Names must be in ALL CAPS for case insensitive comparisons .
*/
static actionpointer_t actionpointers [ ] =
{
{ { A_Explode } , " A_EXPLODE " } ,
{ { A_Pain } , " A_PAIN " } ,
{ { A_Fall } , " A_FALL " } ,
{ { A_MonitorPop } , " A_MONITORPOP " } ,
{ { A_Look } , " A_LOOK " } ,
{ { A_Chase } , " A_CHASE " } ,
{ { A_FaceStabChase } , " A_FACESTABCHASE " } ,
{ { A_FaceTarget } , " A_FACETARGET " } ,
{ { A_FaceTracer } , " A_FACETRACER " } ,
{ { A_Scream } , " A_SCREAM " } ,
{ { A_BossDeath } , " A_BOSSDEATH " } ,
{ { A_CustomPower } , " A_CUSTOMPOWER " } ,
{ { A_GiveWeapon } , " A_GIVEWEAPON " } ,
{ { A_RingShield } , " A_RINGSHIELD " } ,
{ { A_RingBox } , " A_RINGBOX " } ,
{ { A_Invincibility } , " A_INVINCIBILITY " } ,
{ { A_SuperSneakers } , " A_SUPERSNEAKERS " } ,
{ { A_BunnyHop } , " A_BUNNYHOP " } ,
{ { A_BubbleSpawn } , " A_BUBBLESPAWN " } ,
{ { A_FanBubbleSpawn } , " A_FANBUBBLESPAWN " } ,
{ { A_BubbleRise } , " A_BUBBLERISE " } ,
{ { A_BubbleCheck } , " A_BUBBLECHECK " } ,
{ { A_AwardScore } , " A_AWARDSCORE " } ,
{ { A_ExtraLife } , " A_EXTRALIFE " } ,
{ { A_BombShield } , " A_BOMBSHIELD " } ,
{ { A_JumpShield } , " A_JUMPSHIELD " } ,
{ { A_WaterShield } , " A_WATERSHIELD " } ,
{ { A_ForceShield } , " A_FORCESHIELD " } ,
{ { A_PityShield } , " A_PITYSHIELD " } ,
{ { A_GravityBox } , " A_GRAVITYBOX " } ,
{ { A_ScoreRise } , " A_SCORERISE " } ,
{ { A_ParticleSpawn } , " A_PARTICLESPAWN " } ,
{ { A_AttractChase } , " A_ATTRACTCHASE " } ,
{ { A_DropMine } , " A_DROPMINE " } ,
{ { A_FishJump } , " A_FISHJUMP " } ,
{ { A_ThrownRing } , " A_THROWNRING " } ,
{ { A_SetSolidSteam } , " A_SETSOLIDSTEAM " } ,
{ { A_UnsetSolidSteam } , " A_UNSETSOLIDSTEAM " } ,
{ { A_SignPlayer } , " A_SIGNPLAYER " } ,
{ { A_OverlayThink } , " A_OVERLAYTHINK " } ,
{ { A_JetChase } , " A_JETCHASE " } ,
{ { A_JetbThink } , " A_JETBTHINK " } ,
{ { A_JetgThink } , " A_JETGTHINK " } ,
{ { A_JetgShoot } , " A_JETGSHOOT " } ,
{ { A_ShootBullet } , " A_SHOOTBULLET " } ,
{ { A_MinusDigging } , " A_MINUSDIGGING " } ,
{ { A_MinusPopup } , " A_MINUSPOPUP " } ,
{ { A_MinusCheck } , " A_MINUSCHECK " } ,
{ { A_ChickenCheck } , " A_CHICKENCHECK " } ,
{ { A_MouseThink } , " A_MOUSETHINK " } ,
{ { A_DetonChase } , " A_DETONCHASE " } ,
{ { A_CapeChase } , " A_CAPECHASE " } ,
{ { A_RotateSpikeBall } , " A_ROTATESPIKEBALL " } ,
{ { A_SlingAppear } , " A_SLINGAPPEAR " } ,
{ { A_MaceRotate } , " A_MACEROTATE " } ,
{ { A_UnidusBall } , " A_UNIDUSBALL " } ,
{ { A_RockSpawn } , " A_ROCKSPAWN " } ,
{ { A_SetFuse } , " A_SETFUSE " } ,
{ { A_CrawlaCommanderThink } , " A_CRAWLACOMMANDERTHINK " } ,
{ { A_SmokeTrailer } , " A_SMOKETRAILER " } ,
{ { A_RingExplode } , " A_RINGEXPLODE " } ,
{ { A_OldRingExplode } , " A_OLDRINGEXPLODE " } ,
{ { A_MixUp } , " A_MIXUP " } ,
{ { A_RecyclePowers } , " A_RECYCLEPOWERS " } ,
{ { A_Boss1Chase } , " A_BOSS1CHASE " } ,
{ { A_FocusTarget } , " A_FOCUSTARGET " } ,
{ { A_Boss2Chase } , " A_BOSS2CHASE " } ,
{ { A_Boss2Pogo } , " A_BOSS2POGO " } ,
{ { A_BossZoom } , " A_BOSSZOOM " } ,
{ { A_BossScream } , " A_BOSSSCREAM " } ,
{ { A_Boss2TakeDamage } , " A_BOSS2TAKEDAMAGE " } ,
{ { A_Boss7Chase } , " A_BOSS7CHASE " } ,
{ { A_GoopSplat } , " A_GOOPSPLAT " } ,
{ { A_Boss2PogoSFX } , " A_BOSS2POGOSFX " } ,
{ { A_Boss2PogoTarget } , " A_BOSS2POGOTARGET " } ,
{ { A_BossJetFume } , " A_BOSSJETFUME " } ,
{ { A_EggmanBox } , " A_EGGMANBOX " } ,
{ { A_TurretFire } , " A_TURRETFIRE " } ,
{ { A_SuperTurretFire } , " A_SUPERTURRETFIRE " } ,
{ { A_TurretStop } , " A_TURRETSTOP " } ,
{ { A_JetJawRoam } , " A_JETJAWROAM " } ,
{ { A_JetJawChomp } , " A_JETJAWCHOMP " } ,
{ { A_PointyThink } , " A_POINTYTHINK " } ,
{ { A_CheckBuddy } , " A_CHECKBUDDY " } ,
{ { A_HoodThink } , " A_HOODTHINK " } ,
{ { A_ArrowCheck } , " A_ARROWCHECK " } ,
{ { A_SnailerThink } , " A_SNAILERTHINK " } ,
{ { A_SharpChase } , " A_SHARPCHASE " } ,
{ { A_SharpSpin } , " A_SHARPSPIN " } ,
{ { A_VultureVtol } , " A_VULTUREVTOL " } ,
{ { A_VultureCheck } , " A_VULTURECHECK " } ,
{ { A_SkimChase } , " A_SKIMCHASE " } ,
{ { A_1upThinker } , " A_1UPTHINKER " } ,
{ { A_SkullAttack } , " A_SKULLATTACK " } ,
{ { A_LobShot } , " A_LOBSHOT " } ,
{ { A_FireShot } , " A_FIRESHOT " } ,
{ { A_SuperFireShot } , " A_SUPERFIRESHOT " } ,
{ { A_BossFireShot } , " A_BOSSFIRESHOT " } ,
{ { A_Boss7FireMissiles } , " A_BOSS7FIREMISSILES " } ,
{ { A_Boss1Laser } , " A_BOSS1LASER " } ,
{ { A_Boss4Reverse } , " A_BOSS4REVERSE " } ,
{ { A_Boss4SpeedUp } , " A_BOSS4SPEEDUP " } ,
{ { A_Boss4Raise } , " A_BOSS4RAISE " } ,
{ { A_SparkFollow } , " A_SPARKFOLLOW " } ,
{ { A_BuzzFly } , " A_BUZZFLY " } ,
{ { A_GuardChase } , " A_GUARDCHASE " } ,
{ { A_EggShield } , " A_EGGSHIELD " } ,
{ { A_SetReactionTime } , " A_SETREACTIONTIME " } ,
{ { A_Boss1Spikeballs } , " A_BOSS1SPIKEBALLS " } ,
{ { A_Boss3TakeDamage } , " A_BOSS3TAKEDAMAGE " } ,
{ { A_Boss3Path } , " A_BOSS3PATH " } ,
{ { A_LinedefExecute } , " A_LINEDEFEXECUTE " } ,
{ { A_PlaySeeSound } , " A_PLAYSEESOUND " } ,
{ { A_PlayAttackSound } , " A_PLAYATTACKSOUND " } ,
{ { A_PlayActiveSound } , " A_PLAYACTIVESOUND " } ,
{ { A_SpawnObjectAbsolute } , " A_SPAWNOBJECTABSOLUTE " } ,
{ { A_SpawnObjectRelative } , " A_SPAWNOBJECTRELATIVE " } ,
{ { A_ChangeAngleRelative } , " A_CHANGEANGLERELATIVE " } ,
{ { A_ChangeAngleAbsolute } , " A_CHANGEANGLEABSOLUTE " } ,
{ { A_PlaySound } , " A_PLAYSOUND " } ,
{ { A_FindTarget } , " A_FINDTARGET " } ,
{ { A_FindTracer } , " A_FINDTRACER " } ,
{ { A_SetTics } , " A_SETTICS " } ,
{ { A_SetRandomTics } , " A_SETRANDOMTICS " } ,
{ { A_ChangeColorRelative } , " A_CHANGECOLORRELATIVE " } ,
{ { A_ChangeColorAbsolute } , " A_CHANGECOLORABSOLUTE " } ,
{ { A_MoveRelative } , " A_MOVERELATIVE " } ,
{ { A_MoveAbsolute } , " A_MOVEABSOLUTE " } ,
{ { A_Thrust } , " A_THRUST " } ,
{ { A_ZThrust } , " A_ZTHRUST " } ,
{ { A_SetTargetsTarget } , " A_SETTARGETSTARGET " } ,
{ { A_SetObjectFlags } , " A_SETOBJECTFLAGS " } ,
{ { A_SetObjectFlags2 } , " A_SETOBJECTFLAGS2 " } ,
{ { A_RandomState } , " A_RANDOMSTATE " } ,
{ { A_RandomStateRange } , " A_RANDOMSTATERANGE " } ,
{ { A_DualAction } , " A_DUALACTION " } ,
{ { A_RemoteAction } , " A_REMOTEACTION " } ,
{ { A_ToggleFlameJet } , " A_TOGGLEFLAMEJET " } ,
{ { A_OrbitNights } , " A_ORBITNIGHTS " } ,
{ { A_GhostMe } , " A_GHOSTME " } ,
{ { A_SetObjectState } , " A_SETOBJECTSTATE " } ,
{ { A_SetObjectTypeState } , " A_SETOBJECTTYPESTATE " } ,
{ { A_KnockBack } , " A_KNOCKBACK " } ,
{ { A_PushAway } , " A_PUSHAWAY " } ,
{ { A_RingDrain } , " A_RINGDRAIN " } ,
{ { A_SplitShot } , " A_SPLITSHOT " } ,
{ { A_MissileSplit } , " A_MISSILESPLIT " } ,
{ { A_MultiShot } , " A_MULTISHOT " } ,
{ { A_InstaLoop } , " A_INSTALOOP " } ,
{ { A_Custom3DRotate } , " A_CUSTOM3DROTATE " } ,
{ { A_SearchForPlayers } , " A_SEARCHFORPLAYERS " } ,
{ { A_CheckRandom } , " A_CHECKRANDOM " } ,
{ { A_CheckTargetRings } , " A_CHECKTARGETRINGS " } ,
{ { A_CheckRings } , " A_CHECKRINGS " } ,
{ { A_CheckTotalRings } , " A_CHECKTOTALRINGS " } ,
{ { A_CheckHealth } , " A_CHECKHEALTH " } ,
{ { A_CheckRange } , " A_CHECKRANGE " } ,
{ { A_CheckHeight } , " A_CHECKHEIGHT " } ,
{ { A_CheckTrueRange } , " A_CHECKTRUERANGE " } ,
{ { A_CheckThingCount } , " A_CHECKTHINGCOUNT " } ,
{ { A_CheckAmbush } , " A_CHECKAMBUSH " } ,
{ { A_CheckCustomValue } , " A_CHECKCUSTOMVALUE " } ,
{ { A_CheckCusValMemo } , " A_CHECKCUSVALMEMO " } ,
{ { A_SetCustomValue } , " A_SETCUSTOMVALUE " } ,
{ { A_UseCusValMemo } , " A_USECUSVALMEMO " } ,
{ { A_RelayCustomValue } , " A_RELAYCUSTOMVALUE " } ,
{ { A_CusValAction } , " A_CUSVALACTION " } ,
{ { A_ForceStop } , " A_FORCESTOP " } ,
{ { A_ForceWin } , " A_FORCEWIN " } ,
{ { A_SpikeRetract } , " A_SPIKERETRACT " } ,
{ { A_InfoState } , " A_INFOSTATE " } ,
{ { A_Repeat } , " A_REPEAT " } ,
{ { A_SetScale } , " A_SETSCALE " } ,
{ { A_RemoteDamage } , " A_REMOTEDAMAGE " } ,
{ { A_HomingChase } , " A_HOMINGCHASE " } ,
{ { A_TrapShot } , " A_TRAPSHOT " } ,
{ { A_VileTarget } , " A_VILETARGET " } ,
{ { A_VileAttack } , " A_VILEATTACK " } ,
{ { A_VileFire } , " A_VILEFIRE " } ,
{ { A_BrakChase } , " A_BRAKCHASE " } ,
{ { A_BrakFireShot } , " A_BRAKFIRESHOT " } ,
{ { A_BrakLobShot } , " A_BRAKLOBSHOT " } ,
{ { A_NapalmScatter } , " A_NAPALMSCATTER " } ,
{ { A_SpawnFreshCopy } , " A_SPAWNFRESHCOPY " } ,
{ { NULL } , " NONE " } ,
// This NULL entry must be the last in the list
{ { NULL } , NULL } ,
} ;
static void readframe ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word1 ;
char * word2 = NULL ;
char * tmp ;
INT32 j ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
for ( j = 0 ; s [ j ] ! = ' \n ' ; j + + )
{
if ( s [ j ] = = ' = ' )
{
j + = 2 ;
j = atoi ( & s [ j ] ) ;
break ;
}
}
word1 = strtok ( s , " " ) ;
if ( word1 )
strupr ( word1 ) ;
else
break ;
word2 = strtok ( NULL , " = " ) ;
if ( word2 )
strupr ( word2 ) ;
else
break ;
if ( word2 [ strlen ( word2 ) - 1 ] = = ' \n ' )
word2 [ strlen ( word2 ) - 1 ] = ' \0 ' ;
if ( fastcmp ( word1 , " SPRITENUMBER " ) | | fastcmp ( word1 , " SPRITENAME " ) )
{
DEH_WriteUndoline ( word1 , va ( " %u " , states [ num ] . sprite ) , UNDO_NONE ) ;
states [ num ] . sprite = get_sprite ( word2 ) ;
}
else if ( fastcmp ( word1 , " SPRITESUBNUMBER " ) | | fastcmp ( word1 , " SPRITEFRAME " ) )
{
DEH_WriteUndoline ( word1 , va ( " %d " , states [ num ] . frame ) , UNDO_NONE ) ;
states [ num ] . frame = ( INT32 ) get_number ( word2 ) ; // So the FF_ flags get calculated
}
else if ( fastcmp ( word1 , " DURATION " ) )
{
DEH_WriteUndoline ( word1 , va ( " %u " , states [ num ] . tics ) , UNDO_NONE ) ;
states [ num ] . tics = ( INT32 ) get_number ( word2 ) ; // So TICRATE can be used
}
else if ( fastcmp ( word1 , " NEXT " ) )
{
DEH_WriteUndoline ( word1 , va ( " %d " , states [ num ] . nextstate ) , UNDO_NONE ) ;
states [ num ] . nextstate = get_state ( word2 ) ;
}
else if ( fastcmp ( word1 , " VAR1 " ) )
{
DEH_WriteUndoline ( word1 , va ( " %d " , states [ num ] . var1 ) , UNDO_NONE ) ;
states [ num ] . var1 = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word1 , " VAR2 " ) )
{
DEH_WriteUndoline ( word1 , va ( " %d " , states [ num ] . var2 ) , UNDO_NONE ) ;
states [ num ] . var2 = ( INT32 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word1 , " ACTION " ) )
{
size_t z ;
boolean found = false ;
XBOXSTATIC char actiontocompare [ 32 ] ;
memset ( actiontocompare , 0x00 , sizeof ( actiontocompare ) ) ;
strlcpy ( actiontocompare , word2 , sizeof ( actiontocompare ) ) ;
strupr ( actiontocompare ) ;
for ( z = 0 ; z < 32 ; z + + )
{
if ( actiontocompare [ z ] = = ' \n ' | | actiontocompare [ z ] = = ' \r ' )
{
actiontocompare [ z ] = ' \0 ' ;
break ;
}
}
for ( z = 0 ; actionpointers [ z ] . name ; z + + )
{
if ( actionpointers [ z ] . action . acv = = states [ num ] . action . acv )
{
DEH_WriteUndoline ( word1 , actionpointers [ z ] . name , UNDO_NONE ) ;
break ;
}
}
z = 0 ;
# ifdef HAVE_BLUA
found = LUA_SetLuaAction ( & states [ num ] , actiontocompare ) ;
if ( ! found )
# endif
while ( actionpointers [ z ] . name )
{
if ( fastcmp ( actiontocompare , actionpointers [ z ] . name ) )
{
states [ num ] . action = actionpointers [ z ] . action ;
states [ num ] . action . acv = actionpointers [ z ] . action . acv ; // assign
states [ num ] . action . acp1 = actionpointers [ z ] . action . acp1 ;
found = true ;
break ;
}
z + + ;
}
if ( ! found )
deh_warning ( " Unknown action %s " , actiontocompare ) ;
}
else
deh_warning ( " Frame %d: unknown word '%s' " , num , word1 ) ;
}
} while ( ! myfeof ( f ) ) ;
Z_Free ( s ) ;
}
static void readsound ( MYFILE * f , INT32 num , const char * savesfxnames [ ] )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * tmp ;
INT32 value ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
value = searchvalue ( s ) ;
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
/* if (fastcmp(word, "OFFSET"))
{
value - = 150360 ;
if ( value < = 64 )
value / = 8 ;
else if ( value < = 260 )
value = ( value + 4 ) / 8 ;
else
value = ( value + 8 ) / 8 ;
if ( value > = - 1 & & value < sfx_freeslot0 - 1 )
S_sfx [ num ] . name = savesfxnames [ value + 1 ] ;
else
deh_warning ( " Sound %d: offset out of bounds " , num ) ;
}
else */ if ( fastcmp ( word , " SINGULAR " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , S_sfx [ num ] . singularity ) , UNDO_NONE ) ;
S_sfx [ num ] . singularity = value ;
}
else if ( fastcmp ( word , " PRIORITY " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , S_sfx [ num ] . priority ) , UNDO_NONE ) ;
S_sfx [ num ] . priority = value ;
}
else if ( fastcmp ( word , " FLAGS " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , S_sfx [ num ] . pitch ) , UNDO_NONE ) ;
S_sfx [ num ] . pitch = value ;
}
else
deh_warning ( " Sound %d : unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ;
Z_Free ( s ) ;
( void ) savesfxnames ;
}
/** Checks if a game data file name for a mod is good.
* " Good " means that it contains only alphanumerics , _ , and - ;
* ends in " .dat " ; has at least one character before the " .dat " ;
* and is not " gamedata.dat " ( tested case - insensitively ) .
*
* Assumption : that gamedata . dat is the only . dat file that will
* ever be treated specially by the game .
*
* Note : Check for the tail " .dat " case - insensitively since at
* present , we get passed the filename in all uppercase .
*
* \ param s Filename string to check .
* \ return True if the filename is good .
* \ sa readmaincfg ( )
* \ author Graue < graue @ oceanbase . org >
*/
static boolean GoodDataFileName ( const char * s )
{
const char * p ;
const char * tail = " .dat " ;
for ( p = s ; * p ! = ' \0 ' ; p + + )
if ( ! isalnum ( * p ) & & * p ! = ' _ ' & & * p ! = ' - ' & & * p ! = ' . ' )
return false ;
p = s + strlen ( s ) - strlen ( tail ) ;
if ( p < = s ) return false ; // too short
if ( ! fasticmp ( p , tail ) ) return false ; // doesn't end in .dat
# ifdef DELFILE
if ( fasticmp ( s , " gamedata.dat " ) & & ! disableundo ) return false ;
# else
if ( fasticmp ( s , " gamedata.dat " ) ) return false ;
# endif
return true ;
}
static void reademblemdata ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * word2 ;
char * tmp ;
INT32 value ;
// Reset all data initially
DEH_WriteUndoline ( " TYPE " , va ( " %d " , emblemlocations [ num - 1 ] . type ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " X " , va ( " %d " , emblemlocations [ num - 1 ] . x ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " Y " , va ( " %d " , emblemlocations [ num - 1 ] . y ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " Z " , va ( " %d " , emblemlocations [ num - 1 ] . z ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " MAPNUM " , va ( " %d " , emblemlocations [ num - 1 ] . level ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " VAR " , va ( " %d " , emblemlocations [ num - 1 ] . var ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " SPRITE " , va ( " %d " , emblemlocations [ num - 1 ] . sprite ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " COLOR " , va ( " %d " , emblemlocations [ num - 1 ] . color ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " HINT " , extraemblems [ num - 1 ] . hint , UNDO_NONE ) ;
memset ( & emblemlocations [ num - 1 ] , 0 , sizeof ( emblem_t ) ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
value = atoi ( word2 ) ; // used for numerical settings
// Up here to allow lowercase in hints
if ( fastcmp ( word , " HINT " ) )
{
while ( ( tmp = strchr ( word2 , ' \\ ' ) ) )
* tmp = ' \n ' ;
deh_strlcpy ( emblemlocations [ num - 1 ] . hint , word2 , sizeof ( emblemlocations [ num - 1 ] . hint ) , va ( " Emblem %d: hint " , num ) ) ;
continue ;
}
strupr ( word2 ) ;
if ( fastcmp ( word , " TYPE " ) )
{
if ( fastcmp ( word2 , " GLOBAL " ) )
emblemlocations [ num - 1 ] . type = ET_GLOBAL ;
else if ( fastcmp ( word2 , " SKIN " ) )
emblemlocations [ num - 1 ] . type = ET_SKIN ;
else if ( fastcmp ( word2 , " SCORE " ) )
emblemlocations [ num - 1 ] . type = ET_SCORE ;
else if ( fastcmp ( word2 , " TIME " ) )
emblemlocations [ num - 1 ] . type = ET_TIME ;
else if ( fastcmp ( word2 , " RINGS " ) )
emblemlocations [ num - 1 ] . type = ET_RINGS ;
else if ( fastcmp ( word2 , " NGRADE " ) )
emblemlocations [ num - 1 ] . type = ET_NGRADE ;
else if ( fastcmp ( word2 , " NTIME " ) )
emblemlocations [ num - 1 ] . type = ET_NTIME ;
else
emblemlocations [ num - 1 ] . type = ( UINT8 ) value ;
}
else if ( fastcmp ( word , " X " ) )
emblemlocations [ num - 1 ] . x = ( INT16 ) value ;
else if ( fastcmp ( word , " Y " ) )
emblemlocations [ num - 1 ] . y = ( INT16 ) value ;
else if ( fastcmp ( word , " Z " ) )
emblemlocations [ num - 1 ] . z = ( INT16 ) value ;
else if ( fastcmp ( word , " MAPNUM " ) )
{
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' )
value = M_MapNumber ( word2 [ 0 ] , word2 [ 1 ] ) ;
emblemlocations [ num - 1 ] . level = ( INT16 ) value ;
}
else if ( fastcmp ( word , " SPRITE " ) )
{
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' )
value = word2 [ 0 ] ;
else
value + = ' A ' - 1 ;
if ( value < ' A ' | | value > ' Z ' )
deh_warning ( " Emblem %d: sprite must be from A - Z (1 - 26) " , num ) ;
else
emblemlocations [ num - 1 ] . sprite = ( UINT8 ) value ;
}
else if ( fastcmp ( word , " COLOR " ) )
emblemlocations [ num - 1 ] . color = get_number ( word2 ) ;
else if ( fastcmp ( word , " VAR " ) )
emblemlocations [ num - 1 ] . var = get_number ( word2 ) ;
else
deh_warning ( " Emblem %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ;
// Default sprite and color definitions for lazy people like me
if ( ! emblemlocations [ num - 1 ] . sprite ) switch ( emblemlocations [ num - 1 ] . type )
{
case ET_RINGS :
emblemlocations [ num - 1 ] . sprite = ' R ' ; break ;
case ET_SCORE : case ET_NGRADE :
emblemlocations [ num - 1 ] . sprite = ' S ' ; break ;
case ET_TIME : case ET_NTIME :
emblemlocations [ num - 1 ] . sprite = ' T ' ; break ;
default :
emblemlocations [ num - 1 ] . sprite = ' A ' ; break ;
}
if ( ! emblemlocations [ num - 1 ] . color ) switch ( emblemlocations [ num - 1 ] . type )
{
case ET_RINGS :
emblemlocations [ num - 1 ] . color = SKINCOLOR_GOLD ; break ;
case ET_SCORE :
emblemlocations [ num - 1 ] . color = SKINCOLOR_BROWN ; break ;
case ET_NGRADE :
emblemlocations [ num - 1 ] . color = SKINCOLOR_TEAL ; break ;
case ET_TIME : case ET_NTIME :
emblemlocations [ num - 1 ] . color = SKINCOLOR_GREY ; break ;
default :
emblemlocations [ num - 1 ] . color = SKINCOLOR_BLUE ; break ;
}
Z_Free ( s ) ;
}
static void readextraemblemdata ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * word2 ;
char * tmp ;
INT32 value ;
// Reset all data initially
DEH_WriteUndoline ( " NAME " , extraemblems [ num - 1 ] . name , UNDO_NONE ) ;
DEH_WriteUndoline ( " OBJECTIVE " , extraemblems [ num - 1 ] . description , UNDO_NONE ) ;
DEH_WriteUndoline ( " CONDITIONSET " , va ( " %d " , extraemblems [ num - 1 ] . conditionset ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " SPRITE " , va ( " %d " , extraemblems [ num - 1 ] . sprite ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " COLOR " , va ( " %d " , extraemblems [ num - 1 ] . color ) , UNDO_NONE ) ;
memset ( & extraemblems [ num - 1 ] , 0 , sizeof ( extraemblem_t ) ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
strupr ( word2 ) ;
value = atoi ( word2 ) ; // used for numerical settings
if ( fastcmp ( word , " NAME " ) )
deh_strlcpy ( extraemblems [ num - 1 ] . name , word2 ,
sizeof ( extraemblems [ num - 1 ] . name ) , va ( " Extra emblem %d: name " , num ) ) ;
else if ( fastcmp ( word , " OBJECTIVE " ) )
deh_strlcpy ( extraemblems [ num - 1 ] . description , word2 ,
sizeof ( extraemblems [ num - 1 ] . description ) , va ( " Extra emblem %d: objective " , num ) ) ;
else if ( fastcmp ( word , " CONDITIONSET " ) )
extraemblems [ num - 1 ] . conditionset = ( UINT8 ) value ;
else if ( fastcmp ( word , " SPRITE " ) )
{
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' )
value = word2 [ 0 ] ;
else
value + = ' A ' - 1 ;
if ( value < ' A ' | | value > ' Z ' )
deh_warning ( " Emblem %d: sprite must be from A - Z (1 - 26) " , num ) ;
else
extraemblems [ num - 1 ] . sprite = ( UINT8 ) value ;
}
else if ( fastcmp ( word , " COLOR " ) )
extraemblems [ num - 1 ] . color = get_number ( word2 ) ;
else
deh_warning ( " Extra emblem %d: unknown word '%s' " , num , word ) ;
}
} while ( ! myfeof ( f ) ) ;
if ( ! extraemblems [ num - 1 ] . sprite )
extraemblems [ num - 1 ] . sprite = ' X ' ;
if ( ! extraemblems [ num - 1 ] . color )
extraemblems [ num - 1 ] . color = SKINCOLOR_BLUE ;
Z_Free ( s ) ;
}
static void readunlockable ( MYFILE * f , INT32 num )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * word2 ;
char * tmp ;
INT32 i ;
// Same deal with unlockables, clear all first
DEH_WriteUndoline ( " NAME " , unlockables [ num ] . name , UNDO_NONE ) ;
DEH_WriteUndoline ( " OBJECTIVE " , unlockables [ num ] . objective , UNDO_NONE ) ;
DEH_WriteUndoline ( " HEIGHT " , va ( " %d " , unlockables [ num ] . height ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " CONDITIONSET " , va ( " %d " , unlockables [ num ] . conditionset ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " TYPE " , va ( " %d " , unlockables [ num ] . type ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " NOCECHO " , va ( " %d " , unlockables [ num ] . nocecho ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " NOCHECKLIST " , va ( " %d " , unlockables [ num ] . nochecklist ) , UNDO_NONE ) ;
DEH_WriteUndoline ( " VAR " , va ( " %d " , unlockables [ num ] . variable ) , UNDO_NONE ) ;
memset ( & unlockables [ num ] , 0 , sizeof ( unlockable_t ) ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
strupr ( word2 ) ;
i = atoi ( word2 ) ; // used for numerical settings
if ( fastcmp ( word , " NAME " ) )
deh_strlcpy ( unlockables [ num ] . name , word2 ,
sizeof ( unlockables [ num ] . name ) , va ( " Unlockable %d: name " , num ) ) ;
else if ( fastcmp ( word , " OBJECTIVE " ) )
deh_strlcpy ( unlockables [ num ] . objective , word2 ,
sizeof ( unlockables [ num ] . objective ) , va ( " Unlockable %d: objective " , num ) ) ;
else if ( fastcmp ( word , " HEIGHT " ) )
unlockables [ num ] . height = ( UINT16 ) i ;
else if ( fastcmp ( word , " CONDITIONSET " ) )
unlockables [ num ] . conditionset = ( UINT8 ) i ;
else if ( fastcmp ( word , " NOCECHO " ) )
unlockables [ num ] . nocecho = ( UINT8 ) ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' ) ;
else if ( fastcmp ( word , " NOCHECKLIST " ) )
unlockables [ num ] . nochecklist = ( UINT8 ) ( i | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' ) ;
else if ( fastcmp ( word , " TYPE " ) )
{
if ( fastcmp ( word2 , " NONE " ) )
unlockables [ num ] . type = SECRET_NONE ;
else if ( fastcmp ( word2 , " ITEMFINDER " ) )
unlockables [ num ] . type = SECRET_ITEMFINDER ;
else if ( fastcmp ( word2 , " EMBLEMHINTS " ) )
unlockables [ num ] . type = SECRET_EMBLEMHINTS ;
else if ( fastcmp ( word2 , " PANDORA " ) )
unlockables [ num ] . type = SECRET_PANDORA ;
else if ( fastcmp ( word2 , " CREDITS " ) )
unlockables [ num ] . type = SECRET_CREDITS ;
else if ( fastcmp ( word2 , " RECORDATTACK " ) )
unlockables [ num ] . type = SECRET_RECORDATTACK ;
else if ( fastcmp ( word2 , " NIGHTSMODE " ) )
unlockables [ num ] . type = SECRET_NIGHTSMODE ;
else if ( fastcmp ( word2 , " HEADER " ) )
unlockables [ num ] . type = SECRET_HEADER ;
else if ( fastcmp ( word2 , " LEVELSELECT " ) )
unlockables [ num ] . type = SECRET_LEVELSELECT ;
else if ( fastcmp ( word2 , " WARP " ) )
unlockables [ num ] . type = SECRET_WARP ;
else if ( fastcmp ( word2 , " SOUNDTEST " ) )
unlockables [ num ] . type = SECRET_SOUNDTEST ;
else
unlockables [ num ] . type = ( INT16 ) i ;
}
else if ( fastcmp ( word , " VAR " ) )
{
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' )
i = M_MapNumber ( word2 [ 0 ] , word2 [ 1 ] ) ;
unlockables [ num ] . variable = ( INT16 ) i ;
}
else
deh_warning ( " Unlockable %d: unknown word '%s' " , num + 1 , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
# define PARAMCHECK(n) do { if (!params[n]) { deh_warning("Too few parameters, need %d", n); return; }} while (0)
static void readcondition ( UINT8 set , UINT32 id , char * word2 )
{
INT32 i ;
char * params [ 4 ] ; // condition, requirement, extra info, extra info
char * spos ;
conditiontype_t ty ;
INT32 re ;
INT16 x1 = 0 , x2 = 0 ;
INT32 offset = 0 ;
spos = strtok ( word2 , " " ) ;
for ( i = 0 ; i < 4 ; + + i )
{
if ( spos ! = NULL )
{
params [ i ] = spos ;
spos = strtok ( NULL , " " ) ;
}
else
params [ i ] = NULL ;
}
if ( ! params [ 0 ] )
{
deh_warning ( " condition line is empty " ) ;
return ;
}
if ( fastcmp ( params [ 0 ] , " PLAYTIME " ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_PLAYTIME ;
re = atoi ( params [ 1 ] ) ;
}
else if ( fastcmp ( params [ 0 ] , " GAMECLEAR " )
| | ( + + offset & & fastcmp ( params [ 0 ] , " ALLEMERALDS " ) )
| | ( + + offset & & fastcmp ( params [ 0 ] , " ULTIMATECLEAR " ) ) )
{
ty = UC_GAMECLEAR + offset ;
re = ( params [ 1 ] ) ? atoi ( params [ 1 ] ) : 1 ;
}
else if ( ( offset = 0 ) | | fastcmp ( params [ 0 ] , " OVERALLSCORE " )
| | ( + + offset & & fastcmp ( params [ 0 ] , " OVERALLTIME " ) )
| | ( + + offset & & fastcmp ( params [ 0 ] , " OVERALLRINGS " ) ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_OVERALLSCORE + offset ;
re = atoi ( params [ 1 ] ) ;
}
else if ( ( offset = 0 ) | | fastcmp ( params [ 0 ] , " MAPVISITED " )
| | ( + + offset & & fastcmp ( params [ 0 ] , " MAPBEATEN " ) )
| | ( + + offset & & fastcmp ( params [ 0 ] , " MAPALLEMERALDS " ) )
| | ( + + offset & & fastcmp ( params [ 0 ] , " MAPULTIMATE " ) )
| | ( + + offset & & fastcmp ( params [ 0 ] , " MAPPERFECT " ) ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_MAPVISITED + offset ;
// Convert to map number if it appears to be one
if ( params [ 1 ] [ 0 ] > = ' A ' & & params [ 1 ] [ 0 ] < = ' Z ' )
re = M_MapNumber ( params [ 1 ] [ 0 ] , params [ 1 ] [ 1 ] ) ;
else
re = atoi ( params [ 1 ] ) ;
if ( re < 0 | | re > = NUMMAPS )
{
deh_warning ( " Level number %d out of range (1 - %d) " , re , NUMMAPS ) ;
return ;
}
}
else if ( ( offset = 0 ) | | fastcmp ( params [ 0 ] , " MAPSCORE " )
| | ( + + offset & & fastcmp ( params [ 0 ] , " MAPTIME " ) )
| | ( + + offset & & fastcmp ( params [ 0 ] , " MAPRINGS " ) ) )
{
PARAMCHECK ( 2 ) ;
ty = UC_MAPSCORE + offset ;
re = atoi ( params [ 2 ] ) ;
// Convert to map number if it appears to be one
if ( params [ 1 ] [ 0 ] > = ' A ' & & params [ 1 ] [ 0 ] < = ' Z ' )
x1 = ( INT16 ) M_MapNumber ( params [ 1 ] [ 0 ] , params [ 1 ] [ 1 ] ) ;
else
x1 = ( INT16 ) atoi ( params [ 1 ] ) ;
if ( x1 < 0 | | x1 > = NUMMAPS )
{
deh_warning ( " Level number %d out of range (1 - %d) " , re , NUMMAPS ) ;
return ;
}
}
else if ( ( offset = 0 ) | | fastcmp ( params [ 0 ] , " NIGHTSSCORE " )
| | ( + + offset & & fastcmp ( params [ 0 ] , " NIGHTSTIME " ) )
| | ( + + offset & & fastcmp ( params [ 0 ] , " NIGHTSGRADE " ) ) )
{
PARAMCHECK ( 2 ) ; // one optional one
ty = UC_NIGHTSSCORE + offset ;
re = atoi ( params [ 2 + ! ! ( params [ 3 ] ) ] ) ;
// Convert to map number if it appears to be one
if ( params [ 1 ] [ 0 ] > = ' A ' & & params [ 1 ] [ 0 ] < = ' Z ' )
x1 = ( INT16 ) M_MapNumber ( params [ 1 ] [ 0 ] , params [ 1 ] [ 1 ] ) ;
else
x1 = ( INT16 ) atoi ( params [ 1 ] ) ;
if ( x1 < 0 | | x1 > = NUMMAPS )
{
deh_warning ( " Level number %d out of range (1 - %d) " , re , NUMMAPS ) ;
return ;
}
// Mare number (0 for overall)
if ( params [ 3 ] ) // Only if we actually got 3 params (so the second one == mare and not requirement)
x2 = ( INT16 ) atoi ( params [ 2 ] ) ;
else
x2 = 0 ;
}
else if ( fastcmp ( params [ 0 ] , " TRIGGER " ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_TRIGGER ;
re = atoi ( params [ 1 ] ) ;
// constrained by 32 bits
if ( re < 0 | | re > 31 )
{
deh_warning ( " Trigger ID %d out of range (0 - 31) " , re ) ;
return ;
}
}
else if ( fastcmp ( params [ 0 ] , " TOTALEMBLEMS " ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_TOTALEMBLEMS ;
re = atoi ( params [ 1 ] ) ;
}
else if ( fastcmp ( params [ 0 ] , " EMBLEM " ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_EMBLEM ;
re = atoi ( params [ 1 ] ) ;
if ( re < = 0 | | re > MAXEMBLEMS )
{
deh_warning ( " Emblem %d out of range (1 - %d) " , re , MAXEMBLEMS ) ;
return ;
}
}
else if ( fastcmp ( params [ 0 ] , " EXTRAEMBLEM " ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_EXTRAEMBLEM ;
re = atoi ( params [ 1 ] ) ;
if ( re < = 0 | | re > MAXEXTRAEMBLEMS )
{
deh_warning ( " Extra emblem %d out of range (1 - %d) " , re , MAXEXTRAEMBLEMS ) ;
return ;
}
}
else if ( fastcmp ( params [ 0 ] , " CONDITIONSET " ) )
{
PARAMCHECK ( 1 ) ;
ty = UC_CONDITIONSET ;
re = atoi ( params [ 1 ] ) ;
if ( re < = 0 | | re > MAXCONDITIONSETS )
{
deh_warning ( " Condition set %d out of range (1 - %d) " , re , MAXCONDITIONSETS ) ;
return ;
}
}
else
{
deh_warning ( " Invalid condition name %s " , params [ 0 ] ) ;
return ;
}
M_AddRawCondition ( set , ( UINT8 ) id , ty , re , x1 , x2 ) ;
}
# undef PARAMCHECK
static void readconditionset ( MYFILE * f , UINT8 setnum )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * word2 ;
char * tmp ;
UINT8 id ;
UINT8 previd = 0 ;
M_ClearConditionSet ( setnum ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
strupr ( word2 ) ;
if ( fastncmp ( word , " CONDITION " , 9 ) )
{
id = ( UINT8 ) atoi ( word + 9 ) ;
if ( id = = 0 )
{
deh_warning ( " Condition set %d: unknown word '%s' " , setnum , word ) ;
continue ;
}
else if ( previd > id )
{
// out of order conditions can cause problems, so enforce proper order
deh_warning ( " Condition set %d: conditions are out of order, ignoring this line " , setnum ) ;
continue ;
}
previd = id ;
readcondition ( setnum , id , word2 ) ;
}
else
deh_warning ( " Condition set %d: unknown word '%s' " , setnum , word ) ;
}
} while ( ! myfeof ( f ) ) ; // finish when the line is empty
Z_Free ( s ) ;
}
static void readtexture ( MYFILE * f , const char * name )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * word2 ;
char * tmp ;
INT32 i , j , value ;
UINT16 width = 0 , height = 0 ;
INT16 patchcount = 0 ;
texture_t * texture ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
value = searchvalue ( s ) ;
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
word2 = strtok ( NULL , " " ) ;
if ( word2 )
strupr ( word2 ) ;
else
break ;
// Width of the texture.
if ( fastcmp ( word , " WIDTH " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , width ) , UNDO_NONE ) ;
width = SHORT ( ( UINT16 ) value ) ;
}
// Height of the texture.
else if ( fastcmp ( word , " HEIGHT " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , height ) , UNDO_NONE ) ;
height = SHORT ( ( UINT16 ) value ) ;
}
// Number of patches the texture has.
else if ( fastcmp ( word , " NUMPATCHES " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , patchcount ) , UNDO_NONE ) ;
patchcount = SHORT ( ( UINT16 ) value ) ;
}
else
deh_warning ( " readtexture: unknown word '%s' " , word ) ;
}
} while ( ! myfeof ( f ) ) ;
// Error checking.
if ( ! width )
I_Error ( " Texture %s has no width! \n " , name ) ;
if ( ! height )
I_Error ( " Texture %s has no height! \n " , name ) ;
if ( ! patchcount )
I_Error ( " Texture %s has no patches! \n " , name ) ;
// Allocate memory for the texture, and fill in information.
texture = Z_Calloc ( sizeof ( texture_t ) + ( sizeof ( texpatch_t ) * SHORT ( patchcount ) ) , PU_STATIC , NULL ) ;
M_Memcpy ( texture - > name , name , sizeof ( texture - > name ) ) ;
texture - > width = width ;
texture - > height = height ;
texture - > patchcount = patchcount ;
texture - > holes = false ;
// Fill out the texture patches, to allow them to be detected
// accurately by readpatch.
for ( i = 0 ; i < patchcount ; i + + )
{
texture - > patches [ i ] . originx = 0 ;
texture - > patches [ i ] . originy = 0 ;
texture - > patches [ i ] . wad = UINT16_MAX ;
texture - > patches [ i ] . lump = UINT16_MAX ;
}
// Jump to the next empty texture entry.
i = 0 ;
while ( textures [ i ] )
i + + ;
// Fill the global texture buffer entries.
j = 1 ;
while ( j < < 1 < = texture - > width )
j < < = 1 ;
textures [ i ] = texture ;
texturewidthmask [ i ] = j - 1 ;
textureheight [ i ] = texture - > height < < FRACBITS ;
// Clean up.
Z_Free ( s ) ;
}
static void readpatch ( MYFILE * f , const char * name , UINT16 wad )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * word2 ;
char * tmp ;
INT32 i = 0 , j = 0 , value ;
texpatch_t patch = { 0 , 0 , UINT16_MAX , UINT16_MAX } ;
// Jump to the texture this patch belongs to, which,
// coincidentally, is always the last one on the buffer cache.
while ( textures [ i + 1 ] )
i + + ;
// Jump to the next empty patch entry.
while ( memcmp ( & ( textures [ i ] - > patches [ j ] ) , & patch , sizeof ( patch ) ) )
j + + ;
patch . wad = wad ;
// Set the texture number, but only if the lump exists.
if ( ( patch . lump = W_CheckNumForNamePwad ( name , wad , 0 ) ) = = INT16_MAX )
I_Error ( " readpatch: Missing patch in texture %s " , textures [ i ] - > name ) ;
// note: undoing this patch will be done by other means
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
value = searchvalue ( s ) ;
word = strtok ( s , " " ) ;
if ( word )
strupr ( word ) ;
else
break ;
word2 = strtok ( NULL , " " ) ;
if ( word2 )
strupr ( word2 ) ;
else
break ;
// X position of the patch in the texture.
if ( fastcmp ( word , " X " ) )
{
//DEH_WriteUndoline(word, va("%d", patch->originx), UNDO_NONE);
patch . originx = ( INT16 ) value ;
}
// Y position of the patch in the texture.
else if ( fastcmp ( word , " Y " ) )
{
//DEH_WriteUndoline(word, va("%d", patch->originy), UNDO_NONE);
patch . originy = ( INT16 ) value ;
}
else
deh_warning ( " readpatch: unknown word '%s' " , word ) ;
}
} while ( ! myfeof ( f ) ) ;
// Error checking.
/* // Irrelevant. Origins cannot be unsigned.
if ( patch . originx = = UINT16_MAX )
I_Error ( " Patch %s on texture %s has no X position! \n " , name , textures [ i ] - > name ) ;
if ( patch . originy = = UINT16_MAX )
I_Error ( " Patch %s on texture %s has no Y position! \n " , name , textures [ i ] - > name ) ;
*/
// Set the patch as that patch number.
textures [ i ] - > patches [ j ] = patch ;
// Clean up.
Z_Free ( s ) ;
}
static void readmaincfg ( MYFILE * f )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * word2 ;
char * tmp ;
INT32 value ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
strupr ( word2 ) ;
value = atoi ( word2 ) ; // used for numerical settings
if ( fastcmp ( word , " EXECCFG " ) )
COM_BufAddText ( va ( " exec %s \n " , word2 ) ) ;
else if ( fastcmp ( word , " SPSTAGE_START " ) )
{
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' )
value = M_MapNumber ( word2 [ 0 ] , word2 [ 1 ] ) ;
else
value = get_number ( word2 ) ;
DEH_WriteUndoline ( word , va ( " %d " , spstage_start ) , UNDO_NONE ) ;
spstage_start = ( INT16 ) value ;
}
else if ( fastcmp ( word , " SSTAGE_START " ) )
{
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' )
value = M_MapNumber ( word2 [ 0 ] , word2 [ 1 ] ) ;
else
value = get_number ( word2 ) ;
DEH_WriteUndoline ( word , va ( " %d " , sstage_start ) , UNDO_NONE ) ;
sstage_start = ( INT16 ) value ;
sstage_end = ( INT16 ) ( sstage_start + 6 ) ; // 7 special stages total
}
else if ( fastcmp ( word , " USENIGHTSSS " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , useNightsSS ) , UNDO_NONE ) ;
useNightsSS = ( UINT8 ) ( value | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' ) ;
}
else if ( fastcmp ( word , " REDTEAM " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , skincolor_redteam ) , UNDO_NONE ) ;
skincolor_redteam = ( UINT8 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " BLUETEAM " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , skincolor_blueteam ) , UNDO_NONE ) ;
skincolor_blueteam = ( UINT8 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " REDRING " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , skincolor_redring ) , UNDO_NONE ) ;
skincolor_redring = ( UINT8 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " BLUERING " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , skincolor_bluering ) , UNDO_NONE ) ;
skincolor_bluering = ( UINT8 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " INVULNTICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , invulntics ) , UNDO_NONE ) ;
invulntics = ( UINT16 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " SNEAKERTICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , sneakertics ) , UNDO_NONE ) ;
sneakertics = ( UINT16 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " FLASHINGTICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , flashingtics ) , UNDO_NONE ) ;
flashingtics = ( UINT16 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " TAILSFLYTICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , tailsflytics ) , UNDO_NONE ) ;
tailsflytics = ( UINT16 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " UNDERWATERTICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , underwatertics ) , UNDO_NONE ) ;
underwatertics = ( UINT16 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " SPACETIMETICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , spacetimetics ) , UNDO_NONE ) ;
spacetimetics = ( UINT16 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " EXTRALIFETICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , extralifetics ) , UNDO_NONE ) ;
extralifetics = ( UINT16 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " GAMEOVERTICS " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , gameovertics ) , UNDO_NONE ) ;
gameovertics = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " INTROTOPLAY " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , introtoplay ) , UNDO_NONE ) ;
introtoplay = ( UINT8 ) get_number ( word2 ) ;
// range check, you morons.
if ( introtoplay > 128 )
introtoplay = 128 ;
}
else if ( fastcmp ( word , " LOOPTITLE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , looptitle ) , UNDO_NONE ) ;
looptitle = ( boolean ) ( value | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' ) ;
}
else if ( fastcmp ( word , " TITLESCROLLSPEED " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , titlescrollspeed ) , UNDO_NONE ) ;
titlescrollspeed = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " CREDITSCUTSCENE " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , creditscutscene ) , UNDO_NONE ) ;
creditscutscene = ( UINT8 ) get_number ( word2 ) ;
// range check, you morons.
if ( creditscutscene > 128 )
creditscutscene = 128 ;
}
else if ( fastcmp ( word , " DISABLESPEEDADJUST " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , disableSpeedAdjust ) , UNDO_NONE ) ;
disableSpeedAdjust = ( UINT8 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " NUMDEMOS " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , numDemos ) , UNDO_NONE ) ;
numDemos = ( UINT8 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " DEMODELAYTIME " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , demoDelayTime ) , UNDO_NONE ) ;
demoDelayTime = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " DEMOIDLETIME " ) )
{
DEH_WriteUndoline ( word , va ( " %d " , demoIdleTime ) , UNDO_NONE ) ;
demoIdleTime = get_number ( word2 ) ;
}
else if ( fastcmp ( word , " USE1UPSOUND " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , use1upSound ) , UNDO_NONE ) ;
use1upSound = ( UINT8 ) ( value | | word2 [ 0 ] = = ' T ' | | word2 [ 0 ] = = ' Y ' ) ;
}
else if ( fastcmp ( word , " MAXXTRALIFE " ) )
{
DEH_WriteUndoline ( word , va ( " %u " , maxXtraLife ) , UNDO_NONE ) ;
maxXtraLife = ( UINT8 ) get_number ( word2 ) ;
}
else if ( fastcmp ( word , " GAMEDATA " ) )
{
size_t filenamelen ;
// Check the data filename so that mods
// can't write arbitrary files.
if ( ! GoodDataFileName ( word2 ) )
I_Error ( " Maincfg: bad data file name '%s' \n " , word2 ) ;
G_SaveGameData ( ) ;
DEH_WriteUndoline ( word , gamedatafilename , UNDO_NONE ) ;
strlcpy ( gamedatafilename , word2 , sizeof ( gamedatafilename ) ) ;
strlwr ( gamedatafilename ) ;
savemoddata = true ;
// Also save a time attack folder
filenamelen = strlen ( gamedatafilename ) - 4 ; // Strip off the extension
strncpy ( timeattackfolder , gamedatafilename , min ( filenamelen , sizeof ( timeattackfolder ) ) ) ;
timeattackfolder [ min ( filenamelen , sizeof ( timeattackfolder ) - 1 ) ] = ' \0 ' ;
strncpy ( savegamename , timeattackfolder , sizeof ( timeattackfolder ) ) ;
strlcat ( savegamename , " %u.ssg " , sizeof ( savegamename ) ) ;
gamedataadded = true ;
}
else if ( fastcmp ( word , " RESETDATA " ) )
{
DEH_WriteUndoline ( word , " 0 " , UNDO_TODO ) ; /// \todo
P_ResetData ( value ) ;
}
else if ( fastcmp ( word , " CUSTOMVERSION " ) )
{
DEH_WriteUndoline ( word , customversionstring , UNDO_NONE ) ;
strlcpy ( customversionstring , word2 , sizeof ( customversionstring ) ) ;
}
else
deh_warning ( " Maincfg: unknown word '%s' " , word ) ;
}
} while ( ! myfeof ( f ) ) ;
Z_Free ( s ) ;
}
static void readwipes ( MYFILE * f )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word = s ;
char * pword = word ;
char * word2 ;
char * tmp ;
INT32 value ;
INT32 wipeoffset ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
// First remove trailing newline, if there is one
tmp = strchr ( s , ' \n ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
tmp = strchr ( s , ' # ' ) ;
if ( tmp )
* tmp = ' \0 ' ;
if ( s = = tmp )
continue ; // Skip comment lines, but don't break.
// Get the part before the " = "
tmp = strchr ( s , ' = ' ) ;
* ( tmp - 1 ) = ' \0 ' ;
strupr ( word ) ;
// Now get the part after
word2 = tmp + = 2 ;
value = atoi ( word2 ) ; // used for numerical settings
if ( value < - 1 | | value > 99 )
{
deh_warning ( " Wipes: bad value '%s' " , word2 ) ;
continue ;
}
else if ( value = = - 1 )
value = UINT8_MAX ;
// error catching
wipeoffset = - 1 ;
if ( fastncmp ( word , " LEVEL_ " , 6 ) )
{
pword = word + 6 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_level_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_level_final ;
}
else if ( fastncmp ( word , " INTERMISSION_ " , 13 ) )
{
pword = word + 13 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_intermission_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_intermission_final ;
}
else if ( fastncmp ( word , " SPECINTER_ " , 10 ) )
{
pword = word + 10 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_specinter_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_specinter_final ;
}
else if ( fastncmp ( word , " MULTINTER_ " , 10 ) )
{
pword = word + 10 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_multinter_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_multinter_final ;
}
else if ( fastncmp ( word , " CONTINUING_ " , 11 ) )
{
pword = word + 11 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_continuing_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_continuing_final ;
}
else if ( fastncmp ( word , " TITLESCREEN_ " , 12 ) )
{
pword = word + 12 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_titlescreen_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_titlescreen_final ;
}
else if ( fastncmp ( word , " TIMEATTACK_ " , 11 ) )
{
pword = word + 11 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_timeattack_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_timeattack_final ;
}
else if ( fastncmp ( word , " CREDITS_ " , 8 ) )
{
pword = word + 8 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_credits_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_credits_final ;
else if ( fastcmp ( pword , " INTERMEDIATE " ) )
wipeoffset = wipe_credits_intermediate ;
}
else if ( fastncmp ( word , " EVALUATION_ " , 11 ) )
{
pword = word + 11 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_evaluation_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_evaluation_final ;
}
else if ( fastncmp ( word , " GAMEEND_ " , 8 ) )
{
pword = word + 8 ;
if ( fastcmp ( pword , " TOBLACK " ) )
wipeoffset = wipe_gameend_toblack ;
else if ( fastcmp ( pword , " FINAL " ) )
wipeoffset = wipe_gameend_final ;
}
if ( wipeoffset < 0 )
{
deh_warning ( " Wipes: unknown word '%s' " , word ) ;
continue ;
}
if ( value = = UINT8_MAX // Cannot disable non-toblack wipes (or the level toblack wipe)
& & ( wipeoffset < = wipe_level_toblack | | wipeoffset > = wipe_level_final ) )
{
deh_warning ( " Wipes: can't disable wipe of type '%s' " , word ) ;
continue ;
}
wipedefs [ wipeoffset ] = ( UINT8 ) value ;
}
} while ( ! myfeof ( f ) ) ;
Z_Free ( s ) ;
}
// Used when you do something invalid like read a bad item number
// to prevent extra unnecessary errors
static void ignorelines ( MYFILE * f )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
do
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
if ( s [ 0 ] = = ' \n ' )
break ;
}
} while ( ! myfeof ( f ) ) ;
Z_Free ( s ) ;
}
static void DEH_LoadDehackedFile ( MYFILE * f , UINT16 wad )
{
char * s = Z_Malloc ( MAXLINELEN , PU_STATIC , NULL ) ;
char * word ;
char * word2 ;
INT32 i ;
// do a copy of this for cross references probleme
//XBOXSTATIC actionf_t saveactions[NUMSTATES];
//XBOXSTATIC const char *savesprnames[NUMSPRITES];
XBOXSTATIC const char * savesfxnames [ NUMSFX ] ;
if ( ! deh_loaded )
initfreeslots ( ) ;
deh_num_warning = 0 ;
// save values for cross reference
/*
for ( i = 0 ; i < NUMSTATES ; i + + )
saveactions [ i ] = states [ i ] . action ;
for ( i = 0 ; i < NUMSPRITES ; i + + )
savesprnames [ i ] = sprnames [ i ] ;
*/
for ( i = 0 ; i < NUMSFX ; i + + )
savesfxnames [ i ] = S_sfx [ i ] . name ;
gamedataadded = false ;
// it doesn't test the version of SRB2 and version of dehacked file
dbg_line = - 1 ; // start at -1 so the first line is 0.
while ( ! myfeof ( f ) )
{
XBOXSTATIC char origpos [ 128 ] ;
INT32 size = 0 ;
char * traverse ;
myfgets ( s , MAXLINELEN , f ) ;
if ( s [ 0 ] = = ' \n ' | | s [ 0 ] = = ' # ' )
continue ;
traverse = s ;
while ( traverse [ 0 ] ! = ' \n ' )
{
traverse + + ;
size + + ;
}
strncpy ( origpos , s , size ) ;
origpos [ size ] = ' \0 ' ;
if ( NULL ! = ( word = strtok ( s , " " ) ) ) {
strupr ( word ) ;
if ( word [ strlen ( word ) - 1 ] = = ' \n ' )
word [ strlen ( word ) - 1 ] = ' \0 ' ;
}
if ( word )
{
if ( fastcmp ( word , " FREESLOT " ) )
{
readfreeslots ( f ) ;
continue ;
}
else if ( fastcmp ( word , " MAINCFG " ) )
{
readmaincfg ( f ) ;
DEH_WriteUndoline ( word , " " , UNDO_HEADER ) ;
continue ;
}
else if ( fastcmp ( word , " WIPES " ) )
{
readwipes ( f ) ;
DEH_WriteUndoline ( word , " " , UNDO_HEADER ) ;
continue ;
}
word2 = strtok ( NULL , " " ) ;
if ( fastcmp ( word , " CHARACTER " ) )
{
if ( word2 ) {
strupr ( word2 ) ;
if ( word2 [ strlen ( word2 ) - 1 ] = = ' \n ' )
word2 [ strlen ( word2 ) - 1 ] = ' \0 ' ;
i = atoi ( word2 ) ;
} else
i = 0 ;
if ( i > = 0 & & i < 32 )
readPlayer ( f , i ) ;
else
{
deh_warning ( " Character %d out of range (0 - 31) " , i ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
continue ;
}
if ( word2 )
{
strupr ( word2 ) ;
if ( word2 [ strlen ( word2 ) - 1 ] = = ' \n ' )
word2 [ strlen ( word2 ) - 1 ] = ' \0 ' ;
i = atoi ( word2 ) ;
if ( fastcmp ( word , " TEXTURE " ) )
{
// Read texture from spec file.
readtexture ( f , word2 ) ;
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " PATCH " ) )
{
// Read patch from spec file.
readpatch ( f , word2 , wad ) ;
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " THING " ) | | fastcmp ( word , " MOBJ " ) | | fastcmp ( word , " OBJECT " ) )
{
if ( i = = 0 & & word2 [ 0 ] ! = ' 0 ' ) // If word2 isn't a number
i = get_mobjtype ( word2 ) ; // find a thing by name
if ( i < NUMMOBJTYPES & & i > = 0 )
readthing ( f , i ) ;
else
{
deh_warning ( " Thing %d out of range (0 - %d) " , i , NUMMOBJTYPES - 1 ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " MODBY " ) )
{
memset ( modcreditname , 0 , sizeof ( char ) * 32 ) ;
strcpy ( modcreditname , origpos + 6 ) ;
modcredits = true ;
}
/* else if (fastcmp(word, "ANIMTEX"))
{
readAnimTex ( f , i ) ;
} */
else if ( fastcmp ( word , " LIGHT " ) )
{
# ifdef HWRENDER
// TODO: Read lights by name
if ( i > 0 & & i < NUMLIGHTS )
readlight ( f , i ) ;
else
{
deh_warning ( " Light number %d out of range (1 - %d) " , i , NUMLIGHTS - 1 ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
# endif
}
else if ( fastcmp ( word , " SPRITE " ) )
{
# ifdef HWRENDER
if ( i = = 0 & & word2 [ 0 ] ! = ' 0 ' ) // If word2 isn't a number
i = get_sprite ( word2 ) ; // find a sprite by name
if ( i < NUMSPRITES & & i > = 0 )
readspritelight ( f , i ) ;
else
{
deh_warning ( " Sprite number %d out of range (0 - %d) " , i , NUMSPRITES - 1 ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
# endif
}
else if ( fastcmp ( word , " LEVEL " ) )
{
// Support using the actual map name,
// i.e., Level AB, Level FZ, etc.
// Convert to map number
if ( word2 [ 0 ] > = ' A ' & & word2 [ 0 ] < = ' Z ' )
i = M_MapNumber ( word2 [ 0 ] , word2 [ 1 ] ) ;
if ( i > 0 & & i < = NUMMAPS )
readlevelheader ( f , i ) ;
else
{
deh_warning ( " Level number %d out of range (1 - %d) " , i , NUMMAPS ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " CUTSCENE " ) )
{
if ( i > 0 & & i < 129 )
readcutscene ( f , i - 1 ) ;
else
{
deh_warning ( " Cutscene number %d out of range (1 - 128) " , i ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " FRAME " ) | | fastcmp ( word , " STATE " ) )
{
if ( i = = 0 & & word2 [ 0 ] ! = ' 0 ' ) // If word2 isn't a number
i = get_state ( word2 ) ; // find a state by name
if ( i < NUMSTATES & & i > = 0 )
readframe ( f , i ) ;
else
{
deh_warning ( " Frame %d out of range (0 - %d) " , i , NUMSTATES - 1 ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
// <Callum> Added translations to this just in case its re-enabled
/* else if (fastcmp(word, "POINTER"))
{
word = strtok ( NULL , " " ) ; // get frame
word = strtok ( NULL , " ) " ) ;
if ( word )
{
i = atoi ( word ) ;
if ( i < NUMSTATES & & i > = 0 )
{
if ( myfgets ( s , MAXLINELEN , f ) )
states [ i ] . action = saveactions [ searchvalue ( s ) ] ;
}
else
{
deh_warning ( " Pointer: Frame %d doesn't exist " , i ) ;
ignorelines ( f ) ;
}
}
else
deh_warning ( " pointer (Frame %d) : missing ')' " , i ) ;
} */
else if ( fastcmp ( word , " SOUND " ) )
{
if ( i = = 0 & & word2 [ 0 ] ! = ' 0 ' ) // If word2 isn't a number
i = get_sfx ( word2 ) ; // find a sound by name
if ( i < NUMSFX & & i > = 0 )
readsound ( f , i , savesfxnames ) ;
else
{
deh_warning ( " Sound %d out of range (0 - %d) " , i , NUMSFX - 1 ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
/* else if (fastcmp(word, "SPRITE"))
{
if ( i < NUMSPRITES & & i > = 0 )
{
if ( myfgets ( s , MAXLINELEN , f ) )
{
INT32 k ;
k = ( searchvalue ( s ) - 151328 ) / 8 ;
if ( k > = 0 & & k < NUMSPRITES )
sprnames [ i ] = savesprnames [ k ] ;
else
{
deh_warning ( " Sprite %d: offset out of bounds " , i ) ;
ignorelines ( f ) ;
}
}
}
else
deh_warning ( " Sprite %d doesn't exist " , i ) ;
} */
else if ( fastcmp ( word , " HUDITEM " ) )
{
if ( i = = 0 & & word2 [ 0 ] ! = ' 0 ' ) // If word2 isn't a number
i = get_huditem ( word2 ) ; // find a huditem by name
if ( i > = 0 & & i < NUMHUDITEMS )
readhuditem ( f , i ) ;
else
{
deh_warning ( " HUD item number %d out of range (0 - %d) " , i , NUMHUDITEMS - 1 ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " EMBLEM " ) )
{
if ( ! gamedataadded )
{
deh_warning ( " You must define a custom gamedata to use \" %s \" " , word ) ;
ignorelines ( f ) ;
}
else if ( i > 0 & & i < = MAXEMBLEMS )
{
if ( numemblems < i )
numemblems = i ;
reademblemdata ( f , i ) ;
}
else
{
deh_warning ( " Emblem number %d out of range (1 - %d) " , i , MAXEMBLEMS ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " EXTRAEMBLEM " ) )
{
if ( ! gamedataadded )
{
deh_warning ( " You must define a custom gamedata to use \" %s \" " , word ) ;
ignorelines ( f ) ;
}
else if ( i > 0 & & i < = MAXEXTRAEMBLEMS )
{
if ( numextraemblems < i )
numextraemblems = i ;
readextraemblemdata ( f , i ) ;
}
else
{
deh_warning ( " Extra emblem number %d out of range (1 - %d) " , i , MAXEXTRAEMBLEMS ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " UNLOCKABLE " ) )
{
if ( ! gamedataadded )
{
deh_warning ( " You must define a custom gamedata to use \" %s \" " , word ) ;
ignorelines ( f ) ;
}
else if ( i > 0 & & i < = MAXUNLOCKABLES )
readunlockable ( f , i - 1 ) ;
else
{
deh_warning ( " Unlockable number %d out of range (1 - %d) " , i , MAXUNLOCKABLES ) ;
ignorelines ( f ) ;
}
DEH_WriteUndoline ( word , word2 , UNDO_HEADER ) ;
}
else if ( fastcmp ( word , " CONDITIONSET " ) )
{
if ( ! gamedataadded )
{
deh_warning ( " You must define a custom gamedata to use \" %s \" " , word ) ;
ignorelines ( f ) ;
}
else if ( i > 0 & & i < = MAXCONDITIONSETS )
readconditionset ( f , ( UINT8 ) i ) ;
else
{
deh_warning ( " Condition set number %d out of range (1 - %d) " , i , MAXCONDITIONSETS ) ;
ignorelines ( f ) ;
}
// no undo support for this insanity yet
//DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if ( fastcmp ( word , " SRB2 " ) )
{
INT32 ver = searchvalue ( strtok ( NULL , " \n " ) ) ;
if ( ver ! = PATCHVERSION )
deh_warning ( " Patch is for SRB2 version %d, \n only version %d is supported " , ver , PATCHVERSION ) ;
//DEH_WriteUndoline(word, va("%d", ver), UNDO_NONE);
}
// Clear all data in certain locations (mostly for unlocks)
// Unless you REALLY want to piss people off,
// define a custom gamedata /before/ doing this!!
// (then again, modifiedgame will prevent game data saving anyway)
else if ( fastcmp ( word , " CLEAR " ) )
{
boolean clearall = ( fastcmp ( word2 , " ALL " ) ) ;
if ( ! gamedataadded )
{
deh_warning ( " You must define a custom gamedata to use \" %s \" " , word ) ;
continue ;
}
if ( clearall | | fastcmp ( word2 , " UNLOCKABLES " ) )
memset ( & unlockables , 0 , sizeof ( unlockables ) ) ;
if ( clearall | | fastcmp ( word2 , " EMBLEMS " ) )
{
memset ( & emblemlocations , 0 , sizeof ( emblemlocations ) ) ;
numemblems = 0 ;
}
if ( clearall | | fastcmp ( word2 , " EXTRAEMBLEMS " ) )
{
memset ( & extraemblems , 0 , sizeof ( extraemblems ) ) ;
numextraemblems = 0 ;
}
if ( clearall | | fastcmp ( word2 , " CONDITIONSETS " ) )
clear_conditionsets ( ) ;
if ( clearall | | fastcmp ( word2 , " LEVELS " ) )
clear_levels ( ) ;
}
else
deh_warning ( " Unknown word: %s " , word ) ;
}
else
deh_warning ( " missing argument for '%s' " , word ) ;
}
else
deh_warning ( " No word in this line: %s " , s ) ;
} // end while
if ( gamedataadded )
G_LoadGameData ( ) ;
dbg_line = - 1 ;
if ( deh_num_warning )
{
CONS_Printf ( M_GetText ( " %d warning%s in the SOC lump \n " ) , deh_num_warning , deh_num_warning = = 1 ? " " : " s " ) ;
if ( devparm ) {
I_Error ( " %s%s " , va ( M_GetText ( " %d warning%s in the SOC lump \n " ) , deh_num_warning , deh_num_warning = = 1 ? " " : " s " ) , M_GetText ( " See log.txt for details. \n " ) ) ;
//while (!I_GetKey())
//I_OsPolling();
}
}
deh_loaded = true ;
Z_Free ( s ) ;
}
// read dehacked lump in a wad (there is special trick for for deh
// file that are converted to wad in w_wad.c)
void DEH_LoadDehackedLumpPwad ( UINT16 wad , UINT16 lump )
{
MYFILE f ;
# ifdef DELFILE
unsocwad = wad ;
# endif
f . wad = wad ;
f . size = W_LumpLengthPwad ( wad , lump ) ;
f . data = Z_Malloc ( f . size + 1 , PU_STATIC , NULL ) ;
W_ReadLumpPwad ( wad , lump , f . data ) ;
f . curpos = f . data ;
f . data [ f . size ] = 0 ;
DEH_LoadDehackedFile ( & f , wad ) ;
DEH_WriteUndoline ( va ( " # uload for wad: %u, lump: %u " , wad , lump ) , NULL , UNDO_DONE ) ;
Z_Free ( f . data ) ;
}
void DEH_LoadDehackedLump ( lumpnum_t lumpnum )
{
DEH_LoadDehackedLumpPwad ( WADFILENUM ( lumpnum ) , LUMPNUM ( lumpnum ) ) ;
}
# ifdef DELFILE
# define DUMPUNDONE
// read (un)dehacked lump in wad's memory
void DEH_UnloadDehackedWad ( UINT16 wad )
{
undehacked_t * tmp , * curundo = unsocdata [ wad ] ;
MYFILE f ;
size_t len = 0 ;
char * data ;
# ifdef DUMPUNDONE
FILE * UNDO = fopen ( " undo.soc " , " wt " ) ;
# endif
CONS_Printf ( M_GetText ( " Unloading WAD SOC edits \n " ) ) ;
while ( curundo )
{
data = curundo - > undata ;
curundo = curundo - > next ;
if ( data )
len + = strlen ( data ) ;
len + = 1 ;
# ifdef DUMPUNDONE
if ( UNDO )
{
if ( data )
fprintf ( UNDO , " %s \n " , data ) ;
else
fprintf ( UNDO , " \n " ) ;
}
# endif
}
# ifndef DUMPUNDONE
if ( UNDO ) fclose ( UNDO ) ;
# endif
if ( ! len ) return ;
f . size = len ;
data = f . data = Z_Malloc ( f . size + 1 , PU_STATIC , NULL ) ;
curundo = unsocdata [ wad ] ;
unsocdata [ wad ] = NULL ;
while ( curundo )
{
tmp = curundo ;
curundo = curundo - > next ;
if ( tmp - > undata )
data + = sprintf ( data , " %s \n " , tmp - > undata ) ;
else
data + = sprintf ( data , " \n " ) ;
if ( tmp - > undata ) free ( tmp - > undata ) ;
free ( tmp ) ;
}
f . wad = wad ;
f . curpos = f . data ;
f . data [ f . size ] = 0 ;
disableundo = true ;
DEH_LoadDehackedFile ( & f ) ;
disableundo = false ;
Z_Free ( f . data ) ;
}
# endif //DELFILE
////////////////////////////////////////////////////////////////////////////////
// CRAZY LIST OF STATE NAMES AND ALL FROM HERE DOWN
// TODO: Make this all a seperate file or something, like part of info.c??
// TODO: Read the list from a text lump in a WAD as necessary instead
// or something, don't just keep it all in memory like this.
// TODO: Make the lists public so we can start using actual mobj
// and state names in warning and error messages! :D
// RegEx to generate this from info.h: ^\tS_([^,]+), --> \t"S_\1",
// I am leaving the prefixes solely for clarity to programmers,
// because sadly no one remembers this place while searching for full state names.
static const char * const STATE_LIST [ ] = { // array length left dynamic for sanity testing later.
" S_NULL " ,
" S_UNKNOWN " ,
" S_INVISIBLE " , // state for invisible sprite
" S_SPAWNSTATE " ,
" S_SEESTATE " ,
" S_MELEESTATE " ,
" S_MISSILESTATE " ,
" S_DEATHSTATE " ,
" S_XDEATHSTATE " ,
" S_RAISESTATE " ,
// Thok
" S_THOK " ,
" S_PLAY_STND " ,
" S_PLAY_TAP1 " ,
" S_PLAY_TAP2 " ,
" S_PLAY_RUN1 " ,
" S_PLAY_RUN2 " ,
" S_PLAY_RUN3 " ,
" S_PLAY_RUN4 " ,
" S_PLAY_RUN5 " ,
" S_PLAY_RUN6 " ,
" S_PLAY_RUN7 " ,
" S_PLAY_RUN8 " ,
" S_PLAY_SPD1 " ,
" S_PLAY_SPD2 " ,
" S_PLAY_SPD3 " ,
" S_PLAY_SPD4 " ,
" S_PLAY_ATK1 " ,
" S_PLAY_ATK2 " ,
" S_PLAY_ATK3 " ,
" S_PLAY_ATK4 " ,
" S_PLAY_SPRING " ,
" S_PLAY_FALL1 " ,
" S_PLAY_FALL2 " ,
" S_PLAY_ABL1 " ,
" S_PLAY_ABL2 " ,
" S_PLAY_SPC1 " ,
" S_PLAY_SPC2 " ,
" S_PLAY_SPC3 " ,
" S_PLAY_SPC4 " ,
" S_PLAY_CLIMB1 " ,
" S_PLAY_CLIMB2 " ,
" S_PLAY_CLIMB3 " ,
" S_PLAY_CLIMB4 " ,
" S_PLAY_CLIMB5 " ,
" S_PLAY_GASP " ,
" S_PLAY_PAIN " ,
" S_PLAY_DIE " ,
" S_PLAY_TEETER1 " ,
" S_PLAY_TEETER2 " ,
" S_PLAY_CARRY " ,
" S_PLAY_SUPERSTAND " ,
" S_PLAY_SUPERWALK1 " ,
" S_PLAY_SUPERWALK2 " ,
" S_PLAY_SUPERFLY1 " ,
" S_PLAY_SUPERFLY2 " ,
" S_PLAY_SUPERTEETER " ,
" S_PLAY_SUPERHIT " ,
" S_PLAY_SUPERTRANS1 " ,
" S_PLAY_SUPERTRANS2 " ,
" S_PLAY_SUPERTRANS3 " ,
" S_PLAY_SUPERTRANS4 " ,
" S_PLAY_SUPERTRANS5 " ,
" S_PLAY_SUPERTRANS6 " ,
" S_PLAY_SUPERTRANS7 " ,
" S_PLAY_SUPERTRANS8 " ,
" S_PLAY_SUPERTRANS9 " , // This has special significance in the code. If you add more frames, search for it and make the appropriate changes.
// technically the player goes here but it's an infinite tic state
" S_OBJPLACE_DUMMY " ,
// 1-Up Box Sprites (uses player sprite)
" S_PLAY_BOX1 " ,
" S_PLAY_BOX2 " ,
" S_PLAY_ICON1 " ,
" S_PLAY_ICON2 " ,
" S_PLAY_ICON3 " ,
// Level end sign (uses player sprite)
" S_PLAY_SIGN " ,
// Blue Crawla
" S_POSS_STND " ,
" S_POSS_STND2 " ,
" S_POSS_RUN1 " ,
" S_POSS_RUN2 " ,
" S_POSS_RUN3 " ,
" S_POSS_RUN4 " ,
" S_POSS_RUN5 " ,
" S_POSS_RUN6 " ,
// Red Crawla
" S_SPOS_STND " ,
" S_SPOS_STND2 " ,
" S_SPOS_RUN1 " ,
" S_SPOS_RUN2 " ,
" S_SPOS_RUN3 " ,
" S_SPOS_RUN4 " ,
" S_SPOS_RUN5 " ,
" S_SPOS_RUN6 " ,
// Greenflower Fish
" S_FISH1 " ,
" S_FISH2 " ,
" S_FISH3 " ,
" S_FISH4 " ,
// Buzz (Gold)
" S_BUZZLOOK1 " ,
" S_BUZZLOOK2 " ,
" S_BUZZFLY1 " ,
" S_BUZZFLY2 " ,
// Buzz (Red)
" S_RBUZZLOOK1 " ,
" S_RBUZZLOOK2 " ,
" S_RBUZZFLY1 " ,
" S_RBUZZFLY2 " ,
// AquaBuzz
" S_BBUZZFLY1 " ,
" S_BBUZZFLY2 " ,
// Jetty-Syn Bomber
" S_JETBLOOK1 " ,
" S_JETBLOOK2 " ,
" S_JETBZOOM1 " ,
" S_JETBZOOM2 " ,
// Jetty-Syn Gunner
" S_JETGLOOK1 " ,
" S_JETGLOOK2 " ,
" S_JETGZOOM1 " ,
" S_JETGZOOM2 " ,
" S_JETGSHOOT1 " ,
" S_JETGSHOOT2 " ,
// Crawla Commander
" S_CCOMMAND1 " ,
" S_CCOMMAND2 " ,
" S_CCOMMAND3 " ,
" S_CCOMMAND4 " ,
// Deton
" S_DETON1 " ,
" S_DETON2 " ,
" S_DETON3 " ,
" S_DETON4 " ,
" S_DETON5 " ,
" S_DETON6 " ,
" S_DETON7 " ,
" S_DETON8 " ,
" S_DETON9 " ,
" S_DETON10 " ,
" S_DETON11 " ,
" S_DETON12 " ,
" S_DETON13 " ,
" S_DETON14 " ,
" S_DETON15 " ,
" S_DETON16 " ,
// Skim Mine Dropper
" S_SKIM1 " ,
" S_SKIM2 " ,
" S_SKIM3 " ,
" S_SKIM4 " ,
// THZ Turret
" S_TURRET " ,
" S_TURRETFIRE " ,
" S_TURRETSHOCK1 " ,
" S_TURRETSHOCK2 " ,
" S_TURRETSHOCK3 " ,
" S_TURRETSHOCK4 " ,
" S_TURRETSHOCK5 " ,
" S_TURRETSHOCK6 " ,
" S_TURRETSHOCK7 " ,
" S_TURRETSHOCK8 " ,
" S_TURRETSHOCK9 " ,
// Popup Turret
" S_TURRETLOOK " ,
" S_TURRETSEE " ,
" S_TURRETPOPUP1 " ,
" S_TURRETPOPUP2 " ,
" S_TURRETPOPUP3 " ,
" S_TURRETPOPUP4 " ,
" S_TURRETPOPUP5 " ,
" S_TURRETPOPUP6 " ,
" S_TURRETPOPUP7 " ,
" S_TURRETPOPUP8 " ,
" S_TURRETSHOOT " ,
" S_TURRETPOPDOWN1 " ,
" S_TURRETPOPDOWN2 " ,
" S_TURRETPOPDOWN3 " ,
" S_TURRETPOPDOWN4 " ,
" S_TURRETPOPDOWN5 " ,
" S_TURRETPOPDOWN6 " ,
" S_TURRETPOPDOWN7 " ,
" S_TURRETPOPDOWN8 " ,
// Sharp
" S_SHARP_ROAM1 " ,
" S_SHARP_ROAM2 " ,
" S_SHARP_AIM1 " ,
" S_SHARP_AIM2 " ,
" S_SHARP_AIM3 " ,
" S_SHARP_AIM4 " ,
" S_SHARP_SPIN " ,
// Jet Jaw
" S_JETJAW_ROAM1 " ,
" S_JETJAW_ROAM2 " ,
" S_JETJAW_ROAM3 " ,
" S_JETJAW_ROAM4 " ,
" S_JETJAW_ROAM5 " ,
" S_JETJAW_ROAM6 " ,
" S_JETJAW_ROAM7 " ,
" S_JETJAW_ROAM8 " ,
" S_JETJAW_CHOMP1 " ,
" S_JETJAW_CHOMP2 " ,
" S_JETJAW_CHOMP3 " ,
" S_JETJAW_CHOMP4 " ,
" S_JETJAW_CHOMP5 " ,
" S_JETJAW_CHOMP6 " ,
" S_JETJAW_CHOMP7 " ,
" S_JETJAW_CHOMP8 " ,
" S_JETJAW_CHOMP9 " ,
" S_JETJAW_CHOMP10 " ,
" S_JETJAW_CHOMP11 " ,
" S_JETJAW_CHOMP12 " ,
" S_JETJAW_CHOMP13 " ,
" S_JETJAW_CHOMP14 " ,
" S_JETJAW_CHOMP15 " ,
" S_JETJAW_CHOMP16 " ,
// Snailer
" S_SNAILER1 " ,
// Vulture
" S_VULTURE_STND " ,
" S_VULTURE_VTOL1 " ,
" S_VULTURE_VTOL2 " ,
" S_VULTURE_VTOL3 " ,
" S_VULTURE_VTOL4 " ,
" S_VULTURE_ZOOM1 " ,
" S_VULTURE_ZOOM2 " ,
" S_VULTURE_ZOOM3 " ,
" S_VULTURE_ZOOM4 " ,
" S_VULTURE_ZOOM5 " ,
// Pointy
" S_POINTY1 " ,
" S_POINTYBALL1 " ,
// Robo-Hood
" S_ROBOHOOD_LOOK " ,
" S_ROBOHOOD_STND " ,
" S_ROBOHOOD_SHOOT " ,
" S_ROBOHOOD_JUMP " ,
" S_ROBOHOOD_JUMP2 " ,
" S_ROBOHOOD_FALL " ,
// CastleBot FaceStabber
" S_FACESTABBER_STND1 " ,
" S_FACESTABBER_STND2 " ,
" S_FACESTABBER_STND3 " ,
" S_FACESTABBER_STND4 " ,
" S_FACESTABBER_STND5 " ,
" S_FACESTABBER_STND6 " ,
" S_FACESTABBER_CHARGE1 " ,
" S_FACESTABBER_CHARGE2 " ,
" S_FACESTABBER_CHARGE3 " ,
" S_FACESTABBER_CHARGE4 " ,
// Egg Guard
" S_EGGGUARD_STND " ,
" S_EGGGUARD_WALK1 " ,
" S_EGGGUARD_WALK2 " ,
" S_EGGGUARD_WALK3 " ,
" S_EGGGUARD_WALK4 " ,
" S_EGGGUARD_MAD1 " ,
" S_EGGGUARD_MAD2 " ,
" S_EGGGUARD_MAD3 " ,
" S_EGGGUARD_RUN1 " ,
" S_EGGGUARD_RUN2 " ,
" S_EGGGUARD_RUN3 " ,
" S_EGGGUARD_RUN4 " ,
// Egg Shield for Egg Guard
" S_EGGSHIELD " ,
// Green Snapper
" S_GSNAPPER_STND " ,
" S_GSNAPPER1 " ,
" S_GSNAPPER2 " ,
" S_GSNAPPER3 " ,
" S_GSNAPPER4 " ,
// Minus
" S_MINUS_STND " ,
" S_MINUS_DIGGING " ,
" S_MINUS_POPUP " ,
" S_MINUS_UPWARD1 " ,
" S_MINUS_UPWARD2 " ,
" S_MINUS_UPWARD3 " ,
" S_MINUS_UPWARD4 " ,
" S_MINUS_UPWARD5 " ,
" S_MINUS_UPWARD6 " ,
" S_MINUS_UPWARD7 " ,
" S_MINUS_UPWARD8 " ,
" S_MINUS_DOWNWARD1 " ,
" S_MINUS_DOWNWARD2 " ,
" S_MINUS_DOWNWARD3 " ,
" S_MINUS_DOWNWARD4 " ,
" S_MINUS_DOWNWARD5 " ,
" S_MINUS_DOWNWARD6 " ,
" S_MINUS_DOWNWARD7 " ,
" S_MINUS_DOWNWARD8 " ,
// Spring Shell
" S_SSHELL_STND " ,
" S_SSHELL_RUN1 " ,
" S_SSHELL_RUN2 " ,
" S_SSHELL_RUN3 " ,
" S_SSHELL_RUN4 " ,
" S_SSHELL_SPRING1 " ,
" S_SSHELL_SPRING2 " ,
" S_SSHELL_SPRING3 " ,
" S_SSHELL_SPRING4 " ,
// Spring Shell (yellow)
" S_YSHELL_STND " ,
" S_YSHELL_RUN1 " ,
" S_YSHELL_RUN2 " ,
" S_YSHELL_RUN3 " ,
" S_YSHELL_RUN4 " ,
" S_YSHELL_SPRING1 " ,
" S_YSHELL_SPRING2 " ,
" S_YSHELL_SPRING3 " ,
" S_YSHELL_SPRING4 " ,
// Unidus
" S_UNIDUS_STND " ,
" S_UNIDUS_RUN " ,
" S_UNIDUS_BALL " ,
// Boss Explosion
" S_BPLD1 " ,
" S_BPLD2 " ,
" S_BPLD3 " ,
" S_BPLD4 " ,
" S_BPLD5 " ,
" S_BPLD6 " ,
" S_BPLD7 " ,
// S3&K Boss Explosion
" S_SONIC3KBOSSEXPLOSION1 " ,
" S_SONIC3KBOSSEXPLOSION2 " ,
" S_SONIC3KBOSSEXPLOSION3 " ,
" S_SONIC3KBOSSEXPLOSION4 " ,
" S_SONIC3KBOSSEXPLOSION5 " ,
" S_SONIC3KBOSSEXPLOSION6 " ,
" S_JETFUME1 " ,
" S_JETFUME2 " ,
// Boss 1
" S_EGGMOBILE_STND " ,
" S_EGGMOBILE_LATK1 " ,
" S_EGGMOBILE_LATK2 " ,
" S_EGGMOBILE_LATK3 " ,
" S_EGGMOBILE_LATK4 " ,
" S_EGGMOBILE_LATK5 " ,
" S_EGGMOBILE_LATK6 " ,
" S_EGGMOBILE_LATK7 " ,
" S_EGGMOBILE_LATK8 " ,
" S_EGGMOBILE_LATK9 " ,
" S_EGGMOBILE_LATK10 " ,
" S_EGGMOBILE_RATK1 " ,
" S_EGGMOBILE_RATK2 " ,
" S_EGGMOBILE_RATK3 " ,
" S_EGGMOBILE_RATK4 " ,
" S_EGGMOBILE_RATK5 " ,
" S_EGGMOBILE_RATK6 " ,
" S_EGGMOBILE_RATK7 " ,
" S_EGGMOBILE_RATK8 " ,
" S_EGGMOBILE_RATK9 " ,
" S_EGGMOBILE_RATK10 " ,
" S_EGGMOBILE_PANIC1 " ,
" S_EGGMOBILE_PANIC2 " ,
" S_EGGMOBILE_PANIC3 " ,
" S_EGGMOBILE_PANIC4 " ,
" S_EGGMOBILE_PANIC5 " ,
" S_EGGMOBILE_PANIC6 " ,
" S_EGGMOBILE_PANIC7 " ,
" S_EGGMOBILE_PANIC8 " ,
" S_EGGMOBILE_PANIC9 " ,
" S_EGGMOBILE_PANIC10 " ,
" S_EGGMOBILE_PAIN " ,
" S_EGGMOBILE_PAIN2 " ,
" S_EGGMOBILE_DIE1 " ,
" S_EGGMOBILE_DIE2 " ,
" S_EGGMOBILE_DIE3 " ,
" S_EGGMOBILE_DIE4 " ,
" S_EGGMOBILE_DIE5 " ,
" S_EGGMOBILE_DIE6 " ,
" S_EGGMOBILE_DIE7 " ,
" S_EGGMOBILE_DIE8 " ,
" S_EGGMOBILE_DIE9 " ,
" S_EGGMOBILE_DIE10 " ,
" S_EGGMOBILE_DIE11 " ,
" S_EGGMOBILE_DIE12 " ,
" S_EGGMOBILE_DIE13 " ,
" S_EGGMOBILE_DIE14 " ,
" S_EGGMOBILE_FLEE1 " ,
" S_EGGMOBILE_FLEE2 " ,
" S_EGGMOBILE_BALL " ,
" S_EGGMOBILE_TARGET " ,
// Boss 2
" S_EGGMOBILE2_STND " ,
" S_EGGMOBILE2_POGO1 " ,
" S_EGGMOBILE2_POGO2 " ,
" S_EGGMOBILE2_POGO3 " ,
" S_EGGMOBILE2_POGO4 " ,
" S_EGGMOBILE2_POGO5 " ,
" S_EGGMOBILE2_POGO6 " ,
" S_EGGMOBILE2_POGO7 " ,
" S_EGGMOBILE2_PAIN " ,
" S_EGGMOBILE2_PAIN2 " ,
" S_EGGMOBILE2_DIE1 " ,
" S_EGGMOBILE2_DIE2 " ,
" S_EGGMOBILE2_DIE3 " ,
" S_EGGMOBILE2_DIE4 " ,
" S_EGGMOBILE2_DIE5 " ,
" S_EGGMOBILE2_DIE6 " ,
" S_EGGMOBILE2_DIE7 " ,
" S_EGGMOBILE2_DIE8 " ,
" S_EGGMOBILE2_DIE9 " ,
" S_EGGMOBILE2_DIE10 " ,
" S_EGGMOBILE2_DIE11 " ,
" S_EGGMOBILE2_DIE12 " ,
" S_EGGMOBILE2_DIE13 " ,
" S_EGGMOBILE2_DIE14 " ,
" S_EGGMOBILE2_FLEE1 " ,
" S_EGGMOBILE2_FLEE2 " ,
" S_BOSSTANK1 " ,
" S_BOSSTANK2 " ,
" S_BOSSSPIGOT " ,
// Boss 2 Goop
" S_GOOP1 " ,
" S_GOOP2 " ,
" S_GOOP3 " ,
// Boss 3
" S_EGGMOBILE3_STND " ,
" S_EGGMOBILE3_ATK1 " ,
" S_EGGMOBILE3_ATK2 " ,
" S_EGGMOBILE3_ATK3A " ,
" S_EGGMOBILE3_ATK3B " ,
" S_EGGMOBILE3_ATK3C " ,
" S_EGGMOBILE3_ATK3D " ,
" S_EGGMOBILE3_ATK4 " ,
" S_EGGMOBILE3_ATK5 " ,
" S_EGGMOBILE3_LAUGH1 " ,
" S_EGGMOBILE3_LAUGH2 " ,
" S_EGGMOBILE3_LAUGH3 " ,
" S_EGGMOBILE3_LAUGH4 " ,
" S_EGGMOBILE3_LAUGH5 " ,
" S_EGGMOBILE3_LAUGH6 " ,
" S_EGGMOBILE3_LAUGH7 " ,
" S_EGGMOBILE3_LAUGH8 " ,
" S_EGGMOBILE3_LAUGH9 " ,
" S_EGGMOBILE3_LAUGH10 " ,
" S_EGGMOBILE3_LAUGH11 " ,
" S_EGGMOBILE3_LAUGH12 " ,
" S_EGGMOBILE3_LAUGH13 " ,
" S_EGGMOBILE3_LAUGH14 " ,
" S_EGGMOBILE3_LAUGH15 " ,
" S_EGGMOBILE3_LAUGH16 " ,
" S_EGGMOBILE3_LAUGH17 " ,
" S_EGGMOBILE3_LAUGH18 " ,
" S_EGGMOBILE3_LAUGH19 " ,
" S_EGGMOBILE3_LAUGH20 " ,
" S_EGGMOBILE3_PAIN " ,
" S_EGGMOBILE3_PAIN2 " ,
" S_EGGMOBILE3_DIE1 " ,
" S_EGGMOBILE3_DIE2 " ,
" S_EGGMOBILE3_DIE3 " ,
" S_EGGMOBILE3_DIE4 " ,
" S_EGGMOBILE3_DIE5 " ,
" S_EGGMOBILE3_DIE6 " ,
" S_EGGMOBILE3_DIE7 " ,
" S_EGGMOBILE3_DIE8 " ,
" S_EGGMOBILE3_DIE9 " ,
" S_EGGMOBILE3_DIE10 " ,
" S_EGGMOBILE3_DIE11 " ,
" S_EGGMOBILE3_DIE12 " ,
" S_EGGMOBILE3_DIE13 " ,
" S_EGGMOBILE3_DIE14 " ,
" S_EGGMOBILE3_FLEE1 " ,
" S_EGGMOBILE3_FLEE2 " ,
// Boss 3 Propeller
" S_PROPELLER1 " ,
" S_PROPELLER2 " ,
" S_PROPELLER3 " ,
" S_PROPELLER4 " ,
" S_PROPELLER5 " ,
" S_PROPELLER6 " ,
" S_PROPELLER7 " ,
// Boss 3 pinch
" S_FAKEMOBILE_INIT " ,
" S_FAKEMOBILE " ,
" S_FAKEMOBILE_ATK1 " ,
" S_FAKEMOBILE_ATK2 " ,
" S_FAKEMOBILE_ATK3A " ,
" S_FAKEMOBILE_ATK3B " ,
" S_FAKEMOBILE_ATK3C " ,
" S_FAKEMOBILE_ATK3D " ,
" S_FAKEMOBILE_ATK4 " ,
" S_FAKEMOBILE_ATK5 " ,
// Boss 4
" S_EGGMOBILE4_STND " ,
" S_EGGMOBILE4_LATK1 " ,
" S_EGGMOBILE4_LATK2 " ,
" S_EGGMOBILE4_LATK3 " ,
" S_EGGMOBILE4_LATK4 " ,
" S_EGGMOBILE4_LATK5 " ,
" S_EGGMOBILE4_LATK6 " ,
" S_EGGMOBILE4_RATK1 " ,
" S_EGGMOBILE4_RATK2 " ,
" S_EGGMOBILE4_RATK3 " ,
" S_EGGMOBILE4_RATK4 " ,
" S_EGGMOBILE4_RATK5 " ,
" S_EGGMOBILE4_RATK6 " ,
" S_EGGMOBILE4_RAISE1 " ,
" S_EGGMOBILE4_RAISE2 " ,
" S_EGGMOBILE4_RAISE3 " ,
" S_EGGMOBILE4_RAISE4 " ,
" S_EGGMOBILE4_RAISE5 " ,
" S_EGGMOBILE4_RAISE6 " ,
" S_EGGMOBILE4_RAISE7 " ,
" S_EGGMOBILE4_RAISE8 " ,
" S_EGGMOBILE4_RAISE9 " ,
" S_EGGMOBILE4_RAISE10 " ,
" S_EGGMOBILE4_PAIN " ,
" S_EGGMOBILE4_DIE1 " ,
" S_EGGMOBILE4_DIE2 " ,
" S_EGGMOBILE4_DIE3 " ,
" S_EGGMOBILE4_DIE4 " ,
" S_EGGMOBILE4_DIE5 " ,
" S_EGGMOBILE4_DIE6 " ,
" S_EGGMOBILE4_DIE7 " ,
" S_EGGMOBILE4_DIE8 " ,
" S_EGGMOBILE4_DIE9 " ,
" S_EGGMOBILE4_DIE10 " ,
" S_EGGMOBILE4_DIE11 " ,
" S_EGGMOBILE4_DIE12 " ,
" S_EGGMOBILE4_DIE13 " ,
" S_EGGMOBILE4_DIE14 " ,
" S_EGGMOBILE4_FLEE1 " ,
" S_EGGMOBILE4_FLEE2 " ,
" S_EGGMOBILE4_MACE " ,
// Boss 4 jet flame
" S_JETFLAME1 " ,
" S_JETFLAME2 " ,
// Black Eggman (Boss 7)
" S_BLACKEGG_STND " ,
" S_BLACKEGG_STND2 " ,
" S_BLACKEGG_WALK1 " ,
" S_BLACKEGG_WALK2 " ,
" S_BLACKEGG_WALK3 " ,
" S_BLACKEGG_WALK4 " ,
" S_BLACKEGG_WALK5 " ,
" S_BLACKEGG_WALK6 " ,
" S_BLACKEGG_SHOOT1 " ,
" S_BLACKEGG_SHOOT2 " ,
" S_BLACKEGG_PAIN1 " ,
" S_BLACKEGG_PAIN2 " ,
" S_BLACKEGG_PAIN3 " ,
" S_BLACKEGG_PAIN4 " ,
" S_BLACKEGG_PAIN5 " ,
" S_BLACKEGG_PAIN6 " ,
" S_BLACKEGG_PAIN7 " ,
" S_BLACKEGG_PAIN8 " ,
" S_BLACKEGG_PAIN9 " ,
" S_BLACKEGG_PAIN10 " ,
" S_BLACKEGG_PAIN11 " ,
" S_BLACKEGG_PAIN12 " ,
" S_BLACKEGG_PAIN13 " ,
" S_BLACKEGG_PAIN14 " ,
" S_BLACKEGG_PAIN15 " ,
" S_BLACKEGG_PAIN16 " ,
" S_BLACKEGG_PAIN17 " ,
" S_BLACKEGG_PAIN18 " ,
" S_BLACKEGG_PAIN19 " ,
" S_BLACKEGG_PAIN20 " ,
" S_BLACKEGG_PAIN21 " ,
" S_BLACKEGG_PAIN22 " ,
" S_BLACKEGG_PAIN23 " ,
" S_BLACKEGG_PAIN24 " ,
" S_BLACKEGG_PAIN25 " ,
" S_BLACKEGG_PAIN26 " ,
" S_BLACKEGG_PAIN27 " ,
" S_BLACKEGG_PAIN28 " ,
" S_BLACKEGG_PAIN29 " ,
" S_BLACKEGG_PAIN30 " ,
" S_BLACKEGG_PAIN31 " ,
" S_BLACKEGG_PAIN32 " ,
" S_BLACKEGG_PAIN33 " ,
" S_BLACKEGG_PAIN34 " ,
" S_BLACKEGG_PAIN35 " ,
" S_BLACKEGG_HITFACE1 " ,
" S_BLACKEGG_HITFACE2 " ,
" S_BLACKEGG_HITFACE3 " ,
" S_BLACKEGG_HITFACE4 " ,
" S_BLACKEGG_DIE1 " ,
" S_BLACKEGG_DIE2 " ,
" S_BLACKEGG_DIE3 " ,
" S_BLACKEGG_DIE4 " ,
" S_BLACKEGG_DIE5 " ,
" S_BLACKEGG_MISSILE1 " ,
" S_BLACKEGG_MISSILE2 " ,
" S_BLACKEGG_MISSILE3 " ,
" S_BLACKEGG_GOOP " ,
" S_BLACKEGG_JUMP1 " ,
" S_BLACKEGG_JUMP2 " ,
" S_BLACKEGG_DESTROYPLAT1 " ,
" S_BLACKEGG_DESTROYPLAT2 " ,
" S_BLACKEGG_DESTROYPLAT3 " ,
" S_BLACKEGG_HELPER " , // Collision helper
" S_BLACKEGG_GOOP1 " ,
" S_BLACKEGG_GOOP2 " ,
" S_BLACKEGG_GOOP3 " ,
" S_BLACKEGG_GOOP4 " ,
" S_BLACKEGG_GOOP5 " ,
" S_BLACKEGG_GOOP6 " ,
" S_BLACKEGG_GOOP7 " ,
" S_BLACKEGG_MISSILE " ,
// New Very-Last-Minute 2.1 Brak Eggman (Cy-Brak-demon)
" S_CYBRAKDEMON_IDLE " ,
" S_CYBRAKDEMON_WALK1 " ,
" S_CYBRAKDEMON_WALK2 " ,
" S_CYBRAKDEMON_WALK3 " ,
" S_CYBRAKDEMON_WALK4 " ,
" S_CYBRAKDEMON_WALK5 " ,
" S_CYBRAKDEMON_WALK6 " ,
" S_CYBRAKDEMON_CHOOSE_ATTACK1 " ,
" S_CYBRAKDEMON_MISSILE_ATTACK1 " , // Aim
" S_CYBRAKDEMON_MISSILE_ATTACK2 " , // Fire
" S_CYBRAKDEMON_MISSILE_ATTACK3 " , // Aim
" S_CYBRAKDEMON_MISSILE_ATTACK4 " , // Fire
" S_CYBRAKDEMON_MISSILE_ATTACK5 " , // Aim
" S_CYBRAKDEMON_MISSILE_ATTACK6 " , // Fire
" S_CYBRAKDEMON_FLAME_ATTACK1 " , // Reset
" S_CYBRAKDEMON_FLAME_ATTACK2 " , // Aim
" S_CYBRAKDEMON_FLAME_ATTACK3 " , // Fire
" S_CYBRAKDEMON_FLAME_ATTACK4 " , // Loop
" S_CYBRAKDEMON_CHOOSE_ATTACK2 " ,
" S_CYBRAKDEMON_VILE_ATTACK1 " ,
" S_CYBRAKDEMON_VILE_ATTACK2 " ,
" S_CYBRAKDEMON_VILE_ATTACK3 " ,
" S_CYBRAKDEMON_VILE_ATTACK4 " ,
" S_CYBRAKDEMON_VILE_ATTACK5 " ,
" S_CYBRAKDEMON_VILE_ATTACK6 " ,
" S_CYBRAKDEMON_NAPALM_ATTACK1 " ,
" S_CYBRAKDEMON_NAPALM_ATTACK2 " ,
" S_CYBRAKDEMON_NAPALM_ATTACK3 " ,
" S_CYBRAKDEMON_FINISH_ATTACK " , // If just attacked, remove MF2_FRET w/out going back to spawnstate
" S_CYBRAKDEMON_FINISH_ATTACK2 " , // Force a delay between attacks so you don't get bombarded with them back-to-back
" S_CYBRAKDEMON_PAIN1 " ,
" S_CYBRAKDEMON_PAIN2 " ,
" S_CYBRAKDEMON_PAIN3 " ,
" S_CYBRAKDEMON_DIE1 " ,
" S_CYBRAKDEMON_DIE2 " ,
" S_CYBRAKDEMON_DIE3 " ,
" S_CYBRAKDEMON_DIE4 " ,
" S_CYBRAKDEMON_DIE5 " ,
" S_CYBRAKDEMON_DIE6 " ,
" S_CYBRAKDEMON_DIE7 " ,
" S_CYBRAKDEMON_DIE8 " ,
" S_CYBRAKDEMON_DEINVINCIBLERIZE " ,
" S_CYBRAKDEMON_INVINCIBLERIZE " ,
" S_CYBRAKDEMONMISSILE " ,
" S_CYBRAKDEMONMISSILE_EXPLODE1 " ,
" S_CYBRAKDEMONMISSILE_EXPLODE2 " ,
" S_CYBRAKDEMONMISSILE_EXPLODE3 " ,
" S_CYBRAKDEMONFLAMESHOT_FLY1 " ,
" S_CYBRAKDEMONFLAMESHOT_FLY2 " ,
" S_CYBRAKDEMONFLAMESHOT_FLY3 " ,
" S_CYBRAKDEMONFLAMESHOT_DIE " ,
" S_CYBRAKDEMONFLAMEREST " ,
" S_CYBRAKDEMONELECTRICBARRIER_INIT1 " ,
" S_CYBRAKDEMONELECTRICBARRIER_INIT2 " ,
" S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND " ,
" S_CYBRAKDEMONELECTRICBARRIER1 " ,
" S_CYBRAKDEMONELECTRICBARRIER2 " ,
" S_CYBRAKDEMONELECTRICBARRIER3 " ,
" S_CYBRAKDEMONELECTRICBARRIER4 " ,
" S_CYBRAKDEMONELECTRICBARRIER5 " ,
" S_CYBRAKDEMONELECTRICBARRIER6 " ,
" S_CYBRAKDEMONELECTRICBARRIER7 " ,
" S_CYBRAKDEMONELECTRICBARRIER8 " ,
" S_CYBRAKDEMONELECTRICBARRIER9 " ,
" S_CYBRAKDEMONELECTRICBARRIER10 " ,
" S_CYBRAKDEMONELECTRICBARRIER11 " ,
" S_CYBRAKDEMONELECTRICBARRIER12 " ,
" S_CYBRAKDEMONELECTRICBARRIER13 " ,
" S_CYBRAKDEMONELECTRICBARRIER14 " ,
" S_CYBRAKDEMONELECTRICBARRIER15 " ,
" S_CYBRAKDEMONELECTRICBARRIER16 " ,
" S_CYBRAKDEMONELECTRICBARRIER17 " ,
" S_CYBRAKDEMONELECTRICBARRIER18 " ,
" S_CYBRAKDEMONELECTRICBARRIER19 " ,
" S_CYBRAKDEMONELECTRICBARRIER20 " ,
" S_CYBRAKDEMONELECTRICBARRIER21 " ,
" S_CYBRAKDEMONELECTRICBARRIER22 " ,
" S_CYBRAKDEMONELECTRICBARRIER23 " ,
" S_CYBRAKDEMONELECTRICBARRIER24 " ,
" S_CYBRAKDEMONELECTRICBARRIER_DIE1 " ,
" S_CYBRAKDEMONELECTRICBARRIER_DIE2 " ,
" S_CYBRAKDEMONELECTRICBARRIER_DIE3 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHECK " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHOOSE " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM2 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM3 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM4 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM5 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM6 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM7 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM8 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM9 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM10 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM11 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM12 " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMFAIL " ,
" S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP " ,
" S_CYBRAKDEMONELECTRICBARRIER_REVIVE1 " ,
" S_CYBRAKDEMONELECTRICBARRIER_REVIVE2 " ,
" S_CYBRAKDEMONELECTRICBARRIER_REVIVE3 " ,
" S_CYBRAKDEMONTARGETRETICULE1 " ,
" S_CYBRAKDEMONTARGETRETICULE2 " ,
" S_CYBRAKDEMONTARGETRETICULE3 " ,
" S_CYBRAKDEMONTARGETRETICULE4 " ,
" S_CYBRAKDEMONTARGETRETICULE5 " ,
" S_CYBRAKDEMONTARGETRETICULE6 " ,
" S_CYBRAKDEMONTARGETRETICULE7 " ,
" S_CYBRAKDEMONTARGETRETICULE8 " ,
" S_CYBRAKDEMONTARGETRETICULE9 " ,
" S_CYBRAKDEMONTARGETRETICULE10 " ,
" S_CYBRAKDEMONTARGETRETICULE11 " ,
" S_CYBRAKDEMONTARGETRETICULE12 " ,
" S_CYBRAKDEMONTARGETRETICULE13 " ,
" S_CYBRAKDEMONTARGETRETICULE14 " ,
" S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1 " ,
" S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2 " ,
" S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3 " ,
" S_CYBRAKDEMONNAPALMBOMBLARGE_FLY4 " ,
" S_CYBRAKDEMONNAPALMBOMBLARGE_DIE1 " , // Explode
" S_CYBRAKDEMONNAPALMBOMBLARGE_DIE2 " , // Outer ring
" S_CYBRAKDEMONNAPALMBOMBLARGE_DIE3 " , // Center
" S_CYBRAKDEMONNAPALMBOMBLARGE_DIE4 " , // Sound
" S_CYBRAKDEMONNAPALMBOMBSMALL " ,
" S_CYBRAKDEMONNAPALMBOMBSMALL_DIE1 " , // Explode
" S_CYBRAKDEMONNAPALMBOMBSMALL_DIE2 " , // Outer ring
" S_CYBRAKDEMONNAPALMBOMBSMALL_DIE3 " , // Inner ring
" S_CYBRAKDEMONNAPALMBOMBSMALL_DIE4 " , // Center
" S_CYBRAKDEMONNAPALMBOMBSMALL_DIE5 " , // Sound
" S_CYBRAKDEMONNAPALMFLAME_FLY1 " ,
" S_CYBRAKDEMONNAPALMFLAME_FLY2 " ,
" S_CYBRAKDEMONNAPALMFLAME_FLY3 " ,
" S_CYBRAKDEMONNAPALMFLAME_FLY4 " ,
" S_CYBRAKDEMONNAPALMFLAME_FLY5 " ,
" S_CYBRAKDEMONNAPALMFLAME_FLY6 " ,
" S_CYBRAKDEMONNAPALMFLAME_DIE " ,
" S_CYBRAKDEMONVILEEXPLOSION1 " ,
" S_CYBRAKDEMONVILEEXPLOSION2 " ,
" S_CYBRAKDEMONVILEEXPLOSION3 " ,
// Metal Sonic (Race)
// S_PLAY_STND
" S_METALSONIC_STAND " ,
// S_PLAY_TAP1
" S_METALSONIC_WAIT1 " ,
" S_METALSONIC_WAIT2 " ,
// S_PLAY_RUN1
" S_METALSONIC_WALK1 " ,
" S_METALSONIC_WALK2 " ,
" S_METALSONIC_WALK3 " ,
" S_METALSONIC_WALK4 " ,
" S_METALSONIC_WALK5 " ,
" S_METALSONIC_WALK6 " ,
" S_METALSONIC_WALK7 " ,
" S_METALSONIC_WALK8 " ,
// S_PLAY_SPD1
" S_METALSONIC_RUN1 " ,
" S_METALSONIC_RUN2 " ,
" S_METALSONIC_RUN3 " ,
" S_METALSONIC_RUN4 " ,
// Metal Sonic (Battle)
" S_METALSONIC_FLOAT " ,
" S_METALSONIC_VECTOR " ,
" S_METALSONIC_STUN " ,
" S_METALSONIC_BLOCK " ,
" S_METALSONIC_RAISE " ,
" S_METALSONIC_GATHER " ,
" S_METALSONIC_DASH " ,
" S_METALSONIC_BOUNCE " ,
" S_METALSONIC_SHOOT " ,
" S_METALSONIC_PAIN " ,
" S_METALSONIC_DEATH " ,
" S_METALSONIC_FLEE1 " ,
" S_METALSONIC_FLEE2 " ,
" S_METALSONIC_FLEE3 " ,
" S_METALSONIC_FLEE4 " ,
" S_MSSHIELD_F1 " ,
" S_MSSHIELD_F2 " ,
" S_MSSHIELD_F3 " ,
" S_MSSHIELD_F4 " ,
" S_MSSHIELD_F5 " ,
" S_MSSHIELD_F6 " ,
" S_MSSHIELD_F7 " ,
" S_MSSHIELD_F8 " ,
" S_MSSHIELD_F9 " ,
" S_MSSHIELD_F10 " ,
" S_MSSHIELD_F11 " ,
" S_MSSHIELD_F12 " ,
// Ring
" S_RING1 " ,
" S_RING2 " ,
" S_RING3 " ,
" S_RING4 " ,
" S_RING5 " ,
" S_RING6 " ,
" S_RING7 " ,
" S_RING8 " ,
" S_RING9 " ,
" S_RING10 " ,
" S_RING11 " ,
" S_RING12 " ,
" S_RING13 " ,
" S_RING14 " ,
" S_RING15 " ,
" S_RING16 " ,
" S_RING17 " ,
" S_RING18 " ,
" S_RING19 " ,
" S_RING20 " ,
" S_RING21 " ,
" S_RING22 " ,
" S_RING23 " ,
" S_RING24 " ,
// Blue Sphere for special stages
" S_BLUEBALL " ,
" S_BLUEBALLSPARK " ,
// Gravity Wells for special stages
" S_GRAVWELLGREEN " ,
" S_GRAVWELLGREEN2 " ,
" S_GRAVWELLGREEN3 " ,
" S_GRAVWELLRED " ,
" S_GRAVWELLRED2 " ,
" S_GRAVWELLRED3 " ,
// Individual Team Rings
" S_TEAMRING1 " ,
" S_TEAMRING2 " ,
" S_TEAMRING3 " ,
" S_TEAMRING4 " ,
" S_TEAMRING5 " ,
" S_TEAMRING6 " ,
" S_TEAMRING7 " ,
" S_TEAMRING8 " ,
" S_TEAMRING9 " ,
" S_TEAMRING10 " ,
" S_TEAMRING11 " ,
" S_TEAMRING12 " ,
" S_TEAMRING13 " ,
" S_TEAMRING14 " ,
" S_TEAMRING15 " ,
" S_TEAMRING16 " ,
" S_TEAMRING17 " ,
" S_TEAMRING18 " ,
" S_TEAMRING19 " ,
" S_TEAMRING20 " ,
" S_TEAMRING21 " ,
" S_TEAMRING22 " ,
" S_TEAMRING23 " ,
" S_TEAMRING24 " ,
// Special Stage Token
" S_EMMY1 " ,
" S_EMMY2 " ,
" S_EMMY3 " ,
" S_EMMY4 " ,
" S_EMMY5 " ,
" S_EMMY6 " ,
" S_EMMY7 " ,
// Special Stage Token
" S_TOKEN " ,
" S_MOVINGTOKEN " ,
// CTF Flags
" S_REDFLAG " ,
" S_BLUEFLAG " ,
// Emblem
" S_EMBLEM1 " ,
" S_EMBLEM2 " ,
" S_EMBLEM3 " ,
" S_EMBLEM4 " ,
" S_EMBLEM5 " ,
" S_EMBLEM6 " ,
" S_EMBLEM7 " ,
" S_EMBLEM8 " ,
" S_EMBLEM9 " ,
" S_EMBLEM10 " ,
" S_EMBLEM11 " ,
" S_EMBLEM12 " ,
" S_EMBLEM13 " ,
" S_EMBLEM14 " ,
" S_EMBLEM15 " ,
" S_EMBLEM16 " ,
" S_EMBLEM17 " ,
" S_EMBLEM18 " ,
" S_EMBLEM19 " ,
" S_EMBLEM20 " ,
" S_EMBLEM21 " ,
" S_EMBLEM22 " ,
" S_EMBLEM23 " ,
" S_EMBLEM24 " ,
" S_EMBLEM25 " ,
" S_EMBLEM26 " ,
// Chaos Emeralds
" S_CEMG1 " ,
" S_CEMG2 " ,
" S_CEMG3 " ,
" S_CEMG4 " ,
" S_CEMG5 " ,
" S_CEMG6 " ,
" S_CEMG7 " ,
// Emeralds (for hunt)
" S_EMER1 " ,
" S_FAN " ,
" S_FAN2 " ,
" S_FAN3 " ,
" S_FAN4 " ,
" S_FAN5 " ,
// Bubble Source
" S_BUBBLES1 " ,
" S_BUBBLES2 " ,
// Level End Sign
" S_SIGN1 " ,
" S_SIGN2 " ,
" S_SIGN3 " ,
" S_SIGN4 " ,
" S_SIGN5 " ,
" S_SIGN6 " ,
" S_SIGN7 " ,
" S_SIGN8 " ,
" S_SIGN9 " ,
" S_SIGN10 " ,
" S_SIGN11 " ,
" S_SIGN12 " ,
" S_SIGN13 " ,
" S_SIGN14 " ,
" S_SIGN15 " ,
" S_SIGN16 " ,
" S_SIGN17 " ,
" S_SIGN18 " ,
" S_SIGN19 " ,
" S_SIGN20 " ,
" S_SIGN21 " ,
" S_SIGN22 " ,
" S_SIGN23 " ,
" S_SIGN24 " ,
" S_SIGN25 " ,
" S_SIGN26 " ,
" S_SIGN27 " ,
" S_SIGN28 " ,
" S_SIGN29 " ,
" S_SIGN30 " ,
" S_SIGN31 " ,
" S_SIGN32 " ,
" S_SIGN33 " ,
" S_SIGN34 " ,
" S_SIGN35 " ,
" S_SIGN36 " ,
" S_SIGN37 " ,
" S_SIGN38 " ,
" S_SIGN39 " ,
" S_SIGN40 " ,
" S_SIGN41 " ,
" S_SIGN42 " ,
" S_SIGN43 " ,
" S_SIGN44 " ,
" S_SIGN45 " ,
" S_SIGN46 " ,
" S_SIGN47 " ,
" S_SIGN48 " ,
" S_SIGN49 " ,
" S_SIGN50 " ,
" S_SIGN51 " ,
" S_SIGN52 " , // Eggman
" S_SIGN53 " ,
// Steam Riser
" S_STEAM1 " ,
" S_STEAM2 " ,
" S_STEAM3 " ,
" S_STEAM4 " ,
" S_STEAM5 " ,
" S_STEAM6 " ,
" S_STEAM7 " ,
" S_STEAM8 " ,
// Spike Ball
" S_SPIKEBALL1 " ,
" S_SPIKEBALL2 " ,
" S_SPIKEBALL3 " ,
" S_SPIKEBALL4 " ,
" S_SPIKEBALL5 " ,
" S_SPIKEBALL6 " ,
" S_SPIKEBALL7 " ,
" S_SPIKEBALL8 " ,
// Fire Shield's Spawn
" S_SPINFIRE1 " ,
" S_SPINFIRE2 " ,
" S_SPINFIRE3 " ,
" S_SPINFIRE4 " ,
" S_SPINFIRE5 " ,
" S_SPINFIRE6 " ,
// Spikes
" S_SPIKE1 " ,
" S_SPIKE2 " ,
" S_SPIKE3 " ,
" S_SPIKE4 " ,
" S_SPIKE5 " ,
" S_SPIKE6 " ,
" S_SPIKED1 " ,
" S_SPIKED2 " ,
// Starpost
" S_STARPOST1 " ,
" S_STARPOST2 " ,
" S_STARPOST3 " ,
" S_STARPOST4 " ,
" S_STARPOST5 " ,
" S_STARPOST6 " ,
" S_STARPOST7 " ,
" S_STARPOST8 " ,
" S_STARPOST9 " ,
" S_STARPOST10 " ,
" S_STARPOST11 " ,
" S_STARPOST12 " ,
" S_STARPOST13 " ,
" S_STARPOST14 " ,
" S_STARPOST15 " ,
" S_STARPOST16 " ,
" S_STARPOST17 " ,
" S_STARPOST18 " ,
" S_STARPOST19 " ,
" S_STARPOST20 " ,
" S_STARPOST21 " ,
" S_STARPOST22 " ,
" S_STARPOST23 " ,
" S_STARPOST24 " ,
" S_STARPOST25 " ,
" S_STARPOST26 " ,
" S_STARPOST27 " ,
" S_STARPOST28 " ,
" S_STARPOST29 " ,
" S_STARPOST30 " ,
" S_STARPOST31 " ,
" S_STARPOST32 " ,
" S_STARPOST33 " ,
" S_STARPOST34 " ,
// Big floating mine
" S_BIGMINE1 " ,
" S_BIGMINE2 " ,
" S_BIGMINE3 " ,
" S_BIGMINE4 " ,
" S_BIGMINE5 " ,
" S_BIGMINE6 " ,
" S_BIGMINE7 " ,
" S_BIGMINE8 " ,
// Cannon Launcher
" S_CANNONLAUNCHER1 " ,
" S_CANNONLAUNCHER2 " ,
" S_CANNONLAUNCHER3 " ,
// Super Ring Box
" S_SUPERRINGBOX " ,
" S_SUPERRINGBOX1 " ,
" S_SUPERRINGBOX2 " ,
" S_SUPERRINGBOX3 " ,
" S_SUPERRINGBOX4 " ,
" S_SUPERRINGBOX5 " ,
" S_SUPERRINGBOX6 " ,
// Red Team Ring Box
" S_REDRINGBOX " ,
" S_REDRINGBOX1 " ,
// Blue Team Ring Box
" S_BLUERINGBOX " ,
" S_BLUERINGBOX1 " ,
// Super Sneakers Box
" S_SHTV " ,
" S_SHTV1 " ,
" S_SHTV2 " ,
" S_SHTV3 " ,
" S_SHTV4 " ,
" S_SHTV5 " ,
" S_SHTV6 " ,
// Invincibility Box
" S_PINV " ,
" S_PINV1 " ,
" S_PINV2 " ,
" S_PINV3 " ,
" S_PINV4 " ,
" S_PINV5 " ,
" S_PINV6 " ,
// 1-Up Box
" S_PRUP " ,
" S_PRUP1 " ,
" S_PRUP2 " ,
" S_PRUP3 " ,
" S_PRUP4 " ,
" S_PRUP5 " ,
" S_PRUP6 " ,
// Ring Shield Box
" S_YLTV " ,
" S_YLTV1 " ,
" S_YLTV2 " ,
" S_YLTV3 " ,
" S_YLTV4 " ,
" S_YLTV5 " ,
" S_YLTV6 " ,
// Force Shield Box
" S_BLTV1 " ,
" S_BLTV2 " ,
" S_BLTV3 " ,
" S_BLTV4 " ,
" S_BLTV5 " ,
" S_BLTV6 " ,
" S_BLTV7 " ,
// Bomb Shield Box
" S_BKTV1 " ,
" S_BKTV2 " ,
" S_BKTV3 " ,
" S_BKTV4 " ,
" S_BKTV5 " ,
" S_BKTV6 " ,
" S_BKTV7 " ,
// Jump Shield Box
" S_WHTV1 " ,
" S_WHTV2 " ,
" S_WHTV3 " ,
" S_WHTV4 " ,
" S_WHTV5 " ,
" S_WHTV6 " ,
" S_WHTV7 " ,
// Water Shield Box
" S_GRTV " ,
" S_GRTV1 " ,
" S_GRTV2 " ,
" S_GRTV3 " ,
" S_GRTV4 " ,
" S_GRTV5 " ,
" S_GRTV6 " ,
// Pity Shield Box
" S_PITV1 " ,
" S_PITV2 " ,
" S_PITV3 " ,
" S_PITV4 " ,
" S_PITV5 " ,
" S_PITV6 " ,
" S_PITV7 " ,
// Eggman Box
" S_EGGTV1 " ,
" S_EGGTV2 " ,
" S_EGGTV3 " ,
" S_EGGTV4 " ,
" S_EGGTV5 " ,
" S_EGGTV6 " ,
" S_EGGTV7 " ,
// Teleport Box
" S_MIXUPBOX1 " ,
" S_MIXUPBOX2 " ,
" S_MIXUPBOX3 " ,
" S_MIXUPBOX4 " ,
" S_MIXUPBOX5 " ,
" S_MIXUPBOX6 " ,
" S_MIXUPBOX7 " ,
// Recycler Box
" S_RECYCLETV1 " ,
" S_RECYCLETV2 " ,
" S_RECYCLETV3 " ,
" S_RECYCLETV4 " ,
" S_RECYCLETV5 " ,
" S_RECYCLETV6 " ,
" S_RECYCLETV7 " ,
// Question Box
" S_RANDOMBOX1 " ,
" S_RANDOMBOX2 " ,
" S_RANDOMBOX3 " ,
// Gravity Boots Box
" S_GBTV1 " ,
" S_GBTV2 " ,
" S_GBTV3 " ,
" S_GBTV4 " ,
" S_GBTV5 " ,
" S_GBTV6 " ,
" S_GBTV7 " ,
// Score boxes
" S_SCORETVA1 " ,
" S_SCORETVA2 " ,
" S_SCORETVA3 " ,
" S_SCORETVA4 " ,
" S_SCORETVA5 " ,
" S_SCORETVA6 " ,
" S_SCORETVA7 " ,
" S_SCORETVB1 " ,
" S_SCORETVB2 " ,
" S_SCORETVB3 " ,
" S_SCORETVB4 " ,
" S_SCORETVB5 " ,
" S_SCORETVB6 " ,
" S_SCORETVB7 " ,
// Monitor Explosion
" S_MONITOREXPLOSION1 " ,
" S_MONITOREXPLOSION2 " ,
" S_REDMONITOREXPLOSION1 " ,
" S_REDMONITOREXPLOSION2 " ,
" S_BLUEMONITOREXPLOSION1 " ,
" S_BLUEMONITOREXPLOSION2 " ,
" S_ROCKET " ,
" S_LASER " ,
" S_TORPEDO " ,
" S_ENERGYBALL1 " ,
" S_ENERGYBALL2 " ,
// Skim Mine, also used by Jetty-Syn bomber
" S_MINE1 " ,
" S_MINE_BOOM1 " ,
" S_MINE_BOOM2 " ,
" S_MINE_BOOM3 " ,
" S_MINE_BOOM4 " ,
// Jetty-Syn Bullet
" S_JETBULLET1 " ,
" S_JETBULLET2 " ,
" S_TURRETLASER " ,
" S_TURRETLASEREXPLODE1 " ,
" S_TURRETLASEREXPLODE2 " ,
// Cannonball
" S_CANNONBALL1 " ,
// Arrow
" S_ARROW " ,
" S_ARROWUP " ,
" S_ARROWDOWN " ,
// Trapgoyle Demon fire
" S_DEMONFIRE " ,
" S_GFZFLOWERA " ,
" S_GFZFLOWERA2 " ,
" S_GFZFLOWERB1 " ,
" S_GFZFLOWERB2 " ,
" S_GFZFLOWERC1 " ,
" S_BERRYBUSH " ,
" S_BUSH " ,
// THZ Plant
" S_THZPLANT1 " ,
" S_THZPLANT2 " ,
" S_THZPLANT3 " ,
" S_THZPLANT4 " ,
// THZ Alarm
" S_ALARM1 " ,
// Deep Sea Gargoyle
" S_GARGOYLE " ,
// DSZ Seaweed
" S_SEAWEED1 " ,
" S_SEAWEED2 " ,
" S_SEAWEED3 " ,
" S_SEAWEED4 " ,
" S_SEAWEED5 " ,
" S_SEAWEED6 " ,
// Dripping Water
" S_DRIPA1 " ,
" S_DRIPA2 " ,
" S_DRIPA3 " ,
" S_DRIPA4 " ,
" S_DRIPB1 " ,
" S_DRIPC1 " ,
" S_DRIPC2 " ,
// Coral 1
" S_CORAL1 " ,
// Coral 2
" S_CORAL2 " ,
// Coral 3
" S_CORAL3 " ,
// Blue Crystal
" S_BLUECRYSTAL1 " ,
// CEZ Chain
" S_CEZCHAIN " ,
// Flame
" S_FLAME1 " ,
" S_FLAME2 " ,
" S_FLAME3 " ,
" S_FLAME4 " ,
// Eggman Statue
" S_EGGSTATUE1 " ,
// CEZ hidden sling
" S_SLING1 " ,
" S_SLING2 " ,
// CEZ Small Mace Chain
" S_SMALLMACECHAIN " ,
// CEZ Big Mace Chain
" S_BIGMACECHAIN " ,
// CEZ Small Mace
" S_SMALLMACE " ,
// CEZ Big Mace
" S_BIGMACE " ,
" S_CEZFLOWER1 " ,
// Big Tumbleweed
" S_BIGTUMBLEWEED " ,
" S_BIGTUMBLEWEED_ROLL1 " ,
" S_BIGTUMBLEWEED_ROLL2 " ,
" S_BIGTUMBLEWEED_ROLL3 " ,
" S_BIGTUMBLEWEED_ROLL4 " ,
" S_BIGTUMBLEWEED_ROLL5 " ,
" S_BIGTUMBLEWEED_ROLL6 " ,
" S_BIGTUMBLEWEED_ROLL7 " ,
" S_BIGTUMBLEWEED_ROLL8 " ,
// Little Tumbleweed
" S_LITTLETUMBLEWEED " ,
" S_LITTLETUMBLEWEED_ROLL1 " ,
" S_LITTLETUMBLEWEED_ROLL2 " ,
" S_LITTLETUMBLEWEED_ROLL3 " ,
" S_LITTLETUMBLEWEED_ROLL4 " ,
" S_LITTLETUMBLEWEED_ROLL5 " ,
" S_LITTLETUMBLEWEED_ROLL6 " ,
" S_LITTLETUMBLEWEED_ROLL7 " ,
" S_LITTLETUMBLEWEED_ROLL8 " ,
// Cacti Sprites
" S_CACTI1 " ,
" S_CACTI2 " ,
" S_CACTI3 " ,
" S_CACTI4 " ,
// Flame jet
" S_FLAMEJETSTND " ,
" S_FLAMEJETSTART " ,
" S_FLAMEJETSTOP " ,
" S_FLAMEJETFLAME1 " ,
" S_FLAMEJETFLAME2 " ,
" S_FLAMEJETFLAME3 " ,
// Spinning flame jets
" S_FJSPINAXISA1 " , // Counter-clockwise
" S_FJSPINAXISA2 " ,
" S_FJSPINAXISA3 " ,
" S_FJSPINAXISA4 " ,
" S_FJSPINAXISA5 " ,
" S_FJSPINAXISA6 " ,
" S_FJSPINAXISA7 " ,
" S_FJSPINAXISA8 " ,
" S_FJSPINAXISA9 " ,
" S_FJSPINHELPERA1 " ,
" S_FJSPINHELPERA2 " ,
" S_FJSPINHELPERA3 " ,
" S_FJSPINAXISB1 " , // Clockwise
" S_FJSPINAXISB2 " ,
" S_FJSPINAXISB3 " ,
" S_FJSPINAXISB4 " ,
" S_FJSPINAXISB5 " ,
" S_FJSPINAXISB6 " ,
" S_FJSPINAXISB7 " ,
" S_FJSPINAXISB8 " ,
" S_FJSPINAXISB9 " ,
" S_FJSPINHELPERB1 " ,
" S_FJSPINHELPERB2 " ,
" S_FJSPINHELPERB3 " ,
// Blade's flame
" S_FLAMEJETFLAMEB1 " ,
" S_FLAMEJETFLAMEB2 " ,
" S_FLAMEJETFLAMEB3 " ,
" S_FLAMEJETFLAMEB4 " ,
" S_FLAMEJETFLAMEB5 " ,
" S_FLAMEJETFLAMEB6 " ,
// Trapgoyles
" S_TRAPGOYLE " ,
" S_TRAPGOYLE_CHECK " ,
" S_TRAPGOYLE_FIRE1 " ,
" S_TRAPGOYLE_FIRE2 " ,
" S_TRAPGOYLE_FIRE3 " ,
" S_TRAPGOYLEUP " ,
" S_TRAPGOYLEUP_CHECK " ,
" S_TRAPGOYLEUP_FIRE1 " ,
" S_TRAPGOYLEUP_FIRE2 " ,
" S_TRAPGOYLEUP_FIRE3 " ,
" S_TRAPGOYLEDOWN " ,
" S_TRAPGOYLEDOWN_CHECK " ,
" S_TRAPGOYLEDOWN_FIRE1 " ,
" S_TRAPGOYLEDOWN_FIRE2 " ,
" S_TRAPGOYLEDOWN_FIRE3 " ,
" S_TRAPGOYLELONG " ,
" S_TRAPGOYLELONG_CHECK " ,
" S_TRAPGOYLELONG_FIRE1 " ,
" S_TRAPGOYLELONG_FIRE2 " ,
" S_TRAPGOYLELONG_FIRE3 " ,
" S_TRAPGOYLELONG_FIRE4 " ,
" S_TRAPGOYLELONG_FIRE5 " ,
// ATZ's Red Crystal/Target
" S_TARGET_IDLE " ,
" S_TARGET_HIT1 " ,
" S_TARGET_HIT2 " ,
" S_TARGET_RESPAWN " ,
" S_TARGET_ALLDONE " ,
// Stalagmites
" S_STG0 " ,
" S_STG1 " ,
" S_STG2 " ,
" S_STG3 " ,
" S_STG4 " ,
" S_STG5 " ,
" S_STG6 " ,
" S_STG7 " ,
" S_STG8 " ,
" S_STG9 " ,
// Xmas-specific stuff
" S_XMASPOLE " ,
" S_CANDYCANE " ,
" S_SNOWMAN " ,
// Botanic Serenity's loads of scenery states
" S_BSZTALLFLOWER_RED " ,
" S_BSZTALLFLOWER_PURPLE " ,
" S_BSZTALLFLOWER_BLUE " ,
" S_BSZTALLFLOWER_CYAN " ,
" S_BSZTALLFLOWER_YELLOW " ,
" S_BSZTALLFLOWER_ORANGE " ,
" S_BSZFLOWER_RED " ,
" S_BSZFLOWER_PURPLE " ,
" S_BSZFLOWER_BLUE " ,
" S_BSZFLOWER_CYAN " ,
" S_BSZFLOWER_YELLOW " ,
" S_BSZFLOWER_ORANGE " ,
" S_BSZSHORTFLOWER_RED " ,
" S_BSZSHORTFLOWER_PURPLE " ,
" S_BSZSHORTFLOWER_BLUE " ,
" S_BSZSHORTFLOWER_CYAN " ,
" S_BSZSHORTFLOWER_YELLOW " ,
" S_BSZSHORTFLOWER_ORANGE " ,
" S_BSZTULIP_RED " ,
" S_BSZTULIP_PURPLE " ,
" S_BSZTULIP_BLUE " ,
" S_BSZTULIP_CYAN " ,
" S_BSZTULIP_YELLOW " ,
" S_BSZTULIP_ORANGE " ,
" S_BSZCLUSTER_RED " ,
" S_BSZCLUSTER_PURPLE " ,
" S_BSZCLUSTER_BLUE " ,
" S_BSZCLUSTER_CYAN " ,
" S_BSZCLUSTER_YELLOW " ,
" S_BSZCLUSTER_ORANGE " ,
" S_BSZBUSH_RED " ,
" S_BSZBUSH_PURPLE " ,
" S_BSZBUSH_BLUE " ,
" S_BSZBUSH_CYAN " ,
" S_BSZBUSH_YELLOW " ,
" S_BSZBUSH_ORANGE " ,
" S_BSZVINE_RED " ,
" S_BSZVINE_PURPLE " ,
" S_BSZVINE_BLUE " ,
" S_BSZVINE_CYAN " ,
" S_BSZVINE_YELLOW " ,
" S_BSZVINE_ORANGE " ,
" S_BSZSHRUB " ,
" S_BSZCLOVER " ,
" S_BSZFISH " ,
" S_BSZSUNFLOWER " ,
" S_DBALL1 " ,
" S_DBALL2 " ,
" S_DBALL3 " ,
" S_DBALL4 " ,
" S_DBALL5 " ,
" S_DBALL6 " ,
" S_EGGSTATUE2 " ,
// Shield Orb
" S_ARMA1 " ,
" S_ARMA2 " ,
" S_ARMA3 " ,
" S_ARMA4 " ,
" S_ARMA5 " ,
" S_ARMA6 " ,
" S_ARMA7 " ,
" S_ARMA8 " ,
" S_ARMA9 " ,
" S_ARMA10 " ,
" S_ARMA11 " ,
" S_ARMA12 " ,
" S_ARMA13 " ,
" S_ARMA14 " ,
" S_ARMA15 " ,
" S_ARMA16 " ,
" S_ARMF1 " ,
" S_ARMF2 " ,
" S_ARMF3 " ,
" S_ARMF4 " ,
" S_ARMF5 " ,
" S_ARMF6 " ,
" S_ARMF7 " ,
" S_ARMF8 " ,
" S_ARMF9 " ,
" S_ARMF10 " ,
" S_ARMF11 " ,
" S_ARMF12 " ,
" S_ARMF13 " ,
" S_ARMF14 " ,
" S_ARMF15 " ,
" S_ARMF16 " ,
" S_ARMB1 " ,
" S_ARMB2 " ,
" S_ARMB3 " ,
" S_ARMB4 " ,
" S_ARMB5 " ,
" S_ARMB6 " ,
" S_ARMB7 " ,
" S_ARMB8 " ,
" S_ARMB9 " ,
" S_ARMB10 " ,
" S_ARMB11 " ,
" S_ARMB12 " ,
" S_ARMB13 " ,
" S_ARMB14 " ,
" S_ARMB15 " ,
" S_ARMB16 " ,
" S_WIND1 " ,
" S_WIND2 " ,
" S_WIND3 " ,
" S_WIND4 " ,
" S_WIND5 " ,
" S_WIND6 " ,
" S_WIND7 " ,
" S_WIND8 " ,
" S_MAGN1 " ,
" S_MAGN2 " ,
" S_MAGN3 " ,
" S_MAGN4 " ,
" S_MAGN5 " ,
" S_MAGN6 " ,
" S_MAGN7 " ,
" S_MAGN8 " ,
" S_MAGN9 " ,
" S_MAGN10 " ,
" S_MAGN11 " ,
" S_MAGN12 " ,
" S_FORC1 " ,
" S_FORC2 " ,
" S_FORC3 " ,
" S_FORC4 " ,
" S_FORC5 " ,
" S_FORC6 " ,
" S_FORC7 " ,
" S_FORC8 " ,
" S_FORC9 " ,
" S_FORC10 " ,
" S_FORC11 " ,
" S_FORC12 " ,
" S_FORC13 " ,
" S_FORC14 " ,
" S_FORC15 " ,
" S_FORC16 " ,
" S_FORC17 " ,
" S_FORC18 " ,
" S_FORC19 " ,
" S_FORC20 " ,
" S_ELEM1 " ,
" S_ELEM2 " ,
" S_ELEM3 " ,
" S_ELEM4 " ,
" S_ELEM5 " ,
" S_ELEM6 " ,
" S_ELEM7 " ,
" S_ELEM8 " ,
" S_ELEM9 " ,
" S_ELEM10 " ,
" S_ELEM11 " ,
" S_ELEM12 " ,
" S_ELEMF1 " ,
" S_ELEMF2 " ,
" S_ELEMF3 " ,
" S_ELEMF4 " ,
" S_ELEMF5 " ,
" S_ELEMF6 " ,
" S_ELEMF7 " ,
" S_ELEMF8 " ,
" S_PITY1 " ,
" S_PITY2 " ,
" S_PITY3 " ,
" S_PITY4 " ,
" S_PITY5 " ,
" S_PITY6 " ,
" S_PITY7 " ,
" S_PITY8 " ,
" S_PITY9 " ,
" S_PITY10 " ,
// Invincibility Sparkles
" S_IVSP1 " ,
" S_IVSP2 " ,
" S_IVSP3 " ,
" S_IVSP4 " ,
" S_IVSP5 " ,
" S_IVSP6 " ,
" S_IVSP7 " ,
" S_IVSP8 " ,
" S_IVSP9 " ,
" S_IVSP10 " ,
" S_IVSP11 " ,
" S_IVSP12 " ,
" S_IVSP13 " ,
" S_IVSP14 " ,
" S_IVSP15 " ,
" S_IVSP16 " ,
" S_IVSP17 " ,
" S_IVSP18 " ,
" S_IVSP19 " ,
" S_IVSP20 " ,
" S_IVSP21 " ,
" S_IVSP22 " ,
" S_IVSP23 " ,
" S_IVSP24 " ,
" S_IVSP25 " ,
" S_IVSP26 " ,
" S_IVSP27 " ,
" S_IVSP28 " ,
" S_IVSP29 " ,
" S_IVSP30 " ,
" S_IVSP31 " ,
" S_IVSP32 " ,
// Super Sonic Spark
" S_SSPK1 " ,
" S_SSPK2 " ,
" S_SSPK3 " ,
" S_SSPK4 " ,
" S_SSPK5 " ,
// Freed Birdie
" S_BIRD1 " ,
" S_BIRD2 " ,
" S_BIRD3 " ,
// Freed Bunny
" S_BUNNY1 " ,
" S_BUNNY2 " ,
" S_BUNNY3 " ,
" S_BUNNY4 " ,
" S_BUNNY5 " ,
" S_BUNNY6 " ,
" S_BUNNY7 " ,
" S_BUNNY8 " ,
" S_BUNNY9 " ,
" S_BUNNY10 " ,
// Freed Mouse
" S_MOUSE1 " ,
" S_MOUSE2 " ,
// Freed Chicken
" S_CHICKEN1 " ,
" S_CHICKENHOP " ,
" S_CHICKENFLY1 " ,
" S_CHICKENFLY2 " ,
// Freed Cow
" S_COW1 " ,
" S_COW2 " ,
" S_COW3 " ,
" S_COW4 " ,
// Red Birdie in Bubble
" S_RBIRD1 " ,
" S_RBIRD2 " ,
" S_RBIRD3 " ,
" S_YELLOWSPRING " ,
" S_YELLOWSPRING2 " ,
" S_YELLOWSPRING3 " ,
" S_YELLOWSPRING4 " ,
" S_YELLOWSPRING5 " ,
" S_REDSPRING " ,
" S_REDSPRING2 " ,
" S_REDSPRING3 " ,
" S_REDSPRING4 " ,
" S_REDSPRING5 " ,
// Blue Springs
" S_BLUESPRING " ,
" S_BLUESPRING2 " ,
" S_BLUESPRING3 " ,
" S_BLUESPRING4 " ,
" S_BLUESPRING5 " ,
// Yellow Diagonal Spring
" S_YDIAG1 " ,
" S_YDIAG2 " ,
" S_YDIAG3 " ,
" S_YDIAG4 " ,
" S_YDIAG5 " ,
" S_YDIAG6 " ,
" S_YDIAG7 " ,
" S_YDIAG8 " ,
// Red Diagonal Spring
" S_RDIAG1 " ,
" S_RDIAG2 " ,
" S_RDIAG3 " ,
" S_RDIAG4 " ,
" S_RDIAG5 " ,
" S_RDIAG6 " ,
" S_RDIAG7 " ,
" S_RDIAG8 " ,
// Rain
" S_RAIN1 " ,
" S_RAINRETURN " ,
// Snowflake
" S_SNOW1 " ,
" S_SNOW2 " ,
" S_SNOW3 " ,
// Water Splish
" S_SPLISH1 " ,
" S_SPLISH2 " ,
" S_SPLISH3 " ,
" S_SPLISH4 " ,
" S_SPLISH5 " ,
" S_SPLISH6 " ,
" S_SPLISH7 " ,
" S_SPLISH8 " ,
" S_SPLISH9 " ,
// added water splash
" S_SPLASH1 " ,
" S_SPLASH2 " ,
" S_SPLASH3 " ,
// lava/slime damage burn smoke
" S_SMOKE1 " ,
" S_SMOKE2 " ,
" S_SMOKE3 " ,
" S_SMOKE4 " ,
" S_SMOKE5 " ,
// Bubbles
" S_SMALLBUBBLE " ,
" S_SMALLBUBBLE1 " ,
" S_MEDIUMBUBBLE " ,
" S_MEDIUMBUBBLE1 " ,
" S_LARGEBUBBLE " ,
" S_EXTRALARGEBUBBLE " , // breathable
" S_POP1 " , // Extra Large bubble goes POP!
" S_FOG1 " ,
" S_FOG2 " ,
" S_FOG3 " ,
" S_FOG4 " ,
" S_FOG5 " ,
" S_FOG6 " ,
" S_FOG7 " ,
" S_FOG8 " ,
" S_FOG9 " ,
" S_FOG10 " ,
" S_FOG11 " ,
" S_FOG12 " ,
" S_FOG13 " ,
" S_FOG14 " ,
" S_SEED " ,
" S_PARTICLE " ,
" S_PARTICLEGEN " ,
// Score Logos
" S_SCRA " , // 100
" S_SCRB " , // 200
" S_SCRC " , // 500
" S_SCRD " , // 1000
" S_SCRE " , // 10000
" S_SCRF " , // 400 (mario)
" S_SCRG " , // 800 (mario)
" S_SCRH " , // 2000 (mario)
" S_SCRI " , // 4000 (mario)
" S_SCRJ " , // 8000 (mario)
" S_SCRK " , // 1UP (mario)
// Drowning Timer Numbers
" S_ZERO1 " ,
" S_ONE1 " ,
" S_TWO1 " ,
" S_THREE1 " ,
" S_FOUR1 " ,
" S_FIVE1 " ,
// Tag Sign
" S_TTAG1 " ,
// Got Flag Sign
" S_GOTFLAG1 " ,
" S_GOTFLAG2 " ,
" S_GOTFLAG3 " ,
" S_GOTFLAG4 " ,
// Red Ring
" S_RRNG1 " ,
" S_RRNG2 " ,
" S_RRNG3 " ,
" S_RRNG4 " ,
" S_RRNG5 " ,
" S_RRNG6 " ,
" S_RRNG7 " ,
// Bounce Ring
" S_BOUNCERING1 " ,
" S_BOUNCERING2 " ,
" S_BOUNCERING3 " ,
" S_BOUNCERING4 " ,
" S_BOUNCERING5 " ,
" S_BOUNCERING6 " ,
" S_BOUNCERING7 " ,
" S_BOUNCERING8 " ,
" S_BOUNCERING9 " ,
" S_BOUNCERING10 " ,
" S_BOUNCERING11 " ,
" S_BOUNCERING12 " ,
" S_BOUNCERING13 " ,
" S_BOUNCERING14 " ,
" S_BOUNCERING15 " ,
" S_BOUNCERING16 " ,
" S_BOUNCERING17 " ,
" S_BOUNCERING18 " ,
" S_BOUNCERING19 " ,
" S_BOUNCERING20 " ,
" S_BOUNCERING21 " ,
" S_BOUNCERING22 " ,
" S_BOUNCERING23 " ,
" S_BOUNCERING24 " ,
" S_BOUNCERING25 " ,
" S_BOUNCERING26 " ,
" S_BOUNCERING27 " ,
" S_BOUNCERING28 " ,
" S_BOUNCERING29 " ,
" S_BOUNCERING30 " ,
" S_BOUNCERING31 " ,
" S_BOUNCERING32 " ,
" S_BOUNCERING33 " ,
" S_BOUNCERING34 " ,
" S_BOUNCERING35 " ,
// Rail Ring
" S_RAILRING1 " ,
" S_RAILRING2 " ,
" S_RAILRING3 " ,
" S_RAILRING4 " ,
" S_RAILRING5 " ,
" S_RAILRING6 " ,
" S_RAILRING7 " ,
" S_RAILRING8 " ,
" S_RAILRING9 " ,
" S_RAILRING10 " ,
" S_RAILRING11 " ,
" S_RAILRING12 " ,
" S_RAILRING13 " ,
" S_RAILRING14 " ,
" S_RAILRING15 " ,
" S_RAILRING16 " ,
" S_RAILRING17 " ,
" S_RAILRING18 " ,
" S_RAILRING19 " ,
" S_RAILRING20 " ,
" S_RAILRING21 " ,
" S_RAILRING22 " ,
" S_RAILRING23 " ,
" S_RAILRING24 " ,
" S_RAILRING25 " ,
" S_RAILRING26 " ,
" S_RAILRING27 " ,
" S_RAILRING28 " ,
" S_RAILRING29 " ,
" S_RAILRING30 " ,
" S_RAILRING31 " ,
" S_RAILRING32 " ,
" S_RAILRING33 " ,
" S_RAILRING34 " ,
" S_RAILRING35 " ,
// Infinity ring
" S_INFINITYRING1 " ,
" S_INFINITYRING2 " ,
" S_INFINITYRING3 " ,
" S_INFINITYRING4 " ,
" S_INFINITYRING5 " ,
" S_INFINITYRING6 " ,
" S_INFINITYRING7 " ,
" S_INFINITYRING8 " ,
" S_INFINITYRING9 " ,
" S_INFINITYRING10 " ,
" S_INFINITYRING11 " ,
" S_INFINITYRING12 " ,
" S_INFINITYRING13 " ,
" S_INFINITYRING14 " ,
" S_INFINITYRING15 " ,
" S_INFINITYRING16 " ,
" S_INFINITYRING17 " ,
" S_INFINITYRING18 " ,
" S_INFINITYRING19 " ,
" S_INFINITYRING20 " ,
" S_INFINITYRING21 " ,
" S_INFINITYRING22 " ,
" S_INFINITYRING23 " ,
" S_INFINITYRING24 " ,
" S_INFINITYRING25 " ,
" S_INFINITYRING26 " ,
" S_INFINITYRING27 " ,
" S_INFINITYRING28 " ,
" S_INFINITYRING29 " ,
" S_INFINITYRING30 " ,
" S_INFINITYRING31 " ,
" S_INFINITYRING32 " ,
" S_INFINITYRING33 " ,
" S_INFINITYRING34 " ,
" S_INFINITYRING35 " ,
// Automatic Ring
" S_AUTOMATICRING1 " ,
" S_AUTOMATICRING2 " ,
" S_AUTOMATICRING3 " ,
" S_AUTOMATICRING4 " ,
" S_AUTOMATICRING5 " ,
" S_AUTOMATICRING6 " ,
" S_AUTOMATICRING7 " ,
" S_AUTOMATICRING8 " ,
" S_AUTOMATICRING9 " ,
" S_AUTOMATICRING10 " ,
" S_AUTOMATICRING11 " ,
" S_AUTOMATICRING12 " ,
" S_AUTOMATICRING13 " ,
" S_AUTOMATICRING14 " ,
" S_AUTOMATICRING15 " ,
" S_AUTOMATICRING16 " ,
" S_AUTOMATICRING17 " ,
" S_AUTOMATICRING18 " ,
" S_AUTOMATICRING19 " ,
" S_AUTOMATICRING20 " ,
" S_AUTOMATICRING21 " ,
" S_AUTOMATICRING22 " ,
" S_AUTOMATICRING23 " ,
" S_AUTOMATICRING24 " ,
" S_AUTOMATICRING25 " ,
" S_AUTOMATICRING26 " ,
" S_AUTOMATICRING27 " ,
" S_AUTOMATICRING28 " ,
" S_AUTOMATICRING29 " ,
" S_AUTOMATICRING30 " ,
" S_AUTOMATICRING31 " ,
" S_AUTOMATICRING32 " ,
" S_AUTOMATICRING33 " ,
" S_AUTOMATICRING34 " ,
" S_AUTOMATICRING35 " ,
// Explosion Ring
" S_EXPLOSIONRING1 " ,
" S_EXPLOSIONRING2 " ,
" S_EXPLOSIONRING3 " ,
" S_EXPLOSIONRING4 " ,
" S_EXPLOSIONRING5 " ,
" S_EXPLOSIONRING6 " ,
" S_EXPLOSIONRING7 " ,
" S_EXPLOSIONRING8 " ,
" S_EXPLOSIONRING9 " ,
" S_EXPLOSIONRING10 " ,
" S_EXPLOSIONRING11 " ,
" S_EXPLOSIONRING12 " ,
" S_EXPLOSIONRING13 " ,
" S_EXPLOSIONRING14 " ,
" S_EXPLOSIONRING15 " ,
" S_EXPLOSIONRING16 " ,
" S_EXPLOSIONRING17 " ,
" S_EXPLOSIONRING18 " ,
" S_EXPLOSIONRING19 " ,
" S_EXPLOSIONRING20 " ,
" S_EXPLOSIONRING21 " ,
" S_EXPLOSIONRING22 " ,
" S_EXPLOSIONRING23 " ,
" S_EXPLOSIONRING24 " ,
" S_EXPLOSIONRING25 " ,
" S_EXPLOSIONRING26 " ,
" S_EXPLOSIONRING27 " ,
" S_EXPLOSIONRING28 " ,
" S_EXPLOSIONRING29 " ,
" S_EXPLOSIONRING30 " ,
" S_EXPLOSIONRING31 " ,
" S_EXPLOSIONRING32 " ,
" S_EXPLOSIONRING33 " ,
" S_EXPLOSIONRING34 " ,
" S_EXPLOSIONRING35 " ,
// Scatter Ring
" S_SCATTERRING1 " ,
" S_SCATTERRING2 " ,
" S_SCATTERRING3 " ,
" S_SCATTERRING4 " ,
" S_SCATTERRING5 " ,
" S_SCATTERRING6 " ,
" S_SCATTERRING7 " ,
" S_SCATTERRING8 " ,
" S_SCATTERRING9 " ,
" S_SCATTERRING10 " ,
" S_SCATTERRING11 " ,
" S_SCATTERRING12 " ,
" S_SCATTERRING13 " ,
" S_SCATTERRING14 " ,
" S_SCATTERRING15 " ,
" S_SCATTERRING16 " ,
" S_SCATTERRING17 " ,
" S_SCATTERRING18 " ,
" S_SCATTERRING19 " ,
" S_SCATTERRING20 " ,
" S_SCATTERRING21 " ,
" S_SCATTERRING22 " ,
" S_SCATTERRING23 " ,
" S_SCATTERRING24 " ,
" S_SCATTERRING25 " ,
" S_SCATTERRING26 " ,
" S_SCATTERRING27 " ,
" S_SCATTERRING28 " ,
" S_SCATTERRING29 " ,
" S_SCATTERRING30 " ,
" S_SCATTERRING31 " ,
" S_SCATTERRING32 " ,
" S_SCATTERRING33 " ,
" S_SCATTERRING34 " ,
" S_SCATTERRING35 " ,
// Grenade Ring
" S_GRENADERING1 " ,
" S_GRENADERING2 " ,
" S_GRENADERING3 " ,
" S_GRENADERING4 " ,
" S_GRENADERING5 " ,
" S_GRENADERING6 " ,
" S_GRENADERING7 " ,
" S_GRENADERING8 " ,
" S_GRENADERING9 " ,
" S_GRENADERING10 " ,
" S_GRENADERING11 " ,
" S_GRENADERING12 " ,
" S_GRENADERING13 " ,
" S_GRENADERING14 " ,
" S_GRENADERING15 " ,
" S_GRENADERING16 " ,
" S_GRENADERING17 " ,
" S_GRENADERING18 " ,
" S_GRENADERING19 " ,
" S_GRENADERING20 " ,
" S_GRENADERING21 " ,
" S_GRENADERING22 " ,
" S_GRENADERING23 " ,
" S_GRENADERING24 " ,
" S_GRENADERING25 " ,
" S_GRENADERING26 " ,
" S_GRENADERING27 " ,
" S_GRENADERING28 " ,
" S_GRENADERING29 " ,
" S_GRENADERING30 " ,
" S_GRENADERING31 " ,
" S_GRENADERING32 " ,
" S_GRENADERING33 " ,
" S_GRENADERING34 " ,
" S_GRENADERING35 " ,
// Weapon pickup
" S_BOUNCEPICKUP1 " ,
" S_BOUNCEPICKUP2 " ,
" S_BOUNCEPICKUP3 " ,
" S_BOUNCEPICKUP4 " ,
" S_BOUNCEPICKUP5 " ,
" S_BOUNCEPICKUP6 " ,
" S_BOUNCEPICKUP7 " ,
" S_BOUNCEPICKUP8 " ,
" S_BOUNCEPICKUP9 " ,
" S_BOUNCEPICKUP10 " ,
" S_BOUNCEPICKUP11 " ,
" S_BOUNCEPICKUP12 " ,
" S_BOUNCEPICKUP13 " ,
" S_BOUNCEPICKUP14 " ,
" S_BOUNCEPICKUP15 " ,
" S_BOUNCEPICKUP16 " ,
" S_BOUNCEPICKUPFADE1 " ,
" S_BOUNCEPICKUPFADE2 " ,
" S_BOUNCEPICKUPFADE3 " ,
" S_BOUNCEPICKUPFADE4 " ,
" S_BOUNCEPICKUPFADE5 " ,
" S_BOUNCEPICKUPFADE6 " ,
" S_BOUNCEPICKUPFADE7 " ,
" S_BOUNCEPICKUPFADE8 " ,
" S_RAILPICKUP1 " ,
" S_RAILPICKUP2 " ,
" S_RAILPICKUP3 " ,
" S_RAILPICKUP4 " ,
" S_RAILPICKUP5 " ,
" S_RAILPICKUP6 " ,
" S_RAILPICKUP7 " ,
" S_RAILPICKUP8 " ,
" S_RAILPICKUP9 " ,
" S_RAILPICKUP10 " ,
" S_RAILPICKUP11 " ,
" S_RAILPICKUP12 " ,
" S_RAILPICKUP13 " ,
" S_RAILPICKUP14 " ,
" S_RAILPICKUP15 " ,
" S_RAILPICKUP16 " ,
" S_RAILPICKUPFADE1 " ,
" S_RAILPICKUPFADE2 " ,
" S_RAILPICKUPFADE3 " ,
" S_RAILPICKUPFADE4 " ,
" S_RAILPICKUPFADE5 " ,
" S_RAILPICKUPFADE6 " ,
" S_RAILPICKUPFADE7 " ,
" S_RAILPICKUPFADE8 " ,
" S_AUTOPICKUP1 " ,
" S_AUTOPICKUP2 " ,
" S_AUTOPICKUP3 " ,
" S_AUTOPICKUP4 " ,
" S_AUTOPICKUP5 " ,
" S_AUTOPICKUP6 " ,
" S_AUTOPICKUP7 " ,
" S_AUTOPICKUP8 " ,
" S_AUTOPICKUP9 " ,
" S_AUTOPICKUP10 " ,
" S_AUTOPICKUP11 " ,
" S_AUTOPICKUP12 " ,
" S_AUTOPICKUP13 " ,
" S_AUTOPICKUP14 " ,
" S_AUTOPICKUP15 " ,
" S_AUTOPICKUP16 " ,
" S_AUTOPICKUPFADE1 " ,
" S_AUTOPICKUPFADE2 " ,
" S_AUTOPICKUPFADE3 " ,
" S_AUTOPICKUPFADE4 " ,
" S_AUTOPICKUPFADE5 " ,
" S_AUTOPICKUPFADE6 " ,
" S_AUTOPICKUPFADE7 " ,
" S_AUTOPICKUPFADE8 " ,
" S_EXPLODEPICKUP1 " ,
" S_EXPLODEPICKUP2 " ,
" S_EXPLODEPICKUP3 " ,
" S_EXPLODEPICKUP4 " ,
" S_EXPLODEPICKUP5 " ,
" S_EXPLODEPICKUP6 " ,
" S_EXPLODEPICKUP7 " ,
" S_EXPLODEPICKUP8 " ,
" S_EXPLODEPICKUP9 " ,
" S_EXPLODEPICKUP10 " ,
" S_EXPLODEPICKUP11 " ,
" S_EXPLODEPICKUP12 " ,
" S_EXPLODEPICKUP13 " ,
" S_EXPLODEPICKUP14 " ,
" S_EXPLODEPICKUP15 " ,
" S_EXPLODEPICKUP16 " ,
" S_EXPLODEPICKUPFADE1 " ,
" S_EXPLODEPICKUPFADE2 " ,
" S_EXPLODEPICKUPFADE3 " ,
" S_EXPLODEPICKUPFADE4 " ,
" S_EXPLODEPICKUPFADE5 " ,
" S_EXPLODEPICKUPFADE6 " ,
" S_EXPLODEPICKUPFADE7 " ,
" S_EXPLODEPICKUPFADE8 " ,
" S_SCATTERPICKUP1 " ,
" S_SCATTERPICKUP2 " ,
" S_SCATTERPICKUP3 " ,
" S_SCATTERPICKUP4 " ,
" S_SCATTERPICKUP5 " ,
" S_SCATTERPICKUP6 " ,
" S_SCATTERPICKUP7 " ,
" S_SCATTERPICKUP8 " ,
" S_SCATTERPICKUP9 " ,
" S_SCATTERPICKUP10 " ,
" S_SCATTERPICKUP11 " ,
" S_SCATTERPICKUP12 " ,
" S_SCATTERPICKUP13 " ,
" S_SCATTERPICKUP14 " ,
" S_SCATTERPICKUP15 " ,
" S_SCATTERPICKUP16 " ,
" S_SCATTERPICKUPFADE1 " ,
" S_SCATTERPICKUPFADE2 " ,
" S_SCATTERPICKUPFADE3 " ,
" S_SCATTERPICKUPFADE4 " ,
" S_SCATTERPICKUPFADE5 " ,
" S_SCATTERPICKUPFADE6 " ,
" S_SCATTERPICKUPFADE7 " ,
" S_SCATTERPICKUPFADE8 " ,
" S_GRENADEPICKUP1 " ,
" S_GRENADEPICKUP2 " ,
" S_GRENADEPICKUP3 " ,
" S_GRENADEPICKUP4 " ,
" S_GRENADEPICKUP5 " ,
" S_GRENADEPICKUP6 " ,
" S_GRENADEPICKUP7 " ,
" S_GRENADEPICKUP8 " ,
" S_GRENADEPICKUP9 " ,
" S_GRENADEPICKUP10 " ,
" S_GRENADEPICKUP11 " ,
" S_GRENADEPICKUP12 " ,
" S_GRENADEPICKUP13 " ,
" S_GRENADEPICKUP14 " ,
" S_GRENADEPICKUP15 " ,
" S_GRENADEPICKUP16 " ,
" S_GRENADEPICKUPFADE1 " ,
" S_GRENADEPICKUPFADE2 " ,
" S_GRENADEPICKUPFADE3 " ,
" S_GRENADEPICKUPFADE4 " ,
" S_GRENADEPICKUPFADE5 " ,
" S_GRENADEPICKUPFADE6 " ,
" S_GRENADEPICKUPFADE7 " ,
" S_GRENADEPICKUPFADE8 " ,
// Thrown Weapon Rings
" S_THROWNBOUNCE1 " ,
" S_THROWNBOUNCE2 " ,
" S_THROWNBOUNCE3 " ,
" S_THROWNBOUNCE4 " ,
" S_THROWNBOUNCE5 " ,
" S_THROWNBOUNCE6 " ,
" S_THROWNBOUNCE7 " ,
" S_THROWNINFINITY1 " ,
" S_THROWNINFINITY2 " ,
" S_THROWNINFINITY3 " ,
" S_THROWNINFINITY4 " ,
" S_THROWNINFINITY5 " ,
" S_THROWNINFINITY6 " ,
" S_THROWNINFINITY7 " ,
" S_THROWNAUTOMATIC1 " ,
" S_THROWNAUTOMATIC2 " ,
" S_THROWNAUTOMATIC3 " ,
" S_THROWNAUTOMATIC4 " ,
" S_THROWNAUTOMATIC5 " ,
" S_THROWNAUTOMATIC6 " ,
" S_THROWNAUTOMATIC7 " ,
" S_THROWNEXPLOSION1 " ,
" S_THROWNEXPLOSION2 " ,
" S_THROWNEXPLOSION3 " ,
" S_THROWNEXPLOSION4 " ,
" S_THROWNEXPLOSION5 " ,
" S_THROWNEXPLOSION6 " ,
" S_THROWNEXPLOSION7 " ,
" S_THROWNGRENADE1 " ,
" S_THROWNGRENADE2 " ,
" S_THROWNGRENADE3 " ,
" S_THROWNGRENADE4 " ,
" S_THROWNGRENADE5 " ,
" S_THROWNGRENADE6 " ,
" S_THROWNGRENADE7 " ,
" S_THROWNGRENADE8 " ,
" S_THROWNGRENADE9 " ,
" S_THROWNGRENADE10 " ,
" S_THROWNGRENADE11 " ,
" S_THROWNGRENADE12 " ,
" S_THROWNGRENADE13 " ,
" S_THROWNGRENADE14 " ,
" S_THROWNGRENADE15 " ,
" S_THROWNGRENADE16 " ,
" S_THROWNGRENADE17 " ,
" S_THROWNGRENADE18 " ,
" S_THROWNSCATTER " ,
" S_RINGEXPLODE " ,
" S_COIN1 " ,
" S_COIN2 " ,
" S_COIN3 " ,
" S_COINSPARKLE1 " ,
" S_COINSPARKLE2 " ,
" S_COINSPARKLE3 " ,
" S_COINSPARKLE4 " ,
" S_GOOMBA1 " ,
" S_GOOMBA1B " ,
" S_GOOMBA2 " ,
" S_GOOMBA3 " ,
" S_GOOMBA4 " ,
" S_GOOMBA5 " ,
" S_GOOMBA6 " ,
" S_GOOMBA7 " ,
" S_GOOMBA8 " ,
" S_GOOMBA9 " ,
" S_GOOMBA_DEAD " ,
" S_BLUEGOOMBA1 " ,
" S_BLUEGOOMBA1B " ,
" S_BLUEGOOMBA2 " ,
" S_BLUEGOOMBA3 " ,
" S_BLUEGOOMBA4 " ,
" S_BLUEGOOMBA5 " ,
" S_BLUEGOOMBA6 " ,
" S_BLUEGOOMBA7 " ,
" S_BLUEGOOMBA8 " ,
" S_BLUEGOOMBA9 " ,
" S_BLUEGOOMBA_DEAD " ,
// Mario-specific stuff
" S_FIREFLOWER1 " ,
" S_FIREFLOWER2 " ,
" S_FIREFLOWER3 " ,
" S_FIREFLOWER4 " ,
" S_FIREBALL1 " ,
" S_FIREBALL2 " ,
" S_FIREBALL3 " ,
" S_FIREBALL4 " ,
" S_FIREBALLEXP1 " ,
" S_FIREBALLEXP2 " ,
" S_FIREBALLEXP3 " ,
" S_SHELL " ,
" S_SHELL1 " ,
" S_SHELL2 " ,
" S_SHELL3 " ,
" S_SHELL4 " ,
" S_PUMA1 " ,
" S_PUMA2 " ,
" S_PUMA3 " ,
" S_PUMA4 " ,
" S_PUMA5 " ,
" S_PUMA6 " ,
" S_HAMMER1 " ,
" S_HAMMER2 " ,
" S_HAMMER3 " ,
" S_HAMMER4 " ,
" S_KOOPA1 " ,
" S_KOOPA2 " ,
" S_KOOPAFLAME1 " ,
" S_KOOPAFLAME2 " ,
" S_KOOPAFLAME3 " ,
" S_AXE1 " ,
" S_AXE2 " ,
" S_AXE3 " ,
" S_MARIOBUSH1 " ,
" S_MARIOBUSH2 " ,
" S_TOAD " ,
// Nights-specific stuff
" S_NIGHTSDRONE1 " ,
" S_NIGHTSDRONE2 " ,
" S_NIGHTSDRONE_SPARKLING1 " ,
" S_NIGHTSDRONE_SPARKLING2 " ,
" S_NIGHTSDRONE_SPARKLING3 " ,
" S_NIGHTSDRONE_SPARKLING4 " ,
" S_NIGHTSDRONE_SPARKLING5 " ,
" S_NIGHTSDRONE_SPARKLING6 " ,
" S_NIGHTSDRONE_SPARKLING7 " ,
" S_NIGHTSDRONE_SPARKLING8 " ,
" S_NIGHTSDRONE_SPARKLING9 " ,
" S_NIGHTSDRONE_SPARKLING10 " ,
" S_NIGHTSDRONE_SPARKLING11 " ,
" S_NIGHTSDRONE_SPARKLING12 " ,
" S_NIGHTSDRONE_SPARKLING13 " ,
" S_NIGHTSDRONE_SPARKLING14 " ,
" S_NIGHTSDRONE_SPARKLING15 " ,
" S_NIGHTSDRONE_SPARKLING16 " ,
" S_NIGHTSGOAL1 " ,
" S_NIGHTSGOAL2 " ,
" S_NIGHTSGOAL3 " ,
" S_NIGHTSGOAL4 " ,
" S_NIGHTSFLY1A " ,
" S_NIGHTSFLY1B " ,
" S_NIGHTSDRILL1A " ,
" S_NIGHTSDRILL1B " ,
" S_NIGHTSDRILL1C " ,
" S_NIGHTSDRILL1D " ,
" S_NIGHTSFLY2A " ,
" S_NIGHTSFLY2B " ,
" S_NIGHTSDRILL2A " ,
" S_NIGHTSDRILL2B " ,
" S_NIGHTSDRILL2C " ,
" S_NIGHTSDRILL2D " ,
" S_NIGHTSFLY3A " ,
" S_NIGHTSFLY3B " ,
" S_NIGHTSDRILL3A " ,
" S_NIGHTSDRILL3B " ,
" S_NIGHTSDRILL3C " ,
" S_NIGHTSDRILL3D " ,
" S_NIGHTSFLY4A " ,
" S_NIGHTSFLY4B " ,
" S_NIGHTSDRILL4A " ,
" S_NIGHTSDRILL4B " ,
" S_NIGHTSDRILL4C " ,
" S_NIGHTSDRILL4D " ,
" S_NIGHTSFLY5A " ,
" S_NIGHTSFLY5B " ,
" S_NIGHTSDRILL5A " ,
" S_NIGHTSDRILL5B " ,
" S_NIGHTSDRILL5C " ,
" S_NIGHTSDRILL5D " ,
" S_NIGHTSFLY6A " ,
" S_NIGHTSFLY6B " ,
" S_NIGHTSDRILL6A " ,
" S_NIGHTSDRILL6B " ,
" S_NIGHTSDRILL6C " ,
" S_NIGHTSDRILL6D " ,
" S_NIGHTSFLY7A " ,
" S_NIGHTSFLY7B " ,
" S_NIGHTSDRILL7A " ,
" S_NIGHTSDRILL7B " ,
" S_NIGHTSDRILL7C " ,
" S_NIGHTSDRILL7D " ,
" S_NIGHTSFLY8A " ,
" S_NIGHTSFLY8B " ,
" S_NIGHTSDRILL8A " ,
" S_NIGHTSDRILL8B " ,
" S_NIGHTSDRILL8C " ,
" S_NIGHTSDRILL8D " ,
" S_NIGHTSFLY9A " ,
" S_NIGHTSFLY9B " ,
" S_NIGHTSDRILL9A " ,
" S_NIGHTSDRILL9B " ,
" S_NIGHTSDRILL9C " ,
" S_NIGHTSDRILL9D " ,
" S_NIGHTSHURT1 " ,
" S_NIGHTSHURT2 " ,
" S_NIGHTSHURT3 " ,
" S_NIGHTSHURT4 " ,
" S_NIGHTSHURT5 " ,
" S_NIGHTSHURT6 " ,
" S_NIGHTSHURT7 " ,
" S_NIGHTSHURT8 " ,
" S_NIGHTSHURT9 " ,
" S_NIGHTSHURT10 " ,
" S_NIGHTSHURT11 " ,
" S_NIGHTSHURT12 " ,
" S_NIGHTSHURT13 " ,
" S_NIGHTSHURT14 " ,
" S_NIGHTSHURT15 " ,
" S_NIGHTSHURT16 " ,
" S_NIGHTSHURT17 " ,
" S_NIGHTSHURT18 " ,
" S_NIGHTSHURT19 " ,
" S_NIGHTSHURT20 " ,
" S_NIGHTSHURT21 " ,
" S_NIGHTSHURT22 " ,
" S_NIGHTSHURT23 " ,
" S_NIGHTSHURT24 " ,
" S_NIGHTSHURT25 " ,
" S_NIGHTSHURT26 " ,
" S_NIGHTSHURT27 " ,
" S_NIGHTSHURT28 " ,
" S_NIGHTSHURT29 " ,
" S_NIGHTSHURT30 " ,
" S_NIGHTSHURT31 " ,
" S_NIGHTSHURT32 " ,
" S_NIGHTSPARKLE1 " ,
" S_NIGHTSPARKLE2 " ,
" S_NIGHTSPARKLE3 " ,
" S_NIGHTSPARKLE4 " ,
" S_NIGHTSPARKLESUPER1 " ,
" S_NIGHTSPARKLESUPER2 " ,
" S_NIGHTSPARKLESUPER3 " ,
" S_NIGHTSPARKLESUPER4 " ,
" S_NIGHTSLOOPHELPER " ,
// NiGHTS bumper
" S_NIGHTSBUMPER1 " ,
" S_NIGHTSBUMPER2 " ,
" S_NIGHTSBUMPER3 " ,
" S_NIGHTSBUMPER4 " ,
" S_NIGHTSBUMPER5 " ,
" S_NIGHTSBUMPER6 " ,
" S_NIGHTSBUMPER7 " ,
" S_NIGHTSBUMPER8 " ,
" S_NIGHTSBUMPER9 " ,
" S_NIGHTSBUMPER10 " ,
" S_NIGHTSBUMPER11 " ,
" S_NIGHTSBUMPER12 " ,
" S_HOOP " ,
" S_HOOP_XMASA " ,
" S_HOOP_XMASB " ,
" S_NIGHTSCORE10 " ,
" S_NIGHTSCORE20 " ,
" S_NIGHTSCORE30 " ,
" S_NIGHTSCORE40 " ,
" S_NIGHTSCORE50 " ,
" S_NIGHTSCORE60 " ,
" S_NIGHTSCORE70 " ,
" S_NIGHTSCORE80 " ,
" S_NIGHTSCORE90 " ,
" S_NIGHTSCORE100 " ,
" S_NIGHTSCORE10_2 " ,
" S_NIGHTSCORE20_2 " ,
" S_NIGHTSCORE30_2 " ,
" S_NIGHTSCORE40_2 " ,
" S_NIGHTSCORE50_2 " ,
" S_NIGHTSCORE60_2 " ,
" S_NIGHTSCORE70_2 " ,
" S_NIGHTSCORE80_2 " ,
" S_NIGHTSCORE90_2 " ,
" S_NIGHTSCORE100_2 " ,
" S_NIGHTSWING " ,
" S_NIGHTSWING_XMAS " ,
// NiGHTS Paraloop Powerups
" S_NIGHTSPOWERUP1 " ,
" S_NIGHTSPOWERUP2 " ,
" S_NIGHTSPOWERUP3 " ,
" S_NIGHTSPOWERUP4 " ,
" S_NIGHTSPOWERUP5 " ,
" S_NIGHTSPOWERUP6 " ,
" S_NIGHTSPOWERUP7 " ,
" S_NIGHTSPOWERUP8 " ,
" S_NIGHTSPOWERUP9 " ,
" S_NIGHTSPOWERUP10 " ,
" S_EGGCAPSULE " ,
// Orbiting Chaos Emeralds
" S_ORBITEM1 " ,
" S_ORBITEM2 " ,
" S_ORBITEM3 " ,
" S_ORBITEM4 " ,
" S_ORBITEM5 " ,
" S_ORBITEM6 " ,
" S_ORBITEM7 " ,
2014-03-17 12:13:16 +00:00
" S_ORBITEM8 " ,
" S_ORBITEM9 " ,
" S_ORBITEM10 " ,
" S_ORBITEM11 " ,
" S_ORBITEM12 " ,
" S_ORBITEM13 " ,
" S_ORBITEM14 " ,
" S_ORBITEM15 " ,
" S_ORBITEM16 " ,
2014-03-15 16:59:03 +00:00
// "Flicky" helper
" S_NIGHTOPIANHELPER1 " ,
" S_NIGHTOPIANHELPER2 " ,
" S_NIGHTOPIANHELPER3 " ,
" S_NIGHTOPIANHELPER4 " ,
" S_NIGHTOPIANHELPER5 " ,
" S_NIGHTOPIANHELPER6 " ,
" S_NIGHTOPIANHELPER7 " ,
" S_NIGHTOPIANHELPER8 " ,
" S_CRUMBLE1 " ,
" S_CRUMBLE2 " ,
" S_SUPERTRANS1 " ,
" S_SUPERTRANS2 " ,
" S_SUPERTRANS3 " ,
" S_SUPERTRANS4 " ,
" S_SUPERTRANS5 " ,
" S_SUPERTRANS6 " ,
" S_SUPERTRANS7 " ,
" S_SUPERTRANS8 " ,
" S_SUPERTRANS9 " ,
// Spark
" S_SPRK1 " ,
" S_SPRK2 " ,
" S_SPRK3 " ,
" S_SPRK4 " ,
" S_SPRK5 " ,
" S_SPRK6 " ,
" S_SPRK7 " ,
" S_SPRK8 " ,
" S_SPRK9 " ,
" S_SPRK10 " ,
" S_SPRK11 " ,
" S_SPRK12 " ,
" S_SPRK13 " ,
" S_SPRK14 " ,
" S_SPRK15 " ,
" S_SPRK16 " ,
// Robot Explosion
" S_XPLD1 " ,
" S_XPLD2 " ,
" S_XPLD3 " ,
" S_XPLD4 " ,
// Underwater Explosion
" S_WPLD1 " ,
" S_WPLD2 " ,
" S_WPLD3 " ,
" S_WPLD4 " ,
" S_WPLD5 " ,
" S_WPLD6 " ,
" S_ROCKSPAWN " ,
" S_ROCKCRUMBLEA1 " ,
" S_ROCKCRUMBLEA2 " ,
" S_ROCKCRUMBLEA3 " ,
" S_ROCKCRUMBLEA4 " ,
" S_ROCKCRUMBLEA5 " ,
" S_ROCKCRUMBLEB1 " ,
" S_ROCKCRUMBLEB2 " ,
" S_ROCKCRUMBLEB3 " ,
" S_ROCKCRUMBLEB4 " ,
" S_ROCKCRUMBLEB5 " ,
" S_ROCKCRUMBLEC1 " ,
" S_ROCKCRUMBLEC2 " ,
" S_ROCKCRUMBLEC3 " ,
" S_ROCKCRUMBLEC4 " ,
" S_ROCKCRUMBLEC5 " ,
" S_ROCKCRUMBLED1 " ,
" S_ROCKCRUMBLED2 " ,
" S_ROCKCRUMBLED3 " ,
" S_ROCKCRUMBLED4 " ,
" S_ROCKCRUMBLED5 " ,
" S_ROCKCRUMBLEE1 " ,
" S_ROCKCRUMBLEE2 " ,
" S_ROCKCRUMBLEE3 " ,
" S_ROCKCRUMBLEE4 " ,
" S_ROCKCRUMBLEE5 " ,
" S_ROCKCRUMBLEF1 " ,
" S_ROCKCRUMBLEF2 " ,
" S_ROCKCRUMBLEF3 " ,
" S_ROCKCRUMBLEF4 " ,
" S_ROCKCRUMBLEF5 " ,
" S_ROCKCRUMBLEG1 " ,
" S_ROCKCRUMBLEG2 " ,
" S_ROCKCRUMBLEG3 " ,
" S_ROCKCRUMBLEG4 " ,
" S_ROCKCRUMBLEG5 " ,
" S_ROCKCRUMBLEH1 " ,
" S_ROCKCRUMBLEH2 " ,
" S_ROCKCRUMBLEH3 " ,
" S_ROCKCRUMBLEH4 " ,
" S_ROCKCRUMBLEH5 " ,
" S_ROCKCRUMBLEI1 " ,
" S_ROCKCRUMBLEI2 " ,
" S_ROCKCRUMBLEI3 " ,
" S_ROCKCRUMBLEI4 " ,
" S_ROCKCRUMBLEI5 " ,
" S_ROCKCRUMBLEJ1 " ,
" S_ROCKCRUMBLEJ2 " ,
" S_ROCKCRUMBLEJ3 " ,
" S_ROCKCRUMBLEJ4 " ,
" S_ROCKCRUMBLEJ5 " ,
" S_ROCKCRUMBLEK1 " ,
" S_ROCKCRUMBLEK2 " ,
" S_ROCKCRUMBLEK3 " ,
" S_ROCKCRUMBLEK4 " ,
" S_ROCKCRUMBLEK5 " ,
" S_ROCKCRUMBLEL1 " ,
" S_ROCKCRUMBLEL2 " ,
" S_ROCKCRUMBLEL3 " ,
" S_ROCKCRUMBLEL4 " ,
" S_ROCKCRUMBLEL5 " ,
" S_ROCKCRUMBLEM1 " ,
" S_ROCKCRUMBLEM2 " ,
" S_ROCKCRUMBLEM3 " ,
" S_ROCKCRUMBLEM4 " ,
" S_ROCKCRUMBLEM5 " ,
" S_ROCKCRUMBLEN1 " ,
" S_ROCKCRUMBLEN2 " ,
" S_ROCKCRUMBLEN3 " ,
" S_ROCKCRUMBLEN4 " ,
" S_ROCKCRUMBLEN5 " ,
" S_ROCKCRUMBLEO1 " ,
" S_ROCKCRUMBLEO2 " ,
" S_ROCKCRUMBLEO3 " ,
" S_ROCKCRUMBLEO4 " ,
" S_ROCKCRUMBLEO5 " ,
" S_ROCKCRUMBLEP1 " ,
" S_ROCKCRUMBLEP2 " ,
" S_ROCKCRUMBLEP3 " ,
" S_ROCKCRUMBLEP4 " ,
" S_ROCKCRUMBLEP5 " ,
" S_SRB1_CRAWLA1 " ,
" S_SRB1_CRAWLA2 " ,
" S_SRB1_CRAWLA3 " ,
" S_SRB1_CRAWLA4 " ,
" S_SRB1_BAT1 " ,
" S_SRB1_BAT2 " ,
" S_SRB1_BAT3 " ,
" S_SRB1_BAT4 " ,
" S_SRB1_ROBOFISH1 " ,
" S_SRB1_ROBOFISH2 " ,
" S_SRB1_ROBOFISH3 " ,
" S_SRB1_VOLCANOGUY1 " ,
" S_SRB1_VOLCANOGUY2 " ,
" S_SRB1_HOPPY1 " ,
" S_SRB1_HOPPY2 " ,
" S_SRB1_HOPPYWATER1 " ,
" S_SRB1_HOPPYWATER2 " ,
" S_SRB1_HOPPYSKYLAB1 " ,
" S_SRB1_MMZFLYING1 " ,
" S_SRB1_MMZFLYING2 " ,
" S_SRB1_MMZFLYING3 " ,
" S_SRB1_MMZFLYING4 " ,
" S_SRB1_MMZFLYING5 " ,
" S_SRB1_UFO1 " ,
" S_SRB1_UFO2 " ,
" S_SRB1_GRAYBOT1 " ,
" S_SRB1_GRAYBOT2 " ,
" S_SRB1_GRAYBOT3 " ,
" S_SRB1_GRAYBOT4 " ,
" S_SRB1_GRAYBOT5 " ,
" S_SRB1_GRAYBOT6 " ,
" S_SRB1_ROBOTOPOLIS1 " ,
" S_SRB1_ROBOTOPOLIS2 " ,
" S_SRB1_RBZBUZZ1 " ,
" S_SRB1_RBZBUZZ2 " ,
" S_SRB1_RBZSPIKES1 " ,
" S_SRB1_RBZSPIKES2 " ,
" S_SRB1_METALSONIC1 " ,
" S_SRB1_METALSONIC2 " ,
" S_SRB1_METALSONIC3 " ,
" S_SRB1_GOLDBOT1 " ,
" S_SRB1_GOLDBOT2 " ,
" S_SRB1_GOLDBOT3 " ,
" S_SRB1_GOLDBOT4 " ,
" S_SRB1_GOLDBOT5 " ,
" S_SRB1_GOLDBOT6 " ,
" S_SRB1_GENREX1 " ,
" S_SRB1_GENREX2 " ,
# ifdef SEENAMES
" S_NAMECHECK " ,
# endif
} ;
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
// I am leaving the prefixes solely for clarity to programmers,
// because sadly no one remembers this place while searching for full state names.
static const char * const MOBJTYPE_LIST [ ] = { // array length left dynamic for sanity testing later.
" MT_NULL " ,
" MT_UNKNOWN " ,
" MT_THOK " , // Thok! mobj
" MT_PLAYER " ,
// Enemies
" MT_BLUECRAWLA " ,
" MT_REDCRAWLA " ,
" MT_GFZFISH " , // Greenflower Fish
" MT_GOLDBUZZ " ,
" MT_REDBUZZ " ,
" MT_AQUABUZZ " ,
" MT_JETTBOMBER " , // Jetty-Syn Bomber
" MT_JETTGUNNER " , // Jetty-Syn Gunner
" MT_CRAWLACOMMANDER " , // Crawla Commander
" MT_DETON " , // Deton
" MT_SKIM " , // Skim mine dropper
" MT_TURRET " ,
" MT_POPUPTURRET " ,
" MT_SHARP " , // Sharp
" MT_JETJAW " , // Jet Jaw
" MT_SNAILER " , // Snailer
" MT_VULTURE " , // Vulture
" MT_POINTY " , // Pointy
" MT_POINTYBALL " , // Pointy Ball
" MT_ROBOHOOD " , // Robo-Hood
" MT_FACESTABBER " , // CastleBot FaceStabber
" MT_EGGGUARD " , // Egg Guard
" MT_EGGSHIELD " , // Egg Shield for Egg Guard
" MT_GSNAPPER " , // Green Snapper
" MT_MINUS " , // Minus
" MT_SPRINGSHELL " , // Spring Shell (no drop)
" MT_YELLOWSHELL " , // Spring Shell (yellow)
" MT_UNIDUS " , // Unidus
" MT_UNIBALL " , // Unidus Ball
// Generic Boss Items
" MT_BOSSEXPLODE " ,
" MT_SONIC3KBOSSEXPLODE " ,
" MT_BOSSFLYPOINT " ,
" MT_EGGTRAP " ,
" MT_BOSS3WAYPOINT " ,
" MT_BOSS9GATHERPOINT " ,
// Boss 1
" MT_EGGMOBILE " ,
" MT_JETFUME1 " ,
" MT_EGGMOBILE_BALL " ,
" MT_EGGMOBILE_TARGET " ,
" MT_EGGMOBILE_FIRE " ,
// Boss 2
" MT_EGGMOBILE2 " ,
" MT_EGGMOBILE2_POGO " ,
" MT_BOSSTANK1 " ,
" MT_BOSSTANK2 " ,
" MT_BOSSSPIGOT " ,
" MT_GOOP " ,
// Boss 3
" MT_EGGMOBILE3 " ,
" MT_PROPELLER " ,
" MT_FAKEMOBILE " ,
// Boss 4
" MT_EGGMOBILE4 " ,
" MT_EGGMOBILE4_MACE " ,
" MT_JETFLAME " ,
// Black Eggman (Boss 7)
" MT_BLACKEGGMAN " ,
" MT_BLACKEGGMAN_HELPER " ,
" MT_BLACKEGGMAN_GOOPFIRE " ,
" MT_BLACKEGGMAN_MISSILE " ,
// New Very-Last-Minute 2.1 Brak Eggman (Cy-Brak-demon)
" MT_CYBRAKDEMON " ,
" MT_CYBRAKDEMON_ELECTRIC_BARRIER " ,
" MT_CYBRAKDEMON_MISSILE " ,
" MT_CYBRAKDEMON_FLAMESHOT " ,
" MT_CYBRAKDEMON_FLAMEREST " ,
" MT_CYBRAKDEMON_TARGET_RETICULE " ,
" MT_CYBRAKDEMON_NAPALM_BOMB_LARGE " ,
" MT_CYBRAKDEMON_NAPALM_BOMB_SMALL " ,
" MT_CYBRAKDEMON_NAPALM_FLAMES " ,
" MT_CYBRAKDEMON_VILE_EXPLOSION " ,
// Metal Sonic
" MT_METALSONIC_RACE " ,
" MT_METALSONIC_BATTLE " ,
" MT_MSSHIELD_FRONT " ,
" MT_MSGATHER " ,
// Collectible Items
" MT_RING " ,
" MT_FLINGRING " , // Lost ring
# ifdef BLUE_SPHERES
" MT_BLUEBALL " , // Blue sphere replacement for special stages
# endif
" MT_REDTEAMRING " , //Rings collectable by red team.
" MT_BLUETEAMRING " , //Rings collectable by blue team.
" MT_EMMY " , // emerald token for special stage
" MT_TOKEN " , // Special Stage Token (uncollectible part)
" MT_REDFLAG " , // Red CTF Flag
" MT_BLUEFLAG " , // Blue CTF Flag
" MT_EMBLEM " ,
" MT_EMERALD1 " ,
" MT_EMERALD2 " ,
" MT_EMERALD3 " ,
" MT_EMERALD4 " ,
" MT_EMERALD5 " ,
" MT_EMERALD6 " ,
" MT_EMERALD7 " ,
" MT_EMERHUNT " , // Emerald Hunt
" MT_EMERALDSPAWN " , // Emerald spawner w/ delay
" MT_FLINGEMERALD " , // Lost emerald
// Springs and others
" MT_FAN " ,
" MT_STEAM " , // Steam riser
" MT_BLUESPRING " ,
" MT_YELLOWSPRING " ,
" MT_REDSPRING " ,
" MT_YELLOWDIAG " , // Yellow Diagonal Spring
" MT_REDDIAG " , // Red Diagonal Spring
// Interactive Objects
" MT_BUBBLES " , // Bubble source
" MT_SIGN " , // Level end sign
" MT_SPIKEBALL " , // Spike Ball
" MT_SPECIALSPIKEBALL " ,
" MT_SPINFIRE " ,
" MT_SPIKE " ,
" MT_STARPOST " ,
" MT_BIGMINE " ,
" MT_BIGAIRMINE " ,
" MT_CANNONLAUNCHER " ,
// Monitor Boxes
" MT_SUPERRINGBOX " ,
" MT_REDRINGBOX " ,
" MT_BLUERINGBOX " ,
" MT_SNEAKERTV " ,
" MT_INV " ,
" MT_PRUP " , // 1up Box
" MT_YELLOWTV " , // Attract shield TV
" MT_BLUETV " , // Force shield TV
" MT_BLACKTV " , // Bomb shield TV
" MT_WHITETV " , // Jump shield TV
" MT_GREENTV " , // Elemental shield TV
" MT_PITYTV " , // Pity shield TV
" MT_EGGMANBOX " ,
" MT_MIXUPBOX " ,
" MT_RECYCLETV " ,
" MT_RECYCLEICO " ,
" MT_QUESTIONBOX " ,
" MT_GRAVITYBOX " ,
" MT_SCORETVSMALL " ,
" MT_SCORETVLARGE " ,
// Monitor miscellany
" MT_MONITOREXPLOSION " ,
" MT_REDMONITOREXPLOSION " ,
" MT_BLUEMONITOREXPLOSION " ,
" MT_RINGICO " ,
" MT_SHOESICO " ,
" MT_INVCICO " ,
" MT_1UPICO " ,
" MT_YSHIELDICO " ,
" MT_BSHIELDICO " ,
" MT_KSHIELDICO " ,
" MT_WSHIELDICO " ,
" MT_GSHIELDICO " ,
" MT_PITYSHIELDICO " ,
" MT_EGGMANICO " ,
" MT_MIXUPICO " ,
" MT_GRAVITYICO " ,
" MT_SCOREICOSMALL " ,
" MT_SCOREICOLARGE " ,
// Projectiles
" MT_ROCKET " ,
" MT_LASER " ,
" MT_TORPEDO " ,
" MT_TORPEDO2 " , // silent
" MT_ENERGYBALL " ,
" MT_MINE " , // Skim/Jetty-Syn mine
" MT_JETTBULLET " , // Jetty-Syn Bullet
" MT_TURRETLASER " ,
" MT_CANNONBALL " , // Cannonball
" MT_CANNONBALLDECOR " , // Decorative/still cannonball
" MT_ARROW " , // Arrow
" MT_DEMONFIRE " , // Trapgoyle fire
// Greenflower Scenery
" MT_GFZFLOWER1 " ,
" MT_GFZFLOWER2 " ,
" MT_GFZFLOWER3 " ,
" MT_BERRYBUSH " ,
" MT_BUSH " ,
// Techno Hill Scenery
" MT_THZPLANT " , // THZ Plant
" MT_ALARM " ,
// Deep Sea Scenery
" MT_GARGOYLE " , // Deep Sea Gargoyle
" MT_SEAWEED " , // DSZ Seaweed
" MT_WATERDRIP " , // Dripping Water source
" MT_WATERDROP " , // Water drop from dripping water
" MT_CORAL1 " , // Coral 1
" MT_CORAL2 " , // Coral 2
" MT_CORAL3 " , // Coral 3
" MT_BLUECRYSTAL " , // Blue Crystal
// Castle Eggman Scenery
" MT_CHAIN " , // CEZ Chain
" MT_FLAME " , // Flame (has corona)
" MT_EGGSTATUE " , // Eggman Statue
" MT_MACEPOINT " , // Mace rotation point
" MT_SWINGMACEPOINT " , // Mace swinging point
" MT_HANGMACEPOINT " , // Hangable mace chain
" MT_SPINMACEPOINT " , // Spin/Controllable mace chain
" MT_HIDDEN_SLING " , // Spin mace chain (activatable)
" MT_SMALLMACECHAIN " , // Small Mace Chain
" MT_BIGMACECHAIN " , // Big Mace Chain
" MT_SMALLMACE " , // Small Mace
" MT_BIGMACE " , // Big Mace
" MT_CEZFLOWER " ,
// Arid Canyon Scenery
" MT_BIGTUMBLEWEED " ,
" MT_LITTLETUMBLEWEED " ,
" MT_CACTI1 " ,
" MT_CACTI2 " ,
" MT_CACTI3 " ,
" MT_CACTI4 " ,
// Red Volcano Scenery
" MT_FLAMEJET " ,
" MT_VERTICALFLAMEJET " ,
" MT_FLAMEJETFLAME " ,
" MT_FJSPINAXISA " , // Counter-clockwise
" MT_FJSPINHELPERA " ,
" MT_FJSPINAXISB " , // Clockwise
" MT_FJSPINHELPERB " ,
" MT_FLAMEJETFLAMEB " , // Blade's flame
// Dark City Scenery
// Egg Rock Scenery
// Azure Temple Scenery
" MT_TRAPGOYLE " ,
" MT_TRAPGOYLEUP " ,
" MT_TRAPGOYLEDOWN " ,
" MT_TRAPGOYLELONG " ,
" MT_TARGET " ,
// Stalagmites
" MT_STALAGMITE0 " ,
" MT_STALAGMITE1 " ,
" MT_STALAGMITE2 " ,
" MT_STALAGMITE3 " ,
" MT_STALAGMITE4 " ,
" MT_STALAGMITE5 " ,
" MT_STALAGMITE6 " ,
" MT_STALAGMITE7 " ,
" MT_STALAGMITE8 " ,
" MT_STALAGMITE9 " ,
// Christmas Scenery
" MT_XMASPOLE " ,
" MT_CANDYCANE " ,
" MT_SNOWMAN " ,
// Botanic Serenity
" MT_BSZTALLFLOWER_RED " ,
" MT_BSZTALLFLOWER_PURPLE " ,
" MT_BSZTALLFLOWER_BLUE " ,
" MT_BSZTALLFLOWER_CYAN " ,
" MT_BSZTALLFLOWER_YELLOW " ,
" MT_BSZTALLFLOWER_ORANGE " ,
" MT_BSZFLOWER_RED " ,
" MT_BSZFLOWER_PURPLE " ,
" MT_BSZFLOWER_BLUE " ,
" MT_BSZFLOWER_CYAN " ,
" MT_BSZFLOWER_YELLOW " ,
" MT_BSZFLOWER_ORANGE " ,
" MT_BSZSHORTFLOWER_RED " ,
" MT_BSZSHORTFLOWER_PURPLE " ,
" MT_BSZSHORTFLOWER_BLUE " ,
" MT_BSZSHORTFLOWER_CYAN " ,
" MT_BSZSHORTFLOWER_YELLOW " ,
" MT_BSZSHORTFLOWER_ORANGE " ,
" MT_BSZTULIP_RED " ,
" MT_BSZTULIP_PURPLE " ,
" MT_BSZTULIP_BLUE " ,
" MT_BSZTULIP_CYAN " ,
" MT_BSZTULIP_YELLOW " ,
" MT_BSZTULIP_ORANGE " ,
" MT_BSZCLUSTER_RED " ,
" MT_BSZCLUSTER_PURPLE " ,
" MT_BSZCLUSTER_BLUE " ,
" MT_BSZCLUSTER_CYAN " ,
" MT_BSZCLUSTER_YELLOW " ,
" MT_BSZCLUSTER_ORANGE " ,
" MT_BSZBUSH_RED " ,
" MT_BSZBUSH_PURPLE " ,
" MT_BSZBUSH_BLUE " ,
" MT_BSZBUSH_CYAN " ,
" MT_BSZBUSH_YELLOW " ,
" MT_BSZBUSH_ORANGE " ,
" MT_BSZVINE_RED " ,
" MT_BSZVINE_PURPLE " ,
" MT_BSZVINE_BLUE " ,
" MT_BSZVINE_CYAN " ,
" MT_BSZVINE_YELLOW " ,
" MT_BSZVINE_ORANGE " ,
" MT_BSZSHRUB " ,
" MT_BSZCLOVER " ,
" MT_BSZFISH " ,
" MT_BSZSUNFLOWER " ,
// Misc scenery
" MT_DBALL " ,
" MT_EGGSTATUE2 " ,
// Powerup Indicators
" MT_GREENORB " , // Elemental shield mobj
" MT_YELLOWORB " , // Attract shield mobj
" MT_BLUEORB " , // Force shield mobj
" MT_BLACKORB " , // Armageddon shield mobj
" MT_WHITEORB " , // Whirlwind shield mobj
" MT_PITYORB " , // Pity shield mobj
" MT_IVSP " , // invincibility sparkles
" MT_SUPERSPARK " , // Super Sonic Spark
// Freed Animals
" MT_BIRD " , // Birdie freed!
" MT_BUNNY " , // Bunny freed!
" MT_MOUSE " , // Mouse
" MT_CHICKEN " , // Chicken
" MT_COW " , // Cow
" MT_REDBIRD " , // Red Birdie in Bubble
// Environmental Effects
" MT_RAIN " , // Rain
" MT_SNOWFLAKE " , // Snowflake
" MT_SPLISH " , // Water splish!
" MT_SMOKE " ,
" MT_SMALLBUBBLE " , // small bubble
" MT_MEDIUMBUBBLE " , // medium bubble
" MT_EXTRALARGEBUBBLE " , // extra large bubble
" MT_TFOG " ,
" MT_SEED " ,
" MT_PARTICLE " ,
" MT_PARTICLEGEN " , // For fans, etc.
// Game Indicators
" MT_SCORE " , // score logo
" MT_DROWNNUMBERS " , // Drowning Timer
" MT_GOTEMERALD " , // Chaos Emerald (intangible)
" MT_TAG " , // Tag Sign
" MT_GOTFLAG " , // Got Flag sign
" MT_GOTFLAG2 " , // Got Flag sign
// Ambient Sounds
" MT_AWATERA " , // Ambient Water Sound 1
" MT_AWATERB " , // Ambient Water Sound 2
" MT_AWATERC " , // Ambient Water Sound 3
" MT_AWATERD " , // Ambient Water Sound 4
" MT_AWATERE " , // Ambient Water Sound 5
" MT_AWATERF " , // Ambient Water Sound 6
" MT_AWATERG " , // Ambient Water Sound 7
" MT_AWATERH " , // Ambient Water Sound 8
" MT_RANDOMAMBIENT " ,
" MT_RANDOMAMBIENT2 " ,
// Ring Weapons
" MT_REDRING " ,
" MT_BOUNCERING " ,
" MT_RAILRING " ,
" MT_INFINITYRING " ,
" MT_AUTOMATICRING " ,
" MT_EXPLOSIONRING " ,
" MT_SCATTERRING " ,
" MT_GRENADERING " ,
" MT_BOUNCEPICKUP " ,
" MT_RAILPICKUP " ,
" MT_AUTOPICKUP " ,
" MT_EXPLODEPICKUP " ,
" MT_SCATTERPICKUP " ,
" MT_GRENADEPICKUP " ,
" MT_THROWNBOUNCE " ,
" MT_THROWNINFINITY " ,
" MT_THROWNAUTOMATIC " ,
" MT_THROWNSCATTER " ,
" MT_THROWNEXPLOSION " ,
" MT_THROWNGRENADE " ,
// Mario-specific stuff
" MT_COIN " ,
" MT_FLINGCOIN " ,
" MT_GOOMBA " ,
" MT_BLUEGOOMBA " ,
" MT_FIREFLOWER " ,
" MT_FIREBALL " ,
" MT_SHELL " ,
" MT_PUMA " ,
" MT_HAMMER " ,
" MT_KOOPA " ,
" MT_KOOPAFLAME " ,
" MT_AXE " ,
" MT_MARIOBUSH1 " ,
" MT_MARIOBUSH2 " ,
" MT_TOAD " ,
// NiGHTS Stuff
" MT_AXIS " ,
" MT_AXISTRANSFER " ,
" MT_AXISTRANSFERLINE " ,
" MT_NIGHTSDRONE " ,
" MT_NIGHTSGOAL " ,
" MT_NIGHTSCHAR " ,
" MT_NIGHTSPARKLE " ,
" MT_NIGHTSLOOPHELPER " ,
" MT_NIGHTSBUMPER " , // NiGHTS Bumper
" MT_HOOP " ,
" MT_HOOPCOLLIDE " , // Collision detection for NiGHTS hoops
" MT_HOOPCENTER " , // Center of a hoop
" MT_NIGHTSCORE " ,
" MT_NIGHTSWING " ,
" MT_NIGHTSSUPERLOOP " ,
" MT_NIGHTSDRILLREFILL " ,
" MT_NIGHTSHELPER " ,
" MT_NIGHTSEXTRATIME " ,
" MT_NIGHTSLINKFREEZE " ,
" MT_EGGCAPSULE " ,
" MT_NIGHTOPIANHELPER " , // the actual helper object that orbits you
// Utility Objects
" MT_CHAOSSPAWNER " ,
" MT_TELEPORTMAN " ,
" MT_ALTVIEWMAN " ,
" MT_CRUMBLEOBJ " , // Sound generator for crumbling platform
" MT_TUBEWAYPOINT " ,
" MT_PUSH " ,
" MT_PULL " ,
" MT_GHOST " ,
" MT_OVERLAY " ,
" MT_POLYANCHOR " ,
" MT_POLYSPAWN " ,
" MT_POLYSPAWNCRUSH " ,
// Skybox objects
" MT_SKYBOX " ,
// Debris
" MT_SPARK " , //spark
" MT_EXPLODE " , // Robot Explosion
" MT_UWEXPLODE " , // Underwater Explosion
" MT_ROCKSPAWNER " ,
" MT_FALLINGROCK " ,
" MT_ROCKCRUMBLE1 " ,
" MT_ROCKCRUMBLE2 " ,
" MT_ROCKCRUMBLE3 " ,
" MT_ROCKCRUMBLE4 " ,
" MT_ROCKCRUMBLE5 " ,
" MT_ROCKCRUMBLE6 " ,
" MT_ROCKCRUMBLE7 " ,
" MT_ROCKCRUMBLE8 " ,
" MT_ROCKCRUMBLE9 " ,
" MT_ROCKCRUMBLE10 " ,
" MT_ROCKCRUMBLE11 " ,
" MT_ROCKCRUMBLE12 " ,
" MT_ROCKCRUMBLE13 " ,
" MT_ROCKCRUMBLE14 " ,
" MT_ROCKCRUMBLE15 " ,
" MT_ROCKCRUMBLE16 " ,
" MT_SRB1_CRAWLA " ,
" MT_SRB1_BAT " ,
" MT_SRB1_ROBOFISH " ,
" MT_SRB1_VOLCANOGUY " ,
" MT_SRB1_HOPPY " ,
" MT_SRB1_HOPPYWATER " ,
" MT_SRB1_HOPPYSKYLAB " ,
" MT_SRB1_MMZFLYING " ,
" MT_SRB1_UFO " ,
" MT_SRB1_GRAYBOT " ,
" MT_SRB1_ROBOTOPOLIS " ,
" MT_SRB1_RBZBUZZ " ,
" MT_SRB1_RBZSPIKES " ,
" MT_SRB1_METALSONIC " ,
" MT_SRB1_GOLDBOT " ,
" MT_SRB1_GENREX " ,
# ifdef SEENAMES
" MT_NAMECHECK " ,
# endif
} ;
static const char * const MOBJFLAG_LIST [ ] = {
" SPECIAL " ,
" SOLID " ,
" SHOOTABLE " ,
" NOSECTOR " ,
" NOBLOCKMAP " ,
" AMBUSH " ,
" PUSHABLE " ,
" BOSS " ,
" SPAWNCEILING " ,
" NOGRAVITY " ,
" AMBIENT " ,
" SLIDEME " ,
" NOCLIP " ,
" FLOAT " ,
" BOXICON " ,
" MISSILE " ,
" SPRING " ,
" BOUNCE " ,
" MONITOR " ,
" NOTHINK " ,
" FIRE " ,
" NOCLIPHEIGHT " ,
" ENEMY " ,
" SCENERY " ,
" PAIN " ,
" STICKY " ,
" NIGHTSITEM " ,
" NOCLIPTHING " ,
2014-03-23 16:00:29 +00:00
" GRENADEBOUNCE " ,
2014-03-15 16:59:03 +00:00
" RUNSPAWNFUNC " ,
NULL
} ;
// \tMF2_(\S+).*// (.+) --> \t"\1", // \2
static const char * const MOBJFLAG2_LIST [ ] = {
" AXIS " , // It's a NiGHTS axis! (For faster checking)
" TWOD " , // Moves like it's in a 2D level
" DONTRESPAWN " , // Don't respawn this object!
" DONTDRAW " , // Don't generate a vissprite
" AUTOMATIC " , // Thrown ring has automatic properties
" RAILRING " , // Thrown ring has rail properties
" BOUNCERING " , // Thrown ring has bounce properties
" EXPLOSION " , // Thrown ring has explosive properties
" SCATTER " , // Thrown ring has scatter properties
" BEYONDTHEGRAVE " , // Source of this missile has died and has since respawned.
" PUSHED " , // Mobj was already pushed this tic
" SLIDEPUSH " , // MF_PUSHABLE that pushes continuously.
" CLASSICPUSH " , // Drops straight down when object has negative Z.
" STANDONME " , // While not pushable, stand on me anyway.
" INFLOAT " , // Floating to a height for a move, don't auto float to target's height.
" DEBRIS " , // Splash ring from explosion ring
" NIGHTSPULL " , // Attracted from a paraloop
" JUSTATTACKED " , // can be pushed by other moving mobjs
" FIRING " , // turret fire
" SUPERFIRE " , // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it.
" SHADOW " , // Fuzzy draw, makes targeting harder.
" STRONGBOX " , // Flag used for "strong" random monitors.
" OBJECTFLIP " , // Flag for objects that always have flipped gravity.
" SKULLFLY " , // Special handling: skull in flight.
" FRET " , // Flashing from a previous hit
" BOSSNOTRAP " , // No Egg Trap after boss
" BOSSFLEE " , // Boss is fleeing!
" BOSSDEAD " , // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
NULL
} ;
static const char * const MOBJEFLAG_LIST [ ] = {
" ONGROUND " , // The mobj stands on solid floor (not on another mobj or in air)
" JUSTHITFLOOR " , // The mobj just hit the floor while falling, this is cleared on next frame
" TOUCHWATER " , // The mobj stands in a sector with water, and touches the surface
" UNDERWATER " , // The mobj stands in a sector with water, and his waist is BELOW the water surface
" JUSTSTEPPEDDOWN " , // used for ramp sectors
" VERTICALFLIP " , // Vertically flip sprite/allow upside-down physics
" GOOWATER " , // Goo water
NULL
} ;
static const char * const MAPTHINGFLAG_LIST [ 16 ] = {
NULL ,
" OBJECTFLIP " , // Reverse gravity flag for objects.
" OBJECTSPECIAL " , // Special flag used with certain objects.
" AMBUSH " , // Deaf monsters/do not react to sound.
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
} ;
static const char * const PLAYERFLAG_LIST [ ] = {
// Flip camera angle with gravity flip prefrence.
" FLIPCAM " ,
// Cheats
" GODMODE " ,
" NOCLIP " ,
" INVIS " ,
// True if button down last tic.
" ATTACKDOWN " ,
" USEDOWN " ,
" JUMPDOWN " ,
" WPNDOWN " ,
// Unmoving states
" STASIS " , // Player is not allowed to move
" JUMPSTASIS " , // and that includes jumping.
// (we don't include FULLSTASIS here I guess because it's just those two together...?)
// Did you get a time-over?
" TIMEOVER " ,
// Ready for Super?
" SUPERREADY " ,
// Character action status
" JUMPED " ,
" SPINNING " ,
" STARTDASH " ,
" THOKKED " ,
// Are you gliding?
" GLIDING " ,
// Tails pickup!
" CARRIED " ,
// Sliding (usually in water) like Labyrinth/Oil Ocean
" SLIDING " ,
// Hanging on a rope
" ROPEHANG " ,
// Hanging on an item of some kind - zipline, chain, etc. (->tracer)
" ITEMHANG " ,
// On the mace chain spinning around (->tracer)
" MACESPIN " ,
/*** NIGHTS STUFF ***/
// Is the player in NiGHTS mode?
" NIGHTSMODE " ,
" TRANSFERTOCLOSEST " ,
// Spill rings after falling
" NIGHTSFALL " ,
" DRILLING " ,
" SKIDDOWN " ,
/*** TAG STUFF ***/
" TAGGED " , // Player has been tagged and awaits the next round in hide and seek.
" TAGIT " , // The player is it! For Tag Mode
NULL // stop loop here.
} ;
// Linedef flags
static const char * const ML_LIST [ 16 ] = {
" IMPASSIBLE " ,
" BLOCKMONSTERS " ,
" TWOSIDED " ,
" DONTPEGTOP " ,
" DONTPEGBOTTOM " ,
" EFFECT1 " ,
" NOCLIMB " ,
" EFFECT2 " ,
" EFFECT3 " ,
" EFFECT4 " ,
" EFFECT5 " ,
" NOSONIC " ,
" NOTAILS " ,
" NOKNUX " ,
" BOUNCY " ,
" TFERLINE "
} ;
// This DOES differ from r_draw's Color_Names, unfortunately.
static const char * COLOR_ENUMS [ ] = {
" NONE " , // SKINCOLOR_NONE
" WHITE " , // SKINCOLOR_WHITE
" SILVER " , // SKINCOLOR_SILVER
" GREY " , // SKINCOLOR_GREY
" BLACK " , // SKINCOLOR_BLACK
" CYAN " , // SKINCOLOR_CYAN
" TEAL " , // SKINCOLOR_TEAL
" STEELBLUE " , // SKINCOLOR_STEELBLUE
" BLUE " , // SKINCOLOR_BLUE
" PEACH " , // SKINCOLOR_PEACH
" TAN " , // SKINCOLOR_TAN
" PINK " , // SKINCOLOR_PINK
" LAVENDER " , // SKINCOLOR_LAVENDER
" PURPLE " , // SKINCOLOR_PURPLE
" ORANGE " , // SKINCOLOR_ORANGE
" ROSEWOOD " , // SKINCOLOR_ROSEWOOD
" BEIGE " , // SKINCOLOR_BEIGE
" BROWN " , // SKINCOLOR_BROWN
" RED " , // SKINCOLOR_RED
" DARKRED " , // SKINCOLOR_DARKRED
" NEONGREEN " , // SKINCOLOR_NEONGREEN
" GREEN " , // SKINCOLOR_GREEN
" ZIM " , // SKINCOLOR_ZIM
" OLIVE " , // SKINCOLOR_OLIVE
" YELLOW " , // SKINCOLOR_YELLOW
" GOLD " // SKINCOLOR_GOLD
} ;
static const char * const POWERS_LIST [ ] = {
" INVULNERABILITY " ,
" SNEAKERS " ,
" FLASHING " ,
" SHIELD " ,
" TAILSFLY " , // tails flying
" UNDERWATER " , // underwater timer
" SPACETIME " , // In space, no one can hear you spin!
" EXTRALIFE " , // Extra Life timer
" SUPER " , // Are you super?
" GRAVITYBOOTS " , // gravity boots
// Weapon ammunition
" INFINITYRING " ,
" BOUNCERING " ,
" RAILRING " ,
" AUTOMATICRING " ,
" EXPLOSIONRING " ,
" SCATTERRING " ,
" GRENADERING " ,
// Power Stones
" EMERALDS " , // stored like global 'emeralds' variable
// NiGHTS powerups
" NIGHTS_SUPERLOOP " ,
" NIGHTS_HELPER " ,
" NIGHTS_LINKFREEZE " ,
//for linedef exec 427
" NOCONTROL " ,
" INGOOP " // In goop
} ;
static const char * const HUDITEMS_LIST [ ] = {
" LIVESNAME " ,
" LIVESPIC " ,
" LIVESNUM " ,
" LIVESX " ,
2014-03-21 18:42:55 +00:00
2014-03-15 16:59:03 +00:00
" RINGS " ,
2014-03-21 18:42:55 +00:00
" RINGSSPLIT " ,
2014-03-15 16:59:03 +00:00
" RINGSNUM " ,
2014-03-21 18:42:55 +00:00
" RINGSNUMSPLIT " ,
2014-03-15 16:59:03 +00:00
" SCORE " ,
" SCORENUM " ,
2014-03-21 18:42:55 +00:00
" TIME " ,
2014-03-15 16:59:03 +00:00
" TIMESPLIT " ,
2014-03-21 18:42:55 +00:00
" MINUTES " ,
2014-03-15 16:59:03 +00:00
" MINUTESSPLIT " ,
2014-03-21 18:42:55 +00:00
" TIMECOLON " ,
2014-03-15 16:59:03 +00:00
" TIMECOLONSPLIT " ,
" SECONDS " ,
2014-03-21 18:42:55 +00:00
" SECONDSSPLIT " ,
2014-03-15 16:59:03 +00:00
" TIMETICCOLON " ,
2014-03-21 18:42:55 +00:00
" TICS " ,
2014-03-15 16:59:03 +00:00
" SS_TOTALRINGS " ,
2014-03-21 18:42:55 +00:00
" SS_TOTALRINGS_SPLIT " ,
2014-03-15 16:59:03 +00:00
" GETRINGS " ,
" GETRINGSNUM " ,
" TIMELEFT " ,
" TIMELEFTNUM " ,
" TIMEUP " ,
" HUNTPICS " ,
" GRAVBOOTSICO " ,
" LAP "
} ;
struct {
const char * n ;
// has to be able to hold both fixed_t and angle_t, so drastic measure!!
# ifdef HAVE_BLUA
lua_Integer v ;
# else
INT64 v ;
# endif
} const INT_CONST [ ] = {
// If a mod removes some variables here,
// please leave the names in-tact and just set
// the value to 0 or something.
// integer type limits, from doomtype.h
// INT64 and UINT64 limits not included, they're too big for most purposes anyway
// signed
{ " INT8_MIN " , INT8_MIN } ,
{ " INT16_MIN " , INT16_MIN } ,
{ " INT32_MIN " , INT32_MIN } ,
{ " INT8_MAX " , INT8_MAX } ,
{ " INT16_MAX " , INT16_MAX } ,
{ " INT32_MAX " , INT32_MAX } ,
// unsigned
{ " UINT8_MAX " , UINT8_MAX } ,
{ " UINT16_MAX " , UINT16_MAX } ,
{ " UINT32_MAX " , UINT32_MAX } ,
// fixed_t constants, from m_fixed.h
{ " FRACUNIT " , FRACUNIT } ,
{ " FRACBITS " , FRACBITS } ,
// doomdef.h constants
{ " TICRATE " , TICRATE } ,
{ " RING_DIST " , RING_DIST } ,
{ " PUSHACCEL " , PUSHACCEL } ,
{ " MODID " , MODID } , // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into.
{ " CODEBASE " , CODEBASE } , // or what release of SRB2 this is.
// Special linedef executor tag numbers!
{ " LE_PINCHPHASE " , LE_PINCHPHASE } , // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!)
{ " LE_ALLBOSSESDEAD " , LE_ALLBOSSESDEAD } , // All bosses in the map are dead (Egg capsule raise)
{ " LE_BOSSDEAD " , LE_BOSSDEAD } , // A boss in the map died (Chaos mode boss tally)
{ " LE_BOSS4DROP " , LE_BOSS4DROP } , // CEZ boss dropped its cage
{ " LE_BRAKVILEATACK " , LE_BRAKVILEATACK } , // Brak's doing his LOS attack, oh noes
/// \todo Get all this stuff into its own sections, maybe. Maybe.
// Frame settings
{ " FF_FRAMEMASK " , FF_FRAMEMASK } ,
{ " FF_FULLBRIGHT " , FF_FULLBRIGHT } ,
{ " FF_TRANSMASK " , FF_TRANSMASK } ,
{ " FF_TRANSSHIFT " , FF_TRANSSHIFT } ,
// Transparency for SOCs is pre-shifted
{ " TR_TRANS10 " , tr_trans10 < < FF_TRANSSHIFT } ,
{ " TR_TRANS20 " , tr_trans20 < < FF_TRANSSHIFT } ,
{ " TR_TRANS30 " , tr_trans30 < < FF_TRANSSHIFT } ,
{ " TR_TRANS40 " , tr_trans40 < < FF_TRANSSHIFT } ,
{ " TR_TRANS50 " , tr_trans50 < < FF_TRANSSHIFT } ,
{ " TR_TRANS60 " , tr_trans60 < < FF_TRANSSHIFT } ,
{ " TR_TRANS70 " , tr_trans70 < < FF_TRANSSHIFT } ,
{ " TR_TRANS80 " , tr_trans80 < < FF_TRANSSHIFT } ,
{ " TR_TRANS90 " , tr_trans90 < < FF_TRANSSHIFT } ,
// Transparency for Lua is not, unless capitalized as above.
{ " tr_trans10 " , tr_trans10 } ,
{ " tr_trans20 " , tr_trans20 } ,
{ " tr_trans30 " , tr_trans30 } ,
{ " tr_trans40 " , tr_trans40 } ,
{ " tr_trans50 " , tr_trans50 } ,
{ " tr_trans60 " , tr_trans60 } ,
{ " tr_trans70 " , tr_trans70 } ,
{ " tr_trans80 " , tr_trans80 } ,
{ " tr_trans90 " , tr_trans90 } ,
{ " NUMTRANSMAPS " , NUMTRANSMAPS } ,
// Type of levels
{ " TOL_SP " , TOL_SP } ,
{ " TOL_COOP " , TOL_COOP } ,
{ " TOL_COMPETITION " , TOL_COMPETITION } ,
{ " TOL_RACE " , TOL_RACE } ,
{ " TOL_MATCH " , TOL_MATCH } ,
{ " TOL_TAG " , TOL_TAG } ,
{ " TOL_CTF " , TOL_CTF } ,
{ " TOL_2D " , TOL_2D } ,
{ " TOL_MARIO " , TOL_MARIO } ,
{ " TOL_NIGHTS " , TOL_NIGHTS } ,
{ " TOL_ERZ3 " , TOL_ERZ3 } ,
{ " TOL_XMAS " , TOL_XMAS } ,
// NiGHTS grades
{ " GRADE_F " , GRADE_F } ,
{ " GRADE_E " , GRADE_E } ,
{ " GRADE_D " , GRADE_D } ,
{ " GRADE_C " , GRADE_C } ,
{ " GRADE_B " , GRADE_B } ,
{ " GRADE_A " , GRADE_A } ,
{ " GRADE_S " , GRADE_S } ,
// Emeralds
{ " EMERALD1 " , EMERALD1 } ,
{ " EMERALD2 " , EMERALD2 } ,
{ " EMERALD3 " , EMERALD3 } ,
{ " EMERALD4 " , EMERALD4 } ,
{ " EMERALD5 " , EMERALD5 } ,
{ " EMERALD6 " , EMERALD6 } ,
{ " EMERALD7 " , EMERALD7 } ,
// SKINCOLOR_ doesn't include this..!
{ " MAXSKINCOLORS " , MAXSKINCOLORS } ,
// Precipitation
{ " PRECIP_NONE " , PRECIP_NONE } ,
{ " PRECIP_STORM " , PRECIP_STORM } ,
{ " PRECIP_SNOW " , PRECIP_SNOW } ,
{ " PRECIP_RAIN " , PRECIP_RAIN } ,
{ " PRECIP_BLANK " , PRECIP_BLANK } ,
{ " PRECIP_STORM_NORAIN " , PRECIP_STORM_NORAIN } ,
{ " PRECIP_STORM_NOSTRIKES " , PRECIP_STORM_NOSTRIKES } ,
// Shields
// These ones use the lower 8 bits
{ " SH_NONE " , SH_NONE } ,
{ " SH_JUMP " , SH_JUMP } ,
{ " SH_ATTRACT " , SH_ATTRACT } ,
{ " SH_ELEMENTAL " , SH_ELEMENTAL } ,
{ " SH_BOMB " , SH_BOMB } ,
{ " SH_BUBBLEWRAP " , SH_BUBBLEWRAP } ,
{ " SH_THUNDERCOIN " , SH_THUNDERCOIN } ,
{ " SH_FLAMEAURA " , SH_FLAMEAURA } ,
{ " SH_PITY " , SH_PITY } ,
// These ones are special and use the upper bits
{ " SH_FIREFLOWER " , SH_FIREFLOWER } , // Lower bits are a normal shield stacked on top of the fire flower
{ " SH_FORCE " , SH_FORCE } , // Lower bits are how many hits left, 0 is the last hit
// Stack masks
{ " SH_STACK " , SH_STACK } ,
{ " SH_NOSTACK " , SH_NOSTACK } ,
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon
{ " RW_AUTO " , RW_AUTO } ,
{ " RW_BOUNCE " , RW_BOUNCE } ,
{ " RW_SCATTER " , RW_SCATTER } ,
{ " RW_GRENADE " , RW_GRENADE } ,
{ " RW_EXPLODE " , RW_EXPLODE } ,
{ " RW_RAIL " , RW_RAIL } ,
// Character flags (skinflags_t)
{ " SF_SUPER " , SF_SUPER } ,
{ " SF_SUPERANIMS " , SF_SUPERANIMS } ,
{ " SF_SUPERSPIN " , SF_SUPERSPIN } ,
{ " SF_HIRES " , SF_HIRES } ,
{ " SF_NOSKID " , SF_NOSKID } ,
{ " SF_NOSPEEDADJUST " , SF_NOSPEEDADJUST } ,
// Character abilities!
// Primary
{ " CA_NONE " , CA_NONE } , // now slot 0!
{ " CA_THOK " , CA_THOK } ,
{ " CA_FLY " , CA_FLY } ,
{ " CA_GLIDEANDCLIMB " , CA_GLIDEANDCLIMB } ,
{ " CA_HOMINGTHOK " , CA_HOMINGTHOK } ,
{ " CA_DOUBLEJUMP " , CA_DOUBLEJUMP } ,
{ " CA_FLOAT " , CA_FLOAT } ,
{ " CA_SLOWFALL " , CA_SLOWFALL } ,
{ " CA_SWIM " , CA_SWIM } ,
{ " CA_TELEKINESIS " , CA_TELEKINESIS } ,
{ " CA_FALLSWITCH " , CA_FALLSWITCH } ,
{ " CA_JUMPBOOST " , CA_JUMPBOOST } ,
{ " CA_AIRDRILL " , CA_AIRDRILL } ,
// Secondary
{ " CA2_NONE " , CA2_NONE } , // now slot 0!
{ " CA2_SPINDASH " , CA2_SPINDASH } ,
{ " CA2_MULTIABILITY " , CA2_MULTIABILITY } ,
// Sound flags
{ " SF_TOTALLYSINGLE " , SF_TOTALLYSINGLE } ,
{ " SF_NOMULTIPLESOUND " , SF_NOMULTIPLESOUND } ,
{ " SF_OUTSIDESOUND " , SF_OUTSIDESOUND } ,
{ " SF_X4AWAYSOUND " , SF_X4AWAYSOUND } ,
{ " SF_X8AWAYSOUND " , SF_X8AWAYSOUND } ,
{ " SF_NOINTERRUPT " , SF_NOINTERRUPT } ,
{ " SF_X2AWAYSOUND " , SF_X2AWAYSOUND } ,
# ifdef HAVE_BLUA
// p_local.h constants
{ " FLOATSPEED " , FLOATSPEED } ,
{ " MAXSTEPMOVE " , MAXSTEPMOVE } ,
{ " USERANGE " , USERANGE } ,
{ " MELEERANGE " , MELEERANGE } ,
{ " MISSILERANGE " , MISSILERANGE } ,
{ " ONFLOORZ " , ONFLOORZ } , // INT32_MIN
{ " ONCEILINGZ " , ONCEILINGZ } , //INT32_MAX
// for P_FlashPal
{ " PAL_WHITE " , PAL_WHITE } ,
{ " PAL_MIXUP " , PAL_MIXUP } ,
{ " PAL_RECYCLE " , PAL_RECYCLE } ,
{ " PAL_NUKE " , PAL_NUKE } ,
// Gametypes, for use with global var "gametype"
{ " GT_COOP " , GT_COOP } ,
{ " GT_COMPETITION " , GT_COMPETITION } ,
{ " GT_RACE " , GT_RACE } ,
{ " GT_MATCH " , GT_MATCH } ,
{ " GT_TEAMMATCH " , GT_TEAMMATCH } ,
{ " GT_TAG " , GT_TAG } ,
{ " GT_HIDEANDSEEK " , GT_HIDEANDSEEK } ,
{ " GT_CTF " , GT_CTF } ,
// Player state (playerstate_t)
{ " PST_LIVE " , PST_LIVE } , // Playing or camping.
{ " PST_DEAD " , PST_DEAD } , // Dead on the ground, view follows killer.
{ " PST_REBORN " , PST_REBORN } , // Ready to restart/respawn???
// Player animation (panim_t)
{ " PA_ETC " , PA_ETC } ,
{ " PA_IDLE " , PA_IDLE } ,
{ " PA_WALK " , PA_WALK } ,
{ " PA_RUN " , PA_RUN } ,
{ " PA_ROLL " , PA_ROLL } ,
{ " PA_FALL " , PA_FALL } ,
{ " PA_ABILITY " , PA_ABILITY } ,
// Current weapon
{ " WEP_AUTO " , WEP_AUTO } ,
{ " WEP_BOUNCE " , WEP_BOUNCE } ,
{ " WEP_SCATTER " , WEP_SCATTER } ,
{ " WEP_GRENADE " , WEP_GRENADE } ,
{ " WEP_EXPLODE " , WEP_EXPLODE } ,
{ " WEP_RAIL " , WEP_RAIL } ,
{ " NUM_WEAPONS " , NUM_WEAPONS } ,
// Got Flags, for player->gotflag!
// Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags
{ " GF_REDFLAG " , GF_REDFLAG } ,
{ " GF_BLUEFLAG " , GF_BLUEFLAG } ,
// Angles
{ " ANG1 " , ANG1 } ,
{ " ANG2 " , ANG2 } ,
{ " ANG10 " , ANG10 } ,
{ " ANG15 " , ANG15 } ,
{ " ANG20 " , ANG20 } ,
{ " ANG30 " , ANG30 } ,
{ " ANG60 " , ANG60 } ,
{ " ANG64h " , ANG64h } ,
{ " ANG105 " , ANG105 } ,
{ " ANG210 " , ANG210 } ,
{ " ANG255 " , ANG255 } ,
{ " ANG340 " , ANG340 } ,
{ " ANG350 " , ANG350 } ,
{ " ANGLE_11hh " , ANGLE_11hh } ,
{ " ANGLE_22h " , ANGLE_22h } ,
{ " ANGLE_45 " , ANGLE_45 } ,
{ " ANGLE_67h " , ANGLE_67h } ,
{ " ANGLE_90 " , ANGLE_90 } ,
{ " ANGLE_112h " , ANGLE_112h } ,
{ " ANGLE_135 " , ANGLE_135 } ,
{ " ANGLE_157h " , ANGLE_157h } ,
{ " ANGLE_180 " , ANGLE_180 } ,
{ " ANGLE_202h " , ANGLE_202h } ,
{ " ANGLE_225 " , ANGLE_225 } ,
{ " ANGLE_247h " , ANGLE_247h } ,
{ " ANGLE_270 " , ANGLE_270 } ,
{ " ANGLE_292h " , ANGLE_292h } ,
{ " ANGLE_315 " , ANGLE_315 } ,
{ " ANGLE_337h " , ANGLE_337h } ,
{ " ANGLE_MAX " , ANGLE_MAX } ,
// P_Chase directions (dirtype_t)
{ " DI_NODIR " , DI_NODIR } ,
{ " DI_EAST " , DI_EAST } ,
{ " DI_NORTHEAST " , DI_NORTHEAST } ,
{ " DI_NORTH " , DI_NORTH } ,
{ " DI_NORTHWEST " , DI_NORTHWEST } ,
{ " DI_WEST " , DI_WEST } ,
{ " DI_SOUTHWEST " , DI_SOUTHWEST } ,
{ " DI_SOUTH " , DI_SOUTH } ,
{ " DI_SOUTHEAST " , DI_SOUTHEAST } ,
{ " NUMDIRS " , NUMDIRS } ,
// Buttons (ticcmd_t)
{ " BT_WEAPONMASK " , BT_WEAPONMASK } , //our first four bits.
{ " BT_WEAPONNEXT " , BT_WEAPONNEXT } ,
{ " BT_WEAPONPREV " , BT_WEAPONPREV } ,
{ " BT_ATTACK " , BT_ATTACK } , // shoot rings
{ " BT_USE " , BT_USE } , // spin
{ " BT_CAMLEFT " , BT_CAMLEFT } , // turn camera left
{ " BT_CAMRIGHT " , BT_CAMRIGHT } , // turn camera right
{ " BT_TOSSFLAG " , BT_TOSSFLAG } ,
{ " BT_JUMP " , BT_JUMP } ,
{ " BT_FIRENORMAL " , BT_FIRENORMAL } , // Fire a normal ring no matter what
2014-03-23 16:00:29 +00:00
{ " BT_CUSTOM1 " , BT_CUSTOM1 } , // Lua customizable
{ " BT_CUSTOM2 " , BT_CUSTOM2 } , // Lua customizable
{ " BT_CUSTOM3 " , BT_CUSTOM3 } , // Lua customizable
2014-03-15 16:59:03 +00:00
// cvflags_t
{ " CV_SAVE " , CV_SAVE } ,
{ " CV_CALL " , CV_CALL } ,
{ " CV_NETVAR " , CV_NETVAR } ,
{ " CV_NOINIT " , CV_NOINIT } ,
{ " CV_FLOAT " , CV_FLOAT } ,
{ " CV_NOTINNET " , CV_NOTINNET } ,
{ " CV_MODIFIED " , CV_MODIFIED } ,
{ " CV_SHOWMODIF " , CV_SHOWMODIF } ,
{ " CV_SHOWMODIFONETIME " , CV_SHOWMODIFONETIME } ,
{ " CV_NOSHOWHELP " , CV_NOSHOWHELP } ,
{ " CV_HIDEN " , CV_HIDEN } ,
{ " CV_HIDDEN " , CV_HIDEN } ,
{ " CV_CHEAT " , CV_CHEAT } ,
// v_video flags
{ " V_NOSCALEPATCH " , V_NOSCALEPATCH } ,
{ " V_SMALLSCALEPATCH " , V_SMALLSCALEPATCH } ,
{ " V_MEDSCALEPATCH " , V_MEDSCALEPATCH } ,
{ " V_6WIDTHSPACE " , V_6WIDTHSPACE } ,
{ " V_OLDSPACING " , V_OLDSPACING } ,
{ " V_MONOSPACE " , V_MONOSPACE } ,
{ " V_PURPLEMAP " , V_PURPLEMAP } ,
{ " V_YELLOWMAP " , V_YELLOWMAP } ,
{ " V_GREENMAP " , V_GREENMAP } ,
{ " V_BLUEMAP " , V_BLUEMAP } ,
{ " V_REDMAP " , V_REDMAP } ,
{ " V_GRAYMAP " , V_GRAYMAP } ,
{ " V_ORANGEMAP " , V_ORANGEMAP } ,
{ " V_TRANSLUCENT " , V_TRANSLUCENT } ,
{ " V_10TRANS " , V_10TRANS } ,
{ " V_20TRANS " , V_20TRANS } ,
{ " V_30TRANS " , V_30TRANS } ,
{ " V_40TRANS " , V_40TRANS } ,
{ " V_50TRANS " , V_TRANSLUCENT } , // alias
{ " V_60TRANS " , V_60TRANS } ,
{ " V_70TRANS " , V_70TRANS } ,
{ " V_80TRANS " , V_80TRANS } ,
{ " V_90TRANS " , V_90TRANS } ,
2014-03-21 18:42:55 +00:00
{ " V_HUDTRANSHALF " , V_HUDTRANSHALF } ,
{ " V_HUDTRANS " , V_HUDTRANS } ,
{ " V_HUDTRANSDOUBLE " , V_HUDTRANSDOUBLE } ,
2014-03-15 16:59:03 +00:00
{ " V_AUTOFADEOUT " , V_AUTOFADEOUT } ,
{ " V_RETURN8 " , V_RETURN8 } ,
{ " V_OFFSET " , V_OFFSET } ,
{ " V_ALLOWLOWERCASE " , V_ALLOWLOWERCASE } ,
{ " V_FLIP " , V_FLIP } ,
{ " V_SNAPTOTOP " , V_SNAPTOTOP } ,
{ " V_SNAPTOBOTTOM " , V_SNAPTOBOTTOM } ,
{ " V_SNAPTOLEFT " , V_SNAPTOLEFT } ,
{ " V_SNAPTORIGHT " , V_SNAPTORIGHT } ,
{ " V_WRAPX " , V_WRAPX } ,
{ " V_WRAPY " , V_WRAPY } ,
{ " V_NOSCALESTART " , V_NOSCALESTART } ,
{ " V_SPLITSCREEN " , V_SPLITSCREEN } ,
{ " V_PARAMMASK " , V_PARAMMASK } ,
{ " V_SCALEPATCHMASK " , V_SCALEPATCHMASK } ,
{ " V_SPACINGMASK " , V_SPACINGMASK } ,
{ " V_CHARCOLORMASK " , V_CHARCOLORMASK } ,
{ " V_ALPHAMASK " , V_ALPHAMASK } ,
{ " V_CHARCOLORSHIFT " , V_CHARCOLORSHIFT } ,
{ " V_ALPHASHIFT " , V_ALPHASHIFT } ,
# endif
{ NULL , 0 }
} ;
static mobjtype_t get_mobjtype ( const char * word )
{ // Returns the vlaue of MT_ enumerations
mobjtype_t i ;
if ( * word > = ' 0 ' & & * word < = ' 9 ' )
return atoi ( word ) ;
if ( fastncmp ( " MT_ " , word , 3 ) )
word + = 3 ; // take off the MT_
for ( i = 0 ; i < NUMMOBJFREESLOTS ; i + + ) {
if ( ! FREE_MOBJS [ i ] )
break ;
if ( fastcmp ( word , FREE_MOBJS [ i ] ) )
return MT_FIRSTFREESLOT + i ;
}
for ( i = 0 ; i < MT_FIRSTFREESLOT ; i + + )
if ( fastcmp ( word , MOBJTYPE_LIST [ i ] + 3 ) )
return i ;
deh_warning ( " Couldn't find mobjtype named 'MT_%s' " , word ) ;
return MT_BLUECRAWLA ;
}
static statenum_t get_state ( const char * word )
{ // Returns the value of S_ enumerations
statenum_t i ;
if ( * word > = ' 0 ' & & * word < = ' 9 ' )
return atoi ( word ) ;
if ( fastncmp ( " S_ " , word , 2 ) )
word + = 2 ; // take off the S_
for ( i = 0 ; i < NUMSTATEFREESLOTS ; i + + ) {
if ( ! FREE_STATES [ i ] )
break ;
if ( fastcmp ( word , FREE_STATES [ i ] ) )
return S_FIRSTFREESLOT + i ;
}
for ( i = 0 ; i < S_FIRSTFREESLOT ; i + + )
if ( fastcmp ( word , STATE_LIST [ i ] + 2 ) )
return i ;
deh_warning ( " Couldn't find state named 'S_%s' " , word ) ;
return S_NULL ;
}
static spritenum_t get_sprite ( const char * word )
{ // Returns the value of SPR_ enumerations
spritenum_t i ;
if ( * word > = ' 0 ' & & * word < = ' 9 ' )
return atoi ( word ) ;
if ( fastncmp ( " SPR_ " , word , 4 ) )
word + = 4 ; // take off the SPR_
for ( i = 0 ; i < NUMSPRITES ; i + + )
if ( ! sprnames [ i ] [ 4 ] & & memcmp ( word , sprnames [ i ] , 4 ) = = 0 )
return i ;
deh_warning ( " Couldn't find sprite named 'SPR_%s' " , word ) ;
return SPR_NULL ;
}
static sfxenum_t get_sfx ( const char * word )
{ // Returns the value of SFX_ enumerations
sfxenum_t i ;
if ( * word > = ' 0 ' & & * word < = ' 9 ' )
return atoi ( word ) ;
if ( fastncmp ( " SFX_ " , word , 4 ) )
word + = 4 ; // take off the SFX_
else if ( fastncmp ( " DS " , word , 2 ) )
word + = 2 ; // take off the DS
for ( i = 0 ; i < NUMSFX ; i + + )
if ( S_sfx [ i ] . name & & fasticmp ( word , S_sfx [ i ] . name ) )
return i ;
deh_warning ( " Couldn't find sfx named 'SFX_%s' " , word ) ;
return sfx_None ;
}
static UINT16 get_mus ( const char * word )
{ // Returns the value of SFX_ enumerations
UINT16 i ;
if ( * word > = ' 0 ' & & * word < = ' 9 ' )
return atoi ( word ) ;
if ( fastncmp ( " MUS_ " , word , 4 ) )
word + = 4 ; // take off the MUS_
else if ( fastncmp ( " O_ " , word , 2 ) | | fastncmp ( " D_ " , word , 2 ) )
word + = 2 ; // take off the O_ or D_
for ( i = 0 ; i < NUMMUSIC ; i + + )
if ( S_music [ i ] . name & & fasticmp ( word , S_music [ i ] . name ) )
return i ;
deh_warning ( " Couldn't find music named 'MUS_%s' " , word ) ;
return mus_None ;
}
static hudnum_t get_huditem ( const char * word )
{ // Returns the value of HUD_ enumerations
hudnum_t i ;
if ( * word > = ' 0 ' & & * word < = ' 9 ' )
return atoi ( word ) ;
if ( fastncmp ( " HUD_ " , word , 4 ) )
word + = 4 ; // take off the HUD_
for ( i = 0 ; i < NUMHUDITEMS ; i + + )
if ( fastcmp ( word , HUDITEMS_LIST [ i ] ) )
return i ;
deh_warning ( " Couldn't find huditem named 'HUD_%s' " , word ) ;
return HUD_LIVESNAME ;
}
# ifndef HAVE_BLUA
static powertype_t get_power ( const char * word )
{ // Returns the vlaue of pw_ enumerations
powertype_t i ;
if ( * word > = ' 0 ' & & * word < = ' 9 ' )
return atoi ( word ) ;
if ( fastncmp ( " PW_ " , word , 3 ) )
word + = 3 ; // take off the pw_
for ( i = 0 ; i < NUMPOWERS ; i + + )
if ( fastcmp ( word , POWERS_LIST [ i ] ) )
return i ;
deh_warning ( " Couldn't find power named 'pw_%s' " , word ) ;
return pw_invulnerability ;
}
/// \todo Make ANY of this completely over-the-top math craziness obey the order of operations.
static fixed_t op_mul ( fixed_t a , fixed_t b ) { return a * b ; }
static fixed_t op_div ( fixed_t a , fixed_t b ) { return a / b ; }
static fixed_t op_add ( fixed_t a , fixed_t b ) { return a + b ; }
static fixed_t op_sub ( fixed_t a , fixed_t b ) { return a - b ; }
static fixed_t op_or ( fixed_t a , fixed_t b ) { return a | b ; }
static fixed_t op_and ( fixed_t a , fixed_t b ) { return a & b ; }
static fixed_t op_lshift ( fixed_t a , fixed_t b ) { return a < < b ; }
static fixed_t op_rshift ( fixed_t a , fixed_t b ) { return a > > b ; }
struct {
const char c ;
fixed_t ( * v ) ( fixed_t , fixed_t ) ;
} OPERATIONS [ ] = {
{ ' * ' , op_mul } ,
{ ' / ' , op_div } ,
{ ' + ' , op_add } ,
{ ' - ' , op_sub } ,
{ ' | ' , op_or } ,
{ ' & ' , op_and } ,
{ ' < ' , op_lshift } ,
{ ' > ' , op_rshift } ,
{ 0 , NULL }
} ;
// Returns the full word, cut at the first symbol or whitespace
static char * read_word ( const char * line )
{
// Part 1: You got the start of the word, now find the end.
const char * p ;
INT32 i ;
for ( p = line + 1 ; * p ; p + + ) {
if ( * p = = ' ' | | * p = = ' \t ' )
break ;
for ( i = 0 ; OPERATIONS [ i ] . c ; i + + )
if ( * p = = OPERATIONS [ i ] . c ) {
i = - 1 ;
break ;
}
if ( i = = - 1 )
break ;
}
// Part 2: Make a copy of the word and return it.
{
size_t len = ( p - line ) ;
char * word = malloc ( len + 1 ) ;
M_Memcpy ( word , line , len ) ;
word [ len ] = ' \0 ' ;
return word ;
}
}
static INT32 operation_pad ( const char * * word )
{ // Brings word the next operation and returns the operation number.
INT32 i ;
for ( ; * * word ; ( * word ) + + ) {
if ( * * word = = ' ' | | * * word = = ' \t ' )
continue ;
for ( i = 0 ; OPERATIONS [ i ] . c ; i + + )
if ( * * word = = OPERATIONS [ i ] . c )
{
if ( ( * * word = = ' < ' & & * ( * word + 1 ) = = ' < ' ) | | ( * * word = = ' > ' & & * ( * word + 1 ) = = ' > ' ) ) ( * word ) + + ; // These operations are two characters long.
else if ( * * word = = ' < ' | | * * word = = ' > ' ) continue ; // ... do not accept one character long.
( * word ) + + ;
return i ;
}
deh_warning ( " Unknown operation '%c' " , * * word ) ;
return - 1 ;
}
return - 1 ;
}
static void const_warning ( const char * type , const char * word )
{
deh_warning ( " Couldn't find %s named '%s' " , type , word ) ;
}
static fixed_t find_const ( const char * * rword )
{ // Finds the value of constants and returns it, bringing word to the next operation.
INT32 i ;
fixed_t r ;
char * word = read_word ( * rword ) ;
* rword + = strlen ( word ) ;
if ( ( * word > = ' 0 ' & & * word < = ' 9 ' ) | | * word = = ' - ' ) { // Parse a number
r = atoi ( word ) ;
free ( word ) ;
return r ;
}
if ( * word > = ' A ' & & ! * ( word + 1 ) ) { // Turn a single A-z symbol into numbers, like sprite frames.
r = * word - ' A ' ;
free ( word ) ;
return r ;
}
if ( fastncmp ( " MF_ " , word , 3 ) ) {
char * p = word + 3 ;
for ( i = 0 ; MOBJFLAG_LIST [ i ] ; i + + )
if ( fastcmp ( p , MOBJFLAG_LIST [ i ] ) ) {
free ( word ) ;
return ( 1 < < i ) ;
}
// Not found error
const_warning ( " mobj flag " , word ) ;
free ( word ) ;
return 0 ;
}
else if ( fastncmp ( " MF2_ " , word , 4 ) ) {
char * p = word + 4 ;
for ( i = 0 ; MOBJFLAG2_LIST [ i ] ; i + + )
if ( fastcmp ( p , MOBJFLAG2_LIST [ i ] ) ) {
free ( word ) ;
return ( 1 < < i ) ;
}
// Not found error
const_warning ( " mobj flag2 " , word ) ;
free ( word ) ;
return 0 ;
}
else if ( fastncmp ( " MFE_ " , word , 4 ) ) {
char * p = word + 4 ;
for ( i = 0 ; MOBJEFLAG_LIST [ i ] ; i + + )
if ( fastcmp ( p , MOBJEFLAG_LIST [ i ] ) ) {
free ( word ) ;
return ( 1 < < i ) ;
}
// Not found error
const_warning ( " mobj eflag " , word ) ;
free ( word ) ;
return 0 ;
}
else if ( fastncmp ( " PF_ " , word , 3 ) ) {
char * p = word + 3 ;
for ( i = 0 ; PLAYERFLAG_LIST [ i ] ; i + + )
if ( fastcmp ( p , PLAYERFLAG_LIST [ i ] ) ) {
free ( word ) ;
return ( 1 < < i ) ;
}
if ( fastcmp ( p , " FULLSTASIS " ) )
return PF_FULLSTASIS ;
// Not found error
const_warning ( " player flag " , word ) ;
free ( word ) ;
return 0 ;
}
else if ( fastncmp ( " S_ " , word , 2 ) ) {
r = get_state ( word ) ;
free ( word ) ;
return r ;
}
else if ( fastncmp ( " MT_ " , word , 3 ) ) {
r = get_mobjtype ( word ) ;
free ( word ) ;
return r ;
}
else if ( fastncmp ( " SPR_ " , word , 4 ) ) {
r = get_sprite ( word ) ;
free ( word ) ;
return r ;
}
else if ( fastncmp ( " SFX_ " , word , 4 ) | | fastncmp ( " DS " , word , 2 ) ) {
r = get_sfx ( word ) ;
free ( word ) ;
return r ;
}
else if ( fastncmp ( " MUS_ " , word , 4 ) | | fastncmp ( " O_ " , word , 2 ) ) {
r = get_mus ( word ) ;
free ( word ) ;
return r ;
}
else if ( fastncmp ( " PW_ " , word , 3 ) ) {
r = get_power ( word ) ;
free ( word ) ;
return r ;
}
else if ( fastncmp ( " HUD_ " , word , 4 ) ) {
r = get_huditem ( word ) ;
free ( word ) ;
return r ;
}
else if ( fastncmp ( " SKINCOLOR_ " , word , 10 ) ) {
char * p = word + 10 ;
for ( i = 0 ; i < MAXSKINCOLORS ; i + + )
if ( fastcmp ( p , COLOR_ENUMS [ i ] ) ) {
free ( word ) ;
return i ;
}
const_warning ( " color " , word ) ;
free ( word ) ;
return 0 ;
}
for ( i = 0 ; INT_CONST [ i ] . n ; i + + )
if ( fastcmp ( word , INT_CONST [ i ] . n ) ) {
free ( word ) ;
return INT_CONST [ i ] . v ;
}
// Not found error.
const_warning ( " constant " , word ) ;
free ( word ) ;
return 0 ;
}
# endif
// Loops through every constant and operation in word and performs its calculations, returning the final value.
fixed_t get_number ( const char * word )
{
# ifdef HAVE_BLUA
return LUA_EvalMath ( word ) ;
# else
// DESPERATELY NEEDED: Order of operations support! :x
fixed_t i = find_const ( & word ) ;
INT32 o ;
while ( * word ) {
o = operation_pad ( & word ) ;
if ( o ! = - 1 )
i = OPERATIONS [ o ] . v ( i , find_const ( & word ) ) ;
else
break ;
}
return i ;
# endif
}
void DEH_Check ( void )
{
# if defined(_DEBUG) || defined(PARANOIA)
const size_t dehstates = sizeof ( STATE_LIST ) / sizeof ( const char * ) ;
const size_t dehmobjs = sizeof ( MOBJTYPE_LIST ) / sizeof ( const char * ) ;
const size_t dehpowers = sizeof ( POWERS_LIST ) / sizeof ( const char * ) ;
const size_t dehcolors = sizeof ( COLOR_ENUMS ) / sizeof ( const char * ) ;
if ( dehstates ! = S_FIRSTFREESLOT )
I_Error ( " You forgot to update the Dehacked states list, you dolt! \n (%d states defined, versus %s in the Dehacked list) \n " , S_FIRSTFREESLOT , sizeu1 ( dehstates ) ) ;
if ( dehmobjs ! = MT_FIRSTFREESLOT )
I_Error ( " You forgot to update the Dehacked mobjtype list, you dolt! \n (%d mobj types defined, versus %s in the Dehacked list) \n " , MT_FIRSTFREESLOT , sizeu1 ( dehmobjs ) ) ;
if ( dehpowers ! = NUMPOWERS )
I_Error ( " You forgot to update the Dehacked powers list, you dolt! \n (%d powers defined, versus %s in the Dehacked list) \n " , NUMPOWERS , sizeu1 ( dehpowers ) ) ;
if ( dehcolors ! = MAXSKINCOLORS )
I_Error ( " You forgot to update the Dehacked colors list, you dolt! \n (%d colors defined, versus %s in the Dehacked list) \n " , MAXSKINCOLORS , sizeu1 ( dehcolors ) ) ;
# endif
}
# ifdef HAVE_BLUA
# include "lua_script.h"
# include "lua_libs.h"
// freeslot takes a name (string only!)
// and allocates it to the appropriate free slot.
// Returns the slot number allocated for it or nil if failed.
// ex. freeslot("MT_MYTHING","S_MYSTATE1","S_MYSTATE2")
// TODO: Error checking! @.@; There's currently no way to know which ones failed and why!
//
static inline int lib_freeslot ( lua_State * L )
{
int n = lua_gettop ( L ) ;
int r = 0 ; // args returned
char * s , * type , * word ;
while ( n - - > 0 )
{
s = Z_StrDup ( luaL_checkstring ( L , 1 ) ) ;
type = strtok ( s , " _ " ) ;
if ( type )
strupr ( type ) ;
else {
Z_Free ( s ) ;
return luaL_error ( L , " Unknown enum type in '%s' \n " , luaL_checkstring ( L , 1 ) ) ;
}
word = strtok ( NULL , " \n " ) ;
if ( word )
strupr ( word ) ;
else {
Z_Free ( s ) ;
return luaL_error ( L , " Missing enum name in '%s' \n " , luaL_checkstring ( L , 1 ) ) ;
}
if ( fastcmp ( type , " SFX " ) ) {
sfxenum_t sfx ;
strlwr ( word ) ;
CONS_Printf ( " Sound sfx_%s allocated. \n " , word ) ;
2014-03-18 17:56:54 +00:00
sfx = S_AddSoundFx ( word , false , 0 , false ) ;
2014-03-15 16:59:03 +00:00
if ( sfx ! = sfx_None ) {
lua_pushinteger ( L , sfx ) ;
r + + ;
} else
return r ;
}
else if ( fastcmp ( type , " SPR " ) )
{
char wad ;
spritenum_t j ;
lua_getfield ( L , LUA_REGISTRYINDEX , " WAD " ) ;
wad = ( char ) lua_tointeger ( L , - 1 ) ;
lua_pop ( L , 1 ) ;
for ( j = SPR_FIRSTFREESLOT ; j < = SPR_LASTFREESLOT ; j + + )
{
if ( used_spr [ ( j - SPR_FIRSTFREESLOT ) / 8 ] & ( 1 < < ( j % 8 ) ) )
{
if ( ! sprnames [ j ] [ 4 ] & & memcmp ( sprnames [ j ] , word , 4 ) = = 0 )
sprnames [ j ] [ 4 ] = wad ;
continue ; // Already allocated, next.
}
// Found a free slot!
CONS_Printf ( " Sprite SPR_%s allocated. \n " , word ) ;
strncpy ( sprnames [ j ] , word , 4 ) ;
//sprnames[j][4] = 0;
used_spr [ ( j - SPR_FIRSTFREESLOT ) / 8 ] | = 1 < < ( j % 8 ) ; // Okay, this sprite slot has been named now.
lua_pushinteger ( L , j ) ;
r + + ;
break ;
}
if ( j > SPR_LASTFREESLOT )
return r ;
}
else if ( fastcmp ( type , " S " ) )
{
statenum_t i ;
for ( i = 0 ; i < NUMSTATEFREESLOTS ; i + + )
if ( ! FREE_STATES [ i ] ) {
CONS_Printf ( " State S_%s allocated. \n " , word ) ;
FREE_STATES [ i ] = Z_Malloc ( strlen ( word ) + 1 , PU_STATIC , NULL ) ;
strcpy ( FREE_STATES [ i ] , word ) ;
lua_pushinteger ( L , i ) ;
r + + ;
break ;
}
if ( i = = NUMSTATEFREESLOTS )
return r ;
}
else if ( fastcmp ( type , " MT " ) )
{
mobjtype_t i ;
for ( i = 0 ; i < NUMMOBJFREESLOTS ; i + + )
if ( ! FREE_MOBJS [ i ] ) {
CONS_Printf ( " MobjType MT_%s allocated. \n " , word ) ;
FREE_MOBJS [ i ] = Z_Malloc ( strlen ( word ) + 1 , PU_STATIC , NULL ) ;
strcpy ( FREE_MOBJS [ i ] , word ) ;
lua_pushinteger ( L , i ) ;
r + + ;
break ;
}
if ( i = = NUMMOBJFREESLOTS )
return r ;
}
Z_Free ( s ) ;
lua_remove ( L , 1 ) ;
continue ;
}
return r ;
}
// Wrapper for ALL A_Action functions.
// Upvalue: actionf_t to represent
// Arguments: mobj_t actor, int var1, int var2
static inline int lib_action ( lua_State * L )
{
actionf_t * action = lua_touserdata ( L , lua_upvalueindex ( 1 ) ) ;
2014-03-18 17:56:54 +00:00
mobj_t * actor = * ( ( mobj_t * * ) luaL_checkudata ( L , 1 , META_MOBJ ) ) ;
2014-03-15 16:59:03 +00:00
var1 = ( INT32 ) luaL_optinteger ( L , 2 , 0 ) ;
var2 = ( INT32 ) luaL_optinteger ( L , 3 , 0 ) ;
2014-03-18 17:56:54 +00:00
if ( ! actor )
2014-03-15 16:59:03 +00:00
return LUA_ErrInvalid ( L , " mobj_t " ) ;
2014-03-18 17:56:54 +00:00
action - > acp1 ( actor ) ;
2014-03-15 16:59:03 +00:00
return 0 ;
}
// Hardcoded A_Action name to call for super() or NULL if super() would be invalid.
// Set in lua_infolib.
const char * superactions [ MAXRECURSION ] ;
UINT8 superstack = 0 ;
static int lib_dummysuper ( lua_State * L )
{
return luaL_error ( L , " Can't call super() outside of hardcode - replacing A_Action functions being called by state changes ! " ) ; // convoluted, I know. @_@;;
}
static inline int lib_getenum ( lua_State * L )
{
const char * word , * p ;
fixed_t i ;
boolean mathlib = lua_toboolean ( L , lua_upvalueindex ( 1 ) ) ;
if ( lua_type ( L , 2 ) ! = LUA_TSTRING )
return 0 ;
word = lua_tostring ( L , 2 ) ;
if ( strlen ( word ) = = 1 ) { // Assume sprite frame if length 1.
if ( * word > = ' A ' & & * word < = ' ~ ' )
{
lua_pushinteger ( L , * word - ' A ' ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " constant '%s' could not be parsed. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " MF_ " , word , 3 ) ) {
p = word + 3 ;
for ( i = 0 ; MOBJFLAG_LIST [ i ] ; i + + )
if ( fastcmp ( p , MOBJFLAG_LIST [ i ] ) ) {
lua_pushinteger ( L , ( ( lua_Integer ) 1 < < i ) ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " mobjflag '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " MF2_ " , word , 4 ) ) {
p = word + 4 ;
for ( i = 0 ; MOBJFLAG2_LIST [ i ] ; i + + )
if ( fastcmp ( p , MOBJFLAG2_LIST [ i ] ) ) {
lua_pushinteger ( L , ( ( lua_Integer ) 1 < < i ) ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " mobjflag2 '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " MFE_ " , word , 4 ) ) {
p = word + 4 ;
for ( i = 0 ; MOBJEFLAG_LIST [ i ] ; i + + )
if ( fastcmp ( p , MOBJEFLAG_LIST [ i ] ) ) {
lua_pushinteger ( L , ( ( lua_Integer ) 1 < < i ) ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " mobjeflag '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " MTF_ " , word , 4 ) ) {
p = word + 4 ;
for ( i = 0 ; i < 16 ; i + + )
if ( MAPTHINGFLAG_LIST [ i ] & & fastcmp ( p , MAPTHINGFLAG_LIST [ i ] ) ) {
lua_pushinteger ( L , ( ( lua_Integer ) 1 < < i ) ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " mapthingflag '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " PF_ " , word , 3 ) ) {
p = word + 3 ;
for ( i = 0 ; PLAYERFLAG_LIST [ i ] ; i + + )
if ( fastcmp ( p , PLAYERFLAG_LIST [ i ] ) ) {
lua_pushinteger ( L , ( ( lua_Integer ) 1 < < i ) ) ;
return 1 ;
}
if ( fastcmp ( p , " FULLSTASIS " ) )
{
lua_pushinteger ( L , ( lua_Integer ) PF_FULLSTASIS ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " playerflag '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " ML_ " , word , 3 ) ) {
p = word + 3 ;
for ( i = 0 ; i < 16 ; i + + )
if ( ML_LIST [ i ] & & fastcmp ( p , ML_LIST [ i ] ) ) {
lua_pushinteger ( L , ( ( lua_Integer ) 1 < < i ) ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " linedef flag '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " S_ " , word , 2 ) ) {
p = word + 2 ;
for ( i = 0 ; i < NUMSTATEFREESLOTS ; i + + ) {
if ( ! FREE_STATES [ i ] )
break ;
if ( fastcmp ( p , FREE_STATES [ i ] ) ) {
lua_pushinteger ( L , S_FIRSTFREESLOT + i ) ;
return 1 ;
}
}
for ( i = 0 ; i < S_FIRSTFREESLOT ; i + + )
if ( fastcmp ( p , STATE_LIST [ i ] + 2 ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return luaL_error ( L , " state '%s' does not exist. \n " , word ) ;
}
else if ( fastncmp ( " MT_ " , word , 3 ) ) {
p = word + 3 ;
for ( i = 0 ; i < NUMMOBJFREESLOTS ; i + + ) {
if ( ! FREE_MOBJS [ i ] )
break ;
if ( fastcmp ( p , FREE_MOBJS [ i ] ) ) {
lua_pushinteger ( L , MT_FIRSTFREESLOT + i ) ;
return 1 ;
}
}
for ( i = 0 ; i < MT_FIRSTFREESLOT ; i + + )
if ( fastcmp ( p , MOBJTYPE_LIST [ i ] + 3 ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return luaL_error ( L , " mobjtype '%s' does not exist. \n " , word ) ;
}
else if ( fastncmp ( " SPR_ " , word , 4 ) ) {
p = word + 4 ;
for ( i = 0 ; i < NUMSPRITES ; i + + )
if ( ! sprnames [ i ] [ 4 ] & & fastncmp ( p , sprnames [ i ] , 4 ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " sprite '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( ! mathlib & & fastncmp ( " sfx_ " , word , 4 ) ) {
p = word + 4 ;
for ( i = 0 ; i < NUMSFX ; i + + )
if ( S_sfx [ i ] . name & & fastcmp ( p , S_sfx [ i ] . name ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return 0 ;
}
else if ( mathlib & & fastncmp ( " SFX_ " , word , 4 ) ) { // SOCs are ALL CAPS!
p = word + 4 ;
for ( i = 0 ; i < NUMSFX ; i + + )
if ( S_sfx [ i ] . name & & fasticmp ( p , S_sfx [ i ] . name ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return luaL_error ( L , " sfx '%s' could not be found. \n " , word ) ;
}
else if ( mathlib & & fastncmp ( " DS " , word , 2 ) ) {
p = word + 2 ;
for ( i = 0 ; i < NUMSFX ; i + + )
if ( S_sfx [ i ] . name & & fasticmp ( p , S_sfx [ i ] . name ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " sfx '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( ! mathlib & & fastncmp ( " mus_ " , word , 4 ) ) {
p = word + 4 ;
for ( i = 0 ; i < NUMMUSIC ; i + + )
if ( S_music [ i ] . name & & fastcmp ( p , S_music [ i ] . name ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return 0 ;
}
else if ( mathlib & & fastncmp ( " MUS_ " , word , 4 ) ) { // SOCs are ALL CAPS!
p = word + 4 ;
for ( i = 0 ; i < NUMMUSIC ; i + + )
if ( S_music [ i ] . name & & fasticmp ( p , S_music [ i ] . name ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return luaL_error ( L , " music '%s' could not be found. \n " , word ) ;
}
else if ( mathlib & & ( fastncmp ( " O_ " , word , 2 ) | | fastncmp ( " D_ " , word , 2 ) ) ) {
p = word + 2 ;
for ( i = 0 ; i < NUMMUSIC ; i + + )
if ( S_music [ i ] . name & & fasticmp ( p , S_music [ i ] . name ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return luaL_error ( L , " music '%s' could not be found. \n " , word ) ;
}
else if ( ! mathlib & & fastncmp ( " pw_ " , word , 3 ) ) {
p = word + 3 ;
for ( i = 0 ; i < NUMPOWERS ; i + + )
if ( fasticmp ( p , POWERS_LIST [ i ] ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return 0 ;
}
else if ( mathlib & & fastncmp ( " PW_ " , word , 3 ) ) { // SOCs are ALL CAPS!
p = word + 3 ;
for ( i = 0 ; i < NUMPOWERS ; i + + )
if ( fastcmp ( p , POWERS_LIST [ i ] ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
return luaL_error ( L , " power '%s' could not be found. \n " , word ) ;
}
else if ( fastncmp ( " HUD_ " , word , 4 ) ) {
p = word + 4 ;
for ( i = 0 ; i < NUMHUDITEMS ; i + + )
if ( fastcmp ( p , HUDITEMS_LIST [ i ] ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " huditem '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( fastncmp ( " SKINCOLOR_ " , word , 10 ) ) {
p = word + 10 ;
for ( i = 0 ; i < MAXSKINCOLORS ; i + + )
if ( fastcmp ( p , COLOR_ENUMS [ i ] ) ) {
lua_pushinteger ( L , i ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " skincolor '%s' could not be found. \n " , word ) ;
return 0 ;
}
else if ( ! mathlib & & fastncmp ( " A_ " , word , 2 ) ) {
char * caps ;
// Try to get a Lua action first.
/// \todo Push a closure that sets superactions[] and superstack.
lua_getfield ( L , LUA_REGISTRYINDEX , LREG_ACTIONS ) ;
// actions are stored in all uppercase.
caps = Z_StrDup ( word ) ;
strupr ( caps ) ;
lua_getfield ( L , - 1 , caps ) ;
Z_Free ( caps ) ;
if ( ! lua_isnil ( L , - 1 ) )
return 1 ; // Success! :D That was easy.
// Welp, that failed.
lua_pop ( L , 2 ) ; // pop nil and LREG_ACTIONS
// Hardcoded actions as callable Lua functions!
// Retrieving them from this metatable allows them to be case-insensitive!
for ( i = 0 ; actionpointers [ i ] . name ; i + + )
if ( fasticmp ( word , actionpointers [ i ] . name ) ) {
// push lib_action as a C closure with the actionf_t* as an upvalue.
lua_pushlightuserdata ( L , & actionpointers [ i ] . action ) ;
lua_pushcclosure ( L , lib_action , 1 ) ;
return 1 ;
}
return 0 ;
}
else if ( ! mathlib & & fastcmp ( " super " , word ) )
{
if ( ! superstack )
{
lua_pushcfunction ( L , lib_dummysuper ) ;
return 1 ;
}
for ( i = 0 ; actionpointers [ i ] . name ; i + + )
if ( fasticmp ( superactions [ superstack - 1 ] , actionpointers [ i ] . name ) ) {
lua_pushlightuserdata ( L , & actionpointers [ i ] . action ) ;
lua_pushcclosure ( L , lib_action , 1 ) ;
return 1 ;
}
return 0 ;
}
for ( i = 0 ; INT_CONST [ i ] . n ; i + + )
if ( fastcmp ( word , INT_CONST [ i ] . n ) ) {
lua_pushinteger ( L , INT_CONST [ i ] . v ) ;
return 1 ;
}
if ( mathlib ) return luaL_error ( L , " constant '%s' could not be parsed. \n " , word ) ;
// DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
if ( fastcmp ( word , " maptol " ) ) {
lua_pushinteger ( L , maptol ) ;
return 1 ;
} else if ( fastcmp ( word , " mariomode " ) ) {
lua_pushboolean ( L , mariomode ! = 0 ) ;
return 1 ;
} else if ( fastcmp ( word , " twodlevel " ) ) {
lua_pushboolean ( L , twodlevel ! = 0 ) ;
return 1 ;
} else if ( fastcmp ( word , " circuitmap " ) ) {
lua_pushboolean ( L , circuitmap ) ;
return 1 ;
} else if ( fastcmp ( word , " netgame " ) ) {
lua_pushboolean ( L , netgame ) ;
return 1 ;
} else if ( fastcmp ( word , " multiplayer " ) ) {
lua_pushboolean ( L , multiplayer ) ;
return 1 ;
} else if ( fastcmp ( word , " modeattacking " ) ) {
lua_pushboolean ( L , modeattacking ) ;
return 1 ;
} else if ( fastcmp ( word , " splitscreen " ) ) {
lua_pushboolean ( L , splitscreen ) ;
return 1 ;
} else if ( fastcmp ( word , " gamecomplete " ) ) {
lua_pushboolean ( L , gamecomplete ) ;
return 1 ;
} else if ( fastcmp ( word , " devparm " ) ) {
lua_pushboolean ( L , devparm ) ;
return 1 ;
} else if ( fastcmp ( word , " modifiedgame " ) ) {
lua_pushboolean ( L , modifiedgame & & ! savemoddata ) ;
return 1 ;
} else if ( fastcmp ( word , " menuactive " ) ) {
lua_pushboolean ( L , menuactive ) ;
return 1 ;
} else if ( fastcmp ( word , " paused " ) ) {
lua_pushboolean ( L , paused ) ;
return 1 ;
} else if ( fastcmp ( word , " gametype " ) ) {
lua_pushinteger ( L , gametype ) ;
return 1 ;
} else if ( fastcmp ( word , " leveltime " ) ) {
lua_pushinteger ( L , leveltime ) ;
return 1 ;
} else if ( fastcmp ( word , " curWeather " ) ) {
lua_pushinteger ( L , curWeather ) ;
return 1 ;
} else if ( fastcmp ( word , " globalweather " ) ) {
lua_pushinteger ( L , globalweather ) ;
return 1 ;
} else if ( fastcmp ( word , " server " ) ) {
if ( dedicated | | ! playeringame [ serverplayer ] )
return 0 ;
LUA_PushUserdata ( L , & players [ serverplayer ] , META_PLAYER ) ;
return 1 ;
} else if ( fastcmp ( word , " admin " ) ) {
if ( ! playeringame [ adminplayer ] | | adminplayer = = serverplayer )
return 0 ;
LUA_PushUserdata ( L , & players [ adminplayer ] , META_PLAYER ) ;
return 1 ;
} else if ( fastcmp ( word , " emeralds " ) ) {
lua_pushinteger ( L , emeralds ) ;
return 1 ;
} else if ( fastcmp ( word , " gravity " ) ) {
lua_pushinteger ( L , gravity ) ;
return 1 ;
}
return 0 ;
}
int LUA_EnumLib ( lua_State * L )
{
if ( lua_gettop ( L ) = = 0 )
lua_pushboolean ( L , 0 ) ;
// Set the global metatable
lua_createtable ( L , 0 , 1 ) ;
lua_pushvalue ( L , 1 ) ; // boolean passed to LUA_EnumLib as first argument.
lua_pushcclosure ( L , lib_getenum , 1 ) ;
lua_setfield ( L , - 2 , " __index " ) ;
lua_setmetatable ( L , LUA_GLOBALSINDEX ) ;
return 0 ;
}
int LUA_SOCLib ( lua_State * L )
{
lua_register ( L , " freeslot " , lib_freeslot ) ;
return 0 ;
}
const char * LUA_GetActionName ( void * action )
{
actionf_t * act = ( actionf_t * ) action ;
size_t z ;
for ( z = 0 ; actionpointers [ z ] . name ; z + + )
{
if ( actionpointers [ z ] . action . acv = = act - > acv )
return actionpointers [ z ] . name ;
}
return NULL ;
}
void LUA_SetActionByName ( void * state , const char * actiontocompare )
{
state_t * st = ( state_t * ) state ;
size_t z ;
for ( z = 0 ; actionpointers [ z ] . name ; z + + )
{
if ( fasticmp ( actiontocompare , actionpointers [ z ] . name ) )
{
st - > action = actionpointers [ z ] . action ;
st - > action . acv = actionpointers [ z ] . action . acv ; // assign
st - > action . acp1 = actionpointers [ z ] . action . acp1 ;
return ;
}
}
}
# endif // HAVE_BLUA