Descent3/legacy/editor/ScriptCompilerAPI.cpp

706 lines
26 KiB
C++
Raw Normal View History

/*
* 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/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $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:24a Kevin
* Made things work in a release build
*
* 15 6/08/99 4:14p Jeff
* added some #ifdefs for new editor, so it can be used in the new editor
* project
*
* 14 2/23/99 11:52p Jeff
* new script dll sync dialog
*
* 13 2/17/99 6:54p Jeff
* added check box for auto check in/out scripts with levels...fix
* checksum mprintf bug
*
* 12 2/17/99 3:24a Jeff
* added checksum parameter
*
* 11 1/15/99 5:27p Jeff
* possible long filename fix
*
* 10 1/13/99 5:00p Jeff
* auto generate string table stuff
*
* 9 1/05/99 4:33p Jeff
* oops, forgot STDCALL when making SaveRestoreState
*
* 8 12/31/98 2:37p Jeff
* added SaveRestoreState import function
*
* 7 12/21/98 6:21p Jeff
* added comments to generated blank scripts
*
* 6 12/18/98 4:32p Jeff
* fixed code that creates empty script
*
* 5 12/18/98 2:37p Jeff
* updated the create new script file
*
* 4 12/14/98 11:32a Jeff
* started work on osiris load and bind functions
*
* 3 12/13/98 7:50p 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:09a 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)\ncannot be found. Please make sure\nyou have specified a proper path and\nthe file exists. Go into the Script and\nLevel dialog to configure your compiler.",Compiler_path);
return CERR_COMPILERMISSING;
}
}else{
OutrageMessageBox("You haven't configured a virtual compiler to use.\nPlease go into the Script and Level Interface\nof the editor and select the configure button\nto configure a virtual compiler to use.\nFind 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)\ncannot be found. Please make sure\nyou have specified a proper path and\nthe file exists. Select the configure button\nto 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.\nPlease select the configure option\nto 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)
{
if(cfexist(filename)){
char buffer[512];
sprintf(buffer,"A script by the name of %s\nalready 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);
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);"));
O(("void STDCALLPTR CreateInstance(int id);"));
O(("void STDCALL DestroyInstance(int id,void *ptr);"));
O(("int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data);"));
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 );"));
O(("#ifdef __cplusplus"));
O(("}"));
O(("#endif"));
O((""));
O(("int String_table_size = 0;"));
O(("char **String_table = NULL;"));
O(("static const char *_Error_string = \"!!ERROR MISSING STRING!!\";"));
O(("static const char *_Empty_string = \"\";"));
O(("const char *GetStringFromTable(int index)"));
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)"));
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"));
O(("int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data)"));
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 )"));
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);"));
O(("void STDCALLPTR CreateInstance(int id);"));
O(("void STDCALL DestroyInstance(int id,void *ptr);"));
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 );"));
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 = \"\";"));
O(("const char *GetStringFromTable(int index)"));
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)"));
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."));
O(("int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data)"));
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 )"));
O(("{"));
O((" return 0;"));
O(("}"));
O((""));
cfclose(CurrentFile);
return true;
}