2024-04-20 16:23:08 +00:00
/*
* Descent 3
* Copyright ( C ) 2024 Parallax Software
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2024-05-06 15:12:44 +00:00
- - - HISTORICAL COMMENTS FOLLOW - - -
2024-04-19 20:58:24 +00:00
* $ Logfile : / DescentIII / Main / editor / ScriptCompilerAPI . cpp $
* $ Revision : 1.1 .1 .1 $
* $ Date : 2003 - 08 - 26 03 : 57 : 38 $
* $ Author : kevinb $
*
* Implementation files for for the script compiler API
*
* $ Log : not supported by cvs2svn $
*
* 16 6 / 17 / 99 10 : 24 a Kevin
* Made things work in a release build
*
* 15 6 / 08 / 99 4 : 14 p Jeff
* added some # ifdefs for new editor , so it can be used in the new editor
* project
*
* 14 2 / 23 / 99 11 : 52 p Jeff
* new script dll sync dialog
*
* 13 2 / 17 / 99 6 : 54 p Jeff
* added check box for auto check in / out scripts with levels . . . fix
* checksum mprintf bug
*
* 12 2 / 17 / 99 3 : 24 a Jeff
* added checksum parameter
*
* 11 1 / 15 / 99 5 : 27 p Jeff
* possible long filename fix
*
* 10 1 / 13 / 99 5 : 00 p Jeff
* auto generate string table stuff
*
* 9 1 / 05 / 99 4 : 33 p Jeff
* oops , forgot STDCALL when making SaveRestoreState
*
* 8 12 / 31 / 98 2 : 37 p Jeff
* added SaveRestoreState import function
*
* 7 12 / 21 / 98 6 : 21 p Jeff
* added comments to generated blank scripts
*
* 6 12 / 18 / 98 4 : 32 p Jeff
* fixed code that creates empty script
*
* 5 12 / 18 / 98 2 : 37 p Jeff
* updated the create new script file
*
* 4 12 / 14 / 98 11 : 32 a Jeff
* started work on osiris load and bind functions
*
* 3 12 / 13 / 98 7 : 50 p Jeff
* automatically add new DLLs that aren ' t in the manage
* system . . . implemented create new script function , even though it ' s still
* in infancy .
*
* 2 12 / 13 / 98 3 : 09 a Jeff
* Initial creation , added ScriptCompile ( ) function
*
* $ NoKeywords : $
*/
# include "stdafx.h"
# include "ScriptCompilerAPI.h"
# include "appdatabase.h"
# include "descent.h"
# include "cfile.h"
# include "manage.h"
# include "pserror.h"
# include "mem.h"
# include "ddio.h"
# include "osiris_dll.h"
# include <stdarg.h>
# ifdef NEWEDITOR
# include "../neweditor/globals.h"
# endif
int ScriptCompile ( tCompilerInfo * ci )
{
char Compiler_path [ _MAX_PATH ] ;
int Warning_level = - 1 ;
int Debug_type = - 1 ;
int len = _MAX_PATH ;
if ( ! cfexist ( ci - > source_filename ) )
return CERR_SOURCENOEXIST ;
# ifndef NEWEDITOR
//make sure there is a compiler defined
if ( Database - > read ( " EditorCompiler " , Compiler_path , & len ) ) {
if ( ! cfexist ( Compiler_path ) ) {
OutrageMessageBox ( " The configured virtual compiler (%s) \n cannot be found. Please make sure \n you have specified a proper path and \n the file exists. Go into the Script and \n Level dialog to configure your compiler. " , Compiler_path ) ;
return CERR_COMPILERMISSING ;
}
} else {
OutrageMessageBox ( " You haven't configured a virtual compiler to use. \n Please go into the Script and Level Interface \n of the editor and select the configure button \n to configure a virtual compiler to use. \n Find Jeff for help on this. " ) ;
return CERR_NOCOMPILERDEFINED ;
}
Database - > read_int ( " EditorVCWarningLevel " , & Warning_level ) ;
Database - > read_int ( " EditorVCDebugLevel " , & Debug_type ) ;
# else
//New Editor setup
// Determine the compiler
CString cs_Compiler_Path = AfxGetApp ( ) - > GetProfileString ( " settings " , " EditorCompiler " , " " ) ;
if ( cs_Compiler_Path . GetLength ( ) > 1 ) {
if ( ! cfexist ( cs_Compiler_Path . GetBuffer ( 0 ) ) ) {
OutrageMessageBox ( " The configured virtual compiler (%s) \n cannot be found. Please make sure \n you have specified a proper path and \n the file exists. Select the configure button \n to configure your virtual compiler. " , cs_Compiler_Path . GetBuffer ( 0 ) ) ;
return CERR_COMPILERMISSING ;
} else
{
//valid compiler
strcpy ( Compiler_path , cs_Compiler_Path . GetBuffer ( 0 ) ) ;
}
} else {
OutrageMessageBox ( " You haven't configured a virtual compiler to use. \n Please select the configure option \n to configure a virtual compiler to use. " ) ;
return CERR_NOCOMPILERDEFINED ;
}
// Determine the Warning level
Warning_level = AfxGetApp ( ) - > GetProfileInt ( " settings " , " EditorVCWarningLevel " , 3 ) ;
ASSERT ( Warning_level > = 0 & & Warning_level < = 4 ) ;
if ( Warning_level < 0 | | Warning_level > 4 ) Warning_level = 3 ;
// Determine the Debug type
Debug_type = AfxGetApp ( ) - > GetProfileInt ( " settings " , " EditorVCDebugLevel " , 2 ) ;
ASSERT ( Debug_type > = 0 & & Debug_type < = 2 ) ;
if ( Debug_type < 0 | | Debug_type > 2 ) Debug_type = 2 ;
# endif
SECURITY_ATTRIBUTES sa = { 0 } ;
STARTUPINFO si = { 0 } ;
PROCESS_INFORMATION pi = { 0 } ;
HANDLE hPipeOutputRead = NULL ;
HANDLE hPipeOutputWrite = NULL ;
HANDLE hPipeInputRead = NULL ;
HANDLE hPipeInputWrite = NULL ;
BOOL bTest = 0 ;
DWORD dwNumberOfBytesRead = 0 ;
CHAR szBuffer [ 256 ] ;
sa . nLength = sizeof ( sa ) ;
sa . bInheritHandle = TRUE ;
sa . lpSecurityDescriptor = NULL ;
// Create pipe for standard output redirection.
CreatePipe ( & hPipeOutputRead , // read handle
& hPipeOutputWrite , // write handle
& sa , // security attributes
0 // number of bytes reserved for pipe - 0 default
) ; // Create pipe for standard input redirection.
CreatePipe ( & hPipeInputRead , // read handle
& hPipeInputWrite , // write handle
& sa , // security attributes
0 // number of bytes reserved for pipe - 0 default
) ;
// Make child process use hPipeOutputWrite as standard out,
// and make sure it does not show on screen.
si . cb = sizeof ( si ) ;
si . dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES ;
si . wShowWindow = SW_HIDE ;
si . hStdInput = hPipeInputRead ;
si . hStdOutput = hPipeOutputWrite ;
si . hStdError = hPipeOutputWrite ;
CString cline ;
cline = Compiler_path ;
cline + = " -f " ;
cline + = " \" " ;
cline + = ci - > source_filename ;
cline + = " \" " ;
cline + = " -dir " ;
cline + = LocalScriptDir ;
if ( ci - > script_type = = ST_LEVEL ) cline + = " -level " ;
switch ( Warning_level ) {
case 0 :
cline + = " -w 0 " ;
break ;
case 1 :
cline + = " -w 1 " ;
break ;
case 2 :
cline + = " -w 2 " ;
break ;
case 3 :
cline + = " -w 3 " ;
break ;
case 4 :
cline + = " -w 4 " ;
break ;
default :
cline + = " -w 3 " ;
break ;
}
switch ( Debug_type ) {
case 1 :
cline + = " -d coff " ;
break ;
case 2 :
cline + = " -d c7 " ;
break ;
}
// Game structure checksum
# ifndef NEWEDITOR
char temp_c [ 128 ] ;
sprintf ( temp_c , " -checksum %lu " , Osiris_game_checksum ) ;
cline + = temp_c ;
# endif
CreateProcess ( NULL , cline . GetBuffer ( 0 ) , NULL , NULL , TRUE , 0 , NULL , NULL , & si , & pi ) ;
// Now that handles have been inherited, close it to be safe.
// You don't want to read or write to them accidentally.
CloseHandle ( hPipeOutputWrite ) ;
CloseHandle ( hPipeInputRead ) ;
// Now test to capture DOS application output by reading
// hPipeOutputRead. Could also write to DOS application
// standard input by writing to hPipeInputWrite.
CString temp ;
while ( TRUE ) {
bTest = ReadFile (
hPipeOutputRead , // handle of the read end of our pipe
& szBuffer , // address of buffer that receives data
256 , // number of bytes to read
& dwNumberOfBytesRead , // address of number of bytes read
NULL // non-overlapped.
) ;
if ( ! bTest ) {
break ;
}
// do something with data.
szBuffer [ dwNumberOfBytesRead ] = 0 ; // null terminate
if ( ci - > callback ) {
int new_line_count = 0 ;
char * ptr = szBuffer ;
while ( * ptr ) {
if ( * ptr = = ' \n ' )
new_line_count + + ;
ptr + + ;
}
char * data , * d_ptr ;
d_ptr = data = ( char * ) mem_malloc ( dwNumberOfBytesRead + 1 + new_line_count ) ;
if ( data ) {
ptr = ( char * ) szBuffer ;
while ( * ptr ) {
if ( * ptr = = ' \n ' ) {
* d_ptr = ' \r ' ; d_ptr + + ;
* d_ptr = ' \n ' ; d_ptr + + ;
} else if ( * ptr ! = ' \r ' ) {
* d_ptr = * ptr ; d_ptr + + ;
}
ptr + + ;
}
* d_ptr = ' \0 ' ;
( * ci - > callback ) ( data ) ;
mem_free ( data ) ;
}
}
}
// Wait for spawn to finish.
WaitForSingleObject ( pi . hProcess , INFINITE ) ;
// Close all remaining handles
CloseHandle ( pi . hProcess ) ;
CloseHandle ( hPipeOutputRead ) ;
CloseHandle ( hPipeInputWrite ) ;
return CERR_NOERR ;
}
bool ScriptCreateEmptyLevelScript ( char * filename ) ;
bool ScriptCreateEmptyGameScript ( char * filename ) ;
2024-05-24 03:07:26 +00:00
bool ScriptCreateEmptyScript ( char * filename , uint8_t script_type )
2024-04-19 20:58:24 +00:00
{
if ( cfexist ( filename ) ) {
char buffer [ 512 ] ;
sprintf ( buffer , " A script by the name of %s \n already exists. " , filename ) ;
AfxMessageBox ( buffer , MB_OK ) ;
return false ;
}
switch ( script_type ) {
case ST_GAME :
return ScriptCreateEmptyGameScript ( filename ) ;
break ;
case ST_LEVEL :
return ScriptCreateEmptyLevelScript ( filename ) ;
break ;
}
return false ;
}
# define VERSION "0.1"
# define O(x) outputtofile x
CFILE * CurrentFile ;
void outputtofile ( char * format , . . . )
{
char buffer [ 1024 ] ;
va_list marker ;
2024-05-24 00:53:51 +00:00
va_start ( marker , format ) ;
std : : vsprintf ( buffer , format , marker ) ;
2024-04-19 20:58:24 +00:00
cf_WriteString ( CurrentFile , buffer ) ;
va_end ( marker ) ;
}
bool ScriptCreateEmptyLevelScript ( char * filename )
{
char fullpath [ _MAX_PATH ] ;
ddio_MakePath ( fullpath , LocalScriptDir , filename , NULL ) ;
CurrentFile = cfopen ( fullpath , " wt " ) ;
if ( ! CurrentFile )
return false ;
O ( ( " // %s " , filename ) ) ;
O ( ( " // %s " , VERSION ) ) ;
O ( ( " #include <stdio.h> " ) ) ;
O ( ( " #include <stdlib.h> " ) ) ;
O ( ( " #include <string.h> " ) ) ;
O ( ( " #include \" osiris_import.h \" " ) ) ;
O ( ( " #include \" osiris_common.h \" " ) ) ;
O ( ( " " ) ) ;
O ( ( " #ifdef _MSC_VER //Visual C++ Build " ) ) ;
O ( ( " #define STDCALL __stdcall " ) ) ;
O ( ( " #define STDCALLPTR *STDCALL " ) ) ;
O ( ( " #else //Non-Visual C++ Build " ) ) ;
O ( ( " #define STDCALL __attribute__((stdcall)) " ) ) ;
O ( ( " #define STDCALLPTR STDCALL* " ) ) ;
O ( ( " #endif " ) ) ;
O ( ( " " ) ) ;
O ( ( " #ifdef __cplusplus " ) ) ;
O ( ( " extern \" C \" { " ) ) ;
O ( ( " #endif " ) ) ;
O ( ( " char STDCALL InitializeDLL(tOSIRISModuleInit *func_list); " ) ) ;
O ( ( " void STDCALL ShutdownDLL(void); " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL GetGOScriptID(const char *name,uint8_t is_door); " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " void STDCALLPTR CreateInstance(int id); " ) ) ;
O ( ( " void STDCALL DestroyInstance(int id,void *ptr); " ) ) ;
2024-05-24 03:27:12 +00:00
O ( ( " int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data); " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " int STDCALL GetTriggerScriptID(int trigger_room, int trigger_face ); " ) ) ;
O ( ( " int STDCALL GetCOScriptList( int **list, int **id_list ); " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL SaveRestoreState( void *file_ptr, uint8_t saving_state ); " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " #ifdef __cplusplus " ) ) ;
O ( ( " } " ) ) ;
O ( ( " #endif " ) ) ;
O ( ( " " ) ) ;
O ( ( " int String_table_size = 0; " ) ) ;
O ( ( " char **String_table = NULL; " ) ) ;
2024-04-28 04:39:29 +00:00
O ( ( " static const char *_Error_string = \" !!ERROR MISSING STRING!! \" ; " ) ) ;
O ( ( " static const char *_Empty_string = \" \" ; " ) ) ;
O ( ( " const char *GetStringFromTable(int index) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " if( (index<0) || (index>=String_table_size) ) " ) ) ;
O ( ( " return _Error_string; " ) ) ;
O ( ( " if(!String_table[index]) " ) ) ;
O ( ( " return _Empty_string; " ) ) ;
O ( ( " return String_table[index]; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " #define TXT(x) GetStringFromTable(x) " ) ) ;
O ( ( " // InitializeDLL " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // This function gets called when the DLL first gets loaded. It will only be called once (until the " ) ) ;
O ( ( " // DLL is unloaded). Passed in is a struct of data passed from the game needed for the DLL to interact " ) ) ;
O ( ( " // with D3. Usually this function will just call osicommon_Initialize(), which sets up the imported " ) ) ;
O ( ( " // functions. However, you can alloc some memory or whatever in this function, and free it in ShutdownDLL(). " ) ) ;
O ( ( " // Note: You cannot call any imported functions until osicommon_Initialize() is called. " ) ) ;
O ( ( " // Returns 1 if initialization went ok, 0 if there was an error and the DLL should not be loaded. " ) ) ;
O ( ( " char STDCALL InitializeDLL(tOSIRISModuleInit *func_list) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " osicommon_Initialize(func_list); " ) ) ;
O ( ( " String_table_size = func_list->string_count; " ) ) ;
O ( ( " String_table = func_list->string_table; " ) ) ;
O ( ( " if(func_list->game_checksum!=CHECKSUM) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " mprintf(0, \" Game-Checksum FAIL!!! (%%ul!=%%ul) \\ n \" ,func_list->game_checksum,CHECKSUM); " ) ) ;
O ( ( " mprintf(0, \" RECOMPILE YOUR SCRIPTS!!! \\ n \" ); " ) ) ;
O ( ( " return 0; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " return 1; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // ShutdownDLL " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // This function is called right before a DLL is about to be unloaded from memory. You can free " ) ) ;
O ( ( " // any unfree'd memory, or anything else you need to do. Don't worry about destroying any instances " ) ) ;
O ( ( " // of scripts, as they will all be automatically destroyed before this function is called. The " ) ) ;
O ( ( " // same goes for any memory allocated with Scrpt_MemAlloc(), as this will automatically be freed " ) ) ;
O ( ( " // when a scripts instance is destroyed. " ) ) ;
O ( ( " void STDCALL ShutdownDLL(void) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // GetGOScriptID " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given the name of the object (from it's pagename), this function will search through it's " ) ) ;
O ( ( " // list of General Object Scripts for a script with a matching name (to see if there is a script " ) ) ;
O ( ( " // for that type/id of object within this DLL). If a matching scriptname is found, a UNIQUE ID " ) ) ;
O ( ( " // is to be returned back to Descent 3. This ID will be used from here on out for all future " ) ) ;
O ( ( " // interaction with the DLL. Since doors are not part of the generic object's, it's possible " ) ) ;
O ( ( " // for a door to have the same name as a generic object (OBJ_POWERUP, OBJ_BUILDING, OBJ_CLUTTER " ) ) ;
O ( ( " // or OBJ_ROBOT), therefore, a 1 is passed in for isdoor if the given object name refers to a " ) ) ;
O ( ( " // door, else it is a 0. The return value is the unique identifier, else -1 if the script " ) ) ;
O ( ( " // does not exist in the DLL. " ) ) ;
O ( ( " // The only reserved ID is 0, which must be used for the level script " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL GetGOScriptID(const char *name,uint8_t isdoor) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " return -1; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // CreateInstance " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given an ID from a call to GetGOScriptID(), GetTriggerScriptID() or GetCOScriptList(), this " ) ) ;
O ( ( " // function will create a new instance for that particular script (by allocating and initializing " ) ) ;
O ( ( " // memory, etc.). A pointer to this instance is to be returned back to Descent 3. This pointer will " ) ) ;
O ( ( " // be passed around, along with the ID for CallInstanceEvent() and DestroyInstance(). Return NULL " ) ) ;
O ( ( " // if there was an error. " ) ) ;
O ( ( " // The only reserved ID is 0, which must be used for the level script " ) ) ;
O ( ( " void STDCALLPTR CreateInstance(int id) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " return NULL; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // DestroyInstance " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given an ID, and a pointer to a particular instance of a script, this function will delete and " ) ) ;
O ( ( " // destruct all information associated with that script, so it will no longer exist. " ) ) ;
O ( ( " void STDCALL DestroyInstance(int id,void *ptr) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // CallInstanceEvent " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given an ID, a pointer to a script instance, an event and a pointer to the struct of " ) ) ;
O ( ( " // information about the event, this function will translate who this event belongs to and " ) ) ;
O ( ( " // passes the event to that instance of the script to be handled. Return a combination of " ) ) ;
O ( ( " // CONTINUE_CHAIN and CONTINUE_DEFAULT, to give instructions on what to do based on the " ) ) ;
O ( ( " // event. CONTINUE_CHAIN means to continue through the chain of scripts (custom script, level " ) ) ;
O ( ( " // script, mission script, and finally default script). If CONTINUE_CHAIN is not specified, " ) ) ;
O ( ( " // than the chain is broken and those scripts of lower priority will never get the event. Return " ) ) ;
O ( ( " // CONTINUE_DEFAULT in order to tell D3 if you want process the normal action that is built into " ) ) ;
O ( ( " // the game for that event. This only pertains to certain events. If the chain continues " ) ) ;
O ( ( " // after this script, than the CONTINUE_DEFAULT setting will be overridden by lower priority " ) ) ;
O ( ( " // scripts return value. " ) ) ;
O ( ( " // The only reserved ID is 0, which must be used for the level script " ) ) ;
2024-05-24 03:27:12 +00:00
O ( ( " int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " return CONTINUE_CHAIN|CONTINUE_DEFAULT; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // GetTriggerScriptID " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given a room and face number, this function will return a unique ID (global DLL unique) " ) ) ;
O ( ( " // in which Descent 3 should use for all future interaction will the DLL when refering to " ) ) ;
O ( ( " // this trigger. Return -1 if there is no trigger script available for the specified trigger. " ) ) ;
O ( ( " // The only reserved ID is 0, which must be used for the level script " ) ) ;
O ( ( " int STDCALL GetTriggerScriptID(int trigger_room,int trigger_face) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " return -1; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // GetCOScriptList " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // This function returns the pointers to the 2 arrays that Descent 3 should use to determine " ) ) ;
O ( ( " // what object's have custom scripts in this level DLL. list should be set to point to the array " ) ) ;
O ( ( " // of object handles that have custom scripts in this DLL. id_list should be set to point to the " ) ) ;
O ( ( " // corresponding array of unique IDs that match with the object handle list. This function should " ) ) ;
O ( ( " // return the size of the arrays returned...if no custom scripts are available, than this function " ) ) ;
O ( ( " // returns 0. " ) ) ;
O ( ( " // The only reserved ID is 0, which must be used for the level script " ) ) ;
O ( ( " int STDCALL GetCOScriptList( int **list, int **id_list ) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " return 0; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " // SaveRestoreState " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // This function is called when Descent 3 is saving or restoring the game state. In this function " ) ) ;
O ( ( " // you should save/restore any global data that you want preserved through load/save (which includes " ) ) ;
O ( ( " // demos). You must be very careful with this function, corrupting the file (reading or writing too " ) ) ;
O ( ( " // much or too little) may be hazardous to the game (possibly making it impossible to restore the " ) ) ;
O ( ( " // state). It would be best to use version information to keep older versions of saved states still " ) ) ;
O ( ( " // able to be used. IT IS VERY IMPORTANT WHEN SAVING THE STATE TO RETURN THE NUMBER OF _BYTES_ WROTE " ) ) ;
O ( ( " // TO THE FILE. When restoring the data, the return value is ignored. saving_state is 1 when you should " ) ) ;
O ( ( " // write data to the file_ptr, 0 when you should read in the data. " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL SaveRestoreState( void *file_ptr, uint8_t saving_state ) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " return 0; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
cfclose ( CurrentFile ) ;
return true ;
}
bool ScriptCreateEmptyGameScript ( char * filename )
{
char fullpath [ _MAX_PATH ] ;
ddio_MakePath ( fullpath , LocalScriptDir , filename , NULL ) ;
CurrentFile = cfopen ( fullpath , " wt " ) ;
if ( ! CurrentFile )
return false ;
O ( ( " // %s " , filename ) ) ;
O ( ( " // %s " , VERSION ) ) ;
O ( ( " #include <stdio.h> " ) ) ;
O ( ( " #include <stdlib.h> " ) ) ;
O ( ( " #include <string.h> " ) ) ;
O ( ( " #include \" osiris_import.h \" " ) ) ;
O ( ( " #include \" osiris_common.h \" " ) ) ;
O ( ( " " ) ) ;
O ( ( " #ifdef _MSC_VER //Visual C++ Build " ) ) ;
O ( ( " #define STDCALL __stdcall " ) ) ;
O ( ( " #define STDCALLPTR *STDCALL " ) ) ;
O ( ( " #else //Non-Visual C++ Build " ) ) ;
O ( ( " #define STDCALL __attribute__((stdcall)) " ) ) ;
O ( ( " #define STDCALLPTR STDCALL* " ) ) ;
O ( ( " #endif " ) ) ;
O ( ( " " ) ) ;
O ( ( " #ifdef __cplusplus " ) ) ;
O ( ( " extern \" C \" { " ) ) ;
O ( ( " #endif " ) ) ;
O ( ( " char STDCALL InitializeDLL(tOSIRISModuleInit *func_list); " ) ) ;
O ( ( " void STDCALL ShutdownDLL(void); " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL GetGOScriptID(const char *name,uint8_t isdoor); " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " void STDCALLPTR CreateInstance(int id); " ) ) ;
O ( ( " void STDCALL DestroyInstance(int id,void *ptr); " ) ) ;
2024-05-24 03:27:12 +00:00
O ( ( " int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data); " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL SaveRestoreState( void *file_ptr, uint8_t saving_state ); " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " #ifdef __cplusplus " ) ) ;
O ( ( " } " ) ) ;
O ( ( " #endif " ) ) ;
O ( ( " " ) ) ;
O ( ( " int String_table_size = 0; " ) ) ;
O ( ( " char **String_table = NULL; " ) ) ;
O ( ( " static char *_Error_string = \" !!ERROR MISSING STRING!! \" ; " ) ) ;
O ( ( " static char *_Empty_string = \" \" ; " ) ) ;
2024-04-28 04:39:29 +00:00
O ( ( " const char *GetStringFromTable(int index) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " if( (index<0) || (index>=String_table_size) ) " ) ) ;
O ( ( " return _Error_string; " ) ) ;
O ( ( " if(!String_table[index]) " ) ) ;
O ( ( " return _Empty_string; " ) ) ;
O ( ( " return String_table[index]; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " #define TXT(x) GetStringFromTable(x) " ) ) ;
O ( ( " // InitializeDLL " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // This function gets called when the DLL first gets loaded. It will only be called once (until the " ) ) ;
O ( ( " // DLL is unloaded). Passed in is a struct of data passed from the game needed for the DLL to interact " ) ) ;
O ( ( " // with D3. Usually this function will just call osicommon_Initialize(), which sets up the imported " ) ) ;
O ( ( " // functions. However, you can alloc some memory or whatever in this function, and free it in ShutdownDLL(). " ) ) ;
O ( ( " // Note: You cannot call any imported functions until osicommon_Initialize() is called. " ) ) ;
O ( ( " // Returns 1 if initialization went ok, 0 if there was an error and the DLL should not be loaded. " ) ) ;
O ( ( " char STDCALL InitializeDLL(tOSIRISModuleInit *func_list) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " osicommon_Initialize((tOSIRISModuleInit *)func_list); " ) ) ;
O ( ( " String_table_size = func_list->string_count; " ) ) ;
O ( ( " String_table = func_list->string_table; " ) ) ;
O ( ( " if(func_list->game_checksum!=CHECKSUM) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " mprintf(0, \" Game-Checksum FAIL!!! (%%ul!=%%ul) \\ n \" ,func_list->game_checksum,CHECKSUM); " ) ) ;
O ( ( " mprintf(0, \" RECOMPILE YOUR SCRIPTS!!! \\ n \" ); " ) ) ;
O ( ( " return 0; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " return 1; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // ShutdownDLL " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // This function is called right before a DLL is about to be unloaded from memory. You can free " ) ) ;
O ( ( " // any unfree'd memory, or anything else you need to do. Don't worry about destroying any instances " ) ) ;
O ( ( " // of scripts, as they will all be automatically destroyed before this function is called. The " ) ) ;
O ( ( " // same goes for any memory allocated with Scrpt_MemAlloc(), as this will automatically be freed " ) ) ;
O ( ( " // when a scripts instance is destroyed. " ) ) ;
O ( ( " void STDCALL ShutdownDLL(void) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // GetGOScriptID " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given the name of the object (from it's pagename), this function will search through it's " ) ) ;
O ( ( " // list of General Object Scripts for a script with a matching name (to see if there is a script " ) ) ;
O ( ( " // for that type/id of object within this DLL). If a matching scriptname is found, a UNIQUE ID " ) ) ;
O ( ( " // is to be returned back to Descent 3. This ID will be used from here on out for all future " ) ) ;
O ( ( " // interaction with the DLL. Since doors are not part of the generic object's, it's possible " ) ) ;
O ( ( " // for a door to have the same name as a generic object (OBJ_POWERUP, OBJ_BUILDING, OBJ_CLUTTER " ) ) ;
O ( ( " // or OBJ_ROBOT), therefore, a 1 is passed in for isdoor if the given object name refers to a " ) ) ;
O ( ( " // door, else it is a 0. The return value is the unique identifier, else -1 if the script " ) ) ;
O ( ( " // does not exist in the DLL. " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL GetGOScriptID(const char *name,uint8_t isdoor) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " return -1; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // CreateInstance " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given an ID from a call to GetGOScriptID(), this function will create a new instance for that " ) ) ;
O ( ( " // particular script (by allocating and initializing memory, etc.). A pointer to this instance " ) ) ;
O ( ( " // is to be returned back to Descent 3. This pointer will be passed around, along with the ID " ) ) ;
O ( ( " // for CallInstanceEvent() and DestroyInstance(). Return NULL if there was an error. " ) ) ;
O ( ( " void STDCALLPTR CreateInstance(int id) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " return NULL; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // DestroyInstance " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given an ID, and a pointer to a particular instance of a script, this function will delete and " ) ) ;
O ( ( " // destruct all information associated with that script, so it will no longer exist. " ) ) ;
O ( ( " void STDCALL DestroyInstance(int id,void *ptr) " ) ) ;
O ( ( " { " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // CallInstanceEvent " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // Given an ID, a pointer to a script instance, an event and a pointer to the struct of " ) ) ;
O ( ( " // information about the event, this function will translate who this event belongs to and " ) ) ;
O ( ( " // passes the event to that instance of the script to be handled. Return a combination of " ) ) ;
O ( ( " // CONTINUE_CHAIN and CONTINUE_DEFAULT, to give instructions on what to do based on the " ) ) ;
O ( ( " // event. CONTINUE_CHAIN means to continue through the chain of scripts (custom script, level " ) ) ;
O ( ( " // script, mission script, and finally default script). If CONTINUE_CHAIN is not specified, " ) ) ;
O ( ( " // than the chain is broken and those scripts of lower priority will never get the event. Return " ) ) ;
O ( ( " // CONTINUE_DEFAULT in order to tell D3 if you want process the normal action that is built into " ) ) ;
O ( ( " // the game for that event. This only pertains to certain events. If the chain continues " ) ) ;
O ( ( " // after this script, than the CONTINUE_DEFAULT setting will be overridden by lower priority " ) ) ;
O ( ( " // scripts return value. " ) ) ;
2024-05-24 03:27:12 +00:00
O ( ( " int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " return CONTINUE_CHAIN|CONTINUE_DEFAULT; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
O ( ( " // SaveRestoreState " ) ) ;
O ( ( " // Purpose: " ) ) ;
O ( ( " // This function is called when Descent 3 is saving or restoring the game state. In this function " ) ) ;
O ( ( " // you should save/restore any global data that you want preserved through load/save (which includes " ) ) ;
O ( ( " // demos). You must be very careful with this function, corrupting the file (reading or writing too " ) ) ;
O ( ( " // much or too little) may be hazardous to the game (possibly making it impossible to restore the " ) ) ;
O ( ( " // state). It would be best to use version information to keep older versions of saved states still " ) ) ;
O ( ( " // able to be used. IT IS VERY IMPORTANT WHEN SAVING THE STATE TO RETURN THE NUMBER OF _BYTES_ WROTE " ) ) ;
O ( ( " // TO THE FILE. When restoring the data, the return value is ignored. saving_state is 1 when you should " ) ) ;
O ( ( " // write data to the file_ptr, 0 when you should read in the data. " ) ) ;
2024-05-24 03:07:26 +00:00
O ( ( " int STDCALL SaveRestoreState( void *file_ptr, uint8_t saving_state ) " ) ) ;
2024-04-19 20:58:24 +00:00
O ( ( " { " ) ) ;
O ( ( " return 0; " ) ) ;
O ( ( " } " ) ) ;
O ( ( " " ) ) ;
cfclose ( CurrentFile ) ;
return true ;
}