/* * 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 . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/editor/DallasMainDlg.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003-08-26 03:57:37 $ * $Author: kevinb $ * * This is the code for the main dialog of the DALLAS graphical scripting interface * * $Log: not supported by cvs2svn $ * * 87 10/23/99 6:16p Nate * Added support for Polish Message Files * * 86 10/08/99 4:55p Nate * Dallas will now attempt to load the english .msg if a foreign language * .msg cannot be found * * 85 8/31/99 12:05p Nate * Copy command now displays an "Invalid Copy" message and returns if * selected item cannot be copied (instead of just copying the entire * script) * * 84 8/30/99 4:11p Nate * Added copy/paste for conditions, log ops, and nested if-then clauses * * 83 6/17/99 10:24a Kevin * Made things work in a release build * * 82 6/09/99 7:05p Jeff * stub functions added. #ifdef NEWEDITORs added, files changed, to get * Dallas integrated into new editor * * 81 5/21/99 7:32p Nate * Added Save and Restore ability to the custom script section * * 80 5/07/99 10:54a Nate * Added fix for fitting more scripts in the script type popup menu * * 79 5/04/99 6:53p Jeff * added event for when a player dies * * 78 4/27/99 4:27p Jeff * added player respawn osiris event * * 77 4/14/99 6:03p Nate * Added Event Type specification to Dallas Script Highlighting system. * * 76 4/02/99 2:16p Nate * Added AI Init event * * 75 4/01/99 6:02p Nate * added clipping of long messages when reading them in * * 74 3/30/99 4:47p Jeff * added level events for when IGC occurs for a player * * 73 3/17/99 3:57p Nate * Added localization support for message files, and added level check to * script grouping system * * 72 3/11/99 10:51a Nate * Added deletion of "Untitled" Dallas files when doing a New from editor * * 71 3/03/99 3:07p Nate * Temporarily allow designer to select named players * * 70 3/03/99 12:05a Nate * Added IT to AI goal complete event, added dynamic message file name * determination, and made it so you can't select a named player for an * object type * * 69 2/22/99 1:17p Nate * Added 'level goal item complete' event * * 68 2/22/99 1:18a Jeff * added handling for evt_use * * 67 2/20/99 6:07p Nate * Added Level Goal events * * 66 2/19/99 5:35p Nate * Added new types and events * * 65 2/17/99 4:14p Nate * Added condition query shortcuts * * 64 2/17/99 11:36a Nate * Fixed mprintf in script checksum code * * 63 2/17/99 10:57a Nate * Added script checksum code for Jeff * * 62 2/11/99 7:26p Nate * Added check to save button to make sure editor is up before doing * anything * * 61 2/10/99 1:47p Matt * Changed object handle symbolic constants * * 60 2/08/99 7:40p Nate * Fixed up event names to reflect IT's * * 59 2/08/99 3:53p Nate * Added new event types * * 58 2/07/99 4:43p Nate * Added OWNER selection to Door parameter types * * 57 2/05/99 11:52a Nate * Added importing/exporting of scripts * * 56 2/03/99 7:20p Nate * Fixed clipboard bug and added script chaining option * * 55 2/03/99 2:19p Nate * Added cool drag-n-drop support * * 54 2/03/99 11:57a Nate * Added script highlighting interface * * 53 2/03/99 10:37a Nate * Max popup items per column is now 40 for Luke * * 52 2/02/99 7:41p Nate * Added columnization of popup menus * * 51 2/02/99 8:43a Chris * I made buildings with AI work correctly (ie really big robots should be * buildings) * anim to and from states are now shorts instead of bytes * * 50 2/01/99 4:15p Nate * Changed TIMER HANDLE to TIMER ID to match DallasFuncs * * 49 2/01/99 3:48p Nate * Added fix to INVALID_SCRIPT_ID errors * * 48 2/01/99 2:41p Nate * Added title bar display of level and modified indicator * * 47 1/29/99 4:41p Nate * A few minor tweaks and fixes * * 46 1/28/99 9:41p Nate * Added tons of new stuff * * 45 1/26/99 1:15p Nate * Added UserTypes Workshop implementation * * 44 1/25/99 7:16p Nate * Added UserTypes dialog (non-functional) * * 43 1/25/99 2:38p Nate * Added Valid Flag Mask range support. * * 42 1/24/99 4:49p Nate * Added code for Dallas Save Format Version 1, but didn't enable it yet * * 41 1/23/99 5:52p Nate * Added flag support * * 40 1/21/99 8:56p Nate * Added warnings when saving objects * * 39 1/20/99 3:51p Nate * Added Specific Name parameter type 'a' * * 38 1/19/99 7:37p Nate * Added sound selection prompt dialog * * 37 1/19/99 12:18p Nate * Made it so Owner objects can now be "other" * * 36 1/19/99 10:35a Nate * Fixed Other object submenu bug * * 35 1/18/99 2:29p Nate * Added support for default parameters and valid range specification * * 34 1/17/99 6:29p Nate * Layed groundwork for default parameter values and valid parameter * ranges * * 33 1/15/99 7:31p Nate * Added some more interface features/fixes * * 32 1/15/99 2:05p Nate * Added collapse/expand all, fixed me and delete problems, made dlg * longer * * 31 1/15/99 10:37a Nate * Fixed highest room index bug * * 30 1/14/99 6:11p Nate * Added Trigger Script support and many other things, too numerous to * count. * * 29 1/13/99 7:28p Nate * Added message file reading from created script * * 28 1/13/99 10:50a Nate * Fixed up copy/pase, added highlighting of all scripts matching * specified owner * * 27 1/12/99 7:32p Nate * Added copy and paste support * * 26 1/12/99 4:45p Nate * Added max exec time support, added more interface features * * 25 1/11/99 8:42p Nate * Added script parameter support * * 24 1/11/99 6:40p Nate * Added ENUM support * * 23 1/11/99 10:19a Nate * Fixed AND/OR insertion bug * * 22 1/08/99 12:32p Nate * Added glue function validation upon loading scripts * * 21 1/07/99 10:17p Nate * Added first round of script loading code... * * 20 1/06/99 7:09p Nate * Added saving of scripts * * 19 1/06/99 1:13p Nate * Added support for IT objects and ELSE clauses * * 18 1/05/99 8:00p Nate * Added conditional code creation... fixed up interface yet a little * more. * * 17 1/05/99 2:03p Nate * Fixed up events and conditional interface a little * * 16 1/04/99 7:34p Nate * Added rough interface for Conditions * * 15 1/02/99 3:22p Matt * Added support for SaveRestoreState() (new code emailed to me from Jeff) * * 14 12/23/98 6:44p Nate * Added reading in of queries * * 13 12/23/98 4:03p Nate * Added code to implement as a modeless dialog * * 12 12/23/98 12:43p Nate * Fixed small message file parse bug. * * 11 12/23/98 12:35p Nate * Added use of level name in Dallas script file naming system. * * 10 12/22/98 3:55p Nate * Added object and room assignments * * 9 12/21/98 8:00p Nate * Added creation of shell code, started conditional interface. * * 8 12/20/98 4:29p Nate * Added script grouping code (based upon owner, then event type) * * 7 12/18/98 3:10p Nate * Added more interface features. * * 6 12/17/98 9:48p Nate * Added editing of paramaters * * 5 12/16/98 8:45p Nate * Added loading of Actions * * 4 12/15/98 7:47p Nate * Added inserting and deleting of default script trees. * * 3 12/13/98 6:08p Nate * Implemented the Message List interface * * 2 12/11/98 6:45p Nate * Initial Version * * $NoKeywords: $ */ // DallasMainDlg.cpp : implementation file // #include "stdafx.h" #include #include #include #include "pserror.h" #include "cfile.h" #include "mem.h" #include "mono.h" #include "ddio.h" #include "manage.h" #include "object.h" #include "room.h" #include "trigger.h" #include "hlsoundlib.h" #include "soundload.h" #include "gametexture.h" #include "gamepath.h" #include "matcen.h" #include "levelgoal.h" #ifdef NEWEDITOR #include "globals.h" #include "NewEditor.h" #else #include "editor.h" #include "editorDoc.h" #include "osiris_predefs.h" #include "descent.h" #endif #include "ScriptCompilerAPI.h" #include "DallasMainDlg.h" #include "DallasGenericPromptDlg.h" #include "DallasVectorPromptDialog.h" #include "DallasSoundDlg.h" #include "DallasStrmAudioDlg.h" #include "DallasTextureDlg.h" #include "DallasFlagDlg.h" #include "DallasImportDlg.h" #include "DallasUserTypesDlg.h" #include "DallasUtilities.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //////////////////////////////////////////////////////////////////////////// // Macro and function to make writing out text to a file a bit easier #define O(x) OutToFile x CFILE *CurrentOutputFile; int CurrentTabLevel; // Writes out text to CurrentFile void OutToFile(char *format, ...) { char buffer[1024]; if(CurrentOutputFile==NULL) return; va_list marker; va_start(marker,format); vsprintf(buffer,format,marker); cf_WriteString(CurrentOutputFile,buffer); va_end(marker); } #define DALLASFUNCS_FILENAME "dallasfuncs.cpp" #define NOT_SPECIFIED_MSG "" #define LEVEL_ID_NAME "ID_LEVEL_0000" #define LEVEL_CLASS_NAME "LevelScript_0000" // Global declaration of event information database #define UNKNOWN_EVENT_STRING "*Unknown Event*" #define UNKNOWN_EVENT_CODE_NAME "EVT_UNKNOWN" #define UNKNOWN_EVENT_DATA_LINE "// No event data line found!" EventInfoItem event_info[] = { {COLLIDE_EVENT_TYPE, "Collided (with IT)", "EVT_COLLIDE", "tOSIRISEVTCOLLIDE *event_data=&data->evt_collide;", OBJECT_MASK|HAS_IT_MASK}, {ACTIVATED_EVENT_TYPE, "Activated (by IT)", "EVT_COLLIDE", "tOSIRISEVTCOLLIDE *event_data=&data->evt_collide;", TRIGGER_MASK|HAS_IT_MASK}, {CREATED_EVENT_TYPE, "Created", "EVT_CREATED", "tOSIRISEVTCREATED *event_data=&data->evt_created;", OBJECT_MASK}, {DAMAGED_EVENT_TYPE, "Damaged (by IT)", "EVT_DAMAGED", "tOSIRISEVTDAMAGED *event_data=&data->evt_damaged;", OBJECT_MASK|HAS_IT_MASK}, {DESTROYED_EVENT_TYPE, "Destroyed", "EVT_DESTROY", "tOSIRISEVTDESTROY *event_data=&data->evt_destroy;", OBJECT_MASK}, {FRAME_INTERVAL_EVENT_TYPE, "Frame Interval", "EVT_INTERVAL", "tOSIRISEVTINTERVAL *event_data=&data->evt_interval;", OBJECT_MASK|LEVEL_MASK}, {LEVEL_START_EVENT_TYPE, "Level Start", "EVT_LEVELSTART", "tOSIRISEVTLEVELSTART *event_data=&data->evt_levelstart;", LEVEL_MASK}, {LEVEL_END_EVENT_TYPE, "Level End", "EVT_LEVELEND", "tOSIRISEVTLEVELEND *event_data=&data->evt_levelend;", LEVEL_MASK}, {CHANGE_SEGMENT_EVENT_TYPE, "Changed Segment", "EVT_CHANGESEG", "tOSIRISEVTCHANGESEG *event_data=&data->evt_changeseg;", OBJECT_MASK}, {TIMER_EVENT_TYPE, "Timer (TIMER ID) Went Off", "EVT_TIMER", "tOSIRISEVTTIMER *event_data=&data->evt_timer;", OBJECT_MASK|LEVEL_MASK|HAS_TIMERID_MASK}, {AI_INIT_EVENT_TYPE, "AI-Initialized", "EVT_AI_INIT", "tOSIRISEVTAIINIT *event_data=&data->evt_ai_init;", OBJECT_MASK}, {AIN_OBJKILLED_EVENT_TYPE, "AI-Target (IT) Killed", "EVT_AIN_OBJKILLED", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_objkilled;", OBJECT_MASK|HAS_IT_MASK}, {AIN_SEEPLAYER_EVENT_TYPE, "AI-Saw Target (IT)", "EVT_AIN_SEEPLAYER", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_seeplayer;", OBJECT_MASK|HAS_IT_MASK}, {AIN_WHITOBJECT_EVENT_TYPE, "AI-Weapon Damaged Target (IT)", "EVT_AIN_WHITOBJECT", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_whitobject;", OBJECT_MASK|HAS_IT_MASK}, {AIN_GOALCOMPLETE_EVENT_TYPE, "AI-Goal (GOAL ID) Completed (by IT)", "EVT_AIN_GOALCOMPLETE", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_goalcomplete;", OBJECT_MASK|LEVEL_MASK|HAS_GOALID_MASK|HAS_IT_MASK}, {AIN_GOALFAIL_EVENT_TYPE, "AI-Goal (GOAL ID) Failed", "EVT_AIN_GOALFAIL", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_goalfail;", OBJECT_MASK|LEVEL_MASK|HAS_GOALID_MASK}, {AIN_MELHIT_EVENT_TYPE, "AI-Melee Hit on Target (IT)", "EVT_AIN_MELEE_HIT", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_melee_hit;", OBJECT_MASK|HAS_IT_MASK}, {AIN_MELATTACKFRAME_EVENT_TYPE, "AI-Melee Attack Frame", "EVT_AIN_MELEE_ATTACK_FRAME", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_melee_attack_frame;", OBJECT_MASK}, {AIN_MOVIE_STARTED_EVENT_TYPE, "AI-Movie Started", "EVT_AIN_MOVIE_START", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_movie_start;", OBJECT_MASK}, {AIN_MOVIE_ENDED_EVENT_TYPE, "AI-Movie Ended", "EVT_AIN_MOVIE_END", "tOSIRISEVTAINOTIFY *event_data=&data->evt_ain_movie_end;", OBJECT_MASK}, {CHILD_DIED_EVENT_TYPE, "A Child (IT) Has Died", "EVT_CHILD_DIED", "tOSIRISEVTCHILDDIED *event_data=&data->evt_child_died;", OBJECT_MASK|HAS_IT_MASK}, {DOOR_CLOSED_EVENT_TYPE, "Door Closed", "EVT_DOOR_CLOSE", "tOSIRISEVTDOORCLOSE *event_data=&data->evt_door_close;", DOOR_OBJECT_MASK}, {DOOR_ACTIVATED_EVENT_TYPE, "Door Activated", "EVT_DOOR_ACTIVATE", "tOSIRISEVTDOORACTIVATE *event_data=&data->evt_door_activate;", DOOR_OBJECT_MASK}, {MATCEN_NOTIFY_EVENT_TYPE, "Matcen (MATCEN ID) Has Spawned (an IT)", "EVT_MATCEN_CREATE", "tOSIRISEVTMATCENCREATE *event_data=&data->evt_matcen_create;", LEVEL_MASK|HAS_MATCENID_MASK|HAS_IT_MASK}, {LGOAL_COMPLETED_EVENT_TYPE, "Level Goal (LEVEL GOAL ID) Completed", "EVT_LEVEL_GOAL_COMPLETE", "tOSIRISEVTLEVELGOALCOMPLETE *event_data=&data->evt_level_goal_complete;", LEVEL_MASK|HAS_LEVGOALID_MASK}, {LGOAL_ITEM_COMPLETE_EVENT_TYPE, "Level Goal (LEVEL GOAL ID) Item Completed", "EVT_LEVEL_GOAL_ITEM_COMPLETE", "tOSIRISEVTLEVELGOALITEMCOMPLETE *event_data=&data->evt_level_goal_item_complete;", LEVEL_MASK|HAS_LEVGOALID_MASK}, {ALL_LGOALS_COMPLETE_EVENT_TYPE, "All Level Goals Completed", "EVT_ALL_LEVEL_GOALS_COMPLETE", "tOSIRISEVTALLLEVELGOALSCOMPLETE *event_data=&data->evt_all_level_goals_complete;", LEVEL_MASK}, {PLAYER_MOVIE_START_TYPE, "Movie Starts With Player Target", "EVT_PLAYER_MOVIE_START", "tOSIRISEVTPLAYERMOVIESTART *event_data=&data->evt_player_movie_start;", LEVEL_MASK}, {PLAYER_MOVIE_END_TYPE, "Movie Ends With Player Target", "EVT_PLAYER_MOVIE_END", "tOSIRISEVTPLAYERMOVIEEND *event_data=&data->evt_player_movie_end;", LEVEL_MASK}, {USED_EVENT_TYPE, "Used (by IT)", "EVT_USE", "tOSIRISEVTUSE *event_data=&data->evt_use;", OBJECT_MASK|HAS_IT_MASK}, {PLAYER_RESPAWN_TYPE, "Player (IT) respawns", "EVT_PLAYER_RESPAWN", "tOSIRISEVTPLAYERRESPAWN *event_data=&data->evt_player_respawn;", LEVEL_MASK|HAS_IT_MASK}, {PLAYER_DIES_TYPE, "Player (IT) dies", "EVT_PLAYER_DIES", "tOSIRISEVTPLAYERDIES *event_data=&data->evt_player_dies;", LEVEL_MASK|HAS_IT_MASK}, {-1,"","","",0} }; // Global declaration of expression operator information database #define UNKNOWN_EXPOP_STRING "???" ExpOpInfoItem expop_info[] = { {EQUAL_TO, "=", "Equal To (==)", "==", COMPARISON_OPERATOR_TYPE}, {NOT_EQUAL_TO, "!=", "Not Equal To (!=)", "!=", COMPARISON_OPERATOR_TYPE}, {GREATER_THAN, ">", "Greater Than (>)", ">", COMPARISON_OPERATOR_TYPE}, {LESS_THAN, "<", "Less Than (<)", "<", COMPARISON_OPERATOR_TYPE}, {GREATER_THAN_OR_EQUAL_TO, ">=", "Greater Than or Equal To (>=)", ">=", COMPARISON_OPERATOR_TYPE}, {LESS_THAN_OR_EQUAL_TO, "<=", "Less Than or Equal To (<=)", "<=", COMPARISON_OPERATOR_TYPE}, {IS_TRUE, "is TRUE", "Is TRUE (!=0)", "==true", BINARY_OPERATOR_TYPE}, {IS_FALSE, "is FALSE", "Is FALSE (==0)", "==false", BINARY_OPERATOR_TYPE}, {-1,"","",""} }; // Global declaration of literal info database #define UNKNOWN_LITERAL_STRING "UNKNOWN" ParamMenuItem param_menu_item[] = { {DOOR_PARAMETER_TYPE,"Door"}, {OBJECT_PARAMETER_TYPE,"Object"}, {ROOM_PARAMETER_TYPE,"Room"}, {TRIGGER_PARAMETER_TYPE,"Trigger"}, {INT_PARAMETER_TYPE,"Integer"}, {BOOL_PARAMETER_TYPE,"Bool"}, {FLOAT_PARAMETER_TYPE,"Float"}, {VECTOR_PARAMETER_TYPE,"Vector"}, {STRING_PARAMETER_TYPE,"String"}, {PERCENTAGE_PARAMETER_TYPE,"Percentage"}, {ENUM_PARAMETER_TYPE,"Enumerated Types"}, {SCRIPT_PARAMETER_TYPE,"Script"}, {SOUND_PARAMETER_TYPE,"Sound"}, {SPECNAME_PARAMETER_TYPE,"Specific Name"}, {TEXTURE_PARAMETER_TYPE,"Texture"}, {FLAG_PARAMETER_TYPE,"Flag"}, {PATH_PARAMETER_TYPE,"Path"}, {MATCEN_PARAMETER_TYPE,"Matcen"}, {LEVEL_GOAL_PARAMETER_TYPE,"Level Goal"}, {STRM_AUDIO_PARAMETER_TYPE,"Streaming Audio File"}, {-1,""} }; #define MAX_MESSAGES 10 // max messages to process during a message deferral // Processes and waiting messages void DeferMsgs(void) { MSG msg; for ( int MsgCount = MAX_MESSAGES; MsgCount && PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); MsgCount--) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } bool Compiling=FALSE; CString CompilerOutputText=""; CEdit *help_edit_ctrl=NULL; // Gets compiler output and displays it #define HELP_EDIT_CTRL_HEIGHT 7 void CompilerCallback(char *text) { CompilerOutputText+=text; if(help_edit_ctrl==NULL) return; help_edit_ctrl->SetWindowText(CompilerOutputText.GetBuffer(0)); int total_lines = help_edit_ctrl->GetLineCount(); int curr_index = help_edit_ctrl->GetFirstVisibleLine(); if( (total_lines-curr_index)>HELP_EDIT_CTRL_HEIGHT ){ //we need to scroll down a line help_edit_ctrl->LineScroll((total_lines-curr_index)-HELP_EDIT_CTRL_HEIGHT); } DeferMsgs(); } ///////////////////////////////////////////////////////////////////////////// // CDallasMainDlg dialog CDallasMainDlg::CDallasMainDlg(CWnd* pParent /*=NULL*/) : CDialog(CDallasMainDlg::IDD, pParent) { //{{AFX_DATA_INIT(CDallasMainDlg) //}}AFX_DATA_INIT InitAll(); help_edit_ctrl=&m_HelpEdit; m_pDragImage=NULL; m_bLDragging=FALSE; m_hitemDrag=NULL; m_hitemDrop=NULL; } void CDallasMainDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDallasMainDlg) DDX_Control(pDX, IDC_EVENT_COMBO, m_EventList); DDX_Control(pDX, IDC_EVENT_TREE, m_ScriptTree); DDX_Control(pDX, IDC_HELP_EDIT, m_HelpEdit); DDX_Control(pDX, IDC_MESSAGE_LIST, m_MessageList); DDX_Control(pDX, IDC_MESSAGE_EDIT, m_MessageEdit); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CDallasMainDlg, CDialog) //{{AFX_MSG_MAP(CDallasMainDlg) ON_BN_CLICKED(IDC_NEW_MESSAGE_BUTTON, OnNewMessageButton) ON_BN_CLICKED(IDC_DELETE_MESSAGE_BUTTON, OnDeleteMessageButton) ON_LBN_SELCHANGE(IDC_MESSAGE_LIST, OnSelchangeMessageList) ON_EN_CHANGE(IDC_MESSAGE_EDIT, OnChangeMessageEdit) ON_LBN_DBLCLK(IDC_MESSAGE_LIST, OnDblclkMessageList) ON_BN_CLICKED(IDC_CHANGE_MESSAGE_NAME_BUTTON, OnChangeMessageNameButton) ON_WM_CLOSE() ON_WM_DESTROY() ON_BN_CLICKED(IDC_NEW_EVENT_BUTTON, OnNewScriptButton) ON_BN_CLICKED(IDC_INSERT_EVENT_BUTTON, OnInsertScriptButton) ON_BN_CLICKED(IDC_DELETE_EVENT_BUTTON, OnDeleteScriptButton) ON_NOTIFY(NM_RCLICK, IDC_EVENT_TREE, OnRclickEventTree) ON_NOTIFY(NM_DBLCLK, IDC_EVENT_TREE, OnDblclkScriptTree) ON_NOTIFY(TVN_SELCHANGED, IDC_EVENT_TREE, OnSelchangedScriptTree) ON_BN_CLICKED(IDC_SAVE_BUTTON, OnSaveButton) ON_NOTIFY(TVN_KEYDOWN, IDC_EVENT_TREE, OnKeydownEventTree) ON_BN_CLICKED(IDC_COPY_BUTTON, OnCopyButton) ON_BN_CLICKED(IDC_PASTE_BUTTON, OnPasteButton) ON_BN_CLICKED(IDC_HIGHLIGHT_BUTTON, OnHighlightButton) ON_BN_CLICKED(IDC_EXPAND_ALL_BUTTON, OnExpandAllButton) ON_BN_CLICKED(IDC_COLLAPSE_ALL_BUTTON, OnCollapseAllButton) ON_BN_CLICKED(IDC_UTYPES_BUTTON, OnUtypesButton) ON_NOTIFY(TVN_BEGINDRAG, IDC_EVENT_TREE, OnBegindragEventTree) ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() ON_BN_CLICKED(IDC_ALLOBJ_RADIO, OnAllobjRadio) ON_BN_CLICKED(IDC_ALLTRIG_RADIO, OnAlltrigRadio) ON_BN_CLICKED(IDC_NONE_RADIO, OnNoneRadio) ON_BN_CLICKED(IDC_SPECIFIC_RADIO, OnSpecificRadio) ON_BN_CLICKED(IDC_LEVEL_RADIO, OnLevelRadio) ON_BN_CLICKED(IDC_IMPORT_BUTTON, OnImportButton) ON_BN_CLICKED(IDC_EXPORT_BUTTON, OnExportButton) ON_BN_CLICKED(IDC_EVENT_RADIO, OnEventRadio) ON_CBN_SELCHANGE(IDC_EVENT_COMBO, OnSelchangeEventCombo) //}}AFX_MSG_MAP ON_WM_ACTIVATE() ON_MESSAGE(WM_HIGHLIGHT_SCRIPTS,OnHighlightScripts) ON_MESSAGE(WM_ADD_SCRIPT,OnAddScript) ON_MESSAGE(WM_ADD_SCRIPT_AND_HIGHLIGHT,OnAddScriptAndHighlight) ON_COMMAND_RANGE(ASSIGN_COMMAND_RANGE_START,ASSIGN_COMMAND_RANGE_END,OnMenuSelectionOfTypeAssign) ON_COMMAND_RANGE(ADD_COMMAND_RANGE_START,ADD_COMMAND_RANGE_END,OnMenuSelectionOfTypeAdd) ON_COMMAND_RANGE(REPLACE_COMMAND_RANGE_START,REPLACE_COMMAND_RANGE_END,OnMenuSelectionOfTypeReplace) ON_COMMAND_RANGE(DELETE_COMMAND_RANGE_START,DELETE_COMMAND_RANGE_END,OnMenuSelectionOfTypeDelete) END_MESSAGE_MAP() // Sets up the dialog before it is displayed BOOL CDallasMainDlg::OnInitDialog() { CDialog::OnInitDialog(); //CString msg; //msg.Format("Starting ID: %d\nEnding ID: %d",STARTING_COMMAND_ID,DELETE_COMMAND_RANGE_END); //MessageBox(msg,"Used ID Range",MB_OK); // Setup the tree image list CBitmap bm; m_TreeImageList.Create(16,16,0,19,0); bm.LoadBitmap(IDB_DALLAS_TREE_ICONS_BITMAP); m_TreeImageList.Add(&bm,&bm); m_ScriptTree.SetImageList(&m_TreeImageList,TVSIL_NORMAL); // Setup the Message List GUI and data m_MessageEdit.SetLimitText(MAX_MESSAGE_LEN); // Make sure everything is cleared out, then load in everything Refresh(); Compiling=FALSE; //m_ScriptOwnerType=LEVEL_TYPE; //m_ScriptOwnerHandle=0; //PostMessage(WM_ADD_SCRIPT_AND_HIGHLIGHT); // Set the highlighting to none ClearHighlightRadioButtons(); ((CButton *) GetDlgItem(IDC_NONE_RADIO))->SetCheck(1); OnNoneRadio(); FillHighlightEventList(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } // Gets called whenever Dallas is activated, allows for validating of script values void CDallasMainDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) { CDialog::OnActivate(nState,pWndOther,bMinimized); #ifndef NEWEDITOR // Make sure we're in the editor if(GetFunctionMode()!=EDITOR_MODE) return; #endif if(pWndOther==NULL) return; CWnd *parent_window; parent_window=pWndOther->GetParent(); // If Dallas has been activated because it's returned from a child popup, // then get out of here... if(parent_window!=NULL) { if(this->m_hWnd==parent_window->m_hWnd) return; } // Make sure it's been activated, then scan the tree for bad values if(nState==WA_ACTIVE || nState==WA_CLICKACTIVE) { ClearNameLists(); FillNameListsFromTree(TVI_ROOT,FALSE); } } // Saves all data void CDallasMainDlg::OnSaveButton() { CString temp_str; char fullpath[_MAX_PATH]; #ifndef NEWEDITOR // Make sure we're in the editor if(GetFunctionMode()!=EDITOR_MODE) return; #endif Compiling=TRUE; // Create the script source file if(!CreateScriptFile(m_ScriptFilename.GetBuffer(0))) { Compiling=FALSE; return; } SetModified(FALSE); // Write out the message list CreateMsgTableFile(m_ScriptMessagesFilename.GetBuffer(0)); // Get the full DLL path, and delete the DLL ddio_MakePath(fullpath,LocalScriptDir,m_ScriptDLLFilename.GetBuffer(0),NULL); ddio_DeleteFile(fullpath); // Attempt to compile it and create the dll CompilerOutputText=""; tCompilerInfo ci; ci.callback = CompilerCallback; ci.script_type = ST_LEVEL; strcpy(ci.source_filename,m_ScriptFilename.GetBuffer(0)); ScriptCompile(&ci); // Check to see if the DLL has been created ddio_MakePath(fullpath,LocalScriptDir,m_ScriptDLLFilename.GetBuffer(0),NULL); if( _access(fullpath,0x00) == -1) { MessageBox("The compile failed. See output for error details.","Compiler Error"); } Compiling=FALSE; } // Called when the cancel button is pressed void CDallasMainDlg::OnCancel() { if(Compiling) return; if(ModifiedPrompt()==IDNO) return; // Shut it all down DestroyWindow(); //CDialog::OnCancel(); } // Called just before the window is destroyed void CDallasMainDlg::OnDestroy() { CDialog::OnDestroy(); // Peform clean-up ClearAll(); } // Destroy this instance void CDallasMainDlg::PostNcDestroy() { help_edit_ctrl=NULL; // Set the pointer back to null so rest of app knows Dallas has shut down #ifdef NEWEDITOR CNewEditorApp *theApp=(CNewEditorApp *)AfxGetApp(); theApp->DallasDone(); #else theApp.m_DallasModelessDlgPtr=NULL; #endif // Delete the Dallas instance delete this; } // Called before the window is closed void CDallasMainDlg::OnClose() { if(Compiling) return; if(ModifiedPrompt()==IDNO) return; // Shut it all down DestroyWindow(); //CDialog::OnClose(); } // HACK to handle the pressing of the ENTER button (DOESN'T WORK RIGHT NOW) void CDallasMainDlg::OnOK() { if(Compiling) return; HTREEITEM selected_item; // Pressing ENTER will now cause an edit popup to appear for selected node selected_item=m_ScriptTree.GetSelectedItem(); if(selected_item==NULL) return; AssignSpecificValue(); } // Launches the UserTypes Dialog void CDallasMainDlg::OnUtypesButton() { CDallasUserTypesDlg dlg; dlg.DoModal(); UpdateTreeText(TVI_ROOT); } ///////////////////////////////////////////////////////////////////////////// // CDallasMainDlg message handlers ///////////////////////////////////////////////////////////////////////////// // Adds a new (default) message to the message list void CDallasMainDlg::OnNewMessageButton() { CString new_name; // Create the new name new_name.Format("%s%d",DEFAULT_MESSAGE_NAME,m_NextMessageID); // Make sure the default name isn't already taken while(FindMessageInList(new_name.GetBuffer(0))!=NULL) { m_NextMessageID++; new_name.Format("%s%d",DEFAULT_MESSAGE_NAME,m_NextMessageID); } // Add it to the list AddToMessageList(new_name.GetBuffer(0),DEFAULT_MESSAGE_TEXT); m_NextMessageID++; // Now let the user change the name if they want to OnDblclkMessageList(); // And then set focus to the message entry box m_MessageEdit.SetFocus(); SetModified(TRUE); } // Deletes the currently selected message from the list void CDallasMainDlg::OnDeleteMessageButton() { int index; tMessageListEntry *msg_entry; index=m_MessageList.GetCurSel(); if(index==LB_ERR) return; // Get the entry for this item msg_entry=(tMessageListEntry *)m_MessageList.GetItemData(index); // Mark this entry as being free DeleteMessageListEntry(msg_entry->name); // Delete the list box item and update edit boxes m_MessageList.DeleteString(index); OnSelchangeMessageList(); SetModified(TRUE); } // Callback for when the Message List Box selection changes void CDallasMainDlg::OnSelchangeMessageList() { int index; CString name; tMessageListEntry *msg_entry; index=m_MessageList.GetCurSel(); if(index==LB_ERR) { m_MessageEdit.SetWindowText(""); return; } // Get the entry for this item msg_entry=(tMessageListEntry *)m_MessageList.GetItemData(index); // Set the edit boxes to reflect the appropriate data m_MessageEdit.SetWindowText(msg_entry->message); } // Allows user to change the name of the string void CDallasMainDlg::OnDblclkMessageList() { CDallasGenericPromptDlg dlg; int index; tMessageListEntry *msg_entry; CString message, old_name; index=m_MessageList.GetCurSel(); if(index==LB_ERR) return; // Get the entry for this item msg_entry=(tMessageListEntry *)m_MessageList.GetItemData(index); // Display the prompt dialog old_name=msg_entry->name; dlg.m_DialogTitle="Message Name Prompt"; dlg.m_PromptText="Enter the new name for this message:"; dlg.m_PromptData=old_name; dlg.m_MaxDataLength=MAX_MESSAGE_NAME_LEN; if(dlg.DoModal()==IDCANCEL) return; // Check if the message name is valid char *msgname=dlg.m_PromptData.GetBuffer(0); if(strlen(msgname)==0) return; for(uint32_t j=0;jmessage; // Remove the old name from list box OnDeleteMessageButton(); // Now, add the new name (and old message) back in AddToMessageList(dlg.m_PromptData.GetBuffer(0),message.GetBuffer(0)); // Update any old messageID's in the tree to use the new name UpdateStringParams(TVI_ROOT,old_name.GetBuffer(0),dlg.m_PromptData.GetBuffer(0)); SetModified(TRUE); } // Does the same thing as double-clicking a name (allows you to change it) void CDallasMainDlg::OnChangeMessageNameButton() { // TODO: Add your control notification handler code here OnDblclkMessageList(); } // Updates the text for the message being edited void CDallasMainDlg::OnChangeMessageEdit() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask() // with the ENM_CHANGE flag ORed into the mask. // TODO: Add your control notification handler code here int index; CString name, new_message; char *message; index=m_MessageList.GetCurSel(); if(index==LB_ERR) return; m_MessageList.GetText(index,name); message=FindMessageInList(name.GetBuffer(0)); if(message==NULL) return; m_MessageEdit.GetWindowText(new_message); strcpy(message,new_message.GetBuffer(0)); SetModified(TRUE); } // Adds a new default script to the end of the list void CDallasMainDlg::OnNewScriptButton() { HTREEITEM new_node; int new_id=GetLowestUnusedScriptID(); new_node=CreateDefaultScriptTree(new_id); if(new_node!=NULL) { if(new_id==m_NextScriptID) m_NextScriptID++; m_ScriptTree.SelectItem(new_node); AssignSpecificValue(); } } // Inserts a new default script before the currently selected script void CDallasMainDlg::OnInsertScriptButton() { HTREEITEM new_node; int new_id=GetLowestUnusedScriptID(); new_node=CreateDefaultScriptTree(new_id,m_ScriptTree.GetSelectedItem()); if(new_node!=NULL) { if(new_id==m_NextScriptID) m_NextScriptID++; m_ScriptTree.SelectItem(new_node); AssignSpecificValue(); } } // Deletes the currently selected script void CDallasMainDlg::OnDeleteScriptButton() { HTREEITEM script_header_node; script_header_node=GetParentNodeOfType(m_ScriptTree.GetSelectedItem(),SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; if(DeletePrompt("Are you sure you want to delete this script?")==IDYES) { FreeTreeItem(script_header_node); SetModified(TRUE); } } // Do a script copy void CDallasMainDlg::OnCopyButton() { PerformScriptCopy(); } // Do a script paste void CDallasMainDlg::OnPasteButton() { PerformScriptPaste(); } // Collapses all node from the selected node on down void CDallasMainDlg::OnExpandAllButton() { HTREEITEM selected_node; selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; ExpandAll(selected_node,TVE_EXPAND); m_ScriptTree.EnsureVisible(selected_node); } // Collapses all node from the selected node on down void CDallasMainDlg::OnCollapseAllButton() { HTREEITEM selected_node; selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; ExpandAll(selected_node,TVE_COLLAPSE); m_ScriptTree.EnsureVisible(selected_node); } // Handles the script highlighting void CDallasMainDlg::OnHighlightButton() { HTREEITEM selected_node, owner_node; selected_node=m_ScriptTree.GetSelectedItem(); owner_node=GetScriptOwnerNode(selected_node); if(owner_node==NULL) return; tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); if(data==NULL) return; m_ScriptOwnerType=data->ID; m_ScriptOwnerHandle=data->int_val; HighlightAllScripts(); ClearHighlightRadioButtons(); ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(1); } // Calls up edit dialogs when double clicking on a node void CDallasMainDlg::OnDblclkScriptTree(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here *pResult = 0; } // Displays a context sensitive pop-up menu void CDallasMainDlg::OnRclickEventTree(NMHDR* pNMHDR, LRESULT* pResult) { POINT pt; TVHITTESTINFO hit_info; ::GetCursorPos(&pt); m_ScriptTree.ScreenToClient(&pt); hit_info.pt=pt; // Check to see if the mouse is lined up with a tree item m_ScriptTree.HitTest(&hit_info); if(hit_info.flags & TVHT_ONITEM || hit_info.flags & TVHT_ONITEMRIGHT || hit_info.flags & TVHT_ONITEMINDENT) { // Select the item m_ScriptTree.SelectItem(hit_info.hItem); // Convert back to screen coordinates for displaying the menu m_ScriptTree.ClientToScreen(&pt); DisplayFloatingPopupMenu(hit_info.hItem,pt); } *pResult = 0; } // Displays a context sensitive pop-up menu for the given node at the given screen pt void CDallasMainDlg::DisplayFloatingPopupMenu(HTREEITEM node, POINT &pt) { int valid_return_type; CString valid_return_name; tTreeNodeData *data; if(node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return; // Call the appropriate Menu Creation function switch(data->type) { case SCRIPT_HEADER_NODE: DisplayScriptHeaderNodeMenu(&pt); break; case SCRIPT_OWNER_NODE: DisplayScriptOwnerNodeMenu(&pt); break; case SCRIPT_EVENT_NODE: DisplayScriptEventNodeMenu(&pt,GetScriptOwnerType(node),ScriptHasADoorMe(node)); break; case CONDITIONAL_HEADER_NODE: break; case ACTIONS_HEADER_NODE: DisplayActionHeaderNodeMenu(&pt,data->ID,data->subID,CanAppendElseToNode(node)); break; case CONDITIONAL_STATEMENT_NODE: DisplayConditionalStatementNodeMenu(&pt); break; case EXPRESSION_NODE: valid_return_type=GetValidParamType(node,valid_return_name); DisplayExpressionNodeMenu(&pt,valid_return_type,valid_return_name.GetBuffer(0)); break; case EXPRESSION_OPERATOR_NODE: DisplayExpressionOperatorNodeMenu(&pt,data->ID); break; case ACTION_STATEMENT_NODE: DisplayActionStatementNodeMenu(&pt); break; case LOGICAL_OPERATOR_NODE: DisplayLogicalOperatorNodeMenu(&pt); break; case PARAMETER_NODE: valid_return_type=GetValidParamType(node,valid_return_name); DisplayParameterNodeMenu(&pt,data->ID,data->name,valid_return_type,valid_return_name.GetBuffer(0),ScriptHasAnIt(node),ScriptHasAMe(node),ScriptHasADoorMe(node),ScriptHasAGoalID(node),ScriptHasATimerID(node),ScriptHasAMatcenID(node),ScriptHasALevelGoalID(node)); break; case PARAMETER_OPERATOR_NODE: break; case UNKNOWN_NODE: break; default: break; } } // Displays appropriate help for the newly selected item void CDallasMainDlg::OnSelchangedScriptTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here HTREEITEM selected_item; tTreeNodeData *data; selected_item=m_ScriptTree.GetSelectedItem(); if(selected_item==NULL) return; data=GetNearestFunctionNode(selected_item); if(data!=NULL) { // If it's an action node, display the help if(data->type==ACTION_STATEMENT_NODE) { char *help=GetActionHelp(data->ID); if(help!=NULL) m_HelpEdit.SetWindowText(help); } // If it's a query node, display the help if(data->type==EXPRESSION_NODE) { char *help=GetQueryHelp(data->ID); if(help!=NULL) m_HelpEdit.SetWindowText(help); } } *pResult = 0; } // Allow keyboard input for the tree control void CDallasMainDlg::OnKeydownEventTree(NMHDR* pNMHDR, LRESULT* pResult) { TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; CTreeCtrl *tree = (CTreeCtrl *)GetDlgItem(pTVKeyDown->hdr.idFrom); HTREEITEM hSelectedItem = tree->GetSelectedItem(); switch (pTVKeyDown->wVKey) { case VK_INSERT: break; case VK_DELETE: break; case VK_SPACE: tree->Expand(hSelectedItem, TVE_TOGGLE); break; } *pResult = 0; } ///////////////////////////////////////////////////////////////////////////// // External DALLAS messaging system ///////////////////////////////////////////////////////////////////////////// LONG CDallasMainDlg::OnHighlightScripts(UINT, LONG) { HighlightAllScripts(); ClearHighlightRadioButtons(); ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(1); return 0; } LONG CDallasMainDlg::OnAddScript(UINT, LONG) { HTREEITEM new_node; int new_id=GetLowestUnusedScriptID(); new_node=CreateDefaultScriptTree(new_id); if(new_node!=NULL) { if(new_id==m_NextScriptID) m_NextScriptID++; m_ScriptTree.SelectItem(new_node); // Assign given data to owner HTREEITEM owner_node=GetScriptOwnerNode(new_node); if(owner_node!=NULL) { tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); if(data!=NULL) { data->ID=m_ScriptOwnerType; data->int_val=m_ScriptOwnerHandle; if(data->ID==OBJECT_TYPE) { object *objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { data->int_val=OBJECT_HANDLE_NONE; strcpy(data->str_val,""); } else { strcpy(data->str_val,objp->name); } } else if(data->ID==TRIGGER_TYPE) { if(data->int_val<0 || data->int_val>=Num_triggers) { data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); } else { strcpy(data->str_val,Triggers[data->int_val].name); } } else { strcpy(data->str_val,""); } UpdateNodeText(owner_node); } } // Prompt the user for the name of this script AssignSpecificValue(); } return 0; } LONG CDallasMainDlg::OnAddScriptAndHighlight(UINT, LONG) { HTREEITEM new_node; int new_id=GetLowestUnusedScriptID(); new_node=CreateDefaultScriptTree(new_id); if(new_node!=NULL) { if(new_id==m_NextScriptID) m_NextScriptID++; m_ScriptTree.SelectItem(new_node); // Assign given data to owner HTREEITEM owner_node=GetScriptOwnerNode(new_node); if(owner_node!=NULL) { tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); if(data!=NULL) { data->ID=m_ScriptOwnerType; data->int_val=m_ScriptOwnerHandle; if(data->ID==OBJECT_TYPE) { object *objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { data->int_val=OBJECT_HANDLE_NONE; strcpy(data->str_val,""); } else { strcpy(data->str_val,objp->name); } } else if(data->ID==TRIGGER_TYPE) { if(data->int_val<0 || data->int_val>=Num_triggers) { data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); } else { strcpy(data->str_val,Triggers[data->int_val].name); } } else { strcpy(data->str_val,""); } UpdateNodeText(owner_node); } } // Highlight all the scripts HighlightAllScripts(); ClearHighlightRadioButtons(); ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(1); // Prompt the user for the name of this script AssignSpecificValue(); } return 0; } // Displays the "are you sure?" dialog int CDallasMainDlg::ModifiedPrompt(void) { // If current file has been modified, check with user first... if(!m_Modified) return(IDYES); if(MessageBox("Your changes will be lost. Proceed?","Script Has Been Modified",MB_YESNO)==IDYES) return(IDYES); return(IDNO); } // Sets the modified flag void CDallasMainDlg::SetModified(bool value) { m_Modified=value; SetTitleBar(); } #define DALLAS_TITLE_STRING "Dallas Graphical Script Editor v1.0" // Updates the Dallas title bar void CDallasMainDlg::SetTitleBar(void) { CString title; // Get the current level name char filename[PSPATHNAME_LEN+1]; if(m_ScriptFilename.IsEmpty()) strcpy(filename,"Untitled"); else ddio_SplitPath(m_ScriptFilename.GetBuffer(0),NULL,filename,NULL); title.Format("%s - %s%s",DALLAS_TITLE_STRING,filename,(m_Modified) ? "*":""); SetWindowText(title.GetBuffer(0)); } ///////////////////////////////////////////////////////////////////////////// // Floating Popup Menu Callbacks ///////////////////////////////////////////////////////////////////////////// // Translates the type of Assign being requested void CDallasMainDlg::OnMenuSelectionOfTypeAssign(UINT nID) { // Check for the assigning of a message name if(nID>=ASSIGN_SCRIPT_ID_RANGE_START && nID=ASSIGN_EXEC_TIME_ID_RANGE_START && nID=ASSIGN_CHAIN_ID_RANGE_START && nID=ASSIGN_MESSAGE_ID_RANGE_START && nID=ASSIGN_EVENT_ID_RANGE_START && nID=ASSIGN_TRIGGER_ID_RANGE_START && nID=ASSIGN_OBJECT_ID_RANGE_START && nID=ASSIGN_ROOM_ID_RANGE_START && nID=ASSIGN_EXPOP_ID_RANGE_START && nID=ASSIGN_ENUM_VALUE_ID_RANGE_START && nID=ASSIGN_PATH_ID_RANGE_START && nID=ASSIGN_MATCEN_ID_RANGE_START && nID=ASSIGN_LEVEL_GOAL_ID_RANGE_START && nID=ADD_ACTION_ID_RANGE_START && nID=ADD_LOGOP_ID_RANGE_START && nID=INSERT_LOGOP_ID_RANGE_START && nID=ADD_CONDITION_ID_RANGE_START && nID=ADD_COND_QBIN_ID_RANGE_START && nID=ADD_COND_QCOMP_ID_RANGE_START && nID=REPLACE_QUERY_ID_RANGE_START && nID=REPLACE_LITERAL_ID_RANGE_START && nID=REPLACE_LIT_ENUM_ID_RANGE_START && nID=REPLACE_LIT_FLAG_ID_RANGE_START && nID=REPLACE_ACTION_ID_RANGE_START && nID=REPLACE_LOGOP_ID_RANGE_START && nID=REPLACE_CONDITION_ID_RANGE_START && nID=REPLACE_COND_QBIN_ID_RANGE_START && nID=REPLACE_COND_QCOMP_ID_RANGE_START && nIDtype) { case ACTION_STATEMENT_NODE: FreeTreeItem(selected_node); ConfirmAfterDelete(parent_node); SetModified(TRUE); break; case CONDITIONAL_STATEMENT_NODE: FreeTreeItem(selected_node); ConfirmAfterDelete(parent_node); SetModified(TRUE); break; case LOGICAL_OPERATOR_NODE: FreeTreeItem(selected_node); ConfirmAfterDelete(parent_node); SetModified(TRUE); break; case ACTIONS_HEADER_NODE: if(data->ID==NESTED) { if(data->subID==THEN_CLAUSE) { HTREEITEM temp_node; // Delete the IF clause temp_node=m_ScriptTree.GetPrevSiblingItem(selected_node); if(GetNodeType(temp_node)==CONDITIONAL_HEADER_NODE) FreeTreeItem(temp_node); // Delete the ELSE clause (if it exists) temp_node=m_ScriptTree.GetNextSiblingItem(selected_node); if(GetNodeType(temp_node)==ACTIONS_HEADER_NODE) FreeTreeItem(temp_node); // Delete the THEN clause FreeTreeItem(selected_node); } else { // Delete just the ELSE clause FreeTreeItem(selected_node); } ConfirmAfterDelete(parent_node); SetModified(TRUE); } break; } return; } // Handle Delete children only's if(nID==DELETE_CHILDREN_ONLY_ID) { switch(data->type) { case ACTIONS_HEADER_NODE: if(DeletePrompt("Are you sure you want to delete all children of this Clause?")==IDYES) { FreeTreeItemChildren(selected_node); ConfirmAfterDelete(selected_node); SetModified(TRUE); } break; } return; } } // Displays a deletion prompt int CDallasMainDlg::DeletePrompt(char *msg) { CString title="Deletion Prompt"; return(MessageBox(msg,title.GetBuffer(0),MB_YESNO|MB_ICONQUESTION)); } // Makes sure everything is as it should be after a delete void CDallasMainDlg::ConfirmAfterDelete(HTREEITEM parent) { tTreeNodeData *data; HTREEITEM new_node; if(parent==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); if(data==NULL) return; // Make sure IF statement has one child! if(data->type==CONDITIONAL_HEADER_NODE) { if(GetChildCount(parent)!=1) { FreeTreeItemChildren(parent); new_node=CreateDefaultConditionalStatementNode(parent); if(new_node!=NULL) m_ScriptTree.SelectItem(new_node); } return; } // Make sure THEN statement has at least one child if(data->type==ACTIONS_HEADER_NODE) { if(GetChildCount(parent)==0) { new_node=CreateDefaultActionStatementNode(parent); if(new_node!=NULL) m_ScriptTree.SelectItem(new_node); } return; } // Make sure Logical operators have right number of children if(data->type==LOGICAL_OPERATOR_NODE) { if(data->ID==AND_TYPE || data->ID==OR_TYPE) { if(GetChildCount(parent)<2) { new_node=CreateDefaultConditionalStatementNode(parent); if(new_node!=NULL) m_ScriptTree.SelectItem(new_node); } } return; } } ///////////////////////////////////////////////////////////////////////////// // General Refresh functions ///////////////////////////////////////////////////////////////////////////// // Performs all basic initialization tasks void CDallasMainDlg::InitAll(void) { m_Modified=FALSE; InitTree(); InitMessageList(); InitEnumDatabase(); InitFlagDatabase(); InitFunctionDatabases(); InitScriptGroupingList(); InitObjectHandleList(); InitCustomScriptStorage(); InitNameLists(); CurrentOutputFile=NULL; CurrentTabLevel=0; m_ScriptOwnerType=NONE_TYPE; m_ScriptOwnerHandle=0; } // Frees up all DALLAS memory void CDallasMainDlg::ClearAll(void) { ClearMessageList(); ClearEnumDatabase(); ClearFlagDatabase(); ClearFunctionDatabases(); ClearTree(); ClearScriptGroupingList(); ClearObjectHandleList(); ClearCustomScriptStorage(); ClearNameLists(); } // Loads in everything void CDallasMainDlg::LoadAll(void) { // Parse the message file (string table) for this level ParseMsgTableFile(m_ScriptMessagesFilename.GetBuffer(0)); // Parse actions into the Action Database ParseFunctionFile(m_DallasFunctionsFilename.GetBuffer(0)); ParseFunctionFile(m_ScriptFilename.GetBuffer(0),FALSE); // Read in the saved script tree ParseSourceScript(m_ScriptFilename.GetBuffer(0)); // Read in the custom script text ParseCustomScriptFile(m_ScriptFilename.GetBuffer(0),FALSE); } // Sets all the filenames to match the currently loaded level void CDallasMainDlg::SetAllFilenames(void) { // Set the Dallas Functions Filename m_DallasFunctionsFilename=DALLASFUNCS_FILENAME; // Get the current level name char filename[PSPATHNAME_LEN+1]; CString level_fname; #ifdef NEWEDITOR level_fname = Level_name; #else level_fname = theApp.main_doc->GetPathName(); #endif if(level_fname.IsEmpty()) strcpy(filename,"Untitled"); else ddio_SplitPath(level_fname.GetBuffer(0),NULL,filename,NULL); // Create the script source filename m_ScriptFilename.Format("%s.cpp",filename); // Create the script DLL filename m_ScriptDLLFilename.Format("%s.dll",filename); // Create the message table filename m_ScriptMessagesFilename.Format("%s.msg",filename); } // Sets all the filenames to match the given level name void CDallasMainDlg::SetAllFilenamesToThis(char *level_path) { if(level_path==NULL) return; // Set the Dallas Functions Filename m_DallasFunctionsFilename=DALLASFUNCS_FILENAME; // Get the current level name char filename[PSPATHNAME_LEN+1]; CString level_fname; level_fname = level_path; if(level_fname.IsEmpty()) strcpy(filename,"Untitled"); else ddio_SplitPath(level_fname.GetBuffer(0),NULL,filename,NULL); // Create the script source filename m_ScriptFilename.Format("%s.cpp",filename); // Create the script DLL filename m_ScriptDLLFilename.Format("%s.dll",filename); // Create the message table filename m_ScriptMessagesFilename.Format("%s.msg",filename); // Reflect changes in the title bar SetTitleBar(); } // Does a complete refresh of DALLAS void CDallasMainDlg::Refresh(void) { // Make sure everything is cleared out ClearAll(); // Set all the filenames to match the currently loaded level SetAllFilenames(); // Load in everything LoadAll(); // Highlight the appropriate scripts HighlightAllScripts(); SetModified(FALSE); } ///////////////////////////////////////////////////////////////////////////// // Manage System functions ///////////////////////////////////////////////////////////////////////////// void CDallasMainDlg::CheckinScriptFiles(void) { } void CDallasMainDlg::CheckoutScriptFiles(void) { } void CDallasMainDlg::DeleteScriptFiles(void) { } ///////////////////////////////////////////////////////////////////////////// // Tree Control Functions ///////////////////////////////////////////////////////////////////////////// // Performs any necessary initialization of the tree control (and node data) void CDallasMainDlg::InitTree(void) { m_NextScriptID=0; m_ClipboardNode=NULL; } // Performs any necessary de-initialization of the tree control (and node data) void CDallasMainDlg::ClearTree(void) { FreeTreeItemChildren(TVI_ROOT); m_NextScriptID=0; m_ClipboardNode=NULL; } // Obtains the string name for an event type char *CDallasMainDlg::GetEventTypeString(int type) { for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==type) return(event_info[j].name); return(UNKNOWN_EVENT_STRING); } // Updates the text for every node in the tree void CDallasMainDlg::UpdateTreeText(HTREEITEM parent) { HTREEITEM child; if(parent==NULL) return; // Process the children child=m_ScriptTree.GetChildItem(parent); while(child!=NULL) { UpdateTreeText(child); UpdateNodeText(child); // Get the next child child=m_ScriptTree.GetNextSiblingItem(child); } } // Obtains the in-code DEFINE name for an event type char *CDallasMainDlg::GetEventCodeName(int type) { for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==type) return(event_info[j].code_name); return(UNKNOWN_EVENT_CODE_NAME); } // Obtains the data line for an event type char *CDallasMainDlg::GetEventDataLine(int type) { for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==type) return(event_info[j].data_line); return(UNKNOWN_EVENT_DATA_LINE); } // Obtains the string name for a logical operator type void CDallasMainDlg::GetLogicalOperatorTypeString(int type, CString &string) { switch(type) { case AND_TYPE: string="AND"; break; case OR_TYPE: string="OR"; break; default: string="Unknown"; break; } } // Checks to see if the given script has an IT (based upon the event type) bool CDallasMainDlg::ScriptHasAnIt(HTREEITEM script_node) { // Check the owner type (only triggers and objects can have an it) //int owner_type=GetScriptOwnerType(script_node); //if(owner_type!=OBJECT_TYPE && owner_type!=TRIGGER_TYPE) // return FALSE; // Check the script's event type int event_type=GetScriptEventType(script_node); for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==event_type) { if(event_info[j].flags & HAS_IT_MASK) return TRUE; else return FALSE; } return FALSE; } // Checks to see if the given script has an ME (based upon the event type) bool CDallasMainDlg::ScriptHasAMe(HTREEITEM script_node) { // Check the owner type (only an object owner can have a me) int owner_type=GetScriptOwnerType(script_node); if(owner_type!=OBJECT_TYPE) return FALSE; return TRUE; } // Checks to see if the given script has a ME of type DOOR (based upon the event type) bool CDallasMainDlg::ScriptHasADoorMe(HTREEITEM script_node) { HTREEITEM owner_node; tTreeNodeData *data; owner_node=GetScriptOwnerNode(script_node); if(owner_node==NULL) return(FALSE); data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); if(data==NULL) return(FALSE); // Check the owner type (only an object owner can have a me) if(data->ID!=OBJECT_TYPE) return FALSE; // Make sure it's a Door object object *objp=ObjGet(data->int_val); if(objp==NULL || objp->type!=OBJ_DOOR || objp->name==NULL) return FALSE; return TRUE; } // Checks to see if the given script has an GoalID (based upon the event type) bool CDallasMainDlg::ScriptHasAGoalID(HTREEITEM script_node) { // Check the owner type (only levels and objects can have a GoalID) int owner_type=GetScriptOwnerType(script_node); if(owner_type!=OBJECT_TYPE && owner_type!=LEVEL_TYPE) return FALSE; // Check the script's event type int event_type=GetScriptEventType(script_node); for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==event_type) { if(event_info[j].flags & HAS_GOALID_MASK) return TRUE; else return FALSE; } return FALSE; } // Checks to see if the given script has a Timer ID (based upon the event type) bool CDallasMainDlg::ScriptHasATimerID(HTREEITEM script_node) { // Check the owner type (only levels and objects can have a MatcenID) int owner_type=GetScriptOwnerType(script_node); if(owner_type!=OBJECT_TYPE && owner_type!=LEVEL_TYPE) return FALSE; // Check the script's event type int event_type=GetScriptEventType(script_node); for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==event_type) { if(event_info[j].flags & HAS_TIMERID_MASK) return TRUE; else return FALSE; } return FALSE; } // Checks to see if the given script has a Matcen ID (based upon the event type) bool CDallasMainDlg::ScriptHasAMatcenID(HTREEITEM script_node) { // Check the owner type (only levels and objects can have a MatcenID) int owner_type=GetScriptOwnerType(script_node); if(owner_type!=OBJECT_TYPE && owner_type!=LEVEL_TYPE) return FALSE; // Check the script's event type int event_type=GetScriptEventType(script_node); for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==event_type) { if(event_info[j].flags & HAS_MATCENID_MASK) return TRUE; else return FALSE; } return FALSE; } // Checks to see if the given script has a Level Goal ID (based upon the event type) bool CDallasMainDlg::ScriptHasALevelGoalID(HTREEITEM script_node) { // Check the owner type (only levels and objects can have a MatcenID) int owner_type=GetScriptOwnerType(script_node); if(owner_type!=LEVEL_TYPE) return FALSE; // Check the script's event type int event_type=GetScriptEventType(script_node); for(int j=0;event_info[j].type>=0;j++) if(event_info[j].type==event_type) { if(event_info[j].flags & HAS_LEVGOALID_MASK) return TRUE; else return FALSE; } return FALSE; } // Checks to see if a given node is a clause of the given type bool CDallasMainDlg::NodeIsIfClause(HTREEITEM node) { tTreeNodeData *data; if(node==NULL) return(FALSE); data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL || data->type!=CONDITIONAL_HEADER_NODE) return(FALSE); if(data->ID!=NESTED) return(FALSE); return(TRUE); } // Checks to see if a given node is a clause of the given type bool CDallasMainDlg::NodeIsClauseOfType(HTREEITEM node, int type) { tTreeNodeData *data; if(node==NULL) return(FALSE); data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL || data->type!=ACTIONS_HEADER_NODE) return(FALSE); if(data->ID!=NESTED) return(FALSE); if(data->subID!=type) return(FALSE); return(TRUE); } // Checks to see if it's ok to add an else clause to the given node bool CDallasMainDlg::CanAppendElseToNode(HTREEITEM node) { HTREEITEM next_node; // Make sure given node is a nested THEN if(!NodeIsClauseOfType(node,THEN_CLAUSE)) return(FALSE); // Make sure this node doesn't already have an else next_node=m_ScriptTree.GetNextSiblingItem(node); if(NodeIsClauseOfType(next_node,ELSE_CLAUSE)) return(FALSE); return(TRUE); } // Obtains the string name for an expression operator type char *CDallasMainDlg::GetExpressionOperatorTypeString(int type) { for(int j=0;expop_info[j].type>=0;j++) if(expop_info[j].type==type) return(expop_info[j].name); return(UNKNOWN_EXPOP_STRING); } // Obtains the string name for an expression operator type char *CDallasMainDlg::GetExpressionOperatorCodeName(int type) { for(int j=0;expop_info[j].type>=0;j++) if(expop_info[j].type==type) return(expop_info[j].code_name); return(UNKNOWN_EXPOP_STRING); } // Obtains the string name for a literal char *CDallasMainDlg::GetLiteralName(int type) { for(int j=0;param_menu_item[j].type>=0;j++) if(param_menu_item[j].type==type) return(param_menu_item[j].name); return(UNKNOWN_LITERAL_STRING); } // Updates the text display of the given node void CDallasMainDlg::UpdateNodeText(HTREEITEM node) { CString new_text; tTreeNodeData *data; if(node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return; // Format and set the new text FormatTreeText(new_text,data,node); m_ScriptTree.SetItemText(node,new_text.GetBuffer(0)); } // Updates the text of given node and all parent nodes above the given node void CDallasMainDlg::UpdateAllParentNodesText(HTREEITEM node) { HTREEITEM parent; if(node==NULL) return; UpdateNodeText(node); parent=m_ScriptTree.GetParentItem(node); while(parent!=NULL) { UpdateNodeText(parent); parent=m_ScriptTree.GetParentItem(parent); } } // Formats the given string according to the given node data void CDallasMainDlg::FormatTreeText(CString &text, tTreeNodeData *data, HTREEITEM node/*=NULL*/) { CString tmp_str1, tmp_str2; object *objp; // Make sure given data is valid if(data==NULL) return; // Format the text according to the tree node type switch(data->type) { case SCRIPT_HEADER_NODE: text.Format("Script %.03d: %s",data->ID,data->name); break; case SCRIPT_OWNER_NODE: switch(data->ID) { case OBJECT_TYPE: if(data->int_val == OBJECT_HANDLE_NONE) { text.Format("Owner: %s (Object)",NONE_STRING); break; } objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) text.Format("Owner: *OBJECT_ERROR*"); else text.Format("Owner: %s (Object)",objp->name); break; case TRIGGER_TYPE: if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("Owner: %s (Trigger)",NOT_SPECIFIED_STRING); break; } if(data->int_val<0 || data->int_val>=Num_triggers) text.Format("Owner: *INVALID_TRIGGER*"); else text.Format("Owner: %s (Trigger)",Triggers[data->int_val].name); break; case LEVEL_TYPE: text.Format("Owner: Level"); break; default: text.Format("Owner: %s",NOT_SPECIFIED_STRING); break; } break; case SCRIPT_EVENT_NODE: text.Format("Event: %s",GetEventTypeString(data->ID)); break; case CONDITIONAL_HEADER_NODE: text.Format("If the following condition is met:"); break; case ACTIONS_HEADER_NODE: if(data->ID==TOP_LEVEL && data->int_val==BREAK_SCRIPT_CHAIN) tmp_str2=" and BREAK script chain"; else tmp_str2=""; if(data->ID==TOP_LEVEL && data->subID==1) tmp_str1.Format(" (only do once%s)",tmp_str2); else if(data->ID==TOP_LEVEL && data->subID==2) tmp_str1.Format(" (only do twice%s)",tmp_str2); else if(data->ID==TOP_LEVEL && data->subID>=3) tmp_str1.Format(" (only do %d times%s)",data->subID,tmp_str2); else tmp_str1.Format("%s",tmp_str2); if(data->ID==NESTED && data->subID==ELSE_CLAUSE) text.Format("Else, perform these actions:"); else text.Format("Then perform the following actions%s:",tmp_str1); break; case CONDITIONAL_STATEMENT_NODE: if(data->ID==ALWAYS_STATEMENT) text.Format("%s",ALWAYS_STRING); else FormatConditionText(text,node); break; case EXPRESSION_NODE: FormatQueryNodeText(tmp_str1,node); text.Format("%s: %s",data->name,tmp_str1); break; case EXPRESSION_OPERATOR_NODE: text.Format("Operation: %s",GetExpressionOperatorTypeString(data->subID)); break; case ACTION_STATEMENT_NODE: if(data->ID==DO_NOTHING_ID) text.Format("%s",DO_NOTHING_STRING); else FormatActionNodeText(text,node); break; case LOGICAL_OPERATOR_NODE: GetLogicalOperatorTypeString(data->ID,tmp_str1); text.Format("%s",tmp_str1); break; case PARAMETER_NODE: FormatParameterValueText(tmp_str1,data); text.Format("%s: %s",data->name, tmp_str1.GetBuffer(0)); break; case PARAMETER_OPERATOR_NODE: text.Format("this is a parameter operator"); break; case CLIPBOARD_HEADER_NODE: text.Format("Clipboard"); break; case UNKNOWN_NODE: text.Format("Unknown Type"); break; default: text.Format("REALLY Unknown Type"); break; } } // Formats the text for a Conditional Statement according to it and its children void CDallasMainDlg::FormatConditionText(CString &text, HTREEITEM condition_node) { tTreeNodeData *data; HTREEITEM child_node; // Make sure given node is valid if(condition_node==NULL) { text="*ERROR*"; return; } // Get node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(condition_node); if(data==NULL) { text="*ERROR*"; return; } // Make sure given data node is a conditional statement node if(data->type!=CONDITIONAL_STATEMENT_NODE) { text=""; return; } text="("; // Get the first child (literal or query) child_node=m_ScriptTree.GetChildItem(condition_node); if(child_node!=NULL) { CString temp_str; FormatGenericExpressionText(temp_str,child_node); text+=temp_str; } else { text+="???"; } text+=") "; // Get the second child (expression operator) if(child_node!=NULL) { child_node=m_ScriptTree.GetNextSiblingItem(child_node); if(child_node!=NULL) { CString temp_str; FormatGenericExpressionText(temp_str,child_node); text+=temp_str; } else { text+="???"; } } // If it's a comparison, get the third child (literal or query) if(child_node!=NULL && data->ID==COMPARISON_STATEMENT) { child_node=m_ScriptTree.GetNextSiblingItem(child_node); if(child_node!=NULL) { CString temp_str; FormatGenericExpressionText(temp_str,child_node); text+=" ("; text+=temp_str; text+=")"; } else { text+=" (???)"; } } } // Formats a child node of a conditional statement node void CDallasMainDlg::FormatGenericExpressionText(CString &text, HTREEITEM gen_exp_node) { tTreeNodeData *data; // Make sure given node is valid if(gen_exp_node==NULL) { text="*ERROR*"; return; } // Get node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(gen_exp_node); if(data==NULL) { text="*ERROR*"; return; } // See if it's a parameter node if(data->type==PARAMETER_NODE) { FormatParameterValueText(text,data); return; } // See if it's a query node if(data->type==EXPRESSION_NODE) { FormatQueryNodeText(text,gen_exp_node); return; } // See if it's an expression operator node if(data->type==EXPRESSION_OPERATOR_NODE) { text.Format("%s",GetExpressionOperatorTypeString(data->subID)); return; } text=""; } // Formats the text for a Parameter Value according to the given node data void CDallasMainDlg::FormatParameterValueText(CString &text, tTreeNodeData *data) { object *objp; char *temp_str; char temp_name[MAX_PATH+1]; // Make sure given data is valid if(data==NULL) { text=""; return; } // Make sure given data node is a parameter node if(data->type!=PARAMETER_NODE) { text=""; return; } // Format the text according to the parameter type and value data switch(data->ID) { case DOOR_PARAMETER_TYPE: if(data->subID == USE_ME_HANDLE) { text.Format("OWNER"); break; } if(data->int_val == OBJECT_HANDLE_NONE) { text.Format("%s",NONE_STRING); break; } objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) text.Format("*DOOR_ERROR*"); else text.Format("%s",objp->name); break; case OBJECT_PARAMETER_TYPE: if(data->subID == USE_IT_HANDLE) { text.Format("IT"); break; } if(data->subID == USE_ME_HANDLE) { text.Format("OWNER"); break; } if(data->int_val == OBJECT_HANDLE_NONE) { text.Format("%s",NONE_STRING); break; } objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) text.Format("*OBJECT_ERROR*"); else text.Format("%s",objp->name); break; case ROOM_PARAMETER_TYPE: if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } if(data->int_val<0 || data->int_val>Highest_room_index) text.Format("*INVALID_ROOM*"); else text.Format("%s",Rooms[data->int_val].name); break; case TRIGGER_PARAMETER_TYPE: if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } if(data->int_val<0 || data->int_val>=Num_triggers) text.Format("*INVALID_TRIGGER*"); else text.Format("%s",Triggers[data->int_val].name); break; case INT_PARAMETER_TYPE: text.Format("%d",data->int_val); break; case BOOL_PARAMETER_TYPE: if(data->int_val) text.Format("TRUE"); else text.Format("FALSE"); break; case FLOAT_PARAMETER_TYPE: text.Format("%.2f",data->float_val1); break; case VECTOR_PARAMETER_TYPE: text.Format("<%.2f,%.2f,%.2f>",data->float_val1,data->float_val2,data->float_val3); break; case STRING_PARAMETER_TYPE: if(strlen(data->str_val)==0) text.Format("No ID Chosen"); else { /* CString msg; char *full_msg; char short_msg[MAX_STRING_DISPLAY_LEN+1]; // Display the first X chars in message full_msg=FindMessageInList(data->str_val); if(full_msg!=NULL) { if(strlen(full_msg) > MAX_STRING_DISPLAY_LEN) { strncpy(short_msg,full_msg,MAX_STRING_DISPLAY_LEN); short_msg[MAX_STRING_DISPLAY_LEN]='\0'; msg=short_msg; msg+="..."; } else msg=full_msg; } else msg=""; text.Format("%s=\"%s\"",data->str_val,msg); */ text.Format("%s",data->str_val); } break; case PERCENTAGE_PARAMETER_TYPE: text.Format("%.1f%%",data->float_val1*100.0); break; case ENUM_PARAMETER_TYPE: if(data->subID==USE_GOALID_VALUE) { text.Format("GOAL ID"); } else if(data->subID==USE_TIMERID_VALUE) { text.Format("TIMER ID"); } else if(data->subID==USE_MATCENID_VALUE) { text.Format("MATCEN ID"); } else { temp_str=GetEnumValueName(data->name,data->int_val); if(temp_str==NULL) text.Format("*UNKNOWN_ENUM*"); else text.Format("%s",temp_str); } break; case SCRIPT_PARAMETER_TYPE: if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } text.Format("%d",data->int_val); break; case SOUND_PARAMETER_TYPE: if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } if(data->int_val<0 || data->int_val>=MAX_SOUNDS || !Sounds[data->int_val].used) text.Format("*INVALID_SOUND*"); else text.Format("%s",Sounds[data->int_val].name); break; case SPECNAME_PARAMETER_TYPE: if(strlen(data->str_val)==0) text.Format("%s",NOT_SPECIFIED_STRING); else text.Format("\"%s\"",data->str_val); break; case TEXTURE_PARAMETER_TYPE: if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } if(data->int_val<0 || data->int_val>=MAX_TEXTURES || !GameTextures[data->int_val].used) text.Format("*INVALID_TEXTURE*"); else text.Format("%s",GameTextures[data->int_val].name); break; case FLAG_PARAMETER_TYPE: if(!FormatFlagValueNames(data->name,data->int_val,text)) text.Format("*UNKNOWN_FLAG*"); break; case PATH_PARAMETER_TYPE: if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } if(data->int_val<0 || data->int_val>=MAX_GAME_PATHS || !GamePaths[data->int_val].used) text.Format("*INVALID_PATH*"); else text.Format("%s",GamePaths[data->int_val].name); break; case MATCEN_PARAMETER_TYPE: if(data->subID==USE_MATCEN_EVENT_ID) { text.Format("MATCEN ID"); break; } if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } if(!MatcenValid(data->int_val)) text.Format("*INVALID_MATCEN*"); else { char name[MAX_MATCEN_NAME_LEN+1]; Matcen[data->int_val]->GetName(name); text.Format("%s",name); } break; case LEVEL_GOAL_PARAMETER_TYPE: if(data->subID==USE_LEVEL_GOAL_ID) { text.Format("LEVEL GOAL ID"); break; } if(data->int_val == NOT_SPECIFIED_TYPE) { text.Format("%s",NOT_SPECIFIED_STRING); break; } if(Level_goals.GoalGetName(data->int_val,temp_name,MAX_PATH)<0) text.Format("*INVALID_LEVEL_GOAL*"); else { text.Format("%s",temp_name); } break; case STRM_AUDIO_PARAMETER_TYPE: if(strlen(data->str_val)==0) text.Format("%s",NOT_SPECIFIED_STRING); else text.Format("\"%s\"",data->str_val); break; default: text.Format("Unknown Value Type"); break; } } // Parses an action desc, replacing arg blocks with value strings taken from // its child parameter nodes void CDallasMainDlg::FormatActionNodeText(CString &text, HTREEITEM action_node) { CString name_text, default_text, range_text; char *desc; tTreeNodeData *data; HTREEITEM child; if(action_node==NULL) { text="*ERROR*"; return; } data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); if(data==NULL) { text="*ERROR*"; return; } if(data->ID==INVALID_FUNCTION_ID) { text=INVALID_FUNCTION_NAME; return; } desc=GetActionDesc(data->ID); if(desc==NULL) { text="*ERROR*"; return; } // obtain the first child child=m_ScriptTree.GetChildItem(action_node); text=""; while((*desc)!='\0') { if((*desc)=='[') { ParseParamBlock(desc,name_text,default_text,range_text); if(child==NULL) text+="???"; else { CString tmp_str; tTreeNodeData *data; // Get node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); if(data->type==PARAMETER_NODE) { FormatParameterValueText(tmp_str,data); text+=tmp_str; } else if(data->type==EXPRESSION_NODE) { FormatQueryNodeText(tmp_str,child); text+="("; text+=tmp_str; text+=")"; } else text+=""; // Get next child child=m_ScriptTree.GetNextSiblingItem(child); } } else { text+=(*desc); desc++; } } } /* OLD VERSION // Parses an action desc, replacing arg blocks with value strings taken from // its child parameter nodes void CDallasMainDlg::FormatActionNodeText(CString &text, HTREEITEM action_node) { char *desc; int j; tTreeNodeData *data; HTREEITEM child; bool ok_to_copy; if(action_node==NULL) { text="*ERROR*"; return; } data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); if(data==NULL) { text="*ERROR*"; return; } if(data->ID==INVALID_FUNCTION_ID) { text=INVALID_FUNCTION_NAME; return; } desc=GetActionDesc(data->ID); if(desc==NULL) { text="*ERROR*"; return; } // obtain the first child child=m_ScriptTree.GetChildItem(action_node); j=0; ok_to_copy=TRUE; text=""; while(desc[j]!='\0') { if(desc[j]=='[') { ok_to_copy=FALSE; } else if(desc[j]==']') { ok_to_copy=TRUE; if(child==NULL) text+="???"; else { CString tmp_str; tTreeNodeData *data; // Get node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); if(data->type==PARAMETER_NODE) { FormatParameterValueText(tmp_str,data); text+=tmp_str; } else if(data->type==EXPRESSION_NODE) { FormatQueryNodeText(tmp_str,child); text+="("; text+=tmp_str; text+=")"; } else text+=""; // Get next child child=m_ScriptTree.GetNextSiblingItem(child); } } else if(ok_to_copy) { text+=desc[j]; } j++; } } */ // Parses a query desc, replacing arg blocks with value strings taken from // its child parameter nodes void CDallasMainDlg::FormatQueryNodeText(CString &text, HTREEITEM query_node) { CString name_text, default_text, range_text; char *desc; HTREEITEM child; tTreeNodeData *data; if(query_node==NULL) { text="*ERROR*"; return; } data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); if(data==NULL) { text="*ERROR*"; return; } if(data->ID==INVALID_FUNCTION_ID) { text=INVALID_FUNCTION_NAME; return; } desc=GetQueryDesc(data->ID); if(desc==NULL) { text="*ERROR*"; return; } // obtain the first child child=m_ScriptTree.GetChildItem(query_node); text=""; // Skip over the return type desc=strchr(desc,':'); if(desc==NULL) return; desc++; while((*desc)!='\0') { if((*desc)=='[') { ParseParamBlock(desc,name_text,default_text,range_text); if(child==NULL) text+="???"; else { CString tmp_str; tTreeNodeData *data; // Get node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); if(data->type==PARAMETER_NODE) { FormatParameterValueText(tmp_str,data); text+=tmp_str; } else if(data->type==EXPRESSION_NODE) { CString tmp_str; FormatQueryNodeText(tmp_str,child); text+="("; text+=tmp_str; text+=")"; } else text+=""; // Get next child child=m_ScriptTree.GetNextSiblingItem(child); } } else { text+=(*desc); desc++; } } } /* OLD VERSION // Parses a query desc, replacing arg blocks with value strings taken from // its child parameter nodes void CDallasMainDlg::FormatQueryNodeText(CString &text, HTREEITEM query_node) { char *desc; int j; HTREEITEM child; tTreeNodeData *data; bool ok_to_copy, first_colon_found; if(query_node==NULL) { text="*ERROR*"; return; } data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); if(data==NULL) { text="*ERROR*"; return; } if(data->ID==INVALID_FUNCTION_ID) { text=INVALID_FUNCTION_NAME; return; } desc=GetQueryDesc(data->ID); if(desc==NULL) { text="*ERROR*"; return; } // obtain the first child child=m_ScriptTree.GetChildItem(query_node); j=0; ok_to_copy=FALSE; first_colon_found=FALSE; text=""; while(desc[j]!='\0') { if(desc[j]=='[') { ok_to_copy=FALSE; } else if(desc[j]==']') { ok_to_copy=TRUE; if(child==NULL) text+="???"; else { CString tmp_str; tTreeNodeData *data; // Get node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); if(data->type==PARAMETER_NODE) { FormatParameterValueText(tmp_str,data); text+=tmp_str; } else if(data->type==EXPRESSION_NODE) { CString tmp_str; FormatQueryNodeText(tmp_str,child); text+="("; text+=tmp_str; text+=")"; } else text+=""; // Get next child child=m_ScriptTree.GetNextSiblingItem(child); } } else if(desc[j]==':' && !first_colon_found) { first_colon_found=TRUE; ok_to_copy=TRUE; } else if(ok_to_copy) { text+=desc[j]; } j++; } } */ // Converts a parameter character ID into a paramter type int CDallasMainDlg::ConvertParamCharToType(int param_char_ID) { int param_type; switch(param_char_ID) { case 'd': param_type=DOOR_PARAMETER_TYPE; break; case 'o': param_type=OBJECT_PARAMETER_TYPE; break; case 'r': param_type=ROOM_PARAMETER_TYPE; break; case 't': param_type=TRIGGER_PARAMETER_TYPE; break; case 'i': param_type=INT_PARAMETER_TYPE; break; case 'b': param_type=BOOL_PARAMETER_TYPE; break; case 'f': param_type=FLOAT_PARAMETER_TYPE; break; case 'v': param_type=VECTOR_PARAMETER_TYPE; break; case 's': param_type=STRING_PARAMETER_TYPE; break; case 'p': param_type=PERCENTAGE_PARAMETER_TYPE; break; case 'e': param_type=ENUM_PARAMETER_TYPE; break; case 'x': param_type=SCRIPT_PARAMETER_TYPE; break; case 'n': param_type=SOUND_PARAMETER_TYPE; break; case 'a': param_type=SPECNAME_PARAMETER_TYPE; break; case 'u': param_type=TEXTURE_PARAMETER_TYPE; break; case 'g': param_type=FLAG_PARAMETER_TYPE; break; case 'h': param_type=PATH_PARAMETER_TYPE; break; case 'm': param_type=MATCEN_PARAMETER_TYPE; break; case 'l': param_type=LEVEL_GOAL_PARAMETER_TYPE; break; case 'z': param_type=STRM_AUDIO_PARAMETER_TYPE; break; default: param_type=UNKNOWN_PARAMETER_TYPE; break; } return(param_type); } // Converts a parameter type into a character ID int CDallasMainDlg::ConvertParamTypeToChar(int param_type) { int param_char_ID; switch(param_type) { case DOOR_PARAMETER_TYPE: param_char_ID='d'; break; case OBJECT_PARAMETER_TYPE: param_char_ID='o'; break; case ROOM_PARAMETER_TYPE: param_char_ID='r'; break; case TRIGGER_PARAMETER_TYPE: param_char_ID='t'; break; case INT_PARAMETER_TYPE: param_char_ID='i'; break; case BOOL_PARAMETER_TYPE: param_char_ID='b'; break; case FLOAT_PARAMETER_TYPE: param_char_ID='f'; break; case VECTOR_PARAMETER_TYPE: param_char_ID='v'; break; case STRING_PARAMETER_TYPE: param_char_ID='s'; break; case PERCENTAGE_PARAMETER_TYPE: param_char_ID='p'; break; case ENUM_PARAMETER_TYPE: param_char_ID='e'; break; case SCRIPT_PARAMETER_TYPE: param_char_ID='x'; break; case SOUND_PARAMETER_TYPE: param_char_ID='n'; break; case SPECNAME_PARAMETER_TYPE: param_char_ID='a'; break; case TEXTURE_PARAMETER_TYPE: param_char_ID='u'; break; case FLAG_PARAMETER_TYPE: param_char_ID='g'; break; case PATH_PARAMETER_TYPE: param_char_ID='h'; break; case MATCEN_PARAMETER_TYPE: param_char_ID='m'; break; case LEVEL_GOAL_PARAMETER_TYPE: param_char_ID='l'; break; case STRM_AUDIO_PARAMETER_TYPE: param_char_ID='z'; break; default: param_char_ID='?'; break; } return(param_char_ID); } // Turns bold on or off for a specified node void CDallasMainDlg::SetBoldNodeText(HTREEITEM node, bool bold_on) { if(node==NULL) return; if(bold_on) m_ScriptTree.SetItemState(node,TVIS_BOLD,TVIS_BOLD); else m_ScriptTree.SetItemState(node,~TVIS_BOLD,TVIS_BOLD); } // Checks to see if the parent of the given node is a Conditional Statement // node of type COMPARISON_STATEMENT bool CDallasMainDlg::ParentIsComparisonConditional(HTREEITEM node) { HTREEITEM parent; tTreeNodeData *data; if(node==NULL) return(FALSE); // Get the parent parent=m_ScriptTree.GetParentItem(node); if(parent==NULL) return(FALSE); // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); if(data==NULL) return(FALSE); // Check the parent node if(data->type==CONDITIONAL_STATEMENT_NODE && data->ID==COMPARISON_STATEMENT) return(TRUE); return(FALSE); } // If the given node is a parameter or query, it determines its type (or return type) // and returns it, unless the parent of the given node is a Comparison conditional // statement. In this case, any parameter type is allowed int CDallasMainDlg::GetValidParamType(HTREEITEM node, CString &name) { tTreeNodeData *data; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return(-1); name=""; if(data->type==PARAMETER_NODE) { if(ParentIsComparisonConditional(node) && GetChildPosition(node)==1) return(ANY_PARAMETER_TYPE); name=data->name; return(data->ID); } if(data->type==EXPRESSION_NODE) { if(ParentIsComparisonConditional(node) && GetChildPosition(node)==1) return(ANY_PARAMETER_TYPE); return(GetQueryReturnType(data->ID,name)); } return(-1); } // If the given node is a parameter or query, it determines its type (or return type) // and returns it int CDallasMainDlg::GetParamType(HTREEITEM node, CString &name) { tTreeNodeData *data; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return(-1); name=""; if(data->type==PARAMETER_NODE) { name=data->name; return(data->ID); } if(data->type==EXPRESSION_NODE) { return(GetQueryReturnType(data->ID,name)); } return(-1); } // Attaches the correct bitmap image to a node void CDallasMainDlg::SetTreeNodeImage(HTREEITEM node) { tTreeNodeData *data; int temp_id; // Make sure node is valid if(node==NULL) return; // Get node data, make sure it's valid data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return; // Set the item's display images appropriately switch(data->type) { case SCRIPT_HEADER_NODE: m_ScriptTree.SetItemImage(node,0,0); break; case SCRIPT_OWNER_NODE: m_ScriptTree.SetItemImage(node,10,10); break; case SCRIPT_EVENT_NODE: m_ScriptTree.SetItemImage(node,11,11); break; case CONDITIONAL_HEADER_NODE: if(data->ID==TOP_LEVEL) m_ScriptTree.SetItemImage(node,1,1); else m_ScriptTree.SetItemImage(node,8,8); break; case ACTIONS_HEADER_NODE: if(data->ID==TOP_LEVEL) m_ScriptTree.SetItemImage(node,2,2); else { if(data->subID==THEN_CLAUSE) m_ScriptTree.SetItemImage(node,9,9); else m_ScriptTree.SetItemImage(node,18,18); } break; case CONDITIONAL_STATEMENT_NODE: m_ScriptTree.SetItemImage(node,3,3); break; case EXPRESSION_NODE: m_ScriptTree.SetItemImage(node,16,16); break; case EXPRESSION_OPERATOR_NODE: m_ScriptTree.SetItemImage(node,17,17); break; case ACTION_STATEMENT_NODE: m_ScriptTree.SetItemImage(node,4,4); break; case LOGICAL_OPERATOR_NODE: if(data->ID==AND_TYPE) m_ScriptTree.SetItemImage(node,6,6); else if(data->ID==OR_TYPE) m_ScriptTree.SetItemImage(node,5,5); else m_ScriptTree.SetItemImage(node,7,7); break; case PARAMETER_NODE: // Get image type based upon what kind of parameter it is switch(data->ID) { case DOOR_PARAMETER_TYPE: temp_id=12; break; case OBJECT_PARAMETER_TYPE: temp_id=12; break; case ROOM_PARAMETER_TYPE: temp_id=12; break; case TRIGGER_PARAMETER_TYPE: temp_id=12; break; case INT_PARAMETER_TYPE: temp_id=13; break; case BOOL_PARAMETER_TYPE: temp_id=14; break; case FLOAT_PARAMETER_TYPE: temp_id=13; break; case VECTOR_PARAMETER_TYPE: temp_id=15; break; case STRING_PARAMETER_TYPE: temp_id=12; break; case PERCENTAGE_PARAMETER_TYPE: temp_id=14; break; case ENUM_PARAMETER_TYPE: temp_id=12; break; case SCRIPT_PARAMETER_TYPE: temp_id=12; break; case SOUND_PARAMETER_TYPE: temp_id=15; break; case SPECNAME_PARAMETER_TYPE: temp_id=13; break; case TEXTURE_PARAMETER_TYPE: temp_id=15; break; case FLAG_PARAMETER_TYPE: temp_id=15; break; case PATH_PARAMETER_TYPE: temp_id=12; break; case MATCEN_PARAMETER_TYPE: temp_id=12; break; case LEVEL_GOAL_PARAMETER_TYPE: temp_id=12; break; case STRM_AUDIO_PARAMETER_TYPE: temp_id=15; break; default: temp_id=12; break; } m_ScriptTree.SetItemImage(node,temp_id,temp_id); break; case PARAMETER_OPERATOR_NODE: m_ScriptTree.SetItemImage(node,13,13); break; case CLIPBOARD_HEADER_NODE: m_ScriptTree.SetItemImage(node,19,19); break; case UNKNOWN_NODE: m_ScriptTree.SetItemImage(node,0,0); break; default: m_ScriptTree.SetItemImage(node,0,0); break; } } // Adds a node to the tree using the given data HTREEITEM CDallasMainDlg::AddNodeToTree(HTREEITEM parent, HTREEITEM insertbefore, HTREEITEM src_node, bool expand /*=FALSE*/) { tTreeNodeData *data; data=(tTreeNodeData *)m_ScriptTree.GetItemData(src_node); return(AddNodeToTree(parent,insertbefore,data,expand)); } // Adds a node to the tree using the given data HTREEITEM CDallasMainDlg::AddNodeToTree(HTREEITEM parent, HTREEITEM insertbefore, tTreeNodeData *data_node, bool expand /*=FALSE*/) { HTREEITEM added_item, insertafter, new_parent; TV_INSERTSTRUCT tvs; TV_ITEM tvi; tTreeNodeData *new_data_node; CString node_text; // Allocate a new data node, and copy given data into it new_data_node=new tTreeNodeData; if(new_data_node==NULL) { MessageBox("Unable to Allocate a New Data Node","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); return NULL; } // Copy given data into new node (*new_data_node)=(*data_node); // Fill out the Item structure tvi.mask=TVIF_TEXT; //FormatTreeText(node_text,new_data_node); //tvi.pszText=node_text.GetBuffer(0); tvi.pszText=""; // Get the previous child node for "insert before" if(insertbefore!=TVI_FIRST && insertbefore!=TVI_LAST && insertbefore!=TVI_SORT) { insertafter=m_ScriptTree.GetPrevSiblingItem(insertbefore); if(insertafter==NULL) insertafter=TVI_FIRST; new_parent=parent; } else { insertafter=insertbefore; new_parent=parent; } // Fill out the Insert structure tvs.hInsertAfter=insertafter; tvs.hParent=new_parent; tvs.item=tvi; added_item=m_ScriptTree.InsertItem(&tvs); // If add was unsuccessfull, delete the item data if(added_item==NULL) { delete new_data_node; MessageBox("Unable to Allocate a New Tree Node","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); return NULL; } // Set the node data and image m_ScriptTree.SetItemData(added_item,(DWORD)new_data_node); SetTreeNodeImage(added_item); // Set the new node's text UpdateNodeText(added_item); // Expand the parent if necessary if(parent!=NULL && expand) m_ScriptTree.Expand(parent,TVE_EXPAND); return(added_item); } // Frees all data for a tree leaf (and all children of the given leaf) void CDallasMainDlg::FreeTreeItem(HTREEITEM item) { tTreeNodeData *data; if (item==NULL) return; // Free all children of this node FreeTreeItemChildren(item); // Deallocate the data structure data=(tTreeNodeData *)m_ScriptTree.GetItemData(item); delete data; // Delete the actual tree node m_ScriptTree.DeleteItem(item); } // Frees all children of the given leaf, but leaves the given leaf intact void CDallasMainDlg::FreeTreeItemChildren(HTREEITEM item) { HTREEITEM child, old_child; if (item==NULL) return; child = m_ScriptTree.GetChildItem(item); while (child) { old_child = child; child = m_ScriptTree.GetNextSiblingItem(child); FreeTreeItem(old_child); } } // Expands given node and all children void CDallasMainDlg::ExpandAll(HTREEITEM node, UINT nCode) { HTREEITEM child; if (node==NULL) return; child = m_ScriptTree.GetChildItem(node); while (child!=NULL) { ExpandAll(child,nCode); child = m_ScriptTree.GetNextSiblingItem(child); } // Expand this node m_ScriptTree.Expand(node,nCode); } // Copies the entire tree starting at src_node to the specified destination HTREEITEM CDallasMainDlg::CopyTree(HTREEITEM dest_parent, HTREEITEM dest_insert_before, HTREEITEM src_node) { HTREEITEM dest_node; dest_node=AddNodeToTree(dest_parent,dest_insert_before,src_node); if(dest_node!=NULL) { CopyChildren(dest_node,src_node); UpdateNodeText(dest_node); } return(dest_node); } // Copies all the children of src_parent to dest_parent HTREEITEM CDallasMainDlg::CopyChildren(HTREEITEM dest_parent, HTREEITEM src_parent) { HTREEITEM src_child, dest_child; dest_child=NULL; src_child=m_ScriptTree.GetChildItem(src_parent); while(src_child!=NULL) { dest_child=AddNodeToTree(dest_parent,TVI_LAST,src_child); if(dest_child==NULL) return NULL; CopyChildren(dest_child,src_child); UpdateNodeText(dest_child); src_child=m_ScriptTree.GetNextSiblingItem(src_child); } return(dest_child); } // Returns the position of the given child (i.e. child is the Nth child of parent) int CDallasMainDlg::GetChildPosition(HTREEITEM child) { HTREEITEM node; int count; if(child==NULL) return 0; count=1; node=m_ScriptTree.GetPrevSiblingItem(child); while(node!=NULL) { node=m_ScriptTree.GetPrevSiblingItem(node); count++; } return(count); } // Returns the Nth child of the given parent (NULL if one doesn't exist) HTREEITEM CDallasMainDlg::GetNthChild(HTREEITEM parent, int n) { HTREEITEM child; int count; if(parent==NULL || n<=0) return NULL; count=1; child=m_ScriptTree.GetChildItem(parent); while(child!=NULL && count!=n) { child=m_ScriptTree.GetNextSiblingItem(child); count++; } return(child); } // Returns the child count int CDallasMainDlg::GetChildCount(HTREEITEM parent) { HTREEITEM child; int count; if(parent==NULL) return 0; count=0; child=m_ScriptTree.GetChildItem(parent); while(child!=NULL) { child=m_ScriptTree.GetNextSiblingItem(child); count++; } return(count); } // Returns the script ID for any given node (must be a descendant of SCRIPT_HEADER_NODE though) int CDallasMainDlg::GetScriptID(HTREEITEM script_node) { HTREEITEM script_header_node; tTreeNodeData *data; script_header_node=GetParentNodeOfType(script_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return(-1); data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_header_node); if(data==NULL) return(-1); return(data->ID); } // Returns script header node of script matching given script ID (NULL if not found) HTREEITEM CDallasMainDlg::FindScriptIDNode(int scriptID) { HTREEITEM node; // Fill up the list node=m_ScriptTree.GetChildItem(TVI_ROOT); while(node!=NULL) { int id=GetScriptID(node); if(id==scriptID) { return(node); } node=m_ScriptTree.GetNextSiblingItem(node); } return(NULL); } // Compare function for GetLowestUnusedScriptID() int id_list_compare( const void *arg1, const void *arg2 ) { int *num1=(int *)arg1; int *num2=(int *)arg2; if((*num1) < (*num2)) return(-1); return (1); } // Looks through scripts to determine the lowest unused script ID int CDallasMainDlg::GetLowestUnusedScriptID(void) { int *list; int size; int max_size; int lowest_id; HTREEITEM node; lowest_id=0; // Create the Script ID List max_size=GetChildCount(TVI_ROOT); if(max_size==0) return(lowest_id); list=(int *)mem_malloc(sizeof(int)*max_size); if(list==NULL) return(m_NextScriptID); // Fill up the list size=0; node=m_ScriptTree.GetChildItem(TVI_ROOT); while(node!=NULL) { int id=GetScriptID(node); if(id>=0 && size %d ",lowest_id); msg+=num; MessageBox(msg,"The Script ID List"); */ // Free up the list mem_free(list); return(lowest_id); } // Returns the node type of given node int CDallasMainDlg::GetNodeType(HTREEITEM node) { tTreeNodeData *data; if(node==NULL) return(UNKNOWN_NODE); data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return(UNKNOWN_NODE); return(data->type); } // Returns the script owner type for any given node (must be a descendant of SCRIPT_HEADER_NODE though) int CDallasMainDlg::GetScriptOwnerType(HTREEITEM script_node) { HTREEITEM script_owner_node; tTreeNodeData *data; script_owner_node=GetScriptOwnerNode(script_node); if(script_owner_node==NULL) return(-1); data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_owner_node); if(data==NULL) return(-1); return(data->ID); } // Returns the script event type for any given node (must be a descendant of SCRIPT_HEADER_NODE though) int CDallasMainDlg::GetScriptEventType(HTREEITEM script_node) { HTREEITEM script_event_node; tTreeNodeData *data; script_event_node=GetScriptEventNode(script_node); if(script_event_node==NULL) return(-1); data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_event_node); if(data==NULL) return(-1); return(data->ID); } // Sets the script event type for any given node (must be a descendant of SCRIPT_HEADER_NODE though) bool CDallasMainDlg::SetScriptEventType(HTREEITEM script_node, int type) { HTREEITEM script_event_node; tTreeNodeData *data; script_event_node=GetScriptEventNode(script_node); if(script_event_node==NULL) return FALSE; data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_event_node); if(data==NULL) return FALSE; data->ID=type; UpdateAllParentNodesText(script_event_node); return TRUE; } // Searches for a parent node (or current node) that matches the given type (returns NULL if none found) HTREEITEM CDallasMainDlg::GetParentNodeOfType(HTREEITEM child_node, int node_type) { HTREEITEM parent; tTreeNodeData *data; parent=child_node; while(parent!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); if(data!=NULL && data->type==node_type) return(parent); parent=m_ScriptTree.GetParentItem(parent); } return(parent); } // Returns the data of the closest EXPRESSION or ACTION node to the given node tTreeNodeData *CDallasMainDlg::GetNearestFunctionNode(HTREEITEM node) { HTREEITEM parent; tTreeNodeData *data; parent=node; while(parent!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); if(data!=NULL && (data->type==EXPRESSION_NODE || data->type==ACTION_STATEMENT_NODE)) return(data); parent=m_ScriptTree.GetParentItem(parent); } return(NULL); } // Searches for either an ACTION_STATEMENT_NODE or an EXPRESSION_NODE // that is the closest parent to the given PARAMETER_NODE (returns NULL if none found) HTREEITEM CDallasMainDlg::GetParameterParentNode(HTREEITEM param_node) { HTREEITEM parent; tTreeNodeData *data; // Make sure given node is a parameter node data=(tTreeNodeData *)m_ScriptTree.GetItemData(param_node); if(data==NULL || data->type!=PARAMETER_NODE) return NULL; // Keep getting the parent until we find a good match (or run out of parents) parent=m_ScriptTree.GetParentItem(param_node); while(parent!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(parent); if(data!=NULL && data->type==ACTION_STATEMENT_NODE) return(parent); if(data!=NULL && data->type==EXPRESSION_NODE) return(parent); parent=m_ScriptTree.GetParentItem(parent); } return(parent); } // Returns the owner node for any given Script node HTREEITEM CDallasMainDlg::GetScriptOwnerNode(HTREEITEM node) { HTREEITEM temp_node; // Get the parent Script header node of the given node temp_node=GetParentNodeOfType(node,SCRIPT_HEADER_NODE); if(temp_node==NULL) return NULL; // Get the owner node (first child of script header) temp_node=m_ScriptTree.GetChildItem(temp_node); return(temp_node); } // Returns the event node for any given Script node HTREEITEM CDallasMainDlg::GetScriptEventNode(HTREEITEM node) { HTREEITEM temp_node; // Get the script owner node temp_node=GetScriptOwnerNode(node); if(node==NULL) return NULL; // Get the event node (next node after owner) temp_node=m_ScriptTree.GetNextSiblingItem(temp_node); return(temp_node); } // Returns the conditional header (TOP LEVEL) node for any given Script node HTREEITEM CDallasMainDlg::GetConditionalHeaderNode(HTREEITEM node) { HTREEITEM temp_node; // Get the script owner node temp_node=GetScriptEventNode(node); if(node==NULL) return NULL; // Get the conditional header node (next node after event node) temp_node=m_ScriptTree.GetNextSiblingItem(temp_node); return(temp_node); } // Returns the action header (TOP LEVEL) node for any given Script node HTREEITEM CDallasMainDlg::GetActionHeaderNode(HTREEITEM node) { HTREEITEM temp_node; // Get the script owner node temp_node=GetConditionalHeaderNode(node); if(node==NULL) return NULL; // Get the action header node (next node after conditional header) temp_node=m_ScriptTree.GetNextSiblingItem(temp_node); return(temp_node); } // Highlights the headers for all scripts whose owner matches // the owner specified in m_ScriptOwnerType and m_ScriptOwnerHandle void CDallasMainDlg::HighlightAllScripts(void) { HTREEITEM script_header_node; // Group each script header node into the list script_header_node=m_ScriptTree.GetChildItem(TVI_ROOT); while(script_header_node!=NULL) { HighlightScript(script_header_node); script_header_node=m_ScriptTree.GetNextSiblingItem(script_header_node); } } // Highlights the headers for all scripts whose owner matches // the owner specified in m_ScriptOwnerType and m_ScriptOwnerHandle void CDallasMainDlg::HighlightScript(HTREEITEM node) { HTREEITEM script_header_node; script_header_node=GetParentNodeOfType(node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; HTREEITEM owner_node, event_node; tTreeNodeData *data; bool owners_match; owners_match=FALSE; owner_node=GetScriptOwnerNode(script_header_node); if(owner_node!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); if(data!=NULL) { if(m_ScriptOwnerType==ALL_OWNERS_TYPE) owners_match=TRUE; else if(m_ScriptOwnerType==LEVEL_TYPE && data->ID==LEVEL_TYPE) owners_match=TRUE; else if(m_ScriptOwnerType==ALL_OBJECTS_TYPE && data->ID==OBJECT_TYPE) owners_match=TRUE; else if(m_ScriptOwnerType==ALL_TRIGGERS_TYPE && data->ID==TRIGGER_TYPE) owners_match=TRUE; else if(m_ScriptOwnerType==data->ID && m_ScriptOwnerHandle==data->int_val) owners_match=TRUE; } } event_node=GetScriptEventNode(script_header_node); if(event_node!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(event_node); if(data!=NULL) { int event_type=GetHighlightedEvent(); if(event_type!=ALL_EVENT_TYPES && data->ID!=event_type) owners_match=FALSE; } } if(owners_match) SetBoldNodeText(script_header_node,TRUE); else SetBoldNodeText(script_header_node,FALSE); } ///////////////////////////////////////////////////////////////////////////// // Message List Functions ///////////////////////////////////////////////////////////////////////////// // Initializes the message list, // MUST BE CALLED BEFORE USING ANY MESSAGE LIST functions!!! void CDallasMainDlg::InitMessageList(void) { int j; // Init the list of message entries to empty for(j=0;jname,name,MAX_MESSAGE_NAME_LEN); empty_slot->name[MAX_MESSAGE_NAME_LEN]='\0'; strncpy(empty_slot->message,message,MAX_MESSAGE_LEN); empty_slot->message[MAX_MESSAGE_LEN]='\0'; // Add to the list and edit controls index=m_MessageList.AddString(name); if(index<0) { m_MessageListErrorCode=MSG_LIST_FULL_ERROR; return FALSE; } m_MessageList.SetItemData(index,(DWORD)empty_slot); // Set the new selection to be the current selection m_MessageList.SetCurSel(index); OnSelchangeMessageList(); return TRUE; } // Returns a message matching the given name, or NULL if none found char *CDallasMainDlg::FindMessageInList(char *name) { int j; // Scan entry list for given name for(j=0;jname,name)==0) return(m_MessageEntryList[j]->message); return(NULL); } // Deletes a message entry int CDallasMainDlg::DeleteMessageListEntry(char *name) { int j; // Scan entry list for given name for(j=0;jname,name)==0) { delete m_MessageEntryList[j]; m_MessageEntryList[j]=NULL; return(TRUE); } return(FALSE); } // Returns an available entry slot, or NULL if none exist tMessageListEntry *CDallasMainDlg::GetEmptyMessageListEntry(void) { int j; // Scan entry list for an empty slot for(j=0;jtype==SCRIPT_OWNER_NODE) { if(data->ID==NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Script Owner"); return 1; } if(data->ID==LEVEL_TYPE) return 0; if(data->ID==OBJECT_TYPE) { // Check for object None if(data->int_val == OBJECT_HANDLE_NONE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Script Owner (Object)"); return 1; } // Check for invalid objects object *objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { int handle=osipf_FindObjectName(data->str_val); if(handle!=OBJECT_HANDLE_NONE) { if(InvObjPrompt(scriptID,data->int_val,data->str_val,handle)==IDYES) { data->int_val=handle; UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } } InvObjMsg(scriptID,data->int_val,data->str_val); data->int_val=OBJECT_HANDLE_NONE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid object names if(strcmp(data->str_val,objp->name)!=0) { int handle=osipf_FindObjectName(data->str_val); if(handle!=OBJECT_HANDLE_NONE) { if(InvNameObjPrompt(scriptID,data->int_val,data->str_val,objp->name,handle)==IDYES) { data->int_val=handle; UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } } InvNameObjMsg(scriptID,data->int_val,data->str_val,objp->name); strcpy(data->str_val,objp->name); UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } // All is cool, so just add the name AddObjectToList(objp->name); return 0; } if(data->ID==TRIGGER_TYPE) { // Check for not specified triggers if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Script Owner (Trigger)"); return 1; } // Check for invalid triggers int t=data->int_val; if(t<0 || t>=Num_triggers || t>=MAX_NAMED_TRIGGERS || strlen(Triggers[t].name)==0) { int index=osipf_FindTriggerName(data->str_val); if(index>=0) { if(InvIndValPrompt(scriptID,"Trigger",t,data->str_val,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddTriggerToList(data->str_val); return 0; } } InvIndValMsg(scriptID,"Trigger",t,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid trigger names if(strcmp(data->str_val,Triggers[t].name)!=0) { int index=osipf_FindTriggerName(data->str_val); if(index>=0) { if(InvNameIndValPrompt(scriptID,"Trigger",t,data->str_val,Triggers[t].name,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddTriggerToList(data->str_val); return 0; } } InvNameIndValMsg(scriptID,"Trigger",t,data->str_val,Triggers[t].name); strcpy(data->str_val,Triggers[t].name); UpdateAllParentNodesText(node); AddTriggerToList(data->str_val); return 0; } // All is cool, so just add the name AddTriggerToList(Triggers[t].name); return 0; } } // See if it's a parameter Node if(data->type==PARAMETER_NODE) { switch(data->ID) { case DOOR_PARAMETER_TYPE: { // Check for ME handle if(data->subID==USE_ME_HANDLE) { if(ScriptHasADoorMe(node)) { return 0; } else { InvSpecParamMsg(scriptID,"an OWNER (Door object)"); return 1; } } // Check for IT handle if(data->subID==USE_IT_HANDLE) return 0; // Check for object None if(data->int_val == OBJECT_HANDLE_NONE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Door Object"); return 1; } // Check for invalid door objects object *objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { int handle=osipf_FindDoorName(data->str_val); if(handle!=OBJECT_HANDLE_NONE) { if(InvObjPrompt(scriptID,data->int_val,data->str_val,handle)==IDYES) { data->int_val=handle; UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } } InvObjMsg(scriptID,data->int_val,data->str_val); data->int_val=OBJECT_HANDLE_NONE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid door object names if(strcmp(data->str_val,objp->name)!=0) { int handle=osipf_FindDoorName(data->str_val); if(handle!=OBJECT_HANDLE_NONE) { if(InvNameObjPrompt(scriptID,data->int_val,data->str_val,objp->name,handle)==IDYES) { data->int_val=handle; UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } } InvNameObjMsg(scriptID,data->int_val,data->str_val,objp->name); strcpy(data->str_val,objp->name); UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } // All is cool, so just add the name AddDoorToList(objp->name); } break; case OBJECT_PARAMETER_TYPE: { // Check for ME and IT handles if(data->subID==USE_ME_HANDLE) { if(ScriptHasAMe(node)) { return 0; } else { InvSpecParamMsg(scriptID,"an OWNER (object)"); return 1; } } if(data->subID==USE_IT_HANDLE) { if(ScriptHasAnIt(node)) { return 0; } else { InvSpecParamMsg(scriptID,"an IT (object)"); return 1; } } // Check for object None if(data->int_val == OBJECT_HANDLE_NONE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Generic Object"); return 1; } // Check for invalid objects object *objp=ObjGet(data->int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { int handle=osipf_FindObjectName(data->str_val); if(handle!=OBJECT_HANDLE_NONE) { if(InvObjPrompt(scriptID,data->int_val,data->str_val,handle)==IDYES) { data->int_val=handle; UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } } InvObjMsg(scriptID,data->int_val,data->str_val); data->int_val=OBJECT_HANDLE_NONE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid object names if(strcmp(data->str_val,objp->name)!=0) { int handle=osipf_FindObjectName(data->str_val); if(handle!=OBJECT_HANDLE_NONE) { if(InvNameObjPrompt(scriptID,data->int_val,data->str_val,objp->name,handle)==IDYES) { data->int_val=handle; UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } } InvNameObjMsg(scriptID,data->int_val,data->str_val,objp->name); strcpy(data->str_val,objp->name); UpdateAllParentNodesText(node); AddObjectToList(data->str_val); return 0; } // All is cool, so just add the name AddObjectToList(objp->name); } break; case ROOM_PARAMETER_TYPE: { // Check for not specified rooms if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Room"); return 1; } // Check for invalid rooms int r=data->int_val; if(r<0 || r>Highest_room_index || !Rooms[r].used || Rooms[r].name==NULL) { int index=osipf_FindRoomName(data->str_val); if(index>=0) { if(InvIndValPrompt(scriptID,"Room",r,data->str_val,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddRoomToList(data->str_val); return 0; } } InvIndValMsg(scriptID,"Room",r,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid room names if(strcmp(data->str_val,Rooms[r].name)!=0) { int index=osipf_FindRoomName(data->str_val); if(index>=0) { if(InvNameIndValPrompt(scriptID,"Room",r,data->str_val,Rooms[r].name,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddRoomToList(data->str_val); return 0; } } InvNameIndValMsg(scriptID,"Room",r,data->str_val,Rooms[r].name); strcpy(data->str_val,Rooms[r].name); UpdateAllParentNodesText(node); AddRoomToList(data->str_val); return 0; } // All is cool, so just add the name AddRoomToList(Rooms[r].name); } break; case TRIGGER_PARAMETER_TYPE: { // Check for not specified triggers if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Trigger"); return 1; } // Check for invalid triggers int t=data->int_val; if(t<0 || t>=Num_triggers || t>=MAX_NAMED_TRIGGERS || strlen(Triggers[t].name)==0) { int index=osipf_FindTriggerName(data->str_val); if(index>=0) { if(InvIndValPrompt(scriptID,"Trigger",t,data->str_val,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddTriggerToList(data->str_val); return 0; } } InvIndValMsg(scriptID,"Trigger",t,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid trigger names if(strcmp(data->str_val,Triggers[t].name)!=0) { int index=osipf_FindTriggerName(data->str_val); if(index>=0) { if(InvNameIndValPrompt(scriptID,"Trigger",t,data->str_val,Triggers[t].name,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddTriggerToList(data->str_val); return 0; } } InvNameIndValMsg(scriptID,"Trigger",t,data->str_val,Triggers[t].name); strcpy(data->str_val,Triggers[t].name); UpdateAllParentNodesText(node); AddTriggerToList(data->str_val); return 0; } // All is cool, so just add the name AddTriggerToList(Triggers[t].name); } break; case SOUND_PARAMETER_TYPE: { // Check for not specified sounds if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Sound"); return 1; } // Check for invalid sounds int s=data->int_val; if(s<0 || s>=MAX_SOUNDS || !Sounds[s].used) { int index=osipf_FindSoundName(data->str_val); if(index>=0) { if(InvIndValPrompt(scriptID,"Sound",s,data->str_val,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddSoundToList(data->str_val); return 0; } } InvIndValMsg(scriptID,"Sound",s,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid sound names if(strcmp(data->str_val,Sounds[s].name)!=0) { int index=osipf_FindSoundName(data->str_val); if(index>=0) { if(InvNameIndValPrompt(scriptID,"Sound",s,data->str_val,Sounds[s].name,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddSoundToList(data->str_val); return 0; } } InvNameIndValMsg(scriptID,"Sound",s,data->str_val,Sounds[s].name); strcpy(data->str_val,Sounds[s].name); UpdateAllParentNodesText(node); AddSoundToList(data->str_val); return 0; } // All is cool, so just add the name AddSoundToList(Sounds[s].name); } break; case TEXTURE_PARAMETER_TYPE: { // Check for not specified textures if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Texture"); return 1; } // Check for invalid textures int t=data->int_val; if(t<0 || t>=MAX_TEXTURES || !GameTextures[t].used) { int index=osipf_FindTextureName(data->str_val); if(index>=0) { if(InvIndValPrompt(scriptID,"Texture",t,data->str_val,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddTextureToList(data->str_val); return 0; } } InvIndValMsg(scriptID,"Texture",t,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid texture names if(strcmp(data->str_val,GameTextures[t].name)!=0) { int index=osipf_FindTextureName(data->str_val); if(index>=0) { if(InvNameIndValPrompt(scriptID,"Texture",t,data->str_val,GameTextures[t].name,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddTextureToList(data->str_val); return 0; } } InvNameIndValMsg(scriptID,"Texture",t,data->str_val,GameTextures[t].name); strcpy(data->str_val,GameTextures[t].name); UpdateAllParentNodesText(node); AddTextureToList(data->str_val); return 0; } // All is cool, so just add the name AddTextureToList(GameTextures[t].name); } break; case PATH_PARAMETER_TYPE: { // Check for not specified paths if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Path"); return 1; } // Check for invalid paths int t=data->int_val; if(t<0 || t>=MAX_GAME_PATHS || !GamePaths[t].used) { int index=osipf_FindPathName(data->str_val); if(index>=0) { if(InvIndValPrompt(scriptID,"Path",t,data->str_val,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddPathToList(data->str_val); return 0; } } InvIndValMsg(scriptID,"Path",t,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid path names if(strcmp(data->str_val,GamePaths[t].name)!=0) { int index=osipf_FindPathName(data->str_val); if(index>=0) { if(InvNameIndValPrompt(scriptID,"Path",t,data->str_val,GamePaths[t].name,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddPathToList(data->str_val); return 0; } } InvNameIndValMsg(scriptID,"Path",t,data->str_val,GamePaths[t].name); strcpy(data->str_val,GamePaths[t].name); UpdateAllParentNodesText(node); AddPathToList(data->str_val); return 0; } // All is cool, so just add the name AddPathToList(GamePaths[t].name); } break; case MATCEN_PARAMETER_TYPE: { // Check for MATCEN ID if(data->subID==USE_MATCEN_EVENT_ID) { if(ScriptHasAMatcenID(node)) { return 0; } else { InvSpecParamMsg(scriptID,"a MATCEN ID (Matcen type)"); return 1; } } // Check for not specified matcens if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Matcen"); return 1; } // Check for invalid matcens int t=data->int_val; if(!MatcenValid(t)) { int index=osipf_FindMatcenName(data->str_val); if(index>=0) { if(InvIndValPrompt(scriptID,"Matcen",t,data->str_val,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddMatcenToList(data->str_val); return 0; } } InvIndValMsg(scriptID,"Matcen",t,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // Check for invalid matcen names char matcen_name[MAX_MATCEN_NAME_LEN+1]; Matcen[t]->GetName(matcen_name); if(strcmp(data->str_val,matcen_name)!=0) { int index=osipf_FindMatcenName(data->str_val); if(index>=0) { if(InvNameIndValPrompt(scriptID,"Matcen",t,data->str_val,matcen_name,index)==IDYES) { data->int_val=index; UpdateAllParentNodesText(node); AddMatcenToList(data->str_val); return 0; } } InvNameIndValMsg(scriptID,"Matcen",t,data->str_val,matcen_name); strcpy(data->str_val,matcen_name); UpdateAllParentNodesText(node); AddMatcenToList(data->str_val); return 0; } // All is cool, so just add the name AddMatcenToList(matcen_name); } break; case LEVEL_GOAL_PARAMETER_TYPE: { // Check for LEVEL GOAL ID if(data->subID==USE_LEVEL_GOAL_ID) { if(ScriptHasALevelGoalID(node)) { return 0; } else { InvSpecParamMsg(scriptID,"a LEVEL GOAL ID (Level Goal type)"); return 1; } } // Check for not specified level goals if(data->int_val == NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Level Goal"); return 1; } // Check for invalid level goals int t=osipf_FindLevelGoalName(data->str_val); if(t<0) { InvIndValMsg(scriptID,"Level Goal",t,data->str_val); data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } data->int_val=t; // All is cool, so just add the name AddGoalToList(data->str_val); } break; case STRM_AUDIO_PARAMETER_TYPE: { // Check for not specified streaming audio filenames if(strlen(data->str_val)==0) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Streaming Audio File"); return 1; } // Check if filename is invalid if(!GamefileExists(data->str_val)) { InvIndValMsg(scriptID,"Streaming Audio File",0,data->str_val); strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // All is cool, so just add the name AddStrmAudioToList(data->str_val); } break; case SPECNAME_PARAMETER_TYPE: { // Check for not specified special names if(strlen(data->str_val)==0) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Specific Name"); return 1; } // All is cool, so just add the name AddSpecnameToList(data->str_val); } break; case STRING_PARAMETER_TYPE: { // Check for not specified messages if(strlen(data->str_val)==0) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Message ID"); return 1; } // Check if message name is invalid if(FindMessageInList(data->str_val)==NULL) { InvIndValMsg(scriptID,"Message ID",0,data->str_val); strcpy(data->str_val,""); UpdateAllParentNodesText(node); return 1; } // All is cool, so just add the message name AddMessageNameToList(data->str_val); } break; case ENUM_PARAMETER_TYPE: { // Check for GOAL ID and TIMER ID handles if(data->subID==USE_GOALID_VALUE) { if(ScriptHasAGoalID(node)) { return 0; } else { InvSpecParamMsg(scriptID,"a GOAL ID (Enumerated type:GoalID)"); return 1; } } if(data->subID==USE_TIMERID_VALUE) { if(ScriptHasATimerID(node)) { return 0; } else { InvSpecParamMsg(scriptID,"a TIMER ID (Enumerated type:TimerID)"); return 1; } } if(data->subID==USE_MATCENID_VALUE) { if(ScriptHasAMatcenID(node)) { return 0; } else { InvSpecParamMsg(scriptID,"a MATCEN ID (Enumerated type:MatcenID)"); return 1; } } // Check for invalid enums if(GetEnumValueName(data->name,data->int_val)==NULL) { IndValNotSpecMsg(scriptID,"Enumerated Type"); UpdateAllParentNodesText(node); return 1; } } break; case SCRIPT_PARAMETER_TYPE: { // Check for NOT SPECIFIED script ID's if(data->int_val==NOT_SPECIFIED_TYPE) { if(show_notspec_warnings) IndValNotSpecMsg(scriptID,"Script ID"); return 1; } // Check for invalid script ID's if(FindScriptIDNode(data->int_val)==NULL) { InvIndValMsg(scriptID,"Script ID",data->int_val,"Unknown"); data->int_val=NOT_SPECIFIED_TYPE; UpdateAllParentNodesText(node); return 1; } } break; } return 0; } return 0; } // Displays the invalid special parameter warning message void CDallasMainDlg::InvSpecParamMsg(int scriptID, char *type_name) { CString msg, title; if(type_name==NULL) return; msg.Format("WARNING: Script #%d references %s even though its selected event (or owner) type does not support one.",scriptID,type_name); title.Format("Invalid Special Parameter Warning!"); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); } // Displays the NOT SPECIFIED indexed value warning message void CDallasMainDlg::IndValNotSpecMsg(int scriptID, char *type_name) { CString msg, title; if(type_name==NULL) return; msg.Format("WARNING: Script #%d references a %s which has not been specified.",scriptID,type_name); title.Format("%s Not Specified Warning!",type_name); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); } // Displays the invalid indexed value warning message void CDallasMainDlg::InvIndValMsg(int scriptID, char *type_name, int index, char *name) { CString msg, title; if(type_name==NULL || name==NULL) return; msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) that no longer exists. It will be changed to NOT SPECIFIED.",scriptID,type_name,index,name); title.Format("Invalid %s Warning!",type_name); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); } // Displays the invalid indexed value prompt int CDallasMainDlg::InvIndValPrompt(int scriptID, char *type_name, int index, char *name, int new_index) { CString msg, title; if(type_name==NULL || name==NULL) return(IDNO); msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) that no longer exists. However, another %s (index=%d) exists with the same name.\n\nDo you want to use this other one instead?",scriptID,type_name,index,name,type_name,new_index); title.Format("Invalid %s Warning!",type_name); return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); } // Displays the invalid indexed value name warning message void CDallasMainDlg::InvNameIndValMsg(int scriptID, char *type_name, int index, char *name, char *new_name) { CString msg, title; if(type_name==NULL || name==NULL || new_name==NULL) return; msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) whose name has changed to \"%s\". Its name will be updated.",scriptID,type_name,index,name,new_name); title.Format("Invalid %s Name Warning!",type_name); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); } // Displays the invalid indexed value name prompt int CDallasMainDlg::InvNameIndValPrompt(int scriptID, char *type_name, int index, char *name, char *new_name, int new_index) { CString msg, title; if(type_name==NULL || name==NULL || new_name==NULL) return(IDNO); msg.Format("WARNING: Script #%d references a %s (index=%d, name=%s) whose name has changed to \"%s\". However, another %s (index=%d) exists with the old name.\n\nDo you want to use this other one instead?",scriptID,type_name,index,name,new_name,type_name,new_index); title.Format("Invalid %s Name Warning!",type_name); return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); } // Displays the invalid Object warning message void CDallasMainDlg::InvObjMsg(int scriptID, int handle, char *name) { CString msg, title; if(name==NULL) return; msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) that no longer exists. It will be changed to Object NONE.",scriptID,handle,name); title.Format("Invalid Object Warning!"); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); } // Displays the invalid Object prompt int CDallasMainDlg::InvObjPrompt(int scriptID, int handle, char *name, int new_handle) { CString msg, title; if(name==NULL) return(IDNO); msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) that no longer exists. However, another object (handle=%d) exists with the same name.\n\nDo you want to use this other one instead?",scriptID,handle,name,new_handle); title.Format("Invalid Object Warning!"); return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); } // Displays the invalid object name warning message void CDallasMainDlg::InvNameObjMsg(int scriptID, int handle, char *name, char *new_name) { CString msg, title; if(name==NULL || new_name==NULL) return; msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) whose name has changed to \"%s\". Its name will be updated.",scriptID,handle,name,new_name); title.Format("Invalid Object Name Warning!"); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); } // Displays the invalid object name prompt int CDallasMainDlg::InvNameObjPrompt(int scriptID, int handle, char *name, char *new_name, int new_handle) { CString msg, title; if(name==NULL || new_name==NULL) return(IDNO); msg.Format("WARNING: Script #%d references an Object (handle=%d, name=%s) whose name has changed to \"%s\". However, another object (handle=%d) exists with the old name.\n\nDo you want to use this other one instead?",scriptID,handle,name,new_name,new_handle); title.Format("Invalid Object Name Warning!"); return(MessageBox(msg,title,MB_YESNO|MB_ICONEXCLAMATION)); } // Adds the given door name to the door name list int CDallasMainDlg::AddDoorToList(char *name) { // Make sure we've got a name if(name==NULL || strlen(name)==0) return FALSE; // See if it's already in the list if(FindDoorInList(name)>=0) return TRUE; // If there's room in the list, add the new name if(m_DoorListSize>=MAX_NAMED_DOORS) return FALSE; int pos=m_DoorListSize; m_DoorList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_DoorList[pos]==NULL) { MessageBox("Out of memory in AddDoorToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_DoorList[pos],name); m_DoorListSize++; return TRUE; } // Returns the list index of the given door name (or -1 if not found) int CDallasMainDlg::FindDoorInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_ObjectListSize>=MAX_NAMED_OBJECTS) return FALSE; int pos=m_ObjectListSize; m_ObjectList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_ObjectList[pos]==NULL) { MessageBox("Out of memory in AddObjectToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_ObjectList[pos],name); m_ObjectListSize++; return TRUE; } // Returns the list index of the given object name (or -1 if not found) int CDallasMainDlg::FindObjectInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_RoomListSize>=MAX_NAMED_ROOMS) return FALSE; int pos=m_RoomListSize; m_RoomList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_RoomList[pos]==NULL) { MessageBox("Out of memory in AddRoomToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_RoomList[pos],name); m_RoomListSize++; return TRUE; } // Returns the list index of the given room name (or -1 if not found) int CDallasMainDlg::FindRoomInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's Trigger in the list, add the new name if(m_TriggerListSize>=MAX_NAMED_TRIGGERS) return FALSE; int pos=m_TriggerListSize; m_TriggerList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_TriggerList[pos]==NULL) { MessageBox("Out of memory in AddTriggerToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_TriggerList[pos],name); m_TriggerListSize++; return TRUE; } // Returns the list index of the given Trigger name (or -1 if not found) int CDallasMainDlg::FindTriggerInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_SoundListSize>=MAX_NAMED_SOUNDS) return FALSE; int pos=m_SoundListSize; m_SoundList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_SoundList[pos]==NULL) { MessageBox("Out of memory in AddSoundToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_SoundList[pos],name); m_SoundListSize++; return TRUE; } // Returns the list index of the given sound name (or -1 if not found) int CDallasMainDlg::FindSoundInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_TextureListSize>=MAX_NAMED_TEXTURES) return FALSE; int pos=m_TextureListSize; m_TextureList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_TextureList[pos]==NULL) { MessageBox("Out of memory in AddTextureToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_TextureList[pos],name); m_TextureListSize++; return TRUE; } // Returns the list index of the given Texture name (or -1 if not found) int CDallasMainDlg::FindTextureInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_SpecnameListSize>=MAX_SPECNAMES) return FALSE; int pos=m_SpecnameListSize; m_SpecnameList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_SpecnameList[pos]==NULL) { MessageBox("Out of memory in AddSpecnameToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_SpecnameList[pos],name); m_SpecnameListSize++; return TRUE; } // Returns the list index of the given Specname name (or -1 if not found) int CDallasMainDlg::FindSpecnameInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_PathListSize>=MAX_NAMED_PATHS) return FALSE; int pos=m_PathListSize; m_PathList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_PathList[pos]==NULL) { MessageBox("Out of memory in AddPathToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_PathList[pos],name); m_PathListSize++; return TRUE; } // Returns the list index of the given Path name (or -1 if not found) int CDallasMainDlg::FindPathInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_MatcenListSize>=MAX_NAMED_MATCENS) return FALSE; int pos=m_MatcenListSize; m_MatcenList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_MatcenList[pos]==NULL) { MessageBox("Out of memory in AddMatcenToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_MatcenList[pos],name); m_MatcenListSize++; return TRUE; } // Returns the list index of the given Matcen name (or -1 if not found) int CDallasMainDlg::FindMatcenInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_GoalListSize>=MAX_NAMED_GOALS) return FALSE; int pos=m_GoalListSize; m_GoalList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_GoalList[pos]==NULL) { MessageBox("Out of memory in AddGoalToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_GoalList[pos],name); m_GoalListSize++; return TRUE; } // Returns the list index of the given Goal name (or -1 if not found) int CDallasMainDlg::FindGoalInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_StrmAudioListSize>=MAX_NAMED_STRM_AUDIO) return FALSE; int pos=m_StrmAudioListSize; m_StrmAudioList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_StrmAudioList[pos]==NULL) { MessageBox("Out of memory in AddStrmAudioToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_StrmAudioList[pos],name); m_StrmAudioListSize++; return TRUE; } // Returns the list index of the given StrmAudio name (or -1 if not found) int CDallasMainDlg::FindStrmAudioInList(char *name) { if(name==NULL) return(-1); for(int j=0;j=0) return TRUE; // If there's room in the list, add the new name if(m_MessageNameListSize>=MAX_MESSAGE_LIST_ENTRIES) return FALSE; int pos=m_MessageNameListSize; m_MessageNameList[pos]=(char *)mem_malloc(strlen(name)+1); if(m_MessageNameList[pos]==NULL) { MessageBox("Out of memory in AddMessageNameToList()!","Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(m_MessageNameList[pos],name); m_MessageNameListSize++; return TRUE; } // Returns the list index of the given MessageName name (or -1 if not found) int CDallasMainDlg::FindMessageNameInList(char *name) { if(name==NULL) return(-1); for(int j=0;jResetContent(); // Add the User Type Names for(j=0;jAddString(m_EnumDatabase[j].name); types_added++; } } // Select the first one box->SetCurSel(0); return(types_added); } // Fills the box with all values for the given User Type int CDallasMainDlg::FillValuesBox(CListBox *box, char *utype_name) { int j, DBslot, values_added; values_added=0; // Clear the box box->ResetContent(); // Fill in the values DBslot=GetEnumID(utype_name); if(DBslot==INVALID_ENUM) return(values_added); for(j=0;jvalue!=-1) { box->AddString(value_entry->name); values_added++; } } // Select the first one box->SetCurSel(0); return(values_added); } // Adds a value to the user type // Returns the new position in list, or -1 if add failed int CDallasMainDlg::AddUserTypeValue(char *utype_name, char *value_name) { int j, k, DBslot, new_value; if(utype_name==NULL || value_name==NULL) return(-1); new_value=-1; DBslot=GetEnumID(utype_name); if(DBslot==INVALID_ENUM) return(-1); tEnumDBEntry *entry=&m_EnumDatabase[DBslot]; if(entry->num_values>=(entry->max_values+2) || entry->num_values>=MAX_ENUM_VALUES) return(-1); // Find a place to insert the new value new_value=0; for(j=0;jnum_values;j++) { tEnumValueEntry *value_entry=&entry->values[j]; if(new_value < value_entry->value) { // Bump the higher ones down the list for(k=entry->num_values;k>j;k--) { entry->values[k].value=entry->values[k-1].value; entry->values[k].name=entry->values[k-1].name; } break; } new_value=value_entry->value+1; } // Store the new value at the current position tEnumValueEntry *value_entry=&entry->values[j]; value_entry->value=new_value; value_entry->name=(char *)mem_malloc(strlen(value_name)+1); if(value_entry->name==NULL) { MessageBox("ERROR: Out of mem in AddUserTypeValue()!","Error!"); return(-1); } strcpy(value_entry->name,value_name); entry->num_values++; SetModified(TRUE); return(j); } // Removes a value int CDallasMainDlg::DeleteUserTypeValue(char *utype_name, char *value_name) { int j, k, DBslot; if(utype_name==NULL || value_name==NULL) return FALSE; DBslot=GetEnumID(utype_name); if(DBslot==INVALID_ENUM) return FALSE; tEnumDBEntry *entry=&m_EnumDatabase[DBslot]; // Find the value name in the list for(j=0;jnum_values;j++) { tEnumValueEntry *value_entry=&entry->values[j]; if(strcmp(value_name,value_entry->name)==0) { // Free the name memory mem_free(value_entry->name); // Compact the list entry->num_values--; for(k=j;k<(entry->num_values);k++) { entry->values[k].value=entry->values[k+1].value; entry->values[k].name=entry->values[k+1].name; } entry->values[k].name=NULL; SetModified(TRUE); return TRUE; } } return FALSE; } // Changes the name of a value int CDallasMainDlg::ChangeValueName(char *utype_name, char *old_name, char *new_name) { int j, DBslot; if(utype_name==NULL || old_name==NULL || new_name==NULL) return FALSE; DBslot=GetEnumID(utype_name); if(DBslot==INVALID_ENUM) return FALSE; tEnumDBEntry *entry=&m_EnumDatabase[DBslot]; // Find the value name in the list for(j=0;jnum_values;j++) { tEnumValueEntry *value_entry=&entry->values[j]; if(strcmp(old_name,value_entry->name)==0) { // Free the name memory mem_free(value_entry->name); // Add the new name value_entry->name=(char *)mem_malloc(strlen(new_name)+1); if(value_entry->name==NULL) { MessageBox("ERROR: Out of mem in ChangeValueName()!","Error!"); return FALSE; } strcpy(value_entry->name,new_name); SetModified(TRUE); return TRUE; } } return FALSE; } ///////////////////////////////////////////////////////////////////////////// // Enumeration Database Functions ///////////////////////////////////////////////////////////////////////////// // Initializes the enum DB for use void CDallasMainDlg::InitEnumDatabase(void) { int j,k; for(j=0;jAppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, name.GetBuffer(0)); enum_types_added++; } else enum_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+i, name.GetBuffer(0)); } return(enum_types_added); } // Fills up the given menu with the enumeration values of the given enum name // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillEnumValuesMenu(CMenu *enum_menu, int command_offset, char *enum_name) { int enum_values_added; int i, DBslot; tEnumDBEntry *enum_entry; // Set the counts enum_values_added=0; // Find the correct enum database entry DBslot=GetEnumID(enum_name); if(DBslot==INVALID_ENUM) return 0; enum_entry=&m_EnumDatabase[DBslot]; // Fill the menu with names of matching enumeration values for (i=0;inum_values;i++) { enum_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, enum_entry->values[i].name); enum_values_added++; } return(enum_values_added); } ///////////////////////////////////////////////////////////////////////////// // Flag Database Functions ///////////////////////////////////////////////////////////////////////////// // Initializes the Flag DB for use void CDallasMainDlg::InitFlagDatabase(void) { int j,k; for(j=0;jAppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, m_FlagDatabase[i].name); flag_types_added++; } else flag_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+i, m_FlagDatabase[i].name); } return(flag_types_added); } // Fills up the given CCheckListBox with the flag values of the given flag name int CDallasMainDlg::FillFlagValuesBox(CCheckListBox *box, char *flag_name, int flags_value, int valid_flags_mask) { int flag_values_added; int i, DBslot; tFlagDBEntry *flag_entry; // Set the counts flag_values_added=0; // Find the correct enum database entry DBslot=GetFlagID(flag_name); if(DBslot==INVALID_FLAG) return 0; flag_entry=&m_FlagDatabase[DBslot]; // Fill the box with names of matching flag values for (i=0;inum_values;i++) { if(valid_flags_mask==0 || (flag_entry->values[i].value & valid_flags_mask)) { int index; index=box->AddString(flag_entry->values[i].name); if(index!=LB_ERR) { box->SetItemData(index,flag_entry->values[i].value); if(flag_entry->values[i].value & flags_value) box->SetCheck(index,1); else box->SetCheck(index,0); /* In case you just wanna dim the invalid flags if(valid_flags_mask==0 || (flag_entry->values[i].value & valid_flags_mask)) box->Enable(index,TRUE); else box->Enable(index,FALSE); */ } flag_values_added++; } } return(flag_values_added); } ///////////////////////////////////////////////////////////////////////////// // Action and Query Database Functions ///////////////////////////////////////////////////////////////////////////// // Initialize the Database Arrays void CDallasMainDlg::InitFunctionDatabases(void) { int j; for(j=0;j=m_NumActions) return NULL; return(m_ActionDatabase[ID].desc); } // Returns a pointer to the action help text char *CDallasMainDlg::GetActionHelp(int ID) { if(ID<0 || ID>=m_NumActions) return NULL; return(m_ActionDatabase[ID].help); } // Returns a pointer to the action function name char *CDallasMainDlg::GetActionFunc(int ID) { if(ID==DO_NOTHING_ID) return DO_NOTHING_STRING; if(ID<0 || ID>=m_NumActions) return INVALID_FUNCTION_NAME; return(m_ActionDatabase[ID].func); } // Searches action list for action matching given function name int CDallasMainDlg::GetActionFuncID(char *func_name) { if(func_name==NULL) return INVALID_FUNCTION_ID; if(strcmp(DO_NOTHING_STRING, func_name)==0) return DO_NOTHING_ID; for(int j=0;j=m_NumQueries) return NULL; return(m_QueryDatabase[ID].desc); } // Returns a pointer to the query help text char *CDallasMainDlg::GetQueryHelp(int ID) { if(ID<0 || ID>=m_NumQueries) return NULL; return(m_QueryDatabase[ID].help); } // Returns a pointer to the query function name char *CDallasMainDlg::GetQueryFunc(int ID) { if(ID<0 || ID>=m_NumQueries) return INVALID_FUNCTION_NAME; return(m_QueryDatabase[ID].func); } // Searches query list for query matching given function name int CDallasMainDlg::GetQueryFuncID(char *func_name) { if(func_name==NULL) return INVALID_FUNCTION_ID; for(int j=0;jname = (char *) mem_malloc(strlen(enum_name)+1); if(enum_entry->name == NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(enum_entry->name,enum_name); enum_entry->num_values=0; enum_entry->is_user_type=TRUE; enum_entry->max_values=atoi(max_value_text); if(enum_entry->max_values<0) enum_entry->max_values=0; if(enum_entry->max_values>(MAX_ENUMS-2)) enum_entry->max_values=(MAX_ENUMS-2); // Add the default (-1:None) value tEnumValueEntry *value_entry; value_entry = &enum_entry->values[enum_entry->num_values++]; value_entry->name = (char *) mem_malloc(strlen(USERTYPE_NONE)+1); if(value_entry->name == NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(value_entry->name,USERTYPE_NONE); value_entry->value=-1; } } else if (strncmp(line,TAG_ENUM,strlen(TAG_ENUM))==0) { // Parse an enumeration block tEnumDBEntry *enum_entry; char *enum_name; bool done; // Strip off the name of this enumeration type enum_name=strtok(line,WHITESPACE_CHARS); if(enum_name!=NULL) enum_name=strtok(NULL,""); if(enum_name==NULL || GetEnumID(enum_name)!=INVALID_ENUM) { FunctionFileParseError(INV_ENUM_ERR,linenum,filename); enum_entry = NULL; } else if(m_NumEnums==MAX_ENUMS) { FunctionFileParseError(MAX_ENUM_ERR,linenum,filename); enum_entry = NULL; } else { enum_entry = &m_EnumDatabase[m_NumEnums++]; enum_entry->name = (char *) mem_malloc(strlen(enum_name)+1); if(enum_entry->name == NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(enum_entry->name,enum_name); enum_entry->num_values=0; enum_entry->is_user_type=FALSE; enum_entry->max_values=0; } // Parse the enumeration values for this entry done = 0; do { cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) done = 1; else if(enum_entry!=NULL) { tEnumValueEntry *value_entry; int enum_value; char *enum_value_string; char *enum_value_name; // Parse out the enum value and value name enum_value_string=strtok(line,":"); if(enum_value_string!=NULL) { enum_value=atoi(enum_value_string); enum_value_name=strtok(NULL,""); } if(enum_value_string==NULL || enum_value_name==NULL || GetEnumValueName(enum_entry->name,enum_value)!=NULL) { FunctionFileParseError(INV_ENUM_VALUE_ERR,linenum,filename); value_entry = NULL; } else if(enum_entry->num_values==MAX_ENUM_VALUES) { FunctionFileParseError(MAX_ENUM_VALUES_ERR,linenum,filename); value_entry = NULL; } else { value_entry = &enum_entry->values[enum_entry->num_values++]; value_entry->name = (char *) mem_malloc(strlen(enum_value_name)+1); if(value_entry->name == NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(value_entry->name,enum_value_name); value_entry->value=enum_value; } } } while (!done && !cfeof(ifile)); if (!done) FunctionFileParseError(UEOF_ERR,linenum,filename); } else if (strncmp(line,TAG_FLAG,strlen(TAG_FLAG))==0) { // Parse a flag block tFlagDBEntry *flag_entry; char *flag_name; bool done; // Strip off the name of this flag type flag_name=strtok(line,WHITESPACE_CHARS); if(flag_name!=NULL) flag_name=strtok(NULL,""); if(flag_name==NULL || GetFlagID(flag_name)!=INVALID_FLAG) { FunctionFileParseError(INV_FLAG_ERR,linenum,filename); flag_entry = NULL; } else if(m_NumFlags==MAX_FLAGS) { FunctionFileParseError(MAX_FLAG_ERR,linenum,filename); flag_entry = NULL; } else { flag_entry = &m_FlagDatabase[m_NumFlags++]; flag_entry->name = (char *) mem_malloc(strlen(flag_name)+1); if(flag_entry->name == NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(flag_entry->name,flag_name); flag_entry->num_values=0; } // Parse the flag values for this entry done = 0; do { cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) done = 1; else if(flag_entry!=NULL) { tFlagValueEntry *value_entry; int flag_value; char *flag_value_string; char *flag_value_name; // Parse out the flag value and value name flag_value_string=strtok(line,":"); if(flag_value_string!=NULL) { flag_value=atoi(flag_value_string); flag_value_name=strtok(NULL,""); } if(flag_value_string==NULL || flag_value_name==NULL || GetFlagValueName(flag_entry->name,flag_value)!=NULL) { FunctionFileParseError(INV_FLAG_VALUE_ERR,linenum,filename); value_entry = NULL; } else if(flag_entry->num_values==MAX_FLAG_VALUES) { FunctionFileParseError(MAX_FLAG_VALUES_ERR,linenum,filename); value_entry = NULL; } else { value_entry = &flag_entry->values[flag_entry->num_values++]; value_entry->name = (char *) mem_malloc(strlen(flag_value_name)+1); if(value_entry->name == NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(value_entry->name,flag_value_name); value_entry->value=flag_value; } } } while (!done && !cfeof(ifile)); if (!done) FunctionFileParseError(UEOF_ERR,linenum,filename); } else if (strncmp(line,TAG_ACTION,strlen(TAG_ACTION)) == 0) { // Parse action block if(m_NumActions>=MAX_ACTIONS) { MessageBox("ERROR: The Maximum Action limit has been exceeded!\n\nParsing must stop immediately.","ERROR!"); cfclose(ifile); return; } tActionDBEntry *action = &m_ActionDatabase[m_NumActions++]; if(m_NumActions==MAX_ACTIONS) { MessageBox("Warning: The Maximum Action limit has been reached!","Warning!"); } //Read category cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); action->category = GetFunctionCategoryID(line); if(action->category==INVALID_CATEGORY) { FunctionFileParseError(INV_CAT_ERR,linenum,filename); cfclose(ifile); return; } //Read action description cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); action->desc = (char *) mem_malloc(strlen(line)+1); if(action->desc==NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(action->desc,line); //Read action function cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); action->func = (char *) mem_malloc(strlen(line)+1); if(action->func==NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(action->func,line); //Read help bool done = 0; helpbuf[0] = 0; do { cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) done = 1; else { strcat(helpbuf,line); strcat(helpbuf,"\r\n"); } } while (!done && !cfeof(ifile)); if (!done) FunctionFileParseError(UEOF_ERR,linenum,filename); action->help = (char *) mem_malloc(strlen(helpbuf)+1); if(action->help==NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(action->help,helpbuf); } else if (strncmp(line,TAG_QUERY,strlen(TAG_QUERY)) == 0) { // Parse Query block if(m_NumQueries>=MAX_QUERIES) { MessageBox("ERROR: The Maximum Query limit has been exceeded!\n\nParsing must stop immediately.","ERROR!"); cfclose(ifile); return; } tQueryDBEntry *query = &m_QueryDatabase[m_NumQueries++]; if(m_NumQueries==MAX_QUERIES) { MessageBox("Warning: The Maximum Query limit has been reached!","Warning!"); } //Read category cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); query->category = GetFunctionCategoryID(line); if(query->category==INVALID_CATEGORY) { FunctionFileParseError(INV_CAT_ERR,linenum,filename); cfclose(ifile); return; } //Read action description cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); query->desc = (char *) mem_malloc(strlen(line)+1); if(query->desc==NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(query->desc,line); //Read action function cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); query->func = (char *) mem_malloc(strlen(line)+1); if(query->func==NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(query->func,line); //Read help bool done = 0; helpbuf[0] = 0; do { cf_ReadString(linebuf,sizeof(linebuf),ifile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,TAG_END,strlen(TAG_END)) == 0) done = 1; else { strcat(helpbuf,line); strcat(helpbuf,"\r\n"); } } while (!done && !cfeof(ifile)); if (!done) FunctionFileParseError(UEOF_ERR,linenum,filename); query->help = (char *) mem_malloc(strlen(helpbuf)+1); if(query->help==NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(ifile); return; } strcpy(query->help,helpbuf); } } cfclose(ifile); } // Returns a description copy with the parameter type info removed void CDallasMainDlg::ParseOutActionVarTypes(char *new_desc, char *old_desc) { CString name_text, default_text, range_text; CString new_desc_text; new_desc_text=""; while((*old_desc)!='\0') { // If it's start of a param block, extract the param name if((*old_desc)=='[') { ParseParamBlock(old_desc,name_text,default_text,range_text); new_desc_text+='['; new_desc_text+=name_text; new_desc_text+=']'; } else { new_desc_text+=(*old_desc); old_desc++; } } strcpy(new_desc,new_desc_text.GetBuffer(0)); } /* OLD VERSION // Returns a description copy with the parameter type info removed void CDallasMainDlg::ParseOutActionVarTypes(char *new_desc, char *old_desc) { int ok_to_write=TRUE; do { if(ok_to_write) { (*new_desc)=(*old_desc); new_desc++; } if((*old_desc)=='[') ok_to_write=FALSE; else if((*old_desc)==':') ok_to_write=TRUE; old_desc++; } while((*old_desc)!='\0'); (*new_desc)=(*old_desc); } */ // Returns a description copy with the parameter type info removed void CDallasMainDlg::ParseOutQueryVarTypes(char *new_desc, char *old_desc) { CString name_text, default_text, range_text; CString new_desc_text; new_desc_text=""; // Skip the return type section old_desc=strchr(old_desc,':'); if(old_desc==NULL) { strcpy(new_desc,new_desc_text.GetBuffer(0)); return; } old_desc++; // Parse the rest like it was an action ParseOutActionVarTypes(new_desc,old_desc); } /* OLD VERSION // Returns a description copy with the parameter type info removed void CDallasMainDlg::ParseOutQueryVarTypes(char *new_desc, char *old_desc) { int ok_to_write=FALSE; do { if(ok_to_write) { (*new_desc)=(*old_desc); new_desc++; } if((*old_desc)=='[') ok_to_write=FALSE; else if((*old_desc)==':') ok_to_write=TRUE; old_desc++; } while((*old_desc)!='\0'); (*new_desc)=(*old_desc); } */ // Validates an action node by conforming its parameters to what they should be // returns FALSE if node was modified significantly, otherwise TRUE bool CDallasMainDlg::ValidateActionNode(HTREEITEM node, int linenum) { CString name_text, default_text, range_text; tTreeNodeData *data; HTREEITEM child_node; int ID; char *desc; if(node==NULL) return TRUE; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL || data->type!=ACTION_STATEMENT_NODE) return TRUE; ID=data->ID; if(ID<0 || ID>=m_NumActions) return TRUE; desc=GetActionDesc(ID); if(desc==NULL) return TRUE; // Get the first child, if one exists child_node=m_ScriptTree.GetChildItem(node); // Parse the description, adding default parameter nodes appropriately bool modified=FALSE; while((*desc)!='\0') { if((*desc)=='[') { // Note the start of a parameter block int param_type=ParseParamBlock(desc,name_text,default_text,range_text); if(param_type>=0) { // Check the corresponding param (if it exists) and make it match up if(ConformParamNode(node,child_node,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0))) modified=TRUE; if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); } } else { desc++; } } // Delete any remaining child parameter nodes (they are no longer used) if(child_node!=NULL) { do { HTREEITEM temp_node=child_node; child_node=m_ScriptTree.GetNextSiblingItem(child_node); FreeTreeItem(temp_node); } while(child_node!=NULL); modified=TRUE; } if(modified) ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetActionFunc(ID)); return (!modified); } /* OLD VERSION // Validates an action node by conforming its parameters to what they should be // returns FALSE if node was modified significantly, otherwise TRUE bool CDallasMainDlg::ValidateActionNode(HTREEITEM node, int linenum) { tTreeNodeData *data; HTREEITEM child_node; int ID; char *desc, *desc_copy; if(node==NULL) return TRUE; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL || data->type!=ACTION_STATEMENT_NODE) return TRUE; ID=data->ID; if(ID<0 || ID>=m_NumActions) return TRUE; desc=GetActionDesc(ID); if(desc==NULL) return TRUE; // Get the first child, if one exists child_node=m_ScriptTree.GetChildItem(node); // Make a copy of description (so null chars can be added) desc_copy=(char *)mem_malloc(strlen(desc)+1); if(desc_copy==NULL) { MessageBox("ERROR: Out of memory in ValidateActionNode()!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(desc_copy,desc); // Parse the description, adding default parameter nodes appropriately int j=0; bool start_block_found=FALSE; bool type_delim_found=FALSE; char *param_name=FALSE; int param_type_char=-1; int param_type; bool modified=FALSE; while(desc_copy[j]!='\0') { if(desc_copy[j]=='[') { // Note the start of a parameter block start_block_found=TRUE; } else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field type_delim_found=TRUE; } else if(desc_copy[j]==']') { // If end of block, add the parameter if(param_type_char!=-1 && param_name!=NULL) { desc_copy[j]='\0'; // mark the end of the variable name // Get the parameter type param_type=ConvertParamCharToType(param_type_char); // Check the corresponding param (if it exists) and make it match up if(ConformParamNode(node,child_node,param_type,param_name)) modified=TRUE; if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); } start_block_found=FALSE; type_delim_found=FALSE; param_name=FALSE; param_type_char=-1; } else if(start_block_found && param_type_char==-1) { param_type_char=desc_copy[j]; } else if(type_delim_found && param_name==NULL) { param_name=&desc_copy[j]; } j++; } // Free up the copy memory mem_free(desc_copy); // Delete any remaining child parameter nodes (they are no longer used) if(child_node!=NULL) { do { HTREEITEM temp_node=child_node; child_node=m_ScriptTree.GetNextSiblingItem(child_node); FreeTreeItem(temp_node); } while(child_node!=NULL); modified=TRUE; } if(modified) ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetActionFunc(ID)); return (!modified); } */ // Checks the given param node (if it exists) and makes it match up with the given data // Returns TRUE if a significant modification had to take place, FALSE otherwise bool CDallasMainDlg::ConformParamNode(HTREEITEM parent_node, HTREEITEM ¶m_node, int type, char *name, char *def_value/*=NULL*/) { tTreeNodeData *data; CString query_ret_name; int index; if(parent_node==NULL) return FALSE; // If the param node doesn't exist, then we need to add a default param if(param_node==NULL) { CreateDefaultParameterNode(parent_node,TVI_LAST,type,name,def_value); return TRUE; } // See if the node matches the given data data=(tTreeNodeData *)m_ScriptTree.GetItemData(param_node); if(data!=NULL) { // Check parameter node if(data->type==PARAMETER_NODE && data->ID==type) { // node matches, so copy over the name in case it's changed (not considered a major mod) strcpy(data->name,name); UpdateNodeText(param_node); return FALSE; } // If it's a SPECNAME, see if we can transfer it over if(data->type==PARAMETER_NODE && data->ID==SPECNAME_PARAMETER_TYPE) { if(type==PATH_PARAMETER_TYPE) { data->ID=type; strcpy(data->name,name); index=osipf_FindPathName(data->str_val); if(index<0) { data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateNodeText(param_node); return TRUE; } data->int_val=index; strcpy(data->str_val,GamePaths[index].name); UpdateNodeText(param_node); return FALSE; } else if(type==MATCEN_PARAMETER_TYPE) { data->ID=type; strcpy(data->name,name); data->subID=USE_MATCEN_VALUE; index=osipf_FindMatcenName(data->str_val); if(index<0) { data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateNodeText(param_node); return TRUE; } char matcen_name[MAX_MATCEN_NAME_LEN+1]; Matcen[index]->GetName(matcen_name); data->int_val=index; strcpy(data->str_val,matcen_name); UpdateNodeText(param_node); return FALSE; } else if(type==LEVEL_GOAL_PARAMETER_TYPE) { data->ID=type; strcpy(data->name,name); data->subID=USE_LEVEL_GOAL_VALUE; index=osipf_FindLevelGoalName(data->str_val); if(index<0) { data->int_val=NOT_SPECIFIED_TYPE; strcpy(data->str_val,""); UpdateNodeText(param_node); return TRUE; } data->int_val=index; UpdateNodeText(param_node); return FALSE; } else if(type==STRM_AUDIO_PARAMETER_TYPE) { data->ID=type; strcpy(data->name,name); if(!GamefileExists(data->str_val)) { strcpy(data->str_val,""); UpdateNodeText(param_node); return TRUE; } UpdateNodeText(param_node); return FALSE; } } // Check query node if(data->type==EXPRESSION_NODE && GetQueryReturnType(data->ID,query_ret_name)==type) { // node matches, so copy over the name in case it's changed (not considered a major mod) strcpy(data->name,name); UpdateNodeText(param_node); return FALSE; } } // Since the param node doesn't match up with the data, replace it with a default that does HTREEITEM new_node; new_node=CreateDefaultParameterNode(parent_node,param_node,type,name,def_value); FreeTreeItem(param_node); param_node=new_node; UpdateNodeText(param_node); return TRUE; } // Validates a query node by conforming its parameters to what they should be // returns FALSE if node was modified significantly, otherwise TRUE bool CDallasMainDlg::ValidateQueryNode(HTREEITEM node, int linenum) { CString name_text, default_text, range_text; tTreeNodeData *data; HTREEITEM child_node; int ID; char *desc; if(node==NULL) return TRUE; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL || data->type!=EXPRESSION_NODE) return TRUE; ID=data->ID; if(ID<0 || ID>=m_NumQueries) return TRUE; desc=strchr(GetQueryDesc(ID),':'); if(desc==NULL) return TRUE; desc++; // Get the first child, if one exists child_node=m_ScriptTree.GetChildItem(node); // Parse the description, adding default parameter nodes appropriately bool modified=FALSE; while((*desc)!='\0') { if((*desc)=='[') { // Note the start of a parameter block int param_type=ParseParamBlock(desc,name_text,default_text,range_text); if(param_type>=0) { // Check the corresponding param (if it exists) and make it match up if(ConformParamNode(node,child_node,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0))) modified=TRUE; if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); } } else { desc++; } } // Delete any remaining child parameter nodes (they are no longer used) if(child_node!=NULL) { do { HTREEITEM temp_node=child_node; child_node=m_ScriptTree.GetNextSiblingItem(child_node); FreeTreeItem(temp_node); } while(child_node!=NULL); modified=TRUE; } if(modified) ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetQueryFunc(ID)); return (!modified); } /* OLD VERSION // Validates a query node by conforming its parameters to what they should be // returns FALSE if node was modified significantly, otherwise TRUE bool CDallasMainDlg::ValidateQueryNode(HTREEITEM node, int linenum) { tTreeNodeData *data; HTREEITEM child_node; int ID; char *desc, *desc_copy; if(node==NULL) return TRUE; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL || data->type!=EXPRESSION_NODE) return TRUE; ID=data->ID; if(ID<0 || ID>=m_NumQueries) return TRUE; desc=strchr(GetQueryDesc(ID),':'); if(desc==NULL) return TRUE; desc++; // Get the first child, if one exists child_node=m_ScriptTree.GetChildItem(node); // Make a copy of description (so null chars can be added) desc_copy=(char *)mem_malloc(strlen(desc)+1); if(desc_copy==NULL) { MessageBox("ERROR: Out of memory in ValidateQueryNode()!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } strcpy(desc_copy,desc); // Parse the description, adding default parameter nodes appropriately int j=0; bool start_block_found=FALSE; bool type_delim_found=FALSE; char *param_name=FALSE; int param_type_char=-1; int param_type; bool modified=FALSE; while(desc_copy[j]!='\0') { if(desc_copy[j]=='[') { // Note the start of a parameter block start_block_found=TRUE; } else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field type_delim_found=TRUE; } else if(desc_copy[j]==']') { // If end of block, add the parameter if(param_type_char!=-1 && param_name!=NULL) { desc_copy[j]='\0'; // mark the end of the variable name // Get the parameter type param_type=ConvertParamCharToType(param_type_char); // Check the corresponding param (if it exists) and make it match up if(ConformParamNode(node,child_node,param_type,param_name)) modified=TRUE; if(child_node!=NULL) child_node=m_ScriptTree.GetNextSiblingItem(child_node); } start_block_found=FALSE; type_delim_found=FALSE; param_name=FALSE; param_type_char=-1; } else if(start_block_found && param_type_char==-1) { param_type_char=desc_copy[j]; } else if(type_delim_found && param_name==NULL) { param_name=&desc_copy[j]; } j++; } // Free up the copy memory mem_free(desc_copy); // Delete any remaining child parameter nodes (they are no longer used) if(child_node!=NULL) { do { HTREEITEM temp_node=child_node; child_node=m_ScriptTree.GetNextSiblingItem(child_node); FreeTreeItem(temp_node); } while(child_node!=NULL); modified=TRUE; } if(modified) ScriptFileParseError(MODIFIED_FUNC_ERR,linenum,GetScriptID(node),GetQueryFunc(ID)); return (!modified); } */ // Fills up the given menu with the categories of actions // NOTE: Command ID's of menu items start at the given command_offset void CDallasMainDlg::FillActionMenu(CMenu *action_menu, int command_offset) { int j,k, actions_added; // Loop through the categories, creating submenu for each one for(j=0;jAppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)category_submenu.Detach(), m_FunctionCategories[j]); else action_menu->AppendMenu(MF_POPUP, (uint32_t)category_submenu.Detach(), m_FunctionCategories[j]); } } // Fills up the given menu with the categories of queries // NOTE: Command ID's of menu items start at the given command_offset void CDallasMainDlg::FillQueryMenu(CMenu *query_menu, int command_offset, int valid_return_type, char *valid_return_name) { int j,k, queries_added; int query_ret_type; CString query_ret_name; bool types_match; // Loop through the categories, creating submenu for each one for(j=0;jAppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)category_submenu.Detach(), m_FunctionCategories[j]); else query_menu->AppendMenu(MF_POPUP, (uint32_t)category_submenu.Detach(), m_FunctionCategories[j]); } } // Attempts to parse the Nth (indexed at 1) bracketed section of the given function node's desc, // and obtain from it the parameter name, default string, and range string. // It returns the param type if successfull, or -1 if the requested Parameter section // does not exist int CDallasMainDlg::ParseNthParam(HTREEITEM func_node, int n, CString &name_text, CString &default_text, CString &range_text) { tTreeNodeData *data; if(func_node==NULL) return(-1); data=(tTreeNodeData *)m_ScriptTree.GetItemData(func_node); if(data==NULL) return(-1); // Handle action nodes if(data->type==ACTION_STATEMENT_NODE) { char *desc=GetActionDesc(data->ID); return(ParseNthParam(desc,n,name_text,default_text,range_text)); } // Handle query nodes if(data->type==EXPRESSION_NODE) { char *desc=GetQueryDesc(data->ID); return(ParseNthParam(desc,n,name_text,default_text,range_text)); } return(-1); } // Attempts to parse the Nth (indexed at 1) bracketed section of the given action desc, // and obtain from it the parameter name, default string, and range string. // It returns the param type if successfull, or -1 if the requested Parameter section // does not exist int CDallasMainDlg::ParseNthParam(char *desc, int n, CString &name_text, CString &default_text, CString &range_text) { // Check validity of desc and given n if(n<=0 || desc==NULL) return(-1); // Find the n'th parameter block (bracketed section) char *s; s=strchr(desc,'['); for(int j=1;j=range_start && value<=range_end) value_in_range=TRUE; } num_text=""; range_start=0; range_end=0; currently_parsing=RANGE_START_NUM; } else if(ch=='|') { currently_parsing=RANGE_END_NUM; range_start=atoi(num_text.GetBuffer(0)); num_text=""; } else { num_text+=ch; } range_desc++; } // Check the last value range if(currently_parsing==RANGE_START_NUM) { range_start=atoi(num_text.GetBuffer(0)); if(value==range_start) value_in_range=TRUE; } else { range_end=atoi(num_text.GetBuffer(0)); if(value>=range_start && value<=range_end) value_in_range=TRUE; } return(value_in_range); } // Returns TRUE if the given float is in the given range, FALSE otherwise bool CDallasMainDlg::VerifyFloatRange(float value, char *range_desc) { CString num_text; float range_start=0.0, range_end=0.0; bool value_in_range=FALSE; int currently_parsing=RANGE_START_NUM; while((*range_desc)!='\0') { char ch=(*range_desc); if(ch==',') { if(currently_parsing==RANGE_START_NUM) { range_start=atof(num_text.GetBuffer(0)); if(value==range_start) value_in_range=TRUE; } else { range_end=atof(num_text.GetBuffer(0)); if(value>=range_start && value<=range_end) value_in_range=TRUE; } num_text=""; range_start=0.0; range_end=0.0; currently_parsing=RANGE_START_NUM; } else if(ch=='|') { currently_parsing=RANGE_END_NUM; range_start=atof(num_text.GetBuffer(0)); num_text=""; } else { num_text+=ch; } range_desc++; } // Check the last value range if(currently_parsing==RANGE_START_NUM) { range_start=atof(num_text.GetBuffer(0)); if(value==range_start) value_in_range=TRUE; } else { range_end=atof(num_text.GetBuffer(0)); if(value>=range_start && value<=range_end) value_in_range=TRUE; } return(value_in_range); } ///////////////////////////////////////////////////////////////////////////// // Script Grouping Functions ///////////////////////////////////////////////////////////////////////////// // Initializes the script grouping list for use void CDallasMainDlg::InitScriptGroupingList(void) { m_ScriptGroupingList=NULL; m_NumScriptGroups=0; } // Deletes memory allocated for the Script Grouping list void CDallasMainDlg::ClearScriptGroupingList(void) { int j,k; // Free up all the individual script node lists for(j=0;jnum_script_nodes > 0) { mem_free(event_section->script_node_list); event_section->script_node_list=NULL; event_section->num_script_nodes=0; } } } // Free up the entire script grouping list if(m_NumScriptGroups>0) { mem_free(m_ScriptGroupingList); m_ScriptGroupingList=NULL; m_NumScriptGroups=0; } } // Adds the node into the appropriate event section of the owner group int CDallasMainDlg::AddNodeToScriptOwnerGroup(int pos, HTREEITEM script_node) { HTREEITEM event_node; tTreeNodeData *event_data; int event_type; // Make sure pos is valid if(pos<0 || pos>=m_NumScriptGroups) return FALSE; // Get the event type event_node=GetScriptEventNode(script_node); if(event_node==NULL) return FALSE; event_data=(tTreeNodeData *)m_ScriptTree.GetItemData(event_node); if(event_data==NULL) return FALSE; event_type=event_data->ID; // Make sure event type is valid if(event_type<0 || event_type>=MAX_EVENT_TYPES) return FALSE; tEventSection *event_section=&m_ScriptGroupingList[pos].event_sections[event_type]; // Add this node to the appropriate event section list if(event_section->num_script_nodes==0) event_section->script_node_list=(HTREEITEM *)mem_malloc(sizeof(HTREEITEM)*1); else event_section->script_node_list=(HTREEITEM *)mem_realloc(event_section->script_node_list,sizeof(HTREEITEM)*(event_section->num_script_nodes+1)); if(event_section->script_node_list==NULL) return FALSE; event_section->num_script_nodes++; int new_pos=event_section->num_script_nodes-1; event_section->script_node_list[new_pos]=script_node; return TRUE; } // Categorizes the given node into the grouping list int CDallasMainDlg::AddNodeToScriptGroupingList(HTREEITEM script_node) { HTREEITEM owner_node; tTreeNodeData *data, *owner_data; int j; // Make sure it's a script header node data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); if(data==NULL || data->type!=SCRIPT_HEADER_NODE) return FALSE; // Get the owner node data owner_node=GetScriptOwnerNode(script_node); if(owner_node==NULL) return FALSE; owner_data=(tTreeNodeData *)m_ScriptTree.GetItemData(owner_node); if(owner_data==NULL) return FALSE; // Search the grouping list for a matching owner group for(j=0;jID) continue; // If it's not a LEVEL owner, we need to make sure the handles also match if(m_ScriptGroupingList[j].owner_type != LEVEL_TYPE) { if(m_ScriptGroupingList[j].owner_handle != owner_data->int_val) continue; } return(AddNodeToScriptOwnerGroup(j,script_node)); } // Since owner does not exist, create a new Script Group entry if(m_NumScriptGroups==0) m_ScriptGroupingList=(tScriptOwnerGroup *)mem_malloc(sizeof(tScriptOwnerGroup)*1); else m_ScriptGroupingList=(tScriptOwnerGroup *)mem_realloc(m_ScriptGroupingList,sizeof(tScriptOwnerGroup)*(m_NumScriptGroups+1)); if(m_ScriptGroupingList==NULL) return FALSE; m_NumScriptGroups++; // Initialize the new entry int new_pos=m_NumScriptGroups-1; m_ScriptGroupingList[new_pos].owner_type=owner_data->ID; m_ScriptGroupingList[new_pos].owner_handle=owner_data->int_val; for(j=0;j=m_NumScriptGroups) return(name.GetBuffer(0)); tScriptOwnerGroup *owner_group=&m_ScriptGroupingList[pos]; switch(owner_group->owner_type) { case OBJECT_TYPE: name.Format("ID_CUSTOM_OBJECT_%04X",owner_group->owner_handle); break; case TRIGGER_TYPE: name.Format("ID_TRIGGER_%04X",owner_group->owner_handle); break; case LEVEL_TYPE: name.Format("%s",LEVEL_ID_NAME); break; default: name.Format("ID_ILLEGAL_SCRIPT_TYPE"); break; } return(name.GetBuffer(0)); } // Creates a Class name for a given owner node char *CDallasMainDlg::CreateScriptClassName(int pos) { static CString name=""; if(pos<0 || pos>=m_NumScriptGroups) return(name.GetBuffer(0)); tScriptOwnerGroup *owner_group=&m_ScriptGroupingList[pos]; switch(owner_group->owner_type) { case OBJECT_TYPE: name.Format("CustomObjectScript_%04X",owner_group->owner_handle); break; case TRIGGER_TYPE: name.Format("TriggerScript_%04X",owner_group->owner_handle); break; case LEVEL_TYPE: name.Format("%s",LEVEL_CLASS_NAME); break; default: name.Format("IllegalScriptType"); break; } return(name.GetBuffer(0)); } // Creates a Class name for a given owner node char *CDallasMainDlg::CreateScriptGlobalCtrName(int ID) { static CString name=""; if(ID<0) return(name.GetBuffer(0)); name.Format("ScriptActionCtr_%03d",ID); return(name.GetBuffer(0)); } ///////////////////////////////////////////////////////////////////////////// // Parsing Functions ///////////////////////////////////////////////////////////////////////////// CString CurrentParsingFilename=""; // Handle Parse Errors void CDallasMainDlg::ScriptFileParseError(int error_code, int linenum, int script_ID, const char *name) { CString err_msg; switch(error_code) { case UEOS_ERR: err_msg.Format("ERROR: Unexpected end of file while parsing %s, line %d.",CurrentParsingFilename.GetBuffer(0),linenum); break; case INVALID_FUNC_ERR: err_msg.Format( "ERROR: An invalid glue function name (%s) was encountered in %s, line %d.\n\n" "Hence, Script #%d now contains an invalid action or query that must be replaced.", name,CurrentParsingFilename.GetBuffer(0),linenum,script_ID); break; case INVALID_NODE_ERR: err_msg.Format( "ERROR: An invalid script node was encountered in %s, line %d.\n\n." "Because this node could not be added, one or more of your scripts may be corrupt.", CurrentParsingFilename.GetBuffer(0),linenum); break; case MODIFIED_FUNC_ERR: err_msg.Format( "ERROR: A glue function (%s) with out of date parameters was encountered in %s, line %d.\n\n" "Hence, Script #%d now contains an action or query that may need to be modified.", name,CurrentParsingFilename.GetBuffer(0),linenum,script_ID); break; case INVALID_MSGID_ERR: err_msg.Format( "ERROR: An invalid Message ID (%s) was encountered in %s, line %d.\n\n" "Hence, Script #%d now contains a Message ID that needs to be replaced.", name,CurrentParsingFilename.GetBuffer(0),linenum,script_ID); break; default: err_msg.Format("ERROR: An unknown error was detected in %s, line %d",CurrentParsingFilename.GetBuffer(0),linenum); break; } MessageBox(err_msg,"Script File Parse Error",MB_OK|MB_ICONEXCLAMATION); } // Reads in the script source file and calls the various parsers for the // Appropriate sections int CDallasMainDlg::ParseSourceScript(char *filename) { CFILE *infile; char linebuf[2048]; char tempbuf[256]; char *line; int linenum; int valid_lines_read, version; char fullpath[_MAX_PATH]; int rc; HTREEITEM last_node_added, current_parent, returned_node; bool skip_children; int skip_depth; bool last_node_childless; CurrentParsingFilename=m_ScriptFilename; ddio_MakePath(fullpath,LocalScriptDir,filename,NULL); // Try to open the file for loading infile=cfopen (fullpath,"rt"); if (!infile) { CString msg; msg.Format("Unable to open \"%s\"!",filename); MessageBox(msg,"No Script Source File Found!",MB_OK|MB_ICONEXCLAMATION); // Clear out the Script Tree ClearTree(); // Add the clipboard node CreateDefaultClipboardNode(); return FALSE; } linenum=0; // Read in and parse each line of the file while (!cfeof(infile)) { // Clear the buffer strcpy(linebuf,""); // Read in a line from the file cf_ReadString(linebuf, sizeof(linebuf), infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); // Check for Start of Script Block Section if (strncmp(line,SCRIPT_BLOCK_START_TAG,strlen(SCRIPT_BLOCK_START_TAG)) == 0) { bool done = false; // Clear out the Script Tree ClearTree(); // Clear out the name lists ClearNameLists(); // Set valid line counter to track whether we're reading header info or tree nodes valid_lines_read=0; // Set tree node trackers so we know where we are in the actual tree last_node_added=NULL; current_parent=TVI_ROOT; // Set variables that allow child nodes to be skipped over // when a bad Action or Query node is read in (invalid function name) skip_children=FALSE; skip_depth=0; last_node_childless=FALSE; // Read all the lines in the block while (!done && !cfeof(infile)) { strcpy(linebuf,""); cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); // If it's an empty line or a comment, skip it if(strlen(line)==0 || strncmp(line,"//",2)==0) continue; // Check for End of Script Block Section if (strncmp(line,SCRIPT_BLOCK_END_TAG,strlen(SCRIPT_BLOCK_END_TAG)) == 0) { done=true; continue; } // Check for Start of User Type values if (strncmp(line,USERTYPE_VALS_START_TAG,strlen(USERTYPE_VALS_START_TAG))==0) { // Parse a user type block tEnumDBEntry *enum_entry; char *enum_name; int DBslot; bool end_of_usertype_found; enum_entry=NULL; // Strip off the name of this enumeration type enum_name=strtok(line,WHITESPACE_CHARS); if(enum_name!=NULL) enum_name=strtok(NULL,""); if(enum_name!=NULL && (DBslot=GetEnumID(enum_name))!=INVALID_ENUM) { enum_entry = &m_EnumDatabase[DBslot]; } // Parse the enumeration values for this user type end_of_usertype_found = FALSE; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,USERTYPE_VALS_END_TAG,strlen(USERTYPE_VALS_END_TAG)) == 0) end_of_usertype_found = TRUE; else if(enum_entry!=NULL) { tEnumValueEntry *value_entry; int enum_value; char *enum_value_string; char *enum_value_name; // Parse out the enum value and value name enum_value_string=strtok(line,":"); if(enum_value_string!=NULL) { enum_value=atoi(enum_value_string); enum_value_name=strtok(NULL,""); } if(enum_value_string==NULL || enum_value_name==NULL || GetEnumValueName(enum_entry->name,enum_value)!=NULL) { value_entry = NULL; } else if(enum_entry->num_values>=MAX_ENUM_VALUES || enum_entry->num_values>=(enum_entry->max_values+2)) { value_entry = NULL; } else { value_entry = &enum_entry->values[enum_entry->num_values++]; value_entry->name = (char *) mem_malloc(strlen(enum_value_name)+1); if(value_entry->name == NULL) { FunctionFileParseError(NO_MEM_ERR,linenum,filename); cfclose(infile); return FALSE; } strcpy(value_entry->name,enum_value_name); value_entry->value=enum_value; } } } while (!end_of_usertype_found && !cfeof(infile)); continue; } // Check for Door List Block, and read it in if (strncmp(line,DOOR_LIST_START_TAG,strlen(DOOR_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,DOOR_LIST_END_TAG,strlen(DOOR_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddDoorToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Object List Block, and read it in if (strncmp(line,OBJECT_LIST_START_TAG,strlen(OBJECT_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,OBJECT_LIST_END_TAG,strlen(OBJECT_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddObjectToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Room List Block, and read it in if (strncmp(line,ROOM_LIST_START_TAG,strlen(ROOM_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,ROOM_LIST_END_TAG,strlen(ROOM_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddRoomToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Trigger List Block, and read it in if (strncmp(line,TRIGGER_LIST_START_TAG,strlen(TRIGGER_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,TRIGGER_LIST_END_TAG,strlen(TRIGGER_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddTriggerToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Sound List Block, and read it in if (strncmp(line,SOUND_LIST_START_TAG,strlen(SOUND_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,SOUND_LIST_END_TAG,strlen(SOUND_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddSoundToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Texture List Block, and read it in if (strncmp(line,TEXTURE_LIST_START_TAG,strlen(TEXTURE_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,TEXTURE_LIST_END_TAG,strlen(TEXTURE_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddTextureToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Specname List Block, and read it in if (strncmp(line,SPECNAME_LIST_START_TAG,strlen(SPECNAME_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,SPECNAME_LIST_END_TAG,strlen(SPECNAME_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddSpecnameToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Path List Block, and read it in if (strncmp(line,PATH_LIST_START_TAG,strlen(PATH_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,PATH_LIST_END_TAG,strlen(PATH_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddPathToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Matcen List Block, and read it in if (strncmp(line,MATCEN_LIST_START_TAG,strlen(MATCEN_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,MATCEN_LIST_END_TAG,strlen(MATCEN_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddMatcenToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for Goal List Block, and read it in if (strncmp(line,GOAL_LIST_START_TAG,strlen(GOAL_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,GOAL_LIST_END_TAG,strlen(GOAL_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddGoalToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Check for StrmAudio List Block, and read it in if (strncmp(line,STRM_AUDIO_LIST_START_TAG,strlen(STRM_AUDIO_LIST_START_TAG)) == 0) { bool end_list_found = 0; do { cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); if (strncmp(line,STRM_AUDIO_LIST_END_TAG,strlen(STRM_AUDIO_LIST_END_TAG)) == 0) end_list_found=TRUE; else if(strlen(line)>0) AddStrmAudioToList(line); } while (!end_list_found && !cfeof(infile)); continue; } // Is it the start of a child block? if(strncmp(line,CHILD_BLOCK_START_TAG,strlen(CHILD_BLOCK_START_TAG)) == 0) { last_node_childless=FALSE; if(!skip_children) { current_parent=last_node_added; if(current_parent==NULL) current_parent=TVI_ROOT; } else { skip_depth++; } continue; } // Handles Validation of childless function nodes if(last_node_added!=NULL && last_node_childless) { ValidateFunctionNode(last_node_added,linenum); // Need this to update node text that depends on subnodes UpdateNodeText(last_node_added); last_node_childless=FALSE; } // Is it the end of a child block? if(strncmp(line,CHILD_BLOCK_END_TAG,strlen(CHILD_BLOCK_END_TAG)) == 0) { if(!skip_children || skip_depth<=0) { skip_children=FALSE; skip_depth=0; last_node_added=current_parent; if(last_node_added==TVI_ROOT) last_node_added=NULL; else { // Need this to validate a function node once all of its params have been added ValidateFunctionNode(last_node_added,linenum); // Need this to update node text that depends on subnodes UpdateNodeText(last_node_added); } if(current_parent!=TVI_ROOT) current_parent=m_ScriptTree.GetParentItem(current_parent); if(current_parent==NULL) current_parent=TVI_ROOT; } else skip_depth--; continue; } // If we're skipping children, but the depth is still zero here, // then must not be any children to skip! if(skip_children && skip_depth<=0) { skip_children=FALSE; skip_depth=0; } // See if it should be the save version line if(valid_lines_read==0) { rc=sscanf(line,"%s %d",tempbuf,&version); if(rc==2 && strcmp(tempbuf,"VERSION")==0) valid_lines_read++; continue; } // See if it should be the next script ID line if(valid_lines_read==1) { rc=sscanf(line,"%s %d",tempbuf,&m_NextScriptID); if(rc==2 && strcmp(tempbuf,"NEXT_ID")==0) valid_lines_read++; continue; } // It must be a node then, // so (if we're not skipping children) parse it and add it to the tree if(!skip_children) { if(version>=1) returned_node=ParseScriptNodeLine_v1U(line,linenum,current_parent,skip_children,version); else returned_node=ParseScriptNodeLine_v0(line,linenum,current_parent,skip_children); if(returned_node!=NULL ) { last_node_added=returned_node; last_node_childless=TRUE; UpdateNodeText(last_node_added); } else ScriptFileParseError(INVALID_NODE_ERR,linenum,0,NULL); if(returned_node==NULL || skip_children) { skip_children=TRUE; skip_depth=0; } } } if (!done) ScriptFileParseError(UEOS_ERR,linenum,0,NULL); } } cfclose(infile); // Add the clipboard node CreateDefaultClipboardNode(); return TRUE; } // VERSION 0: Parses a script node line, and if it's valid, adds it to the given parent HTREEITEM CDallasMainDlg::ParseScriptNodeLine_v0(char *line, int linenum, HTREEITEM parent, bool &skip_all_children, HTREEITEM insert_before/*=TVI_LAST*/) { tTreeNodeData node_data; bool add_node; int index; // Make sure given data is ok if(line==NULL || parent==NULL || skip_all_children) return NULL; // Read in the node type line=strtok(line,":"); if(line==NULL) return NULL; node_data.type=atoi(line); // Read in the rest of this node's data add_node=FALSE; switch(node_data.type) { case SCRIPT_HEADER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case SCRIPT_OWNER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; node_data.int_val=atoi(line); // Verify object name if(node_data.ID==OBJECT_TYPE) { object *objp=ObjGet(node_data.int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { node_data.int_val=OBJECT_HANDLE_NONE; strcpy(node_data.str_val,""); } else { strcpy(node_data.str_val,objp->name); } } // Verify trigger name if(node_data.ID==TRIGGER_TYPE) { int t=node_data.int_val; if(t<0 || t>=Num_triggers || t>=MAX_NAMED_TRIGGERS || strlen(Triggers[t].name)==0) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } else { strcpy(node_data.str_val,Triggers[t].name); } } add_node=TRUE; break; case SCRIPT_EVENT_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case CONDITIONAL_HEADER_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case ACTIONS_HEADER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; node_data.subID=atoi(line); add_node=TRUE; break; case CONDITIONAL_STATEMENT_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case EXPRESSION_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=GetQueryFuncID(line); if(node_data.ID==INVALID_FUNCTION_ID) { ScriptFileParseError(INVALID_FUNC_ERR,linenum,GetScriptID(parent),line); skip_all_children=TRUE; } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case EXPRESSION_OPERATOR_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; node_data.subID=atoi(line); add_node=TRUE; break; case ACTION_STATEMENT_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=GetActionFuncID(line); if(node_data.ID==INVALID_FUNCTION_ID) { ScriptFileParseError(INVALID_FUNC_ERR,linenum,GetScriptID(parent),line); skip_all_children=TRUE; } add_node=TRUE; break; case LOGICAL_OPERATOR_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case PARAMETER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); // Get param data based upon what kind of parameter it is switch(node_data.ID) { case DOOR_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); // Verify door name if(node_data.subID==USE_OBJECT_HANDLE) { object *objp=ObjGet(node_data.int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { node_data.int_val=OBJECT_HANDLE_NONE; strcpy(node_data.str_val,""); } else { strcpy(node_data.str_val,objp->name); } } add_node=TRUE; break; case OBJECT_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); // Verify object name if(node_data.subID==USE_OBJECT_HANDLE) { object *objp=ObjGet(node_data.int_val); if(objp==NULL || objp->type==OBJ_NONE || objp->name==NULL) { node_data.int_val=OBJECT_HANDLE_NONE; strcpy(node_data.str_val,""); } else { strcpy(node_data.str_val,objp->name); } } add_node=TRUE; break; case ROOM_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); // Verify room name index=node_data.int_val; if(index<0 || index>Highest_room_index || !Rooms[index].used || Rooms[index].name==NULL) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } else { strcpy(node_data.str_val,Rooms[index].name); } add_node=TRUE; break; case TRIGGER_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); // Verify trigger name index=node_data.int_val; if(index<0 || index>=Num_triggers || index>=MAX_NAMED_TRIGGERS || strlen(Triggers[index].name)==0) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } else { strcpy(node_data.str_val,Triggers[index].name); } add_node=TRUE; break; case INT_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case BOOL_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case FLOAT_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val1=atof(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case VECTOR_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val1=atof(line); if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val2=atof(line); if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val3=atof(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case STRING_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; strcpy(node_data.str_val,line); if(FindMessageInList(line)==NULL) { strcpy(node_data.str_val,""); if(strcmp(line,NOT_SPECIFIED_MSG)!=0) ScriptFileParseError(INVALID_MSGID_ERR,linenum,GetScriptID(parent),line); } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case PERCENTAGE_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val1=atof(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case ENUM_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case SCRIPT_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case SOUND_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if(index<0 || index>=m_SoundListSize) node_data.int_val=-1; else node_data.int_val=FindSoundName(m_SoundList[atoi(line)]); if(node_data.int_val<0) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); // Display warning message here... } else { strcpy(node_data.str_val,m_SoundList[atoi(line)]); } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case SPECNAME_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; strcpy(node_data.str_val,line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case TEXTURE_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if(index<0 || index>=m_TextureListSize) node_data.int_val=-1; else node_data.int_val=FindTextureName(m_TextureList[atoi(line)]); if(node_data.int_val<0) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); // Display warning message here... } else { strcpy(node_data.str_val,m_TextureList[atoi(line)]); } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case FLAG_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case PATH_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if(index<0 || index>=m_PathListSize) node_data.int_val=-1; else node_data.int_val=osipf_FindPathName(m_PathList[index]); if(node_data.int_val<0) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); // Display warning message here... } else { strcpy(node_data.str_val,m_PathList[index]); } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case MATCEN_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if(index<0 || index>=m_MatcenListSize) node_data.int_val=-1; else node_data.int_val=osipf_FindMatcenName(m_MatcenList[index]); if(node_data.int_val<0) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); // Display warning message here... } else { strcpy(node_data.str_val,m_MatcenList[index]); } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case LEVEL_GOAL_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if(index<0 || index>=m_GoalListSize) node_data.int_val=-1; else node_data.int_val=osipf_FindLevelGoalName(m_GoalList[index]); if(node_data.int_val<0) { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); // Display warning message here... } else { strcpy(node_data.str_val,m_GoalList[index]); } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case STRM_AUDIO_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if(index<0 || index>=m_StrmAudioListSize || !GamefileExists(m_StrmAudioList[index])) strcpy(node_data.str_val,""); else { strcpy(node_data.str_val,m_StrmAudioList[index]); // Display warning message here... } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; default: break; } break; case PARAMETER_OPERATOR_NODE: break; case UNKNOWN_NODE: break; default: break; } if(add_node) return(AddNodeToTree(parent,insert_before,&node_data)); return NULL; } // VERSION 1: Parses a script node line, and if it's valid, adds it to the given parent HTREEITEM CDallasMainDlg::ParseScriptNodeLine_v1U(char *line, int linenum, HTREEITEM parent, bool &skip_all_children, int version, HTREEITEM insert_before/*=TVI_LAST*/) { tTreeNodeData node_data; bool add_node; int index; int scriptID; // Make sure given data is ok if(line==NULL || parent==NULL || skip_all_children) return NULL; // Determine what script we're in scriptID=-1; if(parent!=TVI_ROOT) scriptID=GetScriptID(parent); // Read in the node type line=strtok(line,":"); if(line==NULL) return NULL; node_data.type=atoi(line); // Read in the rest of this node's data add_node=FALSE; switch(node_data.type) { case SCRIPT_HEADER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case SCRIPT_OWNER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; index=atoi(line); if(node_data.ID==OBJECT_TYPE) { if(index>=0 && index=0 && index= 0) { strcpy(node_data.str_val,m_TriggerList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Trigger Script Owner",m_TriggerList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } } else { node_data.int_val=index; strcpy(node_data.str_val,""); } add_node=TRUE; break; case SCRIPT_EVENT_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case CONDITIONAL_HEADER_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case ACTIONS_HEADER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if(version>=3) { if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); } else { node_data.int_val=CONTINUE_SCRIPT_CHAIN; } if((line=strtok(NULL,""))==NULL) return NULL; node_data.subID=atoi(line); add_node=TRUE; break; case CONDITIONAL_STATEMENT_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case EXPRESSION_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=GetQueryFuncID(line); if(node_data.ID==INVALID_FUNCTION_ID) { ScriptFileParseError(INVALID_FUNC_ERR,linenum,scriptID,line); skip_all_children=TRUE; } if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case EXPRESSION_OPERATOR_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; node_data.subID=atoi(line); add_node=TRUE; break; case ACTION_STATEMENT_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=GetActionFuncID(line); if(node_data.ID==INVALID_FUNCTION_ID) { ScriptFileParseError(INVALID_FUNC_ERR,linenum,scriptID,line); skip_all_children=TRUE; } add_node=TRUE; break; case LOGICAL_OPERATOR_NODE: if((line=strtok(NULL,""))==NULL) return NULL; node_data.ID=atoi(line); add_node=TRUE; break; case PARAMETER_NODE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.ID=atoi(line); // Get param data based upon what kind of parameter it is switch(node_data.ID) { case DOOR_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(node_data.subID==USE_OBJECT_HANDLE) { if(index>=0 && index=0 && index=0 && index= 0) { strcpy(node_data.str_val,m_RoomList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Room",m_RoomList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } add_node=TRUE; break; case TRIGGER_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(index>=0 && index= 0) { strcpy(node_data.str_val,m_TriggerList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Trigger",m_TriggerList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } add_node=TRUE; break; case INT_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case BOOL_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case FLOAT_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val1=atof(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case VECTOR_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val1=atof(line); if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val2=atof(line); if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val3=atof(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case STRING_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; strcpy(node_data.str_val,line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(FindMessageInList(node_data.str_val)==NULL) { if(strcmp(node_data.str_val,NOT_SPECIFIED_MSG)!=0) ScriptFileParseError(INVALID_MSGID_ERR,linenum,scriptID,line); strcpy(node_data.str_val,""); } add_node=TRUE; break; case PERCENTAGE_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.float_val1=atof(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case ENUM_PARAMETER_TYPE: if(version>=2) { if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); } else { node_data.subID=USE_ENUM_VALUE; } if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case SCRIPT_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case SOUND_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(index>=0 && index= 0) { strcpy(node_data.str_val,m_SoundList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Sound",m_SoundList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } add_node=TRUE; break; case SPECNAME_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(index>=0 && index=0 && index= 0) { strcpy(node_data.str_val,m_TextureList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Texture",m_TextureList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } add_node=TRUE; break; case FLAG_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.int_val=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); add_node=TRUE; break; case PATH_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(index>=0 && index= 0) { strcpy(node_data.str_val,m_PathList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Path",m_PathList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } add_node=TRUE; break; case MATCEN_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(index>=0 && index= 0) { strcpy(node_data.str_val,m_MatcenList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Matcen",m_MatcenList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } add_node=TRUE; break; case LEVEL_GOAL_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; node_data.subID=atoi(line); if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(index>=0 && index= 0) { strcpy(node_data.str_val,m_GoalList[index]); } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); SpecialScriptFileParseError(linenum,scriptID,"Level Goal",m_GoalList[index]); } } else { node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); } add_node=TRUE; break; case STRM_AUDIO_PARAMETER_TYPE: if((line=strtok(NULL,":"))==NULL) return NULL; index=atoi(line); if((line=strtok(NULL,""))==NULL) return NULL; strcpy(node_data.name,line); if(index>=0 && indextype==EXPRESSION_NODE) return(ValidateQueryNode(node,linenum)); if(data->type==ACTION_STATEMENT_NODE) return(ValidateActionNode(node,linenum)); return TRUE; } // Reads in the message list from a file int CDallasMainDlg::ParseMsgTableFile(char *filename) { CFILE *infile; char filebuffer[MAX_MSG_FILE_BUFFER_LEN]; char *line, *msg_start; int line_num; bool next_msgid_found; char fullpath[_MAX_PATH]; ddio_MakePath(fullpath,LocalScriptDir,filename,NULL); // Try to open the file for loading infile=cfopen (fullpath,"rt"); if (!infile) { CString msg; msg.Format("Unable to open \"%s\"!",filename); MessageBox(msg,"Script Message File Error!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } line_num=0; next_msgid_found=FALSE; // Read in and parse each line of the file while (!cfeof(infile)) { // Clear the buffer strcpy(filebuffer,""); // Read in a line from the file cf_ReadString(filebuffer, MAX_MSG_FILE_BUFFER_LEN, infile); line_num++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(filebuffer); line=SkipInitialWhitespace(filebuffer); // If line is a comment, or empty, discard it if(strlen(line)==0 || strncmp(line,"//",2)==0) continue; if(!next_msgid_found) { // Parse out the last message ID number // Grab the first keyword, make sure it's valid line=strtok(line,WHITESPACE_CHARS); if(line==NULL || strcmp(line,NEXT_MSG_ID_NUM_KEYWORD)!=0) continue; // Grab the second keyword, and assign it as the next message ID line=strtok(NULL,WHITESPACE_CHARS); if(line==NULL) continue; m_NextMessageID=atoi(line); next_msgid_found=TRUE; } else { // Parse line as a message line // Find the start of message, and mark it msg_start=strchr(line,'='); if(msg_start==NULL) continue; msg_start[0]='\0'; msg_start++; // Add the message to the list AddToMessageList(line,msg_start); } } cfclose(infile); return TRUE; } /////////////////////////////////// // Custom Script Block Functions /////////////////////////////////// // Initializes the data storage space void CDallasMainDlg::InitCustomScriptStorage(void) { m_CustomScriptLines=NULL; m_NumCustomScriptLines=0; m_MaxNumCustomScriptLines=0; } // Clears any memory allocated for storage void CDallasMainDlg::ClearCustomScriptStorage(void) { // Clear all the lines for(int j=0;j0) { m_CustomScriptLines=(char **)mem_malloc(sizeof(char *)*m_MaxNumCustomScriptLines); if(m_CustomScriptLines==NULL) { MessageBox("ERROR: Ran out of memory allocating custom script block","Custom Script Parse Error",MB_OK|MB_ICONEXCLAMATION); cfclose(infile); return FALSE; } } // Read all the lines in the block while (!done && !cfeof(infile)) { strcpy(linebuf,""); cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Check for End of Script Block Section if (strncmp(linebuf,CUSTOM_SCRIPT_BLOCK_END_TAG,strlen(CUSTOM_SCRIPT_BLOCK_END_TAG)) == 0) { done=true; continue; } // Store this line if(m_NumCustomScriptLines < m_MaxNumCustomScriptLines) { m_CustomScriptLines[m_NumCustomScriptLines]=(char *)mem_malloc(strlen(linebuf)+1); if(m_CustomScriptLines[m_NumCustomScriptLines]==NULL) { MessageBox("ERROR: Ran out of memory parsing custom script block","Custom Script Parse Error",MB_OK|MB_ICONEXCLAMATION); cfclose(infile); return FALSE; } strcpy(m_CustomScriptLines[m_NumCustomScriptLines],linebuf); m_NumCustomScriptLines++; } else { MessageBox("ERROR: The maximum custom script block line limit has been exceeded.\n\nThe excess lines will not be saved.","Custom Script Parse Error",MB_OK|MB_ICONEXCLAMATION); done=TRUE; } } if (!done) ScriptFileParseError(UEOS_ERR,linenum,0,NULL); } } cfclose(infile); return TRUE; } // Writes out the custom script block void CDallasMainDlg::WriteCustomScriptBlock(void) { if(CurrentOutputFile==NULL) return; // Create the valid event case statements O((" ")); O(("// ===============================================================")); O(("// Start of Custom Script Block - DO NOT EDIT ANYTHING BEFORE THIS")); O(("// ===============================================================")); O(("%s",CUSTOM_SCRIPT_BLOCK_START_TAG)); if(m_NumCustomScriptLines==0) { O((" ")); O(("// Enter your custom script code here")); O((" ")); } else { for(int j=0;jname,msg_data->message); cf_WriteString(outfile,buffer.GetBuffer(0)); } } cfclose(outfile); return TRUE; } // Writes out a series of tabs to the CurrentOutputFile void CDallasMainDlg::TabOver(void) { int j; if(CurrentOutputFile==NULL) return; for(j=0;j")); O(("#include ")); O(("#include ")); O(("#include ")); O(("#include \"osiris_import.h\"")); O(("#include \"osiris_common.h\"")); O(("#include \"%s\"",DALLASFUNCS_FILENAME)); 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);")); 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 );")); O(("int STDCALL SaveRestoreState( void *file_ptr, uint8_t saving_state );")); O(("#ifdef __cplusplus")); O(("}")); O(("#endif")); O(("")); // Write out the script ID list O(("// =================")); O(("// Script ID Numbers")); O(("// =================")); counter=0x000; // Write out the level ID O(("#define %s 0x%03x",LEVEL_ID_NAME,counter++)); O(("")); // Write out the custom object ID's (and count the number of custom object scripts) num_CO_scripts=0; for(j=0;jtype==SCRIPT_HEADER_NODE) { O(("int %s = 0;",CreateScriptGlobalCtrName(data->ID))); } script_node=m_ScriptTree.GetNextSiblingItem(script_node); } O((" ")); O(("// ========================================")); O(("// Function to Clear Global Action Counters")); O(("// ========================================")); O(("void ClearGlobalActionCtrs(void)")); O(("{")); // Write out the clear script statements script_node=m_ScriptTree.GetChildItem(TVI_ROOT); while(script_node!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { O((" %s = 0;",CreateScriptGlobalCtrName(data->ID))); } script_node=m_ScriptTree.GetNextSiblingItem(script_node); } O(("}")); O((" ")); O(("// ========================================")); O(("// Function to Save Global Action Counters")); O(("// ========================================")); O(("void SaveGlobalActionCtrs(void *file_ptr)")); O(("{")); // Write out the clear script statements script_node=m_ScriptTree.GetChildItem(TVI_ROOT); while(script_node!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { O((" File_WriteInt(%s,file_ptr);",CreateScriptGlobalCtrName(data->ID))); } script_node=m_ScriptTree.GetNextSiblingItem(script_node); } O(("}")); O((" ")); O(("// ===========================================")); O(("// Function to Restore Global Action Counters")); O(("// ===========================================")); O(("void RestoreGlobalActionCtrs(void *file_ptr)")); O(("{")); // Write out the clear script statements script_node=m_ScriptTree.GetChildItem(TVI_ROOT); while(script_node!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { O((" %s=File_ReadInt(file_ptr);",CreateScriptGlobalCtrName(data->ID))); } script_node=m_ScriptTree.GetNextSiblingItem(script_node); } O(("}")); O((" ")); // Write out the Custom Script Block WriteCustomScriptBlock(); O((" ")); O(("// =================")); O(("// Message File Data")); O(("// =================")); O((" ")); O(("#define MAX_SCRIPT_MESSAGES 256")); O(("#define MAX_MSG_FILEBUF_LEN 1024")); O(("#define NO_MESSAGE_STRING \"*Message Not Found*\"")); O(("#define INV_MSGNAME_STRING \"*Message Name Invalid*\"")); O(("#define WHITESPACE_CHARS \" \\t\\r\\n\"")); O((" ")); O(("// Structure for storing a script message")); O(("typedef struct {")); O((" char *name; // the name of the message")); O((" char *message; // the actual message text")); O(("} tScriptMessage;")); O((" ")); O(("// Global storage for level script messages")); O(("tScriptMessage *message_list[MAX_SCRIPT_MESSAGES];")); O(("int num_messages;")); O((" ")); O(("// ======================")); O(("// Message File Functions")); O(("// ======================")); O((" ")); O(("// Initializes the Message List")); O(("void InitMessageList(void)")); O(("{")); O((" for(int j=0;jname);")); O((" free(message_list[j]->message);")); O((" free(message_list[j]);")); O((" message_list[j]=NULL;")); O((" }")); O((" num_messages=0;")); O(("}")); O((" ")); O(("// Adds a message to the list")); O(("int AddMessageToList(char *name, char *msg)")); O(("{")); O((" int pos;")); O((" ")); O((" // Make sure there is room in the list")); O((" if(num_messages>=MAX_SCRIPT_MESSAGES) return false;")); O((" ")); O((" // Allocate memory for this message entry")); O((" pos=num_messages;")); O((" message_list[pos]=(tScriptMessage *)malloc(sizeof(tScriptMessage));")); O((" if(message_list[pos]==NULL) return false;")); O((" ")); O((" // Allocate memory for the message name")); O((" message_list[pos]->name=(char *)malloc(strlen(name)+1);")); O((" if(message_list[pos]->name==NULL) {")); O((" free(message_list[pos]);")); O((" return false;")); O((" }")); O((" strcpy(message_list[pos]->name,name);")); O((" ")); O((" // Allocate memory for the message name")); O((" message_list[pos]->message=(char *)malloc(strlen(msg)+1);")); O((" if(message_list[pos]->message==NULL) {")); O((" free(message_list[pos]->name);")); O((" free(message_list[pos]);")); O((" return false;")); O((" }")); O((" strcpy(message_list[pos]->message,msg);")); O((" num_messages++;")); O((" ")); O((" return true;")); O(("}")); O((" ")); O(("// Removes any whitespace padding from the end of a string")); O(("void RemoveTrailingWhitespace(char *s)")); O(("{")); O((" int last_char_pos;")); O((" ")); O((" last_char_pos=strlen(s)-1;")); O((" while(last_char_pos>=0 && isspace(s[last_char_pos])) {")); O((" s[last_char_pos]='\\0';")); O((" last_char_pos--;")); O((" }")); O(("}")); O((" ")); O(("// Returns a pointer to the first non-whitespace char in given string")); O(("char *SkipInitialWhitespace(char *s)")); O(("{")); O((" while((*s)!='\\0' && isspace(*s)) ")); O((" s++;")); O((" ")); O((" return(s);")); O(("}")); O((" ")); O(("// Read in the Messages")); O(("int ReadMessageFile(char *filename)")); O(("{")); O((" void *infile;")); O((" char filebuffer[MAX_MSG_FILEBUF_LEN+1];")); O((" char *line, *msg_start;")); O((" int line_num;")); O((" bool next_msgid_found;")); O((" ")); O((" // Try to open the file for loading")); O((" infile=File_Open(filename,\"rt\");")); O((" if (!infile) return false;")); O((" ")); O((" line_num=0;")); O((" next_msgid_found=true;")); O((" ")); O((" // Clear the message list")); O((" ClearMessageList();")); O((" ")); O((" // Read in and parse each line of the file")); O((" while (!File_eof(infile)) {")); O((" ")); O((" // Clear the buffer")); O((" strcpy(filebuffer,\"\");")); O((" ")); O((" // Read in a line from the file")); O((" File_ReadString(filebuffer, MAX_MSG_FILEBUF_LEN, infile);")); O((" line_num++;")); O((" ")); O((" // Remove whitespace padding at start and end of line")); O((" RemoveTrailingWhitespace(filebuffer);")); O((" line=SkipInitialWhitespace(filebuffer);")); O((" ")); O((" // If line is a comment, or empty, discard it")); O((" if(strlen(line)==0 || strncmp(line,\"//\",2)==0)")); O((" continue;")); O((" ")); O((" if(!next_msgid_found) { // Parse out the last message ID number")); O((" ")); O((" // Grab the first keyword, make sure it's valid")); O((" line=strtok(line,WHITESPACE_CHARS);")); O((" if(line==NULL) continue;")); O((" ")); O((" // Grab the second keyword, and assign it as the next message ID")); O((" line=strtok(NULL,WHITESPACE_CHARS);")); O((" if(line==NULL) continue;")); O((" ")); O((" next_msgid_found=true;")); O((" }")); O((" else { // Parse line as a message line")); O((" ")); O((" // Find the start of message, and mark it")); O((" msg_start=strchr(line,'=');")); O((" if(msg_start==NULL) continue;")); O((" msg_start[0]='\\0';")); O((" msg_start++;")); O((" ")); O((" // Add the message to the list")); O((" AddMessageToList(line,msg_start);")); O((" }")); O((" }")); O((" File_Close(infile);")); O((" ")); O((" return true;")); O(("}")); O((" ")); O(("// Find a message")); O(("const char *GetMessage(const char *name)")); O(("{")); O((" // Make sure given name is valid")); O((" if(name==NULL) return INV_MSGNAME_STRING;")); O((" ")); O((" // Search message list for name")); O((" for(int j=0;jname,name)==0) return(message_list[j]->message);")); O((" ")); O((" // Couldn't find it")); O((" return NO_MESSAGE_STRING;")); O(("}")); O((" ")); // Write out the global name arrays WriteNameListArrays(); O(("// ===============")); O(("// InitializeDLL()")); O(("// ===============")); O(("char STDCALL InitializeDLL(tOSIRISModuleInit *func_list)")); O(("{")); O((" osicommon_Initialize((tOSIRISModuleInit *)func_list);")); #ifndef NEWEDITOR 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((" }")); #endif O((" ")); O((" ClearGlobalActionCtrs();")); O((" dfInit();")); O((" InitMessageList();")); O((" ")); O((" // Build the filename of the message file")); O((" char filename[_MAX_PATH+1];")); O((" char english_filename[_MAX_PATH+1];")); O((" int lang_type;")); O((" if(func_list->script_identifier!=NULL) {")); O((" _splitpath(func_list->script_identifier,NULL,NULL,filename,NULL);")); O((" sprintf(english_filename,\"%%s.msg\",filename);")); O((" lang_type=Game_GetLanguage();")); O((" if(lang_type==LANGUAGE_FRENCH) strcat(filename,\"_FRN\");")); O((" else if(lang_type==LANGUAGE_GERMAN) strcat(filename,\"_GER\");")); O((" else if(lang_type==LANGUAGE_ITALIAN) strcat(filename,\"_ITN\");")); O((" else if(lang_type==LANGUAGE_SPANISH) strcat(filename,\"_SPN\");")); O((" else if(lang_type==LANGUAGE_POLISH) strcat(filename,\"_POL\");")); O((" strcat(filename,\".msg\");")); O((" }")); O((" else {")); O((" strcpy(filename,\"%s\");",m_ScriptMessagesFilename.GetBuffer(0))); O((" lang_type=LANGUAGE_ENGLISH;")); O((" }")); O((" if(!ReadMessageFile(filename)) {")); O((" if(lang_type == LANGUAGE_ENGLISH) {")); O((" mprintf(0,\"ERROR: Could not load message file - %%s\\n\",filename);")); O((" }")); O((" else if(!ReadMessageFile(english_filename)) {")); O((" mprintf(0,\"ERROR: Could not load message file - %%s\\n\",english_filename);")); O((" }")); O((" }")); O((" ")); // Write out the name array lookup code WriteNameArrayLookupCode(); O((" ")); O((" return 1;")); O(("}")); O(("")); O(("// =============")); O(("// ShutdownDLL()")); O(("// =============")); O(("void STDCALL ShutdownDLL(void)")); O(("{")); O((" ClearMessageList();")); O(("}")); O(("")); O(("// ===============")); O(("// GetGOScriptID()")); O(("// ===============")); O(("int STDCALL GetGOScriptID(const char *name,uint8_t isdoor)")); O(("{")); O((" return -1;")); O(("}")); O(("")); O(("// ================")); O(("// CreateInstance()")); O(("// ================")); O(("void STDCALLPTR CreateInstance(int id)")); O(("{")); O((" switch(id) {")); // Level Case O((" case %s:",LEVEL_ID_NAME)); O((" return new %s;",LEVEL_CLASS_NAME)); O((" break;")); // Custom object Cases for(j=0;jCallEvent(event,data);")); O((" break;")); O((" default:")); O((" mprintf(0,\"SCRIPT: Illegal ID (%%d)\\n\",id);")); O((" break;")); O((" }")); O((" return CONTINUE_CHAIN|CONTINUE_DEFAULT;")); O(("}")); O(("")); O(("// ==================")); O(("// SaveRestoreState()")); O(("// ==================")); O(("int STDCALL SaveRestoreState( void *file_ptr, uint8_t saving_state )")); O(("{")); O((" return 0;")); O(("}")); O(("")); O(("// ====================")); O(("// GetTriggerScriptID()")); O(("// ====================")); O(("int STDCALL GetTriggerScriptID(int trigger_room,int trigger_face)")); O(("{")); // Trigger ID Listing for(j=0;j=0 && t=0) { troom_text.Format("Trigger_rooms[%d]",index); tface_text.Format("Trigger_faces[%d]",index); } } O((" if(trigger_room==%s && trigger_face==%s)",troom_text.GetBuffer(0),tface_text.GetBuffer(0))); O((" return %s;",CreateScriptConstantName(j))); O((" ")); } O((" return -1;")); O(("}")); O(("")); O(("// =================")); O(("// GetCOScriptList()")); O(("// =================")); O(("int STDCALL GetCOScriptList( int **list, int **id_list )")); O(("{")); if(num_CO_scripts==0) { O((" static int *cust_handle_list=NULL;")); O((" static int *cust_id_list=NULL;")); } else { O((" static int cust_handle_list[%d];",num_CO_scripts)); O((" static int cust_id_list[%d] = { ",num_CO_scripts)); // Write out the custom object IDs counter=0; for(j=0;jtype!=OBJ_NONE && objp->name!=NULL) { int index=FindObjectInList(objp->name); if(index>=0 && strlen(objp->name)!=0) handle_text.Format("Object_handles[%d]",index); } if(counter==0) O((" // Fill in the custom handle list")); O((" cust_handle_list[%d]=%s;",counter,handle_text.GetBuffer(0))); counter++; } O(("")); O((" *list = cust_handle_list;")); O((" *id_list = cust_id_list;")); O(("")); O((" return %d;",num_CO_scripts)); O(("}")); O(("")); O(("//=======================")); O(("// Script Implementation ")); O(("//=======================")); O(("")); O(("BaseScript::BaseScript()")); O(("{")); O(("}")); O(("")); O(("BaseScript::~BaseScript()")); O(("{")); O(("}")); O(("")); O(("int16_t BaseScript::CallEvent(int event,tOSIRISEventInfo *data)")); O(("{")); O((" mprintf(0,\"BaseScript::CallEvent()\\n\");")); O((" return CONTINUE_CHAIN|CONTINUE_DEFAULT;")); O(("}")); O(("")); // Create the Level Script Class' CallEvent() method O(("int16_t %s::CallEvent(int event,tOSIRISEventInfo *data)",LEVEL_CLASS_NAME)); O(("{")); O((" switch(event) { ")); // Find the level script group (if it exists) tScriptOwnerGroup *owner_group=NULL;; for(j=0;jevt_savestate;")); O((" ")); O((" SaveGlobalActionCtrs(event_data->fileptr);")); O((" dfSave(event_data->fileptr);")); O(("#ifdef ENABLE_CUSTOM_SAVE_AND_RESTORE")); O((" dsCustomSave(event_data->fileptr);")); O(("#endif")); O((" }")); O((" break;")); // Handle the loading event O((" case EVT_RESTORESTATE:")); O((" {")); O((" tOSIRISEVTRESTORESTATE *event_data=&data->evt_restorestate;")); O((" ")); O((" RestoreGlobalActionCtrs(event_data->fileptr);")); O((" dfRestore(event_data->fileptr);")); O(("#ifdef ENABLE_CUSTOM_SAVE_AND_RESTORE")); O((" dsCustomRestore(event_data->fileptr);")); O(("#endif")); O((" }")); O((" break;")); // Create the valid event case statements for(j=0;jevent_sections[j]; else event_section=NULL; // See if this case has certain events if(j!=LEVEL_START_EVENT_TYPE && (event_section==NULL || event_section->num_script_nodes==0)) continue; O((" case %s:",GetEventCodeName(j))); O((" {")); // Get the event data code line and write it out O((" %s",GetEventDataLine(j))); // If it's a LEVEL STARTED event, then initialize all the data if(j==LEVEL_START_EVENT_TYPE) { O((" ")); O((" ClearGlobalActionCtrs();")); O((" dfInit();")); } // If it's a DESTROYED event, then add the conditional code to // break out if the object is being destroyed because the level is ending if(j==DESTROYED_EVENT_TYPE) { O((" ")); O((" // If destroy event is due to level ending, don't run scripts")); O((" if(!event_data->is_dying) break;")); } // If there is an owner group, do the scripts if(event_section!=NULL) { // Write out all the scripts for this event case for(k=0;knum_script_nodes;k++) WriteScriptCode(event_section->script_node_list[k]); } O((" }")); O((" break;")); } } // Creates the event cases void CDallasMainDlg::CreateEventCases(tScriptOwnerGroup *owner_group) { int j,k; if(CurrentOutputFile==NULL || owner_group==NULL) return; // Create the valid event case statements for(j=0;jevent_sections[j]; if(event_section->num_script_nodes==0) continue; O((" case %s:",GetEventCodeName(j))); O((" {")); // Get the event data code line and write it out O((" %s",GetEventDataLine(j))); // If it's a DESTROYED event, then add the conditional code to // break out if the object is being destroyed because the level is ending if(j==DESTROYED_EVENT_TYPE) { O((" ")); O((" // If destroy event is due to level ending, don't run scripts")); O((" if(!event_data->is_dying) break;")); } // Write out all the scripts for this event case for(k=0;knum_script_nodes;k++) WriteScriptCode(event_section->script_node_list[k]); O((" }")); O((" break;")); } } // Writes out the code for the given script (handles the top level IF-THEN) void CDallasMainDlg::WriteScriptCode(HTREEITEM script_node) { HTREEITEM conditional_header_node, action_header_node; tTreeNodeData *data; if(CurrentOutputFile==NULL || script_node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); if(data==NULL || data->type!=SCRIPT_HEADER_NODE) return; // Comment this section of script O((" ")); O((" // Script %03d: %s",data->ID,data->name)); // Set the tab level CurrentTabLevel=4; // Write out the top level conditional statement conditional_header_node=GetConditionalHeaderNode(script_node); WriteConditionalCodeBlock(conditional_header_node); // Write out the top level action block action_header_node=GetActionHeaderNode(script_node); WriteActionCodeBlock(action_header_node); } // Writes out the code body for a conditional header block (an IF statement) void CDallasMainDlg::WriteConditionalCodeBlock(HTREEITEM conditional_header_node) { tTreeNodeData *data, *action_hdr_data; HTREEITEM child_node, action_hdr_node; if(CurrentOutputFile==NULL || conditional_header_node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(conditional_header_node); if(data==NULL || data->type!=CONDITIONAL_HEADER_NODE) return; // Get the first child (literal or query) child_node=m_ScriptTree.GetChildItem(conditional_header_node); if(child_node==NULL) return; TabOver(); cfprintf(CurrentOutputFile,"if("); // Write out the max script execution times conditional (if it's not infinite) action_hdr_data=NULL; if(data->ID==TOP_LEVEL) { action_hdr_node=GetActionHeaderNode(conditional_header_node); if(action_hdr_node!=NULL) { action_hdr_data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_hdr_node); if(action_hdr_data!=NULL && action_hdr_data->subID!=0) { CString tmp_name=CreateScriptGlobalCtrName(GetScriptID(action_hdr_node)); cfprintf(CurrentOutputFile,"(%s < %d) && (",tmp_name.GetBuffer(0),action_hdr_data->subID); } } } // Write out the conditional expressions WriteLogicalOpExpression(child_node); // If max script execution expression was added, then tack on another parentheses if(action_hdr_data!=NULL && action_hdr_data->subID!=0) { cfprintf(CurrentOutputFile,")"); } O((")")); } // Writes out a logical operation block (AND, OR) void CDallasMainDlg::WriteLogicalOpExpression(HTREEITEM logop_node) { tTreeNodeData *data; HTREEITEM child_node; if(CurrentOutputFile==NULL || logop_node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(logop_node); if(data==NULL || (data->type!=LOGICAL_OPERATOR_NODE && data->type!=CONDITIONAL_STATEMENT_NODE)) return; // If it's a Condition, write it out if(data->type==CONDITIONAL_STATEMENT_NODE) { WriteConditionalStatement(logop_node); return; } // If it's an AND or an OR, process it if(data->ID==AND_TYPE || data->ID==OR_TYPE) { child_node=m_ScriptTree.GetChildItem(logop_node); while(child_node!=NULL) { cfprintf(CurrentOutputFile,"("); WriteLogicalOpExpression(child_node); cfprintf(CurrentOutputFile,")"); child_node=m_ScriptTree.GetNextSiblingItem(child_node); if(child_node!=NULL) { if(data->ID==AND_TYPE) cfprintf(CurrentOutputFile," && "); else cfprintf(CurrentOutputFile," || "); } } } } // Writes out a conditional statement void CDallasMainDlg::WriteConditionalStatement(HTREEITEM condition_node) { tTreeNodeData *data; HTREEITEM child_node; if(CurrentOutputFile==NULL || condition_node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(condition_node); if(data==NULL || data->type!=CONDITIONAL_STATEMENT_NODE) return; // If it's an ALWAYS statement, just write out a 1 and get outta here if(data->ID==ALWAYS_STATEMENT) { cfprintf(CurrentOutputFile,"1"); return; } // Get the first child (literal or query) child_node=m_ScriptTree.GetChildItem(condition_node); if(child_node!=NULL) { WriteFunctionParameter(child_node); } else { cfprintf(CurrentOutputFile,"???"); } // Get the second child (expression operator) if(child_node!=NULL) { child_node=m_ScriptTree.GetNextSiblingItem(child_node); if(child_node!=NULL) { tTreeNodeData *child_data; child_data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); if(child_data!=NULL && child_data->type==EXPRESSION_OPERATOR_NODE) { cfprintf(CurrentOutputFile,"%s",GetExpressionOperatorCodeName(child_data->subID)); } else cfprintf(CurrentOutputFile,"/* Exp Op Error */"); } else { cfprintf(CurrentOutputFile,"/* Exp Op Missing */"); } } // If it's a comparison, get the third child (literal or query) if(child_node!=NULL && data->ID==COMPARISON_STATEMENT) { child_node=m_ScriptTree.GetNextSiblingItem(child_node); if(child_node!=NULL) { WriteFunctionParameter(child_node); } else { cfprintf(CurrentOutputFile,"/* 2nd Comparison Value Missing */"); } } } // Writes out a query function call void CDallasMainDlg::WriteQueryFunctionCall(HTREEITEM query_node) { tTreeNodeData *data; if(CurrentOutputFile==NULL || query_node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); if(data==NULL || data->type!=EXPRESSION_NODE) return; // Check Query ID validity if(data->ID<0 || data->ID>=m_NumQueries) { cfprintf(CurrentOutputFile,"/* ERROR: Invalid Query Function Encountered!!! */"); return; } // Handle the DALLAS custom queries first if(strcmp(m_QueryDatabase[data->ID].func,"qScriptExecuted_DALLAS")==0) { HTREEITEM child_node; tTreeNodeData *child_data; child_node=m_ScriptTree.GetChildItem(query_node); if(child_node==NULL) return; child_data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); if(child_data==NULL || child_data->type!=PARAMETER_NODE || child_data->ID!=SCRIPT_PARAMETER_TYPE) return; CString tmp_name=CreateScriptGlobalCtrName(child_data->int_val); cfprintf(CurrentOutputFile,"(%s > 0)",tmp_name.GetBuffer(0)); return; } if(strcmp(m_QueryDatabase[data->ID].func,"qTimesScriptExecuted_DALLAS")==0) { HTREEITEM child_node; tTreeNodeData *child_data; child_node=m_ScriptTree.GetChildItem(query_node); if(child_node==NULL) return; child_data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); if(child_data==NULL || child_data->type!=PARAMETER_NODE || child_data->ID!=SCRIPT_PARAMETER_TYPE) return; CString tmp_name=CreateScriptGlobalCtrName(child_data->int_val); cfprintf(CurrentOutputFile,"%s",tmp_name.GetBuffer(0)); return; } // Write out the function name cfprintf(CurrentOutputFile,"%s(",m_QueryDatabase[data->ID].func); // Write out the parameter arguments HTREEITEM param_node; param_node=m_ScriptTree.GetChildItem(query_node); while(param_node!=NULL) { WriteFunctionParameter(param_node); param_node=m_ScriptTree.GetNextSiblingItem(param_node); if(param_node!=NULL) cfprintf(CurrentOutputFile,", "); } cfprintf(CurrentOutputFile,")"); } // Writes out the code body for an action header block (the block to immediately follow an IF statement) void CDallasMainDlg::WriteActionCodeBlock(HTREEITEM action_header_node) { HTREEITEM child_node; tTreeNodeData *header_data, *data; if(action_header_node==NULL) return; header_data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_header_node); if(header_data==NULL || header_data->type!=ACTIONS_HEADER_NODE) return; // Write out starting brace TabOver(); if(header_data->ID==NESTED && header_data->subID==ELSE_CLAUSE) O(("else {")); else O(("{")); CurrentTabLevel++; child_node=m_ScriptTree.GetChildItem(action_header_node); while(child_node!=NULL) { // Get the type of child node this is data=(tTreeNodeData *)m_ScriptTree.GetItemData(child_node); if(data != NULL) { if(data->type==ACTION_STATEMENT_NODE) { WriteActionFunctionCall(child_node); } else if(data->type==CONDITIONAL_HEADER_NODE) { WriteConditionalCodeBlock(child_node); } else if(data->type==ACTIONS_HEADER_NODE) { WriteActionCodeBlock(child_node); } } // Get the next node child_node=m_ScriptTree.GetNextSiblingItem(child_node); } // If it's a top level action header node, increment the global counter if(header_data->ID==TOP_LEVEL) { CString tmp_name=CreateScriptGlobalCtrName(GetScriptID(action_header_node)); TabOver(); O(("")); TabOver(); O(("// Increment the script action counter")); TabOver(); O(("if(%s < MAX_ACTION_CTR_VALUE) %s++;",tmp_name.GetBuffer(0),tmp_name.GetBuffer(0))); // If user wants to break script chain, do it here if(header_data->int_val==BREAK_SCRIPT_CHAIN) { TabOver(); O(("")); TabOver(); O(("return CONTINUE_DEFAULT;")); } } CurrentTabLevel--; // Write out closing brace TabOver(); O(("}")); } // Writes out an action function call void CDallasMainDlg::WriteActionFunctionCall(HTREEITEM action_node) { tTreeNodeData *data; if(CurrentOutputFile==NULL || action_node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); if(data==NULL || data->type!=ACTION_STATEMENT_NODE) return; // Check Action ID validity if(data->ID<0 || data->ID>=m_NumActions) { if(data->ID != DO_NOTHING_ID) { TabOver(); O(("// ERROR: Invalid Action Function Encountered!!!")); } return; } // Write out the function name TabOver(); cfprintf(CurrentOutputFile,"%s(",m_ActionDatabase[data->ID].func); // Write out the parameter arguments HTREEITEM param_node; param_node=m_ScriptTree.GetChildItem(action_node); while(param_node!=NULL) { WriteFunctionParameter(param_node); param_node=m_ScriptTree.GetNextSiblingItem(param_node); if(param_node!=NULL) cfprintf(CurrentOutputFile,", "); } O((");")); } // Writes out an action function call void CDallasMainDlg::WriteFunctionParameter(HTREEITEM param_node) { tTreeNodeData *data; int index; if(CurrentOutputFile==NULL || param_node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(param_node); if(data==NULL || (data->type!=PARAMETER_NODE && data->type!=EXPRESSION_NODE)) return; // If it's a query, write out the query function if(data->type==EXPRESSION_NODE) { WriteQueryFunctionCall(param_node); return; } // Output the parameter values switch(data->ID) { case DOOR_PARAMETER_TYPE: if(data->subID == USE_IT_HANDLE) cfprintf(CurrentOutputFile,"event_data->it_handle"); else if(data->subID == USE_ME_HANDLE) cfprintf(CurrentOutputFile,"data->me_handle"); else { int index=FindDoorInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",OBJECT_HANDLE_NONE); else cfprintf(CurrentOutputFile,"Door_handles[%d]",index); } break; case OBJECT_PARAMETER_TYPE: if(data->subID == USE_IT_HANDLE) cfprintf(CurrentOutputFile,"event_data->it_handle"); else if(data->subID == USE_ME_HANDLE) cfprintf(CurrentOutputFile,"data->me_handle"); else { int index=FindObjectInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",OBJECT_HANDLE_NONE); else cfprintf(CurrentOutputFile,"Object_handles[%d]",index); } break; case ROOM_PARAMETER_TYPE: index=FindRoomInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",-1); else cfprintf(CurrentOutputFile,"Room_indexes[%d]",index); break; case TRIGGER_PARAMETER_TYPE: index=FindTriggerInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",-1); else cfprintf(CurrentOutputFile,"Trigger_indexes[%d]",index); break; case INT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%d",data->int_val); break; case BOOL_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%d",data->int_val); break; case FLOAT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%ff",data->float_val1); break; case VECTOR_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"NO VECTOR YET"); break; case STRING_PARAMETER_TYPE: index=FindMessageNameInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"\"*MESSAGE_ERROR*\""); else cfprintf(CurrentOutputFile,"Message_strings[%d]",index); break; case PERCENTAGE_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%ff",data->float_val1); break; case ENUM_PARAMETER_TYPE: if(data->subID == USE_GOALID_VALUE) cfprintf(CurrentOutputFile,"event_data->goal_uid"); else if(data->subID == USE_TIMERID_VALUE) cfprintf(CurrentOutputFile,"event_data->id"); else if(data->subID == USE_MATCENID_VALUE) cfprintf(CurrentOutputFile,"event_data->id"); else { cfprintf(CurrentOutputFile,"%d",data->int_val); } break; case SCRIPT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%d",data->int_val); break; case SOUND_PARAMETER_TYPE: index=FindSoundInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",-1); else cfprintf(CurrentOutputFile,"Sound_indexes[%d]",index); break; case SPECNAME_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"\"%s\"",data->str_val); break; case TEXTURE_PARAMETER_TYPE: index=FindTextureInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",-1); else cfprintf(CurrentOutputFile,"Texture_indexes[%d]",index); break; case FLAG_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%d",data->int_val); break; case PATH_PARAMETER_TYPE: index=FindPathInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",-1); else cfprintf(CurrentOutputFile,"Path_indexes[%d]",index); break; case MATCEN_PARAMETER_TYPE: if(data->subID == USE_MATCEN_EVENT_ID) { cfprintf(CurrentOutputFile,"event_data->id"); } else { index=FindMatcenInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",-1); else cfprintf(CurrentOutputFile,"Matcen_indexes[%d]",index); } break; case LEVEL_GOAL_PARAMETER_TYPE: if(data->subID == USE_LEVEL_GOAL_ID) { cfprintf(CurrentOutputFile,"event_data->level_goal_index"); } else { index=FindGoalInList(data->str_val); if(index<0 || strlen(data->str_val)==0) cfprintf(CurrentOutputFile,"%d",-1); else cfprintf(CurrentOutputFile,"Goal_indexes[%d]",index); } break; case STRM_AUDIO_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"\"%s\"",data->str_val); break; default: break; } } // Creates the tree block (for saving scripts) void CDallasMainDlg::WriteScriptSaveBlock(void) { if(CurrentOutputFile==NULL) return; // Create the header O((" ")); O((" ")); O(("/*********************************************************")); O(("Script Save Block: DO NOT TOUCH ANYTHING IN THIS BLOCK!!! ")); O(("**********************************************************")); O(("%s",SCRIPT_BLOCK_START_TAG)); O((" ")); O(("VERSION %d",DALLAS_SAVE_VERSION)); O(("NEXT_ID %d",m_NextScriptID)); O((" ")); O(("// UserType value blocks")); // Writes out the name lists WriteUserTypeVals(); O((" ")); O(("// Name Lists")); // Writes out the name lists WriteNameLists(); O((" ")); O(("// Script Tree Dump")); // Write out the list of nodes WriteScriptTreeDump(); O((" ")); O(("%s",SCRIPT_BLOCK_END_TAG)); O(("*********************************************************/")); } // Writes out the UserType value blocks void CDallasMainDlg::WriteUserTypeVals(void) { int j,k; if(CurrentOutputFile==NULL) return; for(j=0;jvalue!=-1) O(("%d:%s",value_entry->value,value_entry->name)); } O(("%s",USERTYPE_VALS_END_TAG)); O((" ")); } } } // Writes out the name lists void CDallasMainDlg::WriteNameLists(void) { int j; if(CurrentOutputFile==NULL) return; // Write out the door list O(("%s",DOOR_LIST_START_TAG)); for(j=0;j0) { O(("const char *Door_names[NUM_DOOR_NAMES] = {")); for(j=0;j<(m_DoorListSize-1);j++) O((" \"%s\",",m_DoorList[j])); O((" \"%s\"",m_DoorList[j])); O(("};")); O(("int Door_handles[NUM_DOOR_NAMES];")); } else { O(("const char **Door_names=NULL;")); O(("int *Door_handles=NULL;")); } O((" ")); // Write out the object list O(("#define NUM_OBJECT_NAMES %d",m_ObjectListSize)); if(m_ObjectListSize>0) { O(("const char *Object_names[NUM_OBJECT_NAMES] = {")); for(j=0;j<(m_ObjectListSize-1);j++) O((" \"%s\",",m_ObjectList[j])); O((" \"%s\"",m_ObjectList[j])); O(("};")); O(("int Object_handles[NUM_OBJECT_NAMES];")); } else { O(("const char **Object_names=NULL;")); O(("int *Object_handles=NULL;")); } O((" ")); // Write out the room list O(("#define NUM_ROOM_NAMES %d",m_RoomListSize)); if(m_RoomListSize>0) { O(("const char *Room_names[NUM_ROOM_NAMES] = {")); for(j=0;j<(m_RoomListSize-1);j++) O((" \"%s\",",m_RoomList[j])); O((" \"%s\"",m_RoomList[j])); O(("};")); O(("int Room_indexes[NUM_ROOM_NAMES];")); } else { O(("const char **Room_names=NULL;")); O(("int *Room_indexes=NULL;")); } O((" ")); // Write out the Trigger list O(("#define NUM_TRIGGER_NAMES %d",m_TriggerListSize)); if(m_TriggerListSize>0) { O(("const char *Trigger_names[NUM_TRIGGER_NAMES] = {")); for(j=0;j<(m_TriggerListSize-1);j++) O((" \"%s\",",m_TriggerList[j])); O((" \"%s\"",m_TriggerList[j])); O(("};")); O(("int Trigger_indexes[NUM_TRIGGER_NAMES];")); O(("int Trigger_faces[NUM_TRIGGER_NAMES];")); O(("int Trigger_rooms[NUM_TRIGGER_NAMES];")); } else { O(("const char **Trigger_names=NULL;")); O(("int *Trigger_indexes=NULL;")); O(("int *Trigger_faces=NULL;")); O(("int *Trigger_rooms=NULL;")); } O((" ")); // Write out the sound list O(("#define NUM_SOUND_NAMES %d",m_SoundListSize)); if(m_SoundListSize>0) { O(("const char *Sound_names[NUM_SOUND_NAMES] = {")); for(j=0;j<(m_SoundListSize-1);j++) O((" \"%s\",",m_SoundList[j])); O((" \"%s\"",m_SoundList[j])); O(("};")); O(("int Sound_indexes[NUM_SOUND_NAMES];")); } else { O(("const char **Sound_names=NULL;")); O(("int *Sound_indexes=NULL;")); } O((" ")); // Write out the texture list O(("#define NUM_TEXTURE_NAMES %d",m_TextureListSize)); if(m_TextureListSize>0) { O(("const char *Texture_names[NUM_TEXTURE_NAMES] = {")); for(j=0;j<(m_TextureListSize-1);j++) O((" \"%s\",",m_TextureList[j])); O((" \"%s\"",m_TextureList[j])); O(("};")); O(("int Texture_indexes[NUM_TEXTURE_NAMES];")); } else { O(("const char **Texture_names=NULL;")); O(("int *Texture_indexes=NULL;")); } O((" ")); // Write out the Path list O(("#define NUM_PATH_NAMES %d",m_PathListSize)); if(m_PathListSize>0) { O(("const char *Path_names[NUM_PATH_NAMES] = {")); for(j=0;j<(m_PathListSize-1);j++) O((" \"%s\",",m_PathList[j])); O((" \"%s\"",m_PathList[j])); O(("};")); O(("int Path_indexes[NUM_PATH_NAMES];")); } else { O(("const char **Path_names=NULL;")); O(("int *Path_indexes=NULL;")); } O((" ")); // Write out the Matcen list O(("#define NUM_MATCEN_NAMES %d",m_MatcenListSize)); if(m_MatcenListSize>0) { O(("const char *Matcen_names[NUM_MATCEN_NAMES] = {")); for(j=0;j<(m_MatcenListSize-1);j++) O((" \"%s\",",m_MatcenList[j])); O((" \"%s\"",m_MatcenList[j])); O(("};")); O(("int Matcen_indexes[NUM_MATCEN_NAMES];")); } else { O(("const char **Matcen_names=NULL;")); O(("int *Matcen_indexes=NULL;")); } O((" ")); // Write out the Goal list O(("#define NUM_GOAL_NAMES %d",m_GoalListSize)); if(m_GoalListSize>0) { O(("const char *Goal_names[NUM_GOAL_NAMES] = {")); for(j=0;j<(m_GoalListSize-1);j++) O((" \"%s\",",m_GoalList[j])); O((" \"%s\"",m_GoalList[j])); O(("};")); O(("int Goal_indexes[NUM_GOAL_NAMES];")); } else { O(("const char **Goal_names=NULL;")); O(("int *Goal_indexes=NULL;")); } O((" ")); // Write out the message name list O(("#define NUM_MESSAGE_NAMES %d",m_MessageNameListSize)); if(m_MessageNameListSize>0) { O(("const char *Message_names[NUM_MESSAGE_NAMES] = {")); for(j=0;j<(m_MessageNameListSize-1);j++) O((" \"%s\",",m_MessageNameList[j])); O((" \"%s\"",m_MessageNameList[j])); O(("};")); O(("const char *Message_strings[NUM_MESSAGE_NAMES];")); } else { O(("const char **Message_names=NULL;")); O(("const char **Message_strings=NULL;")); } O((" ")); } // Writes out the name list lookup code void CDallasMainDlg::WriteNameArrayLookupCode(void) { O((" int j;")); O((" ")); O((" // Do Door Index lookups")); O((" for(j=0;jtype==SCRIPT_HEADER_NODE) { if(DALLAS_SAVE_VERSION>=1) WriteScriptNodeDump_v1U(node); else WriteScriptNodeDump_v0(node); WriteScriptChildrenDump(node); } node=m_ScriptTree.GetNextSiblingItem(node); } } // Writes out codes versions of all children of the given node void CDallasMainDlg::WriteScriptChildrenDump(HTREEITEM parent, bool filter_on/*=FALSE*/) { HTREEITEM child_node; if(CurrentOutputFile==NULL || parent==NULL) return; // Make sure the parent has at least one child child_node=m_ScriptTree.GetChildItem(parent); if(child_node==NULL) return; // Write out each child node (and any of their children) CurrentTabLevel++; TabOver(); O(("%s",CHILD_BLOCK_START_TAG)); while(child_node!=NULL) { if(DALLAS_SAVE_VERSION>=1) WriteScriptNodeDump_v1U(child_node,filter_on); else WriteScriptNodeDump_v0(child_node); WriteScriptChildrenDump(child_node,filter_on); child_node=m_ScriptTree.GetNextSiblingItem(child_node); } TabOver(); O(("%s",CHILD_BLOCK_END_TAG)); CurrentTabLevel--; } // VERSION 0: Writes out a coded version of the given script node void CDallasMainDlg::WriteScriptNodeDump_v0(HTREEITEM node) { tTreeNodeData *data; CString tmp_name; int index; char goal_name[MAX_PATH+1]; if(CurrentOutputFile==NULL || node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return; TabOver(); switch(data->type) { case SCRIPT_HEADER_NODE: cfprintf(CurrentOutputFile,"%02d:%d:%s", data->type, data->ID, data->name); break; case SCRIPT_OWNER_NODE: cfprintf(CurrentOutputFile,"%02d:%d:%d", data->type, data->ID, data->int_val); break; case SCRIPT_EVENT_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case CONDITIONAL_HEADER_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case ACTIONS_HEADER_NODE: cfprintf(CurrentOutputFile,"%02d:%d:%d", data->type, data->ID, data->subID); break; case CONDITIONAL_STATEMENT_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case EXPRESSION_NODE: cfprintf(CurrentOutputFile,"%02d:%s:%s", data->type, GetQueryFunc(data->ID), data->name); break; case EXPRESSION_OPERATOR_NODE: cfprintf(CurrentOutputFile,"%02d:%d:%d", data->type, data->ID, data->subID); break; case ACTION_STATEMENT_NODE: cfprintf(CurrentOutputFile,"%02d:%s", data->type, GetActionFunc(data->ID)); break; case LOGICAL_OPERATOR_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case PARAMETER_NODE: // Get image type based upon what kind of parameter it is switch(data->ID) { case DOOR_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, data->int_val, data->name); break; case OBJECT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, data->int_val, data->name); break; case ROOM_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case TRIGGER_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case INT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case BOOL_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case FLOAT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", data->type, data->ID, data->float_val1, data->name); break; case VECTOR_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%f:%f:%f:%s", data->type, data->ID, data->float_val1, data->float_val2, data->float_val3, data->name); break; case STRING_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%s:%s", data->type, data->ID, data->str_val, data->name); break; case PERCENTAGE_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", data->type, data->ID, data->float_val1, data->name); break; case ENUM_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case SCRIPT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case SOUND_PARAMETER_TYPE: if(data->int_val==NOT_SPECIFIED_TYPE) index=-1; else index=FindSoundInList(Sounds[data->int_val].name); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case SPECNAME_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%s:%s", data->type, data->ID, data->str_val, data->name); break; case TEXTURE_PARAMETER_TYPE: if(data->int_val==NOT_SPECIFIED_TYPE) index=-1; else index=FindTextureInList(GameTextures[data->int_val].name); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case FLAG_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case PATH_PARAMETER_TYPE: if(data->int_val==NOT_SPECIFIED_TYPE) index=-1; else index=FindPathInList(GamePaths[data->int_val].name); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case MATCEN_PARAMETER_TYPE: if(data->subID==USE_MATCEN_VALUE) { if(data->int_val==NOT_SPECIFIED_TYPE || !MatcenValid(data->int_val)) index=-1; else { char matcen_name[MAX_MATCEN_NAME_LEN+1]; Matcen[data->int_val]->GetName(matcen_name); index=FindMatcenInList(matcen_name); } } else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, index, data->name); break; case LEVEL_GOAL_PARAMETER_TYPE: if(data->subID==USE_LEVEL_GOAL_VALUE) { if(data->int_val==NOT_SPECIFIED_TYPE || Level_goals.GoalGetName(data->int_val,goal_name,MAX_PATH)<0) index=-1; else { index=FindGoalInList(goal_name); } } else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, index, data->name); break; case STRM_AUDIO_PARAMETER_TYPE: if(strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindStrmAudioInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; default: cfprintf(CurrentOutputFile,"%02d:%d:%s", data->type, data->ID, data->name); break; } break; case PARAMETER_OPERATOR_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case UNKNOWN_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; default: cfprintf(CurrentOutputFile,"%02d:%d", UNKNOWN_NODE, data->ID); break; } O((" ")); } // VERSION 1: Writes out a coded version of the given script node void CDallasMainDlg::WriteScriptNodeDump_v1U(HTREEITEM node, bool filter_on/*=FALSE*/) { tTreeNodeData *data; CString tmp_name; int index; if(CurrentOutputFile==NULL || node==NULL) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(node); if(data==NULL) return; TabOver(); switch(data->type) { case SCRIPT_HEADER_NODE: cfprintf(CurrentOutputFile,"%02d:%d:%s", data->type, data->ID, data->name); break; case SCRIPT_OWNER_NODE: if(data->ID==OBJECT_TYPE) { if(filter_on || data->int_val==OBJECT_HANDLE_NONE || strlen(data->str_val)==0) index=OBJECT_NONE_HANDLE; else index=FindObjectInList(data->str_val); } else if(data->ID==TRIGGER_TYPE) { if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindTriggerInList(data->str_val); } else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d", data->type, data->ID, index); break; case SCRIPT_EVENT_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case CONDITIONAL_HEADER_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case ACTIONS_HEADER_NODE: if(DALLAS_SAVE_VERSION>=3) { cfprintf(CurrentOutputFile,"%02d:%d:%d:%d", data->type, data->ID, data->int_val, data->subID); } else { cfprintf(CurrentOutputFile,"%02d:%d:%d", data->type, data->ID, data->subID); } break; case CONDITIONAL_STATEMENT_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case EXPRESSION_NODE: cfprintf(CurrentOutputFile,"%02d:%s:%s", data->type, GetQueryFunc(data->ID), data->name); break; case EXPRESSION_OPERATOR_NODE: cfprintf(CurrentOutputFile,"%02d:%d:%d", data->type, data->ID, data->subID); break; case ACTION_STATEMENT_NODE: cfprintf(CurrentOutputFile,"%02d:%s", data->type, GetActionFunc(data->ID)); break; case LOGICAL_OPERATOR_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case PARAMETER_NODE: // Get image type based upon what kind of parameter it is switch(data->ID) { case DOOR_PARAMETER_TYPE: if(data->subID==USE_OBJECT_HANDLE) { if(filter_on || data->int_val==OBJECT_HANDLE_NONE || strlen(data->str_val)==0) index=OBJECT_NONE_HANDLE; else index=FindDoorInList(data->str_val); } else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, index, data->name); break; case OBJECT_PARAMETER_TYPE: if(data->subID==USE_OBJECT_HANDLE) { if(filter_on || data->int_val==OBJECT_HANDLE_NONE || strlen(data->str_val)==0) index=OBJECT_NONE_HANDLE; else index=FindObjectInList(data->str_val); } else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, index, data->name); break; case ROOM_PARAMETER_TYPE: if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindRoomInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case TRIGGER_PARAMETER_TYPE: if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindTriggerInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case INT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case BOOL_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case FLOAT_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", data->type, data->ID, data->float_val1, data->name); break; case VECTOR_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%f:%f:%f:%s", data->type, data->ID, data->float_val1, data->float_val2, data->float_val3, data->name); break; case STRING_PARAMETER_TYPE: if(filter_on || strlen(data->str_val)==0) tmp_name=NOT_SPECIFIED_MSG; else tmp_name=data->str_val; cfprintf(CurrentOutputFile,"%02d:%d:%s:%s", data->type, data->ID, tmp_name.GetBuffer(0), data->name); break; case PERCENTAGE_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%f:%s", data->type, data->ID, data->float_val1, data->name); break; case ENUM_PARAMETER_TYPE: if(DALLAS_SAVE_VERSION>=2) { cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, data->int_val, data->name); } else { cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); } break; case SCRIPT_PARAMETER_TYPE: if(filter_on) index=NOT_SPECIFIED_TYPE; else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case SOUND_PARAMETER_TYPE: if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindSoundInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case SPECNAME_PARAMETER_TYPE: if(filter_on || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindSpecnameInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case TEXTURE_PARAMETER_TYPE: if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindTextureInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case FLAG_PARAMETER_TYPE: cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, data->int_val, data->name); break; case PATH_PARAMETER_TYPE: if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindPathInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; case MATCEN_PARAMETER_TYPE: if(data->subID==USE_MATCEN_VALUE) { if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindMatcenInList(data->str_val); } else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, index, data->name); break; case LEVEL_GOAL_PARAMETER_TYPE: if(data->subID==USE_LEVEL_GOAL_VALUE) { if(filter_on || data->int_val==NOT_SPECIFIED_TYPE || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else { index=FindGoalInList(data->str_val); } } else index=data->int_val; cfprintf(CurrentOutputFile,"%02d:%d:%d:%d:%s", data->type, data->ID, data->subID, index, data->name); break; case STRM_AUDIO_PARAMETER_TYPE: if(filter_on || strlen(data->str_val)==0) index=NOT_SPECIFIED_TYPE; else index=FindStrmAudioInList(data->str_val); cfprintf(CurrentOutputFile,"%02d:%d:%d:%s", data->type, data->ID, index, data->name); break; default: cfprintf(CurrentOutputFile,"%02d:%d:%s", data->type, data->ID, data->name); break; } break; case PARAMETER_OPERATOR_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; case UNKNOWN_NODE: cfprintf(CurrentOutputFile,"%02d:%d", data->type, data->ID); break; default: cfprintf(CurrentOutputFile,"%02d:%d", UNKNOWN_NODE, data->ID); break; } O((" ")); } ///////////////////////////////////////////////////////////////////////////// // Object Handle List Functions ///////////////////////////////////////////////////////////////////////////// // Sets up the object handle list void CDallasMainDlg::InitObjectHandleList(void) { m_NumObjectHandles=0; } // Clears the object handle list void CDallasMainDlg::ClearObjectHandleList(void) { m_NumObjectHandles=0; } // Adds a handle to the list int CDallasMainDlg::AddToObjectHandleList(int handle) { // Is list full? if(m_NumObjectHandles==MAX_NAMED_OBJECTS) return 0; m_ObjectHandleList[m_NumObjectHandles]=handle; m_NumObjectHandles++; return(m_NumObjectHandles-1); } ///////////////////////////////////////////////////////////////////////////// // Floating Menu Creation Functions ///////////////////////////////////////////////////////////////////////////// // Fills up the given menu with the object categories // NOTE: Command ID's of objects items start at the given command_offset void CDallasMainDlg::FillObjectMenu(CMenu *object_menu, int command_offset, bool show_other) { CMenu powerup_submenu, robot_submenu, clutter_submenu, building_submenu, door_submenu, other_submenu; int powerups_added, robots_added, clutter_added, buildings_added, doors_added, others_added; int i; object *objp; // Create the category submenus powerup_submenu.CreatePopupMenu(); robot_submenu.CreatePopupMenu(); clutter_submenu.CreatePopupMenu(); building_submenu.CreatePopupMenu(); door_submenu.CreatePopupMenu(); other_submenu.CreatePopupMenu(); // Before filling with objects, reset the object handle list m_NumObjectHandles=0; // Set the object counts powerups_added=0; robots_added=0; clutter_added=0; buildings_added=0; doors_added=0; others_added=0; // Fill the menus with objects that have custom names for (i=0,objp=Objects;i<=Highest_object_index;i++,objp++) { if((m_NumObjectHandles < MAX_NAMED_OBJECTS) && (objp->name) && (objp->type != OBJ_NONE) /*&& (objp->type != OBJ_PLAYER)*/) { // Add the object handle to the handle list m_ObjectHandleList[m_NumObjectHandles]=objp->handle; // Add menu item to appropriate submenu switch(objp->type) { case OBJ_POWERUP: powerup_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); powerups_added++; break; case OBJ_ROBOT: robot_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); robots_added++; break; case OBJ_CLUTTER: clutter_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); clutter_added++; break; case OBJ_BUILDING: building_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); buildings_added++; break; case OBJ_DOOR: door_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); doors_added++; break; default: other_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); others_added++; break; } m_NumObjectHandles++; } } // Add the powerup submenu ColumnizePopupMenu(&powerup_submenu); if(powerups_added==0) object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)powerup_submenu.Detach(), "Powerup"); else object_menu->AppendMenu(MF_POPUP, (uint32_t)powerup_submenu.Detach(), "Powerup"); // Add the robot submenu ColumnizePopupMenu(&robot_submenu); if(robots_added==0) object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)robot_submenu.Detach(), "Robot"); else object_menu->AppendMenu(MF_POPUP, (uint32_t)robot_submenu.Detach(), "Robot"); // Add the clutter submenu ColumnizePopupMenu(&clutter_submenu); if(clutter_added==0) object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)clutter_submenu.Detach(), "Clutter"); else object_menu->AppendMenu(MF_POPUP, (uint32_t)clutter_submenu.Detach(), "Clutter"); // Add the building submenu ColumnizePopupMenu(&building_submenu); if(buildings_added==0) object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)building_submenu.Detach(), "Building"); else object_menu->AppendMenu(MF_POPUP, (uint32_t)building_submenu.Detach(), "Building"); // Add the door submenu ColumnizePopupMenu(&door_submenu); if(doors_added==0) object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)door_submenu.Detach(), "Door"); else object_menu->AppendMenu(MF_POPUP, (uint32_t)door_submenu.Detach(), "Door"); // Add the other submenu ColumnizePopupMenu(&other_submenu); if(!show_other || others_added==0) object_menu->AppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)other_submenu.Detach(), "Other"); else object_menu->AppendMenu(MF_POPUP, (uint32_t)other_submenu.Detach(), "Other"); } // Fills up the given menu with the named objects of the specified type // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillObjectTypeMenu(CMenu *object_menu, int command_offset, int obj_type) { int objects_added; int i; object *objp; // Before filling with objects, reset the object handle list m_NumObjectHandles=0; // Set the object counts objects_added=0; // Fill the menus with objects that have custom names for (i=0,objp=Objects;i<=Highest_object_index;i++,objp++) { if((m_NumObjectHandles < MAX_NAMED_OBJECTS) && (objp->name) && (objp->type == obj_type)) { // Add the object handle to the handle list m_ObjectHandleList[m_NumObjectHandles]=objp->handle; // Add the menu item object_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+m_NumObjectHandles, objp->name); objects_added++; m_NumObjectHandles++; } } return(objects_added); } // Fills up the given menu with the named rooms // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillRoomMenu(CMenu *room_menu, int command_offset) { int rooms_added; int i; room *rp; // Set the room count rooms_added=0; // Fill the menus with objects that have custom names for (i=0,rp=Rooms;i<=Highest_room_index;i++,rp++) { if((rp->used) && (rp->name)) { room_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+i, rp->name); rooms_added++; } } return(rooms_added); } // Fills up the given menu with the trigger list // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillTriggerMenu(CMenu *trigger_menu, int command_offset) { int t, triggers_added; trigger *tp; // Scan the list, adding triggers to the list triggers_added=0; for (t=0,tp=Triggers;(tname)>0) { trigger_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+t, tp->name); triggers_added++; } } return(triggers_added); } // Fills up the given menu with the path list // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillPathMenu(CMenu *path_menu, int command_offset) { int p, paths_added; // Scan the list, adding triggers to the list paths_added=0; for (p=0;p0) { path_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+p, GamePaths[p].name); paths_added++; } } return(paths_added); } // Fills up the given menu with the matcen list // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillMatcenMenu(CMenu *matcen_menu, int command_offset) { int p, matcens_added; // Scan the list, adding triggers to the list matcens_added=0; for (p=0;pGetName(matcen_name); matcen_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+p, matcen_name); matcens_added++; } } return(matcens_added); } // Fills up the given menu with the level goal list // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillLevelGoalMenu(CMenu *level_goal_menu, int command_offset) { int p, goals_added, num_goals; // Scan the list, adding triggers to the list goals_added=0; num_goals=Level_goals.GetNumGoals(); for (p=0;p=0) { level_goal_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+p, goal_name); goals_added++; } } return(goals_added); } // Fills up the given menu with the Script ID List // NOTE: Command ID's of objects items start at the given command_offset #define MAX_SCRIPT_MENU_NAME_LEN 32 int CDallasMainDlg::FillScriptMenu(CMenu *script_menu, int command_offset) { HTREEITEM script_node; tTreeNodeData *data; int scripts_added, child_pos; // Scan the list, adding each script to the list scripts_added=0; child_pos=0; script_node=m_ScriptTree.GetChildItem(TVI_ROOT); while(script_node!=NULL) { data=(tTreeNodeData *)m_ScriptTree.GetItemData(script_node); if(data->type==SCRIPT_HEADER_NODE) { CString menu_string; FormatTreeText(menu_string,data); // Truncate the name (if necessary) so that more will fit char menu_name[MAX_SCRIPT_MENU_NAME_LEN+3+1]; strncpy(menu_name,menu_string.GetBuffer(0),MAX_SCRIPT_MENU_NAME_LEN); menu_name[MAX_SCRIPT_MENU_NAME_LEN]='\0'; if(menu_string.GetLength() > MAX_SCRIPT_MENU_NAME_LEN) { strcat(menu_name,"..."); } script_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+child_pos, menu_name); scripts_added++; } script_node=m_ScriptTree.GetNextSiblingItem(script_node); child_pos++; } return(scripts_added); } // Fills up the given menu with the logical operations // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillLogOpMenu(CMenu *log_op_menu, int command_offset) { int log_ops_added; // Scan the list, adding triggers to the list log_ops_added=0; log_op_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+AND_TYPE, "AND"); log_op_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+OR_TYPE, "OR"); return(log_ops_added); } // Fills up the given menu with the appropriate expression operators // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillExpOpMenu(CMenu *exp_op_menu, int command_offset, int op_type) { int exp_ops_added=0; int j; // Scan the list, adding triggers to the list for(j=0;expop_info[j].type>=0;j++) { if(op_type==expop_info[j].op_type) { exp_op_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+expop_info[j].type, expop_info[j].menu_name); exp_ops_added++; } else exp_op_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+expop_info[j].type, expop_info[j].menu_name); } return(exp_ops_added); } // Fills up the given menu with the literal's available // NOTE: Command ID's of objects items start at the given command_offset int CDallasMainDlg::FillLiteralMenu(CMenu *literal_menu, int command_offset, int enum_command_offset, int flag_command_offset, int valid_type, char *valid_name) { CMenu enum_submenu, flag_submenu; int literals_added, j; // Create the enum/flag submenus enum_submenu.CreatePopupMenu(); flag_submenu.CreatePopupMenu(); int types_added=FillEnumTypesMenu(&enum_submenu,enum_command_offset,valid_name); int flag_types_added=FillFlagTypesMenu(&flag_submenu,flag_command_offset,valid_name); // Scan the list, adding literals literals_added=0; for(j=0;param_menu_item[j].type>=0;j++) { if(valid_type==ANY_PARAMETER_TYPE || valid_type==param_menu_item[j].type) { if(j==ENUM_PARAMETER_TYPE) { ColumnizePopupMenu(&enum_submenu); if(types_added>0) literal_menu->AppendMenu(MF_POPUP, (uint32_t)enum_submenu.Detach(), param_menu_item[j].name); else literal_menu->AppendMenu(MF_GRAYED | MF_POPUP, (uint32_t)enum_submenu.Detach(), param_menu_item[j].name); } else if(j==FLAG_PARAMETER_TYPE) { ColumnizePopupMenu(&flag_submenu); if(flag_types_added>0) literal_menu->AppendMenu(MF_POPUP, (uint32_t)flag_submenu.Detach(), param_menu_item[j].name); else literal_menu->AppendMenu(MF_GRAYED | MF_POPUP, (uint32_t)flag_submenu.Detach(), param_menu_item[j].name); } else literal_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+param_menu_item[j].type, param_menu_item[j].name); literals_added++; } else literal_menu->AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, command_offset+param_menu_item[j].type, param_menu_item[j].name); } return(literals_added); } // Fills up the given menu with the Condition options // NOTE: Command ID's of objects items start at the given command_offset void CDallasMainDlg::FillConditionMenu(CMenu *condition_menu, int command_offset) { int qbin_cmd_offset, qcomp_cmd_offset; CMenu qbin_submenu, qcomp_submenu; if(command_offset==ADD_CONDITION_ID_RANGE_START) { qbin_cmd_offset=ADD_COND_QBIN_ID_RANGE_START; qcomp_cmd_offset=ADD_COND_QCOMP_ID_RANGE_START; } else { qbin_cmd_offset=REPLACE_COND_QBIN_ID_RANGE_START; qcomp_cmd_offset=REPLACE_COND_QCOMP_ID_RANGE_START; } qbin_submenu.CreatePopupMenu(); FillQueryMenu(&qbin_submenu,qbin_cmd_offset,BOOL_PARAMETER_TYPE,""); qcomp_submenu.CreatePopupMenu(); FillQueryMenu(&qcomp_submenu,qcomp_cmd_offset,ANY_PARAMETER_TYPE,""); // Add basic condition types to the list condition_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+ALWAYS_STATEMENT, ALWAYS_STRING); condition_menu->AppendMenu(MF_SEPARATOR, 0, ""); condition_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+BINARY_STATEMENT, "Default Binary Statement"); condition_menu->AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, command_offset+COMPARISON_STATEMENT, "Default Comparison Statement"); condition_menu->AppendMenu(MF_SEPARATOR, 0, ""); ColumnizePopupMenu(&qbin_submenu); condition_menu->AppendMenu(MF_POPUP, (uint32_t)qbin_submenu.Detach(), "Binary Statement with Query"); ColumnizePopupMenu(&qcomp_submenu); condition_menu->AppendMenu(MF_POPUP, (uint32_t)qcomp_submenu.Detach(), "Comparison Statement with Query"); } // Creates the Popup menu for the Script Header node void CDallasMainDlg::DisplayScriptHeaderNodeMenu(POINT *point) { // Create the popup menu CMenu main_menu; main_menu.CreatePopupMenu(); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Script Description..."); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Script Owner node void CDallasMainDlg::DisplayScriptOwnerNodeMenu(POINT *point) { // Create the popup menu int triggers_added; CMenu main_menu, object_submenu, trigger_submenu; main_menu.CreatePopupMenu(); // Fill the object menu object_submenu.CreatePopupMenu(); FillObjectMenu(&object_submenu,ASSIGN_OBJECT_ID_RANGE_START,TRUE); ColumnizePopupMenu(&object_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)object_submenu.Detach(), "Object"); trigger_submenu.CreatePopupMenu(); triggers_added=FillTriggerMenu(&trigger_submenu,ASSIGN_TRIGGER_ID_RANGE_START); ColumnizePopupMenu(&trigger_submenu); if(triggers_added==0) main_menu.AppendMenu(MF_POPUP|MF_GRAYED, (uint32_t)trigger_submenu.Detach(), "Trigger"); else main_menu.AppendMenu(MF_POPUP, (uint32_t)trigger_submenu.Detach(), "Trigger"); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_LEVEL_ID, "Level"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Script Event node void CDallasMainDlg::DisplayScriptEventNodeMenu(POINT *point, int owner_type, bool has_a_door_me) { int j; // Create the popup menu CMenu main_menu; main_menu.CreatePopupMenu(); for(j=0;event_info[j].type>=0;j++) { if ( (owner_type==OBJECT_TYPE && (event_info[j].flags & OBJECT_MASK)) || (owner_type==TRIGGER_TYPE && (event_info[j].flags & TRIGGER_MASK)) || (owner_type==LEVEL_TYPE && (event_info[j].flags & LEVEL_MASK)) || (has_a_door_me && (event_info[j].flags & DOOR_OBJECT_MASK)) ) main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EVENT_ID_RANGE_START+event_info[j].type, event_info[j].name); else main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, ASSIGN_EVENT_ID_RANGE_START+event_info[j].type, event_info[j].name); } main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Logical Operator node void CDallasMainDlg::DisplayLogicalOperatorNodeMenu(POINT *point) { // Create the popup menu CMenu main_menu, insert_logop_submenu, condition_submenu, add_logop_submenu; CMenu replace_logop_submenu, replace_condition_submenu; insert_logop_submenu.CreatePopupMenu(); FillLogOpMenu(&insert_logop_submenu,INSERT_LOGOP_ID_RANGE_START); condition_submenu.CreatePopupMenu(); FillConditionMenu(&condition_submenu,ADD_CONDITION_ID_RANGE_START); add_logop_submenu.CreatePopupMenu(); FillLogOpMenu(&add_logop_submenu,ADD_LOGOP_ID_RANGE_START); replace_condition_submenu.CreatePopupMenu(); FillConditionMenu(&replace_condition_submenu,REPLACE_CONDITION_ID_RANGE_START); replace_logop_submenu.CreatePopupMenu(); FillLogOpMenu(&replace_logop_submenu,REPLACE_LOGOP_ID_RANGE_START); main_menu.CreatePopupMenu(); ColumnizePopupMenu(&insert_logop_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)insert_logop_submenu.Detach(), "Insert Logical Operator"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); ColumnizePopupMenu(&condition_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)condition_submenu.Detach(), "Add a New Condition"); ColumnizePopupMenu(&add_logop_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)add_logop_submenu.Detach(), "Add Logical Operator"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); ColumnizePopupMenu(&replace_condition_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)replace_condition_submenu.Detach(), "Replace with a Condition"); ColumnizePopupMenu(&replace_logop_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)replace_logop_submenu.Detach(), "Replace with a New Logical Operator"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Operator"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Conditional Statement node void CDallasMainDlg::DisplayConditionalStatementNodeMenu(POINT *point) { // Create the popup menu CMenu main_menu, log_op_submenu; CMenu replace_logop_submenu, replace_condition_submenu; log_op_submenu.CreatePopupMenu(); FillLogOpMenu(&log_op_submenu,INSERT_LOGOP_ID_RANGE_START); replace_condition_submenu.CreatePopupMenu(); FillConditionMenu(&replace_condition_submenu,REPLACE_CONDITION_ID_RANGE_START); replace_logop_submenu.CreatePopupMenu(); FillLogOpMenu(&replace_logop_submenu,REPLACE_LOGOP_ID_RANGE_START); main_menu.CreatePopupMenu(); ColumnizePopupMenu(&log_op_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)log_op_submenu.Detach(), "Insert Logical Operator"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); ColumnizePopupMenu(&replace_condition_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)replace_condition_submenu.Detach(), "Replace with a New Condition"); ColumnizePopupMenu(&replace_logop_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)replace_logop_submenu.Detach(), "Replace with a Logical Operator"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Condition"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Expression node void CDallasMainDlg::DisplayExpressionNodeMenu(POINT *point, int valid_return_type, char *valid_return_name) { CMenu main_menu, replace_with_query_submenu, replace_with_literal_submenu; replace_with_query_submenu.CreatePopupMenu(); FillQueryMenu(&replace_with_query_submenu,REPLACE_QUERY_ID_RANGE_START,valid_return_type,valid_return_name); replace_with_literal_submenu.CreatePopupMenu(); FillLiteralMenu(&replace_with_literal_submenu,REPLACE_LITERAL_ID_RANGE_START,REPLACE_LIT_ENUM_ID_RANGE_START,REPLACE_LIT_FLAG_ID_RANGE_START,valid_return_type,valid_return_name); main_menu.CreatePopupMenu(); ColumnizePopupMenu(&replace_with_query_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)replace_with_query_submenu.Detach(), "Replace with Query"); ColumnizePopupMenu(&replace_with_literal_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)replace_with_literal_submenu.Detach(), "Replace with Literal"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Expression Operator node void CDallasMainDlg::DisplayExpressionOperatorNodeMenu(POINT *point, int op_type) { CMenu main_menu; main_menu.CreatePopupMenu(); FillExpOpMenu(&main_menu,ASSIGN_EXPOP_ID_RANGE_START,op_type); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Action Statement node void CDallasMainDlg::DisplayActionStatementNodeMenu(POINT *point) { // Create the popup menu CMenu main_menu; CMenu insert_actions_submenu, replace_actions_submenu; insert_actions_submenu.CreatePopupMenu(); insert_actions_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_DO_NOTHING_ACTION_ID, DO_NOTHING_STRING); insert_actions_submenu.AppendMenu(MF_SEPARATOR, 0, ""); FillActionMenu(&insert_actions_submenu,ADD_ACTION_ID_RANGE_START); replace_actions_submenu.CreatePopupMenu(); replace_actions_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, REPLACE_DO_NOTHING_ACTION_ID, DO_NOTHING_STRING); replace_actions_submenu.AppendMenu(MF_SEPARATOR, 0, ""); FillActionMenu(&replace_actions_submenu,REPLACE_ACTION_ID_RANGE_START); main_menu.CreatePopupMenu(); ColumnizePopupMenu(&insert_actions_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)insert_actions_submenu.Detach(), "Insert a New Action"); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_CLAUSE_ID, "Insert a Nested IF-THEN Clause"); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_ELSE_CLAUSE_ID, "Insert a Nested IF-THEN-ELSE Clause"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); ColumnizePopupMenu(&replace_actions_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)replace_actions_submenu.Detach(), "Replace with a Different Action"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Creates the Popup menu for the Action Header node void CDallasMainDlg::DisplayActionHeaderNodeMenu(POINT *point, int level_type, int clause_type, bool can_add_else) { // Create the popup menu CMenu main_menu, add_actions_submenu, select_extimes_submenu, select_chain_submenu; add_actions_submenu.CreatePopupMenu(); add_actions_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_DO_NOTHING_ACTION_ID, DO_NOTHING_STRING); add_actions_submenu.AppendMenu(MF_SEPARATOR, 0, ""); FillActionMenu(&add_actions_submenu,ADD_ACTION_ID_RANGE_START); select_extimes_submenu.CreatePopupMenu(); select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+ENTER_EXEC_TIMES, "Enter number of times..."); select_extimes_submenu.AppendMenu(MF_SEPARATOR, 0, ""); select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+EXECUTE_INFINITELY, "Run Infinitely"); select_extimes_submenu.AppendMenu(MF_SEPARATOR, 0, ""); select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+EXECUTE_ONCE, "Once"); select_extimes_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_EXEC_TIME_ID_RANGE_START+EXECUTE_TWICE, "Twice"); select_chain_submenu.CreatePopupMenu(); select_chain_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_CHAIN_ID_RANGE_START+CONTINUE_SCRIPT_CHAIN, "Continue the Script Chain (DEFAULT)"); select_chain_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_CHAIN_ID_RANGE_START+BREAK_SCRIPT_CHAIN, "Break the Script Chain"); main_menu.CreatePopupMenu(); ColumnizePopupMenu(&select_extimes_submenu); if(level_type==TOP_LEVEL) main_menu.AppendMenu(MF_POPUP, (uint32_t)select_extimes_submenu.Detach(), "Select Max Times to Execute"); else main_menu.AppendMenu(MF_GRAYED|MF_POPUP, (uint32_t)select_extimes_submenu.Detach(), "Select Max Times to Execute"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); if(level_type==TOP_LEVEL) main_menu.AppendMenu(MF_POPUP, (uint32_t)select_chain_submenu.Detach(), "Select Script Chaining Option"); else main_menu.AppendMenu(MF_GRAYED|MF_POPUP, (uint32_t)select_chain_submenu.Detach(), "Select Script Chaining Option"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); ColumnizePopupMenu(&add_actions_submenu); main_menu.AppendMenu(MF_POPUP, (uint32_t)add_actions_submenu.Detach(), "Add a New Action"); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_CLAUSE_ID, "Add a Nested IF-THEN Clause"); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_IF_THEN_ELSE_CLAUSE_ID, "Add a Nested IF-THEN-ELSE Clause"); if(can_add_else) main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ADD_ELSE_CLAUSE_ID, "Append an ELSE to this Clause"); else main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, ADD_ELSE_CLAUSE_ID, "Append an ELSE to this Clause"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_CHILDREN_ONLY_ID, "Delete all Child Actions and Clauses"); if(level_type==TOP_LEVEL) main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Entire IF-THEN Clause"); else { if(clause_type==THEN_CLAUSE) main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Entire IF-THEN Clause"); else main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, DELETE_ALL_ID, "Delete this Else Clause"); } main_menu.AppendMenu(MF_SEPARATOR, 0, ""); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, CANCEL_COMMAND_ID, "Cancel"); ColumnizePopupMenu(&main_menu); main_menu.TrackPopupMenu(0,point->x,point->y,this); main_menu.DestroyMenu(); } // Displays the popup menus for the various parameter types void CDallasMainDlg::DisplayParameterNodeMenu(POINT *point, int param_type, char *param_name, int valid_return_type, char *valid_return_name, bool has_an_it, bool has_a_me, bool has_a_door_me, bool has_a_goalID, bool has_a_timerID, bool has_a_matcenID, bool has_a_levgoalID) { CMenu main_menu, replace_with_query_submenu, replace_with_literal_submenu; replace_with_query_submenu.CreatePopupMenu(); FillQueryMenu(&replace_with_query_submenu,REPLACE_QUERY_ID_RANGE_START,valid_return_type,valid_return_name); replace_with_literal_submenu.CreatePopupMenu(); FillLiteralMenu(&replace_with_literal_submenu,REPLACE_LITERAL_ID_RANGE_START,REPLACE_LIT_ENUM_ID_RANGE_START,REPLACE_LIT_FLAG_ID_RANGE_START,valid_return_type,valid_return_name); main_menu.CreatePopupMenu(); switch(param_type) { case DOOR_PARAMETER_TYPE: { if(has_a_door_me) main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); else main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); FillObjectTypeMenu(&main_menu,ASSIGN_OBJECT_ID_RANGE_START,OBJ_DOOR); } break; case OBJECT_PARAMETER_TYPE: { main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_NONE_ID,NONE_STRING); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); if(has_a_me) main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); else main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_ME_ID, "OWNER"); if(has_an_it) main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_IT_ID, "IT"); else main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_OBJECT_IT_ID, "IT"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); FillObjectMenu(&main_menu,ASSIGN_OBJECT_ID_RANGE_START,TRUE); } break; case ROOM_PARAMETER_TYPE: { FillRoomMenu(&main_menu,ASSIGN_ROOM_ID_RANGE_START); } break; case TRIGGER_PARAMETER_TYPE: { FillTriggerMenu(&main_menu,ASSIGN_TRIGGER_ID_RANGE_START); } break; case INT_PARAMETER_TYPE: { main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Integer Value..."); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); } break; case BOOL_PARAMETER_TYPE: { main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_TRUE_ID, "TRUE"); main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_FALSE_ID, "FALSE"); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); } break; case FLOAT_PARAMETER_TYPE: { main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Float Value..."); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); } break; case VECTOR_PARAMETER_TYPE: { main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Vector Values..."); main_menu.AppendMenu(MF_SEPARATOR, 0, ""); } break; case STRING_PARAMETER_TYPE: { int j, num_msgs; // Fill list with Message ID Names num_msgs=m_MessageList.GetCount(); for(j=0;jx,point->y,this); main_menu.DestroyMenu(); } // Takes the given popup menu and breaks it into columns void CDallasMainDlg::ColumnizePopupMenu(CMenu *menu) { int screen_height, menu_item_height; int item_count; int items_per_column; int pos; if(menu==NULL) return; item_count=menu->GetMenuItemCount(); if(item_count==0) return; screen_height=GetSystemMetrics(SM_CYSCREEN); menu_item_height=GetSystemMetrics(SM_CYMENU); if(menu_item_height>0) items_per_column=screen_height/menu_item_height; else items_per_column=25; // Clip the items per column to a min and max if necessary if(items_per_column<25) items_per_column=25; if(items_per_column>40) items_per_column=40; pos=items_per_column; while(posGetMenuString(pos,name,MF_BYPOSITION); // Set the default flags flags=MF_BYPOSITION|MF_MENUBARBREAK; state=menu->GetMenuState(pos,MF_BYPOSITION); if(state & MF_GRAYED) flags |= MF_GRAYED; if(state & MF_ENABLED) flags |= MF_ENABLED; if(state & MF_UNCHECKED) flags |= MF_UNCHECKED; // Get the item ID id=menu->GetMenuItemID(pos); if(id==0) { // is it a separator? flags |= MF_SEPARATOR; id=0; } else if(id==-1) { // is it a popup? CMenu *submenu; submenu=menu->GetSubMenu(pos); if(submenu!=NULL) { id=(uint32_t)submenu->Detach(); flags |= MF_POPUP; } } if(name.IsEmpty()) menu->ModifyMenu(pos,flags,id); else menu->ModifyMenu(pos,flags,id,name.GetBuffer(0)); pos+=items_per_column; } } ///////////////////////////////////////////////////////////////////////////// // Functions to Assign Values To Data Nodes ///////////////////////////////////////////////////////////////////////////// // Obtains the appropriate script ID void CDallasMainDlg::AssignScriptID(int pos) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Handle entering Script Header node descriptions if(data->type==PARAMETER_NODE && data->ID==SCRIPT_PARAMETER_TYPE) { HTREEITEM script_node; script_node=GetNthChild(TVI_ROOT,pos+1); if(script_node==NULL) return; data->int_val=GetScriptID(script_node); UpdateAllParentNodesText(selected_node); SetModified(TRUE); } } // Obtains the appropriate data through popup dialogs void CDallasMainDlg::AssignExecTime(int ID) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Handle entering Script Header node descriptions if(data->type==ACTIONS_HEADER_NODE && data->ID==TOP_LEVEL) { switch(ID) { case ENTER_EXEC_TIMES: { CDallasGenericPromptDlg dlg; // Display the prompt dialog dlg.m_DialogTitle="Maximum Execution Times Prompt"; dlg.m_PromptText="Enter the maximum times to execute script:"; dlg.m_PromptData.Format("%d",data->subID); dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; if(dlg.DoModal()==IDCANCEL) return; data->subID=atoi(dlg.m_PromptData.GetBuffer(0)); } break; case EXECUTE_INFINITELY: data->subID=0; break; case EXECUTE_ONCE: data->subID=1; break; case EXECUTE_TWICE: data->subID=2; break; } UpdateNodeText(selected_node); SetModified(TRUE); } } // Sets the chain option for the action header void CDallasMainDlg::AssignChainOption(int ID) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Handle entering Script Header node descriptions if(data->type==ACTIONS_HEADER_NODE && data->ID==TOP_LEVEL) { data->int_val=ID; UpdateNodeText(selected_node); SetModified(TRUE); } } // Obtains the appropriate data through popup dialogs void CDallasMainDlg::AssignSpecificValue(void) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Handle entering Script Header node descriptions if(data->type==SCRIPT_HEADER_NODE) { CDallasGenericPromptDlg dlg; // Display the prompt dialog dlg.m_DialogTitle="Script Description Prompt"; dlg.m_PromptText="Enter the new script description:"; dlg.m_PromptData=data->name; dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; if(dlg.DoModal()==IDCANCEL) return; strncpy(data->name,dlg.m_PromptData.GetBuffer(0),MAX_NDATA_NAME_LEN); data->name[MAX_NDATA_NAME_LEN]='\0'; UpdateNodeText(selected_node); SetModified(TRUE); return; } // Handle entering a Parameter Int value if(data->type==PARAMETER_NODE && data->ID==INT_PARAMETER_TYPE) { CDallasGenericPromptDlg dlg; // Display the prompt dialog dlg.m_DialogTitle="Integer Value Prompt"; dlg.m_PromptText.Format("Enter value for %s (integer):",data->name); dlg.m_PromptData.Format("%d",data->int_val); dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; if(dlg.DoModal()==IDCANCEL) return; int value=atoi(dlg.m_PromptData.GetBuffer(0)); // If a range is specified, verify that entered value is in it CString name_text, default_text, range_text; int n, param_type; n=GetChildPosition(selected_node); param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); if(param_type>=0 && !range_text.IsEmpty()) { if(!VerifyIntegerRange(value,range_text.GetBuffer(0))) { CString msg; msg.Format("That value is outside the legal range (%s) for this parameter!",range_text); MessageBox(msg,"Invalid Value Entered",MB_OK|MB_ICONEXCLAMATION); return; } } data->int_val=value; UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Parameter Float value if(data->type==PARAMETER_NODE && data->ID==FLOAT_PARAMETER_TYPE) { CDallasGenericPromptDlg dlg; // Display the prompt dialog dlg.m_DialogTitle="Float Value Prompt"; dlg.m_PromptText.Format("Enter value for %s (float):",data->name); dlg.m_PromptData.Format("%f",data->float_val1); dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; if(dlg.DoModal()==IDCANCEL) return; float value=atof(dlg.m_PromptData.GetBuffer(0)); // If a range is specified, verify that entered value is in it CString name_text, default_text, range_text; int n, param_type; n=GetChildPosition(selected_node); param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); if(param_type>=0 && !range_text.IsEmpty()) { if(!VerifyFloatRange(value,range_text.GetBuffer(0))) { CString msg; msg.Format("That value is outside the legal range (%s) for this parameter!",range_text); MessageBox(msg,"Invalid Value Entered",MB_OK|MB_ICONEXCLAMATION); return; } } data->float_val1=value; UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Parameter Vector value if(data->type==PARAMETER_NODE && data->ID==VECTOR_PARAMETER_TYPE) { CDallasVectorPromptDialog dlg; // Display the prompt dialog dlg.m_PromptData1=data->float_val1; dlg.m_PromptData2=data->float_val2; dlg.m_PromptData3=data->float_val3; if(dlg.DoModal()==IDCANCEL) return; data->float_val1=dlg.m_PromptData1; data->float_val2=dlg.m_PromptData2; data->float_val3=dlg.m_PromptData3; UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Sound value if(data->type==PARAMETER_NODE && data->ID==SOUND_PARAMETER_TYPE) { CDallasSoundDlg dlg; // Display the prompt dialog if(data->int_val>=0 && data->int_valint_val].used) dlg.m_SoundName=Sounds[data->int_val].name; if(dlg.DoModal()==IDCANCEL) return; if(dlg.m_SoundIndex>=0 && dlg.m_SoundIndexint_val=dlg.m_SoundIndex; strncpy(data->str_val,Sounds[data->int_val].name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Streaming Audio value if(data->type==PARAMETER_NODE && data->ID==STRM_AUDIO_PARAMETER_TYPE) { CDallasStrmAudioDlg dlg; // Display the prompt dialog if(strlen(data->str_val)>0) dlg.m_Filename=data->str_val; if(dlg.DoModal()==IDCANCEL) return; if(!dlg.m_Filename.IsEmpty()) { strncpy(data->str_val,dlg.m_Filename.GetBuffer(0),MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Texture value if(data->type==PARAMETER_NODE && data->ID==TEXTURE_PARAMETER_TYPE) { CDallasTextureDlg dlg; // Display the prompt dialog if(data->int_val>=0 && data->int_valint_val].used) dlg.m_TextureName=GameTextures[data->int_val].name; if(dlg.DoModal()==IDCANCEL) return; if(dlg.m_TextureIndex>=0 && dlg.m_TextureIndexint_val=dlg.m_TextureIndex; strncpy(data->str_val,GameTextures[data->int_val].name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Flag value if(data->type==PARAMETER_NODE && data->ID==FLAG_PARAMETER_TYPE) { CDallasFlagDlg dlg; // Display the prompt dialog dlg.m_FlagsValue=data->int_val; dlg.m_FlagsName=data->name; // Get the range (contains valid flags mask) CString name_text, default_text, range_text; int n, param_type; n=GetChildPosition(selected_node); param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); if(param_type>=0 && !range_text.IsEmpty()) { dlg.m_ValidFlagsMask=atoi(range_text.GetBuffer(0)); } if(dlg.DoModal()==IDCANCEL) return; data->int_val=dlg.m_FlagsValue; UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Specific Name if(data->type==PARAMETER_NODE && data->ID==SPECNAME_PARAMETER_TYPE) { CDallasGenericPromptDlg dlg; // Display the prompt dialog dlg.m_DialogTitle="Specific Name Prompt"; dlg.m_PromptText.Format("Enter the specific name for %s:",data->name); dlg.m_PromptData=data->str_val; dlg.m_MaxDataLength=MAX_MESSAGE_NAME_LEN; if(dlg.DoModal()==IDCANCEL) return; // Check if the message name is valid char *newname=dlg.m_PromptData.GetBuffer(0); if(strlen(newname)==0) return; for(uint32_t j=0;jstr_val,newname,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Handle entering a Parameter Vector value if(data->type==PARAMETER_NODE && data->ID==PERCENTAGE_PARAMETER_TYPE) { CDallasGenericPromptDlg dlg; // Display the prompt dialog dlg.m_DialogTitle="Percent Value Prompt"; dlg.m_PromptText.Format("Enter data for %s (as a percentage):",data->name); dlg.m_PromptData.Format("%f",data->float_val1*100.0); dlg.m_MaxDataLength=MAX_NDATA_NAME_LEN; if(dlg.DoModal()==IDCANCEL) return; float value=atof(dlg.m_PromptData.GetBuffer(0))/100.0; // If a range is specified, verify that entered value is in it CString name_text, default_text, range_text; int n, param_type; n=GetChildPosition(selected_node); param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); if(param_type>=0 && !range_text.IsEmpty()) { if(!VerifyFloatRange(value,range_text.GetBuffer(0))) { CString msg; msg.Format("That value is outside the legal range (%s) for this parameter!",range_text); MessageBox(msg,"Invalid Value Entered",MB_OK|MB_ICONEXCLAMATION); return; } } data->float_val1=value; UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // If we're here, then no popup dialog could be displayed, // so, instead, display the popup menu for the selected node RECT rect; if(m_ScriptTree.GetItemRect(selected_node,&rect,TRUE)) { POINT pt; pt.x=rect.left; pt.y=(rect.top+rect.bottom)/2; m_ScriptTree.ClientToScreen(&pt); DisplayFloatingPopupMenu(selected_node,pt); } } // Assigns an owner to a Script Owner Node void CDallasMainDlg::AssignNamedValue(int type, int handle) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // If it's a script event node, then process accordingly if(data->type == SCRIPT_OWNER_NODE) { int old_type=data->ID; data->ID=type; switch(type) { case LEVEL_TYPE: data->int_val=handle; if(old_type!=LEVEL_TYPE) SetScriptEventType(selected_node,LEVEL_START_EVENT_TYPE); break; case OBJECT_TYPE: if(handle==OBJECT_NONE_HANDLE) { data->int_val=OBJECT_HANDLE_NONE; data->subID=USE_OBJECT_HANDLE; strcpy(data->str_val,""); } else { data->int_val=m_ObjectHandleList[handle]; data->subID=USE_OBJECT_HANDLE; object *objp=ObjGet(data->int_val); if(objp!=NULL && objp->name!=NULL) { strncpy(data->str_val,objp->name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } else strcpy(data->str_val,""); if(old_type!=OBJECT_TYPE) SetScriptEventType(selected_node,COLLIDE_EVENT_TYPE); } break; case TRIGGER_TYPE: data->int_val=handle; if(data->int_val<0 || data->int_val>=Num_triggers) strcpy(data->str_val,""); else { strncpy(data->str_val,Triggers[data->int_val].name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } if(old_type!=TRIGGER_TYPE) SetScriptEventType(selected_node,ACTIVATED_EVENT_TYPE); break; } UpdateNodeText(selected_node); SetModified(TRUE); HighlightScript(selected_node); } // If it's a parameter node, then process accordingly if(data->type == PARAMETER_NODE) { switch(type) { case OBJECT_TYPE: if(data->ID == OBJECT_PARAMETER_TYPE) { if(handle==OBJECT_NONE_HANDLE) { data->int_val=OBJECT_HANDLE_NONE; data->subID=USE_OBJECT_HANDLE; strcpy(data->str_val,""); } else if(handle==OBJECT_ME_HANDLE) { data->int_val=OBJECT_HANDLE_NONE; data->subID=USE_ME_HANDLE; strcpy(data->str_val,""); } else if(handle==OBJECT_IT_HANDLE) { data->int_val=OBJECT_HANDLE_NONE; data->subID=USE_IT_HANDLE; strcpy(data->str_val,""); } else { data->int_val=m_ObjectHandleList[handle]; data->subID=USE_OBJECT_HANDLE; object *objp=ObjGet(data->int_val); if(objp!=NULL && objp->name!=NULL) { strncpy(data->str_val,objp->name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } else strcpy(data->str_val,""); } } else if(data->ID == DOOR_PARAMETER_TYPE) { if(handle==OBJECT_NONE_HANDLE) { data->int_val=OBJECT_HANDLE_NONE; data->subID=USE_OBJECT_HANDLE; strcpy(data->str_val,""); } else if(handle==OBJECT_ME_HANDLE) { data->int_val=OBJECT_HANDLE_NONE; data->subID=USE_ME_HANDLE; strcpy(data->str_val,""); } else { data->int_val=m_ObjectHandleList[handle]; data->subID=USE_OBJECT_HANDLE; object *objp=ObjGet(data->int_val); if(objp!=NULL && objp->name!=NULL) { strncpy(data->str_val,objp->name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } else strcpy(data->str_val,""); } } break; case TRIGGER_TYPE: if(data->ID == TRIGGER_PARAMETER_TYPE) { data->int_val=handle; if(data->int_val<0 || data->int_val>=Num_triggers) strcpy(data->str_val,""); else { strncpy(data->str_val,Triggers[data->int_val].name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } } break; case ROOM_TYPE: if(data->ID == ROOM_PARAMETER_TYPE) { data->int_val=handle; if(data->int_val<0 || data->int_val>Highest_room_index) strcpy(data->str_val,""); else { strncpy(data->str_val,Rooms[data->int_val].name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } } break; case PATH_TYPE: if(data->ID == PATH_PARAMETER_TYPE) { data->int_val=handle; if(data->int_val<0 || data->int_val>=MAX_GAME_PATHS || !GamePaths[data->int_val].used) strcpy(data->str_val,""); else { strncpy(data->str_val,GamePaths[data->int_val].name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } } break; case MATCEN_TYPE: if(data->ID == MATCEN_PARAMETER_TYPE) { if(handle==MATCEN_ID_VALUE) { data->subID=USE_MATCEN_EVENT_ID; data->int_val=0; strcpy(data->str_val,""); } else { data->subID=USE_MATCEN_VALUE; data->int_val=handle; if(!MatcenValid(data->int_val)) strcpy(data->str_val,""); else { char matcen_name[MAX_MATCEN_NAME_LEN+1]; Matcen[data->int_val]->GetName(matcen_name); strncpy(data->str_val,matcen_name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } } } break; case LEVEL_GOAL_TYPE: if(data->ID == LEVEL_GOAL_PARAMETER_TYPE) { if(handle==LEVEL_GOAL_ID_VALUE) { data->subID=USE_LEVEL_GOAL_ID; data->int_val=0; strcpy(data->str_val,""); } else { char goal_name[MAX_PATH+1]; data->subID=USE_LEVEL_GOAL_VALUE; data->int_val=handle; if(Level_goals.GoalGetName(data->int_val,goal_name,MAX_PATH)<0) strcpy(data->str_val,""); else { strncpy(data->str_val,goal_name,MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; } } } break; } UpdateAllParentNodesText(selected_node); SetModified(TRUE); } } // Assigns an event type to a Script Event Node void CDallasMainDlg::AssignEventType(int type) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure it's a script event node if(data->type == SCRIPT_EVENT_NODE) { data->ID=type; UpdateNodeText(selected_node); SetModified(TRUE); } } // Assigns a boolean type to a Bool parameter void CDallasMainDlg::AssignBooleanValue(int type) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure it's a boolean parameter node if(data->type == PARAMETER_NODE && data->ID == BOOL_PARAMETER_TYPE) { data->int_val=type; UpdateAllParentNodesText(selected_node); SetModified(TRUE); } } // Assigns a message name void CDallasMainDlg::AssignMessageName(int msg_ID) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure it's a boolean parameter node if(data->type == PARAMETER_NODE && data->ID == STRING_PARAMETER_TYPE) { CString msg_name; m_MessageList.GetText(msg_ID,msg_name); strncpy(data->str_val,msg_name.GetBuffer(0),MAX_MESSAGE_NAME_LEN); data->str_val[MAX_MESSAGE_NAME_LEN]='\0'; UpdateAllParentNodesText(selected_node); SetModified(TRUE); } } // Assigns an expression operator type void CDallasMainDlg::AssignExpOpType(int type) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure it's a script event node if(data->type == EXPRESSION_OPERATOR_NODE) { data->subID=type; UpdateAllParentNodesText(selected_node); SetModified(TRUE); } } // Assigns an expression operator type void CDallasMainDlg::AssignEnumValueType(int type) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure it's a parameter-enum node if(data->type == PARAMETER_NODE && data->ID==ENUM_PARAMETER_TYPE) { if(type==ENUM_GOALID_VALUE) { data->subID=USE_GOALID_VALUE; data->int_val=0; } else if(type==ENUM_TIMERID_VALUE) { data->subID=USE_TIMERID_VALUE; data->int_val=0; } else if(type==ENUM_MATCENID_VALUE) { data->subID=USE_MATCENID_VALUE; data->int_val=0; } else { int DBslot; DBslot=GetEnumID(data->name); if(DBslot==INVALID_ENUM) return; if(type<0 || type>=m_EnumDatabase[DBslot].num_values) return; data->int_val=m_EnumDatabase[DBslot].values[type].value; data->subID=USE_ENUM_VALUE; } UpdateAllParentNodesText(selected_node); SetModified(TRUE); } } ///////////////////////////////////////////////////////////////////////////// // Functions to Add Tree Nodes (specific types) ///////////////////////////////////////////////////////////////////////////// // Adds nested IF-THEN Clause void CDallasMainDlg::AddNestedIfThenClause(void) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Add node appropriately with respect to selected node if(data->type==ACTIONS_HEADER_NODE) { CreateDefaultIfThenClause(selected_node,TVI_LAST,NESTED); m_ScriptTree.Expand(selected_node,TVE_EXPAND); } else { CreateDefaultIfThenClause(m_ScriptTree.GetParentItem(selected_node),selected_node,NESTED); m_ScriptTree.Expand(m_ScriptTree.GetParentItem(selected_node),TVE_EXPAND); } SetModified(TRUE); } // Adds nested ELSE Clause void CDallasMainDlg::AddNestedElseClause(void) { HTREEITEM selected_node, next_node; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Add node appropriately with respect to selected node if(!CanAppendElseToNode(selected_node)) return; // See if there is a node after this one next_node=m_ScriptTree.GetNextSiblingItem(selected_node); if(next_node==NULL) CreateDefaultElseClause(m_ScriptTree.GetParentItem(selected_node),TVI_LAST); else CreateDefaultElseClause(m_ScriptTree.GetParentItem(next_node),next_node); SetModified(TRUE); } // Adds nested IF-THEN-ELSE Clause void CDallasMainDlg::AddNestedIfThenElseClause(void) { HTREEITEM selected_node; tTreeNodeData *data; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Add node appropriately with respect to selected node if(data->type==ACTIONS_HEADER_NODE) { CreateDefaultIfThenClause(selected_node,TVI_LAST,NESTED); CreateDefaultElseClause(selected_node,TVI_LAST); m_ScriptTree.Expand(selected_node,TVE_EXPAND); } else { CreateDefaultIfThenClause(m_ScriptTree.GetParentItem(selected_node),selected_node,NESTED); CreateDefaultElseClause(m_ScriptTree.GetParentItem(selected_node),selected_node); m_ScriptTree.Expand(m_ScriptTree.GetParentItem(selected_node),TVE_EXPAND); } SetModified(TRUE); } // Adds a conditional statement node void CDallasMainDlg::AddConditionalStatementNode(int type, int query_id/*=-1*/) { HTREEITEM selected_node, new_condition_node; tTreeNodeData *data; // Check the ID validity if(type<0 || type>=MAX_CONDITION_TYPES) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for adding a conditional statement if(data->type==LOGICAL_OPERATOR_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new condition node node_data.type=CONDITIONAL_STATEMENT_NODE; node_data.ID=type; // Add node appropriately with respect to selected node new_condition_node=AddNodeToTree(selected_node,TVI_LAST,&node_data,TRUE); // Create default subnodes for a binary condition CreateDefaultConditionalStatementSubtree(new_condition_node,type,query_id); // Update the new condition node's text to include the expressions UpdateNodeText(new_condition_node); SetModified(TRUE); if(new_condition_node!=NULL) m_ScriptTree.Expand(new_condition_node,TVE_EXPAND); } } // Inserts a logical operator node as parent of current node void CDallasMainDlg::InsertLogicalOperatorNode(int type) { HTREEITEM selected_node, new_logop_node; tTreeNodeData *data; // Check the ID validity if(type<0 || type>=MAX_LOGICAL_OPERATORS) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for inserting a logical operator if(data->type==LOGICAL_OPERATOR_NODE || data->type==CONDITIONAL_STATEMENT_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new condition node node_data.type=LOGICAL_OPERATOR_NODE; node_data.ID=type; // Add node appropriately with respect to selected node new_logop_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); // Now copy the selected item tree over to the new logop CopyTree(new_logop_node,TVI_LAST,selected_node); m_ScriptTree.Expand(new_logop_node,TVE_EXPAND); // Add a default ALWAYS so that the logical operator has TWO children CreateDefaultConditionalStatementNode(new_logop_node); // Now delete the selected item tree m_ScriptTree.SelectItem(new_logop_node); FreeTreeItem(selected_node); SetModified(TRUE); } } // Adds a logical operator subtree to the end of selected node's children void CDallasMainDlg::AddLogicalOperatorNode(int type) { HTREEITEM selected_node, new_logop_node; tTreeNodeData *data; // Check the ID validity if(type<0 || type>=MAX_LOGICAL_OPERATORS) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for inserting a logical operator if(data->type==LOGICAL_OPERATOR_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new condition node node_data.type=LOGICAL_OPERATOR_NODE; node_data.ID=type; // Add node appropriately with respect to selected node new_logop_node=AddNodeToTree(selected_node,TVI_LAST,&node_data,TRUE); // Add a pair of default ALWAYS's so that the logical operator has TWO children CreateDefaultConditionalStatementNode(new_logop_node); CreateDefaultConditionalStatementNode(new_logop_node); if(new_logop_node!=NULL) m_ScriptTree.Expand(new_logop_node,TVE_EXPAND); SetModified(TRUE); } } // Adds an action statement node void CDallasMainDlg::AddActionStatementNode(int action_ID) { HTREEITEM selected_node, new_action_node; tTreeNodeData *data; // Check the ID validity if((action_ID<0 || action_ID>=MAX_ACTIONS) && action_ID!=DO_NOTHING_ID) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for adding an Action if(data->type==ACTIONS_HEADER_NODE || data->type==ACTION_STATEMENT_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new Action node node_data.type=ACTION_STATEMENT_NODE; node_data.ID=action_ID; // Add node appropriately with respect to selected node if(data->type==ACTIONS_HEADER_NODE) new_action_node=AddNodeToTree(selected_node,TVI_LAST,&node_data,TRUE); else new_action_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); // If it's a real Action, add in the parameters with appropriate defaults AddActionParameterNodes(new_action_node); // Update the new action node's text to include the parameters UpdateNodeText(new_action_node); if(new_action_node!=NULL) m_ScriptTree.Expand(new_action_node,TVE_EXPAND); SetModified(TRUE); } } // Adds all parameter nodes to the given action node void CDallasMainDlg::AddActionParameterNodes(HTREEITEM action_node) { CString name_text, default_text, range_text; tTreeNodeData *data; char *desc; // Make sure node is valid if(action_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); if(data==NULL) return; // Make sure it's a valid action if(data->type!=ACTION_STATEMENT_NODE || data->ID<0 || data->ID>=MAX_ACTIONS) return; // Get the action description desc=GetActionDesc(data->ID); if(desc==NULL) return; // Parse the description, adding default parameter nodes appropriately while((*desc)!='\0') { if((*desc)=='[') { // Note the start of a parameter block int param_type=ParseParamBlock(desc,name_text,default_text,range_text); if(param_type>=0 && param_type!=UNKNOWN_PARAMETER_TYPE) CreateDefaultParameterNode(action_node,TVI_LAST,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0)); } else { desc++; } } SetModified(TRUE); } /* OLD VERSION // Adds all parameter nodes to the given action node void CDallasMainDlg::AddActionParameterNodes(HTREEITEM action_node) { tTreeNodeData *data; char *desc, *desc_copy; int param_type_char, param_type; char *param_name; bool start_block_found; bool type_delim_found; int j; // Make sure node is valid if(action_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(action_node); if(data==NULL) return; // Make sure it's a valid action if(data->type!=ACTION_STATEMENT_NODE || data->ID<0 || data->ID>=MAX_ACTIONS) return; // Get the action description desc=GetActionDesc(data->ID); if(desc==NULL) return; // Make a copy of description (so null chars can be added) desc_copy=(char *)mem_malloc(strlen(desc)+1); if(desc_copy==NULL) { MessageBox("ERROR: Out of memory adding action parameter node!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); return; } strcpy(desc_copy,desc); // Parse the description, adding default parameter nodes appropriately j=0; start_block_found=FALSE; type_delim_found=FALSE; param_name=NULL; param_type_char=-1; while(desc_copy[j]!='\0') { if(desc_copy[j]=='[') { // Note the start of a parameter block start_block_found=TRUE; } else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field type_delim_found=TRUE; } else if(desc_copy[j]==']') { // If end of block, add the parameter if(param_type_char!=-1 && param_name!=NULL) { desc_copy[j]='\0'; // mark the end of the variable name // Get the parameter type param_type=ConvertParamCharToType(param_type_char); if(param_type!=UNKNOWN_PARAMETER_TYPE) CreateDefaultParameterNode(action_node,TVI_LAST,param_type,param_name); } start_block_found=FALSE; type_delim_found=FALSE; param_name=NULL; param_type_char=-1; } else if(start_block_found && param_type_char==-1) { param_type_char=desc_copy[j]; } else if(type_delim_found && param_name==NULL) { param_name=&desc_copy[j]; } j++; } // Free up the copy memory mem_free(desc_copy); } */ // Adds all parameter nodes to the given expression (query) node void CDallasMainDlg::AddQueryParameterNodes(HTREEITEM query_node) { CString name_text, default_text, range_text; tTreeNodeData *data; char *desc; // Make sure node is valid if(query_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); if(data==NULL) return; // Make sure it's a valid action if(data->type!=EXPRESSION_NODE || data->ID<0 || data->ID>=MAX_QUERIES) return; // Get the action description desc=GetQueryDesc(data->ID); if(desc==NULL) return; // Parse the description, adding default parameter nodes appropriately while((*desc)!='\0') { if((*desc)=='[') { // Note the start of a parameter block int param_type=ParseParamBlock(desc,name_text,default_text,range_text); if(param_type>=0 && param_type!=UNKNOWN_PARAMETER_TYPE) CreateDefaultParameterNode(query_node,TVI_LAST,param_type,name_text.GetBuffer(0),default_text.GetBuffer(0)); } else { desc++; } } SetModified(TRUE); } /* // Adds all parameter nodes to the given expression (query) node void CDallasMainDlg::AddQueryParameterNodes(HTREEITEM query_node) { tTreeNodeData *data; char *desc, *desc_copy; int param_type_char, param_type; char *param_name; bool start_block_found; bool type_delim_found; int j; // Make sure node is valid if(query_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(query_node); if(data==NULL) return; // Make sure it's a valid action if(data->type!=EXPRESSION_NODE || data->ID<0 || data->ID>=MAX_QUERIES) return; // Get the action description desc=GetQueryDesc(data->ID); if(desc==NULL) return; // Make a copy of description (so null chars can be added) desc_copy=(char *)mem_malloc(strlen(desc)+1); if(desc_copy==NULL) { MessageBox("ERROR: Out of memory adding query parameter node!","Out of Memory Error!",MB_OK|MB_ICONEXCLAMATION); return; } strcpy(desc_copy,desc); // Parse the description, adding default parameter nodes appropriately j=0; start_block_found=FALSE; type_delim_found=FALSE; param_name=NULL; param_type_char=-1; while(desc_copy[j]!='\0') { if(desc_copy[j]=='[') { // Note the start of a parameter block start_block_found=TRUE; } else if(desc_copy[j]==':' && start_block_found) { // Note the end of parameter type field type_delim_found=TRUE; } else if(desc_copy[j]==']') { // If end of block, add the parameter if(param_type_char!=-1 && param_name!=NULL) { desc_copy[j]='\0'; // mark the end of the variable name // Get the parameter type param_type=ConvertParamCharToType(param_type_char); if(param_type!=UNKNOWN_PARAMETER_TYPE) CreateDefaultParameterNode(query_node,TVI_LAST,param_type,param_name); } start_block_found=FALSE; type_delim_found=FALSE; param_name=NULL; param_type_char=-1; } else if(start_block_found && param_type_char==-1) { param_type_char=desc_copy[j]; } else if(type_delim_found && param_name==NULL) { param_name=&desc_copy[j]; } j++; } // Free up the copy memory mem_free(desc_copy); } */ /////////////////////////////////// // Functions to Replace Tree Nodes /////////////////////////////////// // Replaces the currently selected node with a new query void CDallasMainDlg::ReplaceWithQueryNode(int query_ID) { HTREEITEM selected_node, new_query_node; tTreeNodeData *data; int query_return_type; CString query_return_name; // Check the ID validity if(query_ID<0 || query_ID>=MAX_QUERIES) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for adding a query if(data->type==EXPRESSION_NODE || data->type==PARAMETER_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new query node node_data.type=EXPRESSION_NODE; node_data.ID=query_ID; query_return_type=GetQueryReturnType(query_ID,query_return_name); if(query_return_type==ENUM_PARAMETER_TYPE || query_return_type==FLAG_PARAMETER_TYPE) strcpy(node_data.name,query_return_name.GetBuffer(0)); else if(GetNodeType(m_ScriptTree.GetParentItem(selected_node))==CONDITIONAL_STATEMENT_NODE) strcpy(node_data.name,GetLiteralName(query_return_type)); else strcpy(node_data.name,data->name); // Add new query node before current node, then delete the current node new_query_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); // Add in the parameters with appropriate defaults AddQueryParameterNodes(new_query_node); // Now delete the selected item tree m_ScriptTree.SelectItem(new_query_node); FreeTreeItem(selected_node); // Update the new query node's text to include the parameters UpdateAllParentNodesText(new_query_node); // If this node is the first of a comparison conditional, make sure third node's type matches DoComparisonMatchup(new_query_node); if(new_query_node!=NULL) m_ScriptTree.Expand(new_query_node,TVE_EXPAND); SetModified(TRUE); } } // Replaces the currently selected node with a literal (given a default value) void CDallasMainDlg::ReplaceWithLiteralNode(int literal_type, int index) { HTREEITEM selected_node, new_literal_node; tTreeNodeData *data; // Check the ID validity if(literal_type<0 || literal_type>=MAX_LITERALS) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for adding a query if(data->type==EXPRESSION_NODE || data->type==PARAMETER_NODE) { CString tmp_str; if(literal_type==ENUM_PARAMETER_TYPE) tmp_str=m_EnumDatabase[index].name; else if(literal_type==FLAG_PARAMETER_TYPE) tmp_str=m_FlagDatabase[index].name; else if(GetNodeType(m_ScriptTree.GetParentItem(selected_node))==CONDITIONAL_STATEMENT_NODE) tmp_str=GetLiteralName(literal_type); else tmp_str=data->name; // Create a default parameter node for the chosen literal CString name_text, default_text, range_text; int n, param_type; n=GetChildPosition(selected_node); param_type=ParseNthParam(m_ScriptTree.GetParentItem(selected_node),n,name_text,default_text,range_text); if(param_type>=0) new_literal_node=CreateDefaultParameterNode(m_ScriptTree.GetParentItem(selected_node),selected_node,literal_type,tmp_str.GetBuffer(0),default_text.GetBuffer(0)); else new_literal_node=CreateDefaultParameterNode(m_ScriptTree.GetParentItem(selected_node),selected_node,literal_type,tmp_str.GetBuffer(0)); // Now delete the selected item tree m_ScriptTree.SelectItem(new_literal_node); FreeTreeItem(selected_node); // Update the new literal nodes text UpdateAllParentNodesText(new_literal_node); // If this node is the first of a comparison conditional, make sure third node's type matches DoComparisonMatchup(new_literal_node); SetModified(TRUE); } } // If this node is the first of a comparison conditional, make sure third node's type matches // If they don't match, remove the third node and replace it with a default param that does match void CDallasMainDlg::DoComparisonMatchup(HTREEITEM node) { int node_type, onode_type; CString node_name, onode_name; HTREEITEM other_node, new_param_node; if(node==NULL) return; // If it's not the first node of a comparison conditional, nothing need be done if(!ParentIsComparisonConditional(node) || GetChildPosition(node)!=1) return; // ok, it is, so now we need to get the other node being compared other_node=GetNthChild(m_ScriptTree.GetParentItem(node),3); if(other_node==NULL) return; // Get the other node's data onode_type=GetParamType(other_node,onode_name); // Get this node's data node_type=GetParamType(node,node_name); if(node_type<0) return; // Do the node types match? If they do, get out of here if(node_type==onode_type) { if(node_type==ENUM_PARAMETER_TYPE || node_type==FLAG_PARAMETER_TYPE) { if(node_name.IsEmpty()) return; else if(strcmp(node_name.GetBuffer(0),onode_name.GetBuffer(0))==0) return; } else return; } // If we're here, then the nodes don't match... so create a matching default param CString tmp_str; if(node_type==ENUM_PARAMETER_TYPE || node_type==FLAG_PARAMETER_TYPE) tmp_str=node_name; else tmp_str=GetLiteralName(node_type); new_param_node=CreateDefaultParameterNode(m_ScriptTree.GetParentItem(other_node),other_node,node_type,tmp_str.GetBuffer(0)); // Now delete the old param node FreeTreeItem(other_node); // Update the new literal nodes text UpdateAllParentNodesText(new_param_node); SetModified(TRUE); } // Replaces the currently selected node with a new action void CDallasMainDlg::ReplaceWithActionNode(int action_ID) { HTREEITEM selected_node, new_action_node; tTreeNodeData *data; // Check the ID validity if((action_ID<0 || action_ID>=MAX_ACTIONS) && action_ID!=DO_NOTHING_ID) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for adding an Action if(data->type==ACTION_STATEMENT_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new Action node node_data.type=ACTION_STATEMENT_NODE; node_data.ID=action_ID; // Add node appropriately with respect to selected node new_action_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); // If it's a real Action, add in the parameters with appropriate defaults AddActionParameterNodes(new_action_node); // Now delete the selected item tree m_ScriptTree.SelectItem(new_action_node); FreeTreeItem(selected_node); // Update the new action node's text to include the parameters UpdateNodeText(new_action_node); if(new_action_node!=NULL) m_ScriptTree.Expand(new_action_node,TVE_EXPAND); SetModified(TRUE); } } // Replaces the currently selected node with a new logical operation void CDallasMainDlg::ReplaceWithLogOpNode(int type) { HTREEITEM selected_node, new_logop_node; tTreeNodeData *data; // Check the ID validity if(type<0 || type>=MAX_LOGICAL_OPERATORS) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // If this node IS a logical operator, just change its data if(data->type==LOGICAL_OPERATOR_NODE) { data->ID=type; UpdateAllParentNodesText(selected_node); SetModified(TRUE); return; } // Make sure this node is valid for inserting a logical operator if(data->type==LOGICAL_OPERATOR_NODE || data->type==CONDITIONAL_STATEMENT_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new condition node node_data.type=LOGICAL_OPERATOR_NODE; node_data.ID=type; // Add node appropriately with respect to selected node new_logop_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); // Add a pair of default ALWAYS's so that the logical operator has TWO children CreateDefaultConditionalStatementNode(new_logop_node); CreateDefaultConditionalStatementNode(new_logop_node); // Now delete the selected item tree m_ScriptTree.SelectItem(new_logop_node); FreeTreeItem(selected_node); if(new_logop_node!=NULL) m_ScriptTree.Expand(new_logop_node,TVE_EXPAND); SetModified(TRUE); } } // Replaces the currently selected node with a new condition void CDallasMainDlg::ReplaceWithConditionNode(int type, int query_id/*=-1*/) { HTREEITEM selected_node, new_condition_node; tTreeNodeData *data; // Check the ID validity if(type<0 || type>=MAX_CONDITION_TYPES) return; // Obtain the currently selected node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Get the node's data data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; // Make sure this node is valid for adding a conditional statement if(data->type==LOGICAL_OPERATOR_NODE || data->type==CONDITIONAL_STATEMENT_NODE) { tTreeNodeData node_data; // Fill in the data appropriately for the new condition node node_data.type=CONDITIONAL_STATEMENT_NODE; node_data.ID=type; // Add node appropriately with respect to selected node new_condition_node=AddNodeToTree(m_ScriptTree.GetParentItem(selected_node),selected_node,&node_data,TRUE); // Create default subnodes for a binary condition CreateDefaultConditionalStatementSubtree(new_condition_node,type,query_id); // Now delete the selected item tree m_ScriptTree.SelectItem(new_condition_node); FreeTreeItem(selected_node); // Update the new condition node's text to include the expressions UpdateNodeText(new_condition_node); if(new_condition_node!=NULL) m_ScriptTree.Expand(new_condition_node,TVE_EXPAND); SetModified(TRUE); } } ///////////////////////////////////////////////////////////////////////////// // Functions to Create (and Add) default Tree Nodes ///////////////////////////////////////////////////////////////////////////// // Inserts a default script tree before the specified node (or at the end if NULL) HTREEITEM CDallasMainDlg::CreateDefaultScriptTree(int script_ID, HTREEITEM insert_before/*=NULL*/) { HTREEITEM ib_node, parent; tTreeNodeData node_data; ib_node=GetParentNodeOfType(insert_before,SCRIPT_HEADER_NODE); if(ib_node!=NULL && m_ScriptTree.GetParentItem(ib_node)!=NULL) ib_node=m_ClipboardNode; if(ib_node==NULL) { if(m_ClipboardNode!=NULL) ib_node=m_ClipboardNode; else ib_node=TVI_LAST; } // Create the default Script Header node node_data.type=SCRIPT_HEADER_NODE; node_data.ID=script_ID; strcpy(node_data.name,DEFAULT_SCRIPT_HEADER_STRING); parent=AddNodeToTree(TVI_ROOT,ib_node,&node_data); // Create the default Script owner node node_data.type=SCRIPT_OWNER_NODE; node_data.ID=NOT_SPECIFIED_TYPE; node_data.int_val=0; AddNodeToTree(parent,TVI_LAST,&node_data); // Create the default Event Type Node node_data.type=SCRIPT_EVENT_NODE; node_data.ID=COLLIDE_EVENT_TYPE; AddNodeToTree(parent,TVI_LAST,&node_data); CreateDefaultIfThenClause(parent,TVI_LAST,TOP_LEVEL); if(parent!=NULL) m_ScriptTree.Expand(parent,TVE_EXPAND); SetModified(TRUE); return(parent); } // Create default IF-THEN Clause HTREEITEM CDallasMainDlg::CreateDefaultIfThenClause(HTREEITEM parent, HTREEITEM insert_before, int type) { HTREEITEM header; tTreeNodeData node_data; if(parent==NULL || insert_before==NULL) return NULL; // Create the default Conditional header Node node_data.type=CONDITIONAL_HEADER_NODE; node_data.ID=type; header=AddNodeToTree(parent,insert_before,&node_data); if(header==NULL) return(NULL); // Create the default conditional statement Node CreateDefaultConditionalStatementNode(header); if(header!=NULL) m_ScriptTree.Expand(header,TVE_EXPAND); // Create the default Action header Node node_data.type=ACTIONS_HEADER_NODE; node_data.ID=type; if(type==TOP_LEVEL) { node_data.subID=0; node_data.int_val=CONTINUE_SCRIPT_CHAIN; } else { node_data.subID=THEN_CLAUSE; node_data.int_val=0; } header=AddNodeToTree(parent,insert_before,&node_data); // Create the default action statement Node CreateDefaultActionStatementNode(header); if(header!=NULL) m_ScriptTree.Expand(header,TVE_EXPAND); SetModified(TRUE); return(header); } // Create default IF-THEN Clause HTREEITEM CDallasMainDlg::CreateDefaultElseClause(HTREEITEM parent, HTREEITEM insert_before) { HTREEITEM header; tTreeNodeData node_data; if(parent==NULL || insert_before==NULL) return NULL; // Create the default Action header Node node_data.type=ACTIONS_HEADER_NODE; node_data.ID=NESTED; node_data.subID=ELSE_CLAUSE; node_data.int_val=0; header=AddNodeToTree(parent,insert_before,&node_data); // Create the default action statement Node CreateDefaultActionStatementNode(header); if(header!=NULL) m_ScriptTree.Expand(header,TVE_EXPAND); SetModified(TRUE); return(header); } // Create default conditional statement node HTREEITEM CDallasMainDlg::CreateDefaultConditionalStatementNode(HTREEITEM parent) { tTreeNodeData node_data; if(parent==NULL) return NULL; node_data.type=CONDITIONAL_STATEMENT_NODE; node_data.ID=ALWAYS_STATEMENT; SetModified(TRUE); return(AddNodeToTree(parent,TVI_LAST,&node_data)); } // Create default conditional statement node HTREEITEM CDallasMainDlg::CreateDefaultConditionalStatementSubtree(HTREEITEM parent, int type, int query_id/*=-1*/) { HTREEITEM last_added_node, first_parm_node; if(parent==NULL) return NULL; if(type==ALWAYS_STATEMENT) return NULL; // Add default binary subtree if(type==BINARY_STATEMENT) { first_parm_node=CreateDefaultParameterNode(parent,TVI_LAST,BOOL_PARAMETER_TYPE,"Literal"); last_added_node=CreateDefaultExpressionOperatorNode(parent,BINARY_OPERATOR_TYPE); } // Add default comparison subtree if(type==COMPARISON_STATEMENT) { first_parm_node=CreateDefaultParameterNode(parent,TVI_LAST,FLOAT_PARAMETER_TYPE,"Literal"); last_added_node=CreateDefaultExpressionOperatorNode(parent,COMPARISON_OPERATOR_TYPE); last_added_node=CreateDefaultParameterNode(parent,TVI_LAST,FLOAT_PARAMETER_TYPE,"Literal"); } // Replace first node with a query if necessary if(first_parm_node!=NULL && query_id>=0 && query_idtype==EXPRESSION_NODE || data->type==PARAMETER_NODE)) { tTreeNodeData node_data; int query_return_type; HTREEITEM new_query_node; CString query_return_name; // Fill in the data appropriately for the new query node node_data.type=EXPRESSION_NODE; node_data.ID=query_id; query_return_type=GetQueryReturnType(query_id,query_return_name); if(query_return_type==ENUM_PARAMETER_TYPE || query_return_type==FLAG_PARAMETER_TYPE) strcpy(node_data.name,query_return_name.GetBuffer(0)); else if(GetNodeType(m_ScriptTree.GetParentItem(first_parm_node))==CONDITIONAL_STATEMENT_NODE) strcpy(node_data.name,GetLiteralName(query_return_type)); else strcpy(node_data.name,data->name); // Add new query node before current node, then delete the current node new_query_node=AddNodeToTree(m_ScriptTree.GetParentItem(first_parm_node),first_parm_node,&node_data,TRUE); // Add in the parameters with appropriate defaults AddQueryParameterNodes(new_query_node); // Now delete the selected item tree FreeTreeItem(first_parm_node); // Update the new query node's text to include the parameters UpdateAllParentNodesText(new_query_node); // If this node is the first of a comparison conditional, make sure third node's type matches DoComparisonMatchup(new_query_node); if(new_query_node!=NULL) m_ScriptTree.Expand(new_query_node,TVE_EXPAND); } } SetModified(TRUE); return(last_added_node); } // Create default expression operator node HTREEITEM CDallasMainDlg::CreateDefaultExpressionOperatorNode(HTREEITEM parent, int type) { tTreeNodeData node_data; if(parent==NULL) return NULL; if(type!=BINARY_OPERATOR_TYPE && type!=COMPARISON_OPERATOR_TYPE) return NULL; node_data.type=EXPRESSION_OPERATOR_NODE; node_data.ID=type; if(type==BINARY_OPERATOR_TYPE) node_data.subID=IS_TRUE; else node_data.subID=EQUAL_TO; SetModified(TRUE); return(AddNodeToTree(parent,TVI_LAST,&node_data)); } // Create default action statement node HTREEITEM CDallasMainDlg::CreateDefaultActionStatementNode(HTREEITEM parent) { tTreeNodeData node_data; if(parent==NULL) return NULL; node_data.type=ACTION_STATEMENT_NODE; node_data.ID=DO_NOTHING_ID; SetModified(TRUE); return(AddNodeToTree(parent,TVI_LAST,&node_data)); } // Create default parameter node, and assigns it an appropriate default value // based upon the parameter type HTREEITEM CDallasMainDlg::CreateDefaultParameterNode(HTREEITEM parent, HTREEITEM insert_before, int param_type, char *name, char *def_value/*=NULL*/) { tTreeNodeData node_data; if(parent==NULL || insert_before==NULL || name==NULL) return NULL; node_data.type=PARAMETER_NODE; node_data.ID=param_type; strcpy(node_data.name,name); // Store default values switch(param_type) { case DOOR_PARAMETER_TYPE: node_data.int_val=OBJECT_HANDLE_NONE; node_data.subID=USE_OBJECT_HANDLE; strcpy(node_data.str_val,""); break; case OBJECT_PARAMETER_TYPE: if(def_value!=NULL && strlen(def_value)!=0) { if(strcmp(def_value,"ME")==0) { node_data.int_val=OBJECT_HANDLE_NONE; node_data.subID=USE_ME_HANDLE; strcpy(node_data.str_val,""); break; } if(strcmp(def_value,"IT")==0) { node_data.int_val=OBJECT_HANDLE_NONE; node_data.subID=USE_IT_HANDLE; strcpy(node_data.str_val,""); break; } } node_data.int_val=OBJECT_HANDLE_NONE; node_data.subID=USE_OBJECT_HANDLE; strcpy(node_data.str_val,""); break; case ROOM_PARAMETER_TYPE: node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); break; case TRIGGER_PARAMETER_TYPE: node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); break; case INT_PARAMETER_TYPE: if(def_value==NULL || strlen(def_value)==0) node_data.int_val=0; else node_data.int_val=atoi(def_value); break; case BOOL_PARAMETER_TYPE: if(def_value==NULL || strlen(def_value)==0) node_data.int_val=TRUE; else { if(stricmp(def_value,"false")==0) node_data.int_val=FALSE; else node_data.int_val=TRUE; } break; case FLOAT_PARAMETER_TYPE: if(def_value==NULL || strlen(def_value)==0) node_data.float_val1=0.0; else node_data.float_val1=atof(def_value); break; case VECTOR_PARAMETER_TYPE: node_data.float_val1=0.0; node_data.float_val2=0.0; node_data.float_val3=0.0; break; case STRING_PARAMETER_TYPE: strcpy(node_data.str_val,""); break; case PERCENTAGE_PARAMETER_TYPE: if(def_value==NULL || strlen(def_value)==0) node_data.float_val1=0.0; else node_data.float_val1=atof(def_value); break; case ENUM_PARAMETER_TYPE: { if(def_value!=NULL && strlen(def_value)>0) { if(GetEnumValue(name,def_value,node_data.int_val)) { node_data.subID=USE_ENUM_VALUE; break; } } int DBslot; DBslot=GetEnumID(name); node_data.subID=USE_ENUM_VALUE; if(DBslot!=INVALID_ENUM && m_EnumDatabase[DBslot].num_values>0) node_data.int_val=m_EnumDatabase[DBslot].values[0].value; else node_data.int_val=0; } break; case SCRIPT_PARAMETER_TYPE: node_data.int_val=GetScriptID(parent); if(node_data.int_val<0) node_data.int_val=0; break; case SOUND_PARAMETER_TYPE: node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); break; case SPECNAME_PARAMETER_TYPE: strcpy(node_data.str_val,""); break; case TEXTURE_PARAMETER_TYPE: node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); break; case FLAG_PARAMETER_TYPE: if(def_value==NULL || strlen(def_value)==0) node_data.int_val=0; else node_data.int_val=atoi(def_value); break; case PATH_PARAMETER_TYPE: node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); break; case MATCEN_PARAMETER_TYPE: node_data.subID=USE_MATCEN_VALUE; node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); break; case LEVEL_GOAL_PARAMETER_TYPE: node_data.subID=USE_LEVEL_GOAL_VALUE; node_data.int_val=NOT_SPECIFIED_TYPE; strcpy(node_data.str_val,""); break; case STRM_AUDIO_PARAMETER_TYPE: strcpy(node_data.str_val,""); break; default: break; } SetModified(TRUE); return(AddNodeToTree(parent,insert_before,&node_data)); } // Creates the clipboard node and puts it into the tree HTREEITEM CDallasMainDlg::CreateDefaultClipboardNode(void) { tTreeNodeData node_data; if(m_ClipboardNode!=NULL) { FreeTreeItem(m_ClipboardNode); m_ClipboardNode=NULL; } node_data.type=CLIPBOARD_HEADER_NODE; SetModified(TRUE); m_ClipboardNode=AddNodeToTree(TVI_ROOT,TVI_LAST,&node_data); return(m_ClipboardNode); } /////////////////////////////////// // Functions to Handle Copy/Paste /////////////////////////////////// // Copies the selected script into the clipboard void CDallasMainDlg::PerformScriptCopy(void) { HTREEITEM selected_node; HTREEITEM script_header_node; HTREEITEM new_script_node; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // Get the selected tree node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // If it's a conditional statement node, let it be the header if(GetNodeType(selected_node)==CONDITIONAL_STATEMENT_NODE) { PerformConditionalCopy(selected_node); return; } // If it's a logical operator node, let it be the header if(GetNodeType(selected_node)==LOGICAL_OPERATOR_NODE) { PerformLogOpCopy(selected_node); return; } // If it's an action node, let it be the header if(GetNodeType(selected_node)==ACTION_STATEMENT_NODE) { PerformActionCopy(selected_node); return; } // If it's a nested IF clause, let it be the header if(NodeIsIfClause(selected_node)) { PerformClauseCopy(selected_node); return; } // If it's not a script header node, then it can't be copied if(GetNodeType(selected_node)!=SCRIPT_HEADER_NODE) { MessageBox("Copy/Paste is not supported for the currently selected script item.","Invalid Copy/Paste",MB_OK); return; } // Get the script header node script_header_node=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; // If the script header has a parent, then it must be a clipboard node if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; // If the clipboard, has a script already, kill the old one FreeTreeItemChildren(m_ClipboardNode); // Now copy the script over to the clipboard new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,script_header_node); if(new_script_node!=NULL) { UpdateAllParentNodesText(new_script_node); m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); } } // Copies the selected script action into the clipboard void CDallasMainDlg::PerformActionCopy(HTREEITEM action_node) { HTREEITEM script_header_node; HTREEITEM new_script_node; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // Get the selected tree node if(action_node==NULL) return; // If it's an action node, let it be the header if(GetNodeType(action_node)!=ACTION_STATEMENT_NODE) return; // Get the script header node script_header_node=GetParentNodeOfType(action_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; // If the script header has a parent, then it must be a clipboard node if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; // If the clipboard, has a script already, kill the old one FreeTreeItemChildren(m_ClipboardNode); // Now copy the action over to the clipboard new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,action_node); if(new_script_node!=NULL) { UpdateAllParentNodesText(new_script_node); m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); } } // Copies the selected script conditional statement into the clipboard void CDallasMainDlg::PerformConditionalCopy(HTREEITEM conditional_node) { HTREEITEM script_header_node; HTREEITEM new_script_node; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // Get the selected tree node if(conditional_node==NULL) return; // If it's an action node, let it be the header if(GetNodeType(conditional_node)!=CONDITIONAL_STATEMENT_NODE) return; // Get the script header node script_header_node=GetParentNodeOfType(conditional_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; // If the script header has a parent, then it must be a clipboard node if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; // If the clipboard, has a script already, kill the old one FreeTreeItemChildren(m_ClipboardNode); // Now copy the conditional statement over to the clipboard new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,conditional_node); if(new_script_node!=NULL) { UpdateAllParentNodesText(new_script_node); m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); } } // Copies the selected script logical operator into the clipboard void CDallasMainDlg::PerformLogOpCopy(HTREEITEM logop_node) { HTREEITEM script_header_node; HTREEITEM new_script_node; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // Get the selected tree node if(logop_node==NULL) return; // If it's a logop node, let it be the header if(GetNodeType(logop_node)!=LOGICAL_OPERATOR_NODE) return; // Get the script header node script_header_node=GetParentNodeOfType(logop_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; // If the script header has a parent, then it must be a clipboard node if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; // If the clipboard, has a script already, kill the old one FreeTreeItemChildren(m_ClipboardNode); // Now copy the logical operator over to the clipboard new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,logop_node); if(new_script_node!=NULL) { UpdateAllParentNodesText(new_script_node); m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); } } // Copies the selected script if-then-else clause into the clipboard void CDallasMainDlg::PerformClauseCopy(HTREEITEM clause_node) { HTREEITEM script_header_node; HTREEITEM new_script_node; HTREEITEM if_node, then_node, else_node; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // Get the selected tree node if(clause_node==NULL) return; // Make sure it's an IF header if(!NodeIsIfClause(clause_node)) return; // Get the script header node script_header_node=GetParentNodeOfType(clause_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; // If the script header has a parent, then it must be a clipboard node if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return; // Get the then clause node if_node=clause_node; then_node=m_ScriptTree.GetNextSiblingItem(if_node); if(!NodeIsClauseOfType(then_node,THEN_CLAUSE)) return; // Get the else clause node else_node=m_ScriptTree.GetNextSiblingItem(then_node); if(!NodeIsClauseOfType(else_node,ELSE_CLAUSE)) else_node=NULL; // If the clipboard, has a script already, kill the old one FreeTreeItemChildren(m_ClipboardNode); // Now copy the IF clause over to the clipboard new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,if_node); if(new_script_node!=NULL) { UpdateAllParentNodesText(new_script_node); m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); } // Now copy the THEN clause over to the clipboard new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,then_node); if(new_script_node!=NULL) { UpdateAllParentNodesText(new_script_node); m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); } // Now copy the ELSE clause over (if one exists) if(else_node!=NULL) { new_script_node=CopyTree(m_ClipboardNode,TVI_LAST,else_node); if(new_script_node!=NULL) { UpdateAllParentNodesText(new_script_node); m_ScriptTree.Expand(m_ClipboardNode,TVE_COLLAPSE); } } } // Inserts the clipboard script before the selected script (or clipboard) void CDallasMainDlg::PerformScriptPaste(void) { HTREEITEM selected_node; HTREEITEM src_script_header_node; HTREEITEM dest_insert_before; HTREEITEM new_script_header; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // Get the clipboard child script src_script_header_node=m_ScriptTree.GetChildItem(m_ClipboardNode); if(src_script_header_node==NULL) return; // See if the clipboard has a conditional statement if(GetNodeType(src_script_header_node)==CONDITIONAL_STATEMENT_NODE) { PerformConditionalPaste(src_script_header_node); return; } // See if the clipboard has a logical operator if(GetNodeType(src_script_header_node)==LOGICAL_OPERATOR_NODE) { PerformLogOpPaste(src_script_header_node); return; } // See if the clipboard has an action if(GetNodeType(src_script_header_node)==ACTION_STATEMENT_NODE) { PerformActionPaste(src_script_header_node); return; } // See if the clipboard has an IF clause if(NodeIsIfClause(src_script_header_node)) { PerformClausePaste(src_script_header_node); return; } // If the clipboard doesn't have a script header, get outta here if(GetNodeType(src_script_header_node)!=SCRIPT_HEADER_NODE) return; // Get the selected tree node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; if(selected_node==m_ClipboardNode) dest_insert_before=m_ClipboardNode; else { dest_insert_before=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); if(dest_insert_before==NULL) return; // If the script header has a parent, then it must be a clipboard node if(m_ScriptTree.GetParentItem(dest_insert_before)!=NULL) dest_insert_before=m_ClipboardNode; } // Now copy the script over to the clipboard new_script_header=CopyTree(TVI_ROOT,dest_insert_before,src_script_header_node); if(new_script_header==NULL) return; // Change the script ID for the new node tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(new_script_header); if(data==NULL) return; int new_id=GetLowestUnusedScriptID(); data->ID=new_id; UpdateNodeText(new_script_header); HighlightScript(new_script_header); if(new_id==m_NextScriptID) m_NextScriptID++; m_ScriptTree.SelectItem(new_script_header); AssignSpecificValue(); SetModified(TRUE); } // Inserts the clipboard action before the selected node (or to end of children) void CDallasMainDlg::PerformActionPaste(HTREEITEM src_action_node) { HTREEITEM selected_node; HTREEITEM new_action_node; tTreeNodeData *data; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // See if the clipboard has an action if(GetNodeType(src_action_node)!=ACTION_STATEMENT_NODE) return; // Get the selected tree node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Make sure it's not the same node! if(selected_node==src_action_node) return; // Make sure it's not in the clipboard if(NodeIsInClipboard(selected_node)) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) new_action_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,src_action_node); else if(data->type==ACTIONS_HEADER_NODE) { new_action_node=CopyTree(selected_node,TVI_LAST,src_action_node); } else { return; } // Now copy the script over to the clipboard if(new_action_node==NULL) return; UpdateAllParentNodesText(new_action_node); SetModified(TRUE); } // Replaces selected node with the clipboard conditional statement void CDallasMainDlg::PerformConditionalPaste(HTREEITEM src_conditional_node) { HTREEITEM selected_node; HTREEITEM new_conditional_node; HTREEITEM parent; tTreeNodeData *data; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // See if the clipboard has a conditional statement if(GetNodeType(src_conditional_node)!=CONDITIONAL_STATEMENT_NODE) return; // Get the selected tree node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Make sure it's not the same node! if(selected_node==src_conditional_node) return; // Make sure it's not in the clipboard if(NodeIsInClipboard(selected_node)) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; if(data->type==CONDITIONAL_STATEMENT_NODE || data->type==LOGICAL_OPERATOR_NODE) { new_conditional_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,src_conditional_node); m_ScriptTree.SelectItem(new_conditional_node); // Delete the old conditional parent=m_ScriptTree.GetParentItem(selected_node); FreeTreeItem(selected_node); ConfirmAfterDelete(parent); SetModified(TRUE); } else { return; } // Now copy the script over to the clipboard if(new_conditional_node==NULL) return; UpdateAllParentNodesText(new_conditional_node); } // Replaces selected node with the clipboard logical operator node void CDallasMainDlg::PerformLogOpPaste(HTREEITEM src_logop_node) { HTREEITEM selected_node; HTREEITEM new_logop_node; HTREEITEM parent; tTreeNodeData *data; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // See if the clipboard has a logical operator if(GetNodeType(src_logop_node)!=LOGICAL_OPERATOR_NODE) return; // Get the selected tree node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Make sure it's not the same node! if(selected_node==src_logop_node) return; // Make sure it's not in the clipboard if(NodeIsInClipboard(selected_node)) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; if(data->type==CONDITIONAL_STATEMENT_NODE || data->type==LOGICAL_OPERATOR_NODE) { new_logop_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,src_logop_node); m_ScriptTree.SelectItem(new_logop_node); // Delete the old conditional parent=m_ScriptTree.GetParentItem(selected_node); FreeTreeItem(selected_node); ConfirmAfterDelete(parent); SetModified(TRUE); } else { return; } // Now copy the script over to the clipboard if(new_logop_node==NULL) return; UpdateAllParentNodesText(new_logop_node); } // Inserts the clipboard action before the selected node (or to end of children) void CDallasMainDlg::PerformClausePaste(HTREEITEM src_clause_node) { HTREEITEM selected_node; HTREEITEM new_clause_node; HTREEITEM if_node, then_node, else_node; tTreeNodeData *data; // Make sure we have a clipboard if(m_ClipboardNode==NULL) return; // See if the clipboard has an IF clause if(!NodeIsIfClause(src_clause_node)) return; // Get the then clause node if_node=src_clause_node; then_node=m_ScriptTree.GetNextSiblingItem(if_node); if(!NodeIsClauseOfType(then_node,THEN_CLAUSE)) return; // Get the else clause node else_node=m_ScriptTree.GetNextSiblingItem(then_node); if(!NodeIsClauseOfType(else_node,ELSE_CLAUSE)) else_node=NULL; // Get the selected tree node selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; // Make sure it's not the same node! if(selected_node==src_clause_node) return; // Make sure it's not in the clipboard if(NodeIsInClipboard(selected_node)) return; data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node); if(data==NULL) return; if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) { // Copy over IF clause new_clause_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,if_node); UpdateAllParentNodesText(new_clause_node); // Copy over THEN clause new_clause_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,then_node); UpdateAllParentNodesText(new_clause_node); // Copy over ELSE clause (if one exists) if(else_node!=NULL) { new_clause_node=CopyTree(m_ScriptTree.GetParentItem(selected_node),selected_node,else_node); UpdateAllParentNodesText(new_clause_node); } } else if(data->type==ACTIONS_HEADER_NODE) { // Copy over IF clause new_clause_node=CopyTree(selected_node,TVI_LAST,if_node); UpdateAllParentNodesText(new_clause_node); // Copy over THEN clause new_clause_node=CopyTree(selected_node,TVI_LAST,then_node); UpdateAllParentNodesText(new_clause_node); // Copy over ELSE clause (if one exists) if(else_node!=NULL) { new_clause_node=CopyTree(selected_node,TVI_LAST,else_node); UpdateAllParentNodesText(new_clause_node); } } else { return; } // Now copy the script over to the clipboard if(new_clause_node==NULL) return; SetModified(TRUE); } // Checks to see if the given node is a child of the clipboard header bool CDallasMainDlg::NodeIsInClipboard(HTREEITEM node) { HTREEITEM parent; parent=GetParentNodeOfType(node,CLIPBOARD_HEADER_NODE); if(parent==NULL) return FALSE; else return TRUE; } /////////////////////////////////////////////// // Functions to search tree and replace values /////////////////////////////////////////////// // Goes through the tree, and changes old messageID's to the new one int CDallasMainDlg::UpdateStringParams(HTREEITEM root, char *old_name, char *new_name) { HTREEITEM child; tTreeNodeData *data; int num_changed; if(root==NULL) return 0; // Process the children num_changed=0; child=m_ScriptTree.GetChildItem(root); while(child!=NULL) { num_changed+=UpdateStringParams(child,old_name,new_name); // Check this child to see if it's a string parameter in need of updating data=(tTreeNodeData *)m_ScriptTree.GetItemData(child); if(data!=NULL && data->type==PARAMETER_NODE && data->ID==STRING_PARAMETER_TYPE) { if(strcmp(data->str_val,old_name)==0) { strcpy(data->str_val,new_name); UpdateAllParentNodesText(child); num_changed++; } } // Get the next child child=m_ScriptTree.GetNextSiblingItem(child); } if(num_changed>0) SetModified(TRUE); return(num_changed); } /////////////////////////////////////////////////////////////////// // Functions to Handle Script Drag-n-Drop /////////////////////////////////////////////////////////////////// bool CDallasMainDlg::IsDropSource(HTREEITEM item) { if(item==NULL) return FALSE; // See if it's an action node if(GetNodeType(item)==ACTION_STATEMENT_NODE) { HTREEITEM parent; // Make sure it's not in the clipboard parent=GetParentNodeOfType(item,SCRIPT_HEADER_NODE); if(parent==NULL) return FALSE; if(m_ScriptTree.GetParentItem(parent)!=NULL) return FALSE; return TRUE; } // Make sure it's a script header node if(GetNodeType(item)!=SCRIPT_HEADER_NODE) return FALSE; // Make sure it's not in the Clipboard if(m_ScriptTree.GetParentItem(item)!=NULL) return FALSE; return TRUE; } HTREEITEM CDallasMainDlg::GetDropTarget(HTREEITEM item) { HTREEITEM target_item, parent_item; if(item==NULL || m_hitemDrag==NULL) return NULL; // See if the dragged node is an action if(GetNodeType(m_hitemDrag)==ACTION_STATEMENT_NODE) { tTreeNodeData *data; HTREEITEM parent; // Make sure it's not in the clipboard parent=GetParentNodeOfType(item,SCRIPT_HEADER_NODE); if(parent==NULL) return NULL; if(m_ScriptTree.GetParentItem(parent)!=NULL) return NULL; // Make sure it's a valid drop node data=(tTreeNodeData *)m_ScriptTree.GetItemData(item); if(data==NULL) return NULL; if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) return(item); if(data->type==ACTIONS_HEADER_NODE) return(item); return NULL; } // See if it's the clipboard if(GetNodeType(item)==CLIPBOARD_HEADER_NODE) return(item); // Get the script header for the selected node target_item=GetParentNodeOfType(item,SCRIPT_HEADER_NODE); if(target_item==NULL) return NULL; parent_item=m_ScriptTree.GetParentItem(target_item); if(m_ScriptTree.GetParentItem(target_item)==NULL) return(target_item); if(GetNodeType(parent_item)==CLIPBOARD_HEADER_NODE) return(parent_item); return NULL; } void CDallasMainDlg::OnBegindragEventTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; m_hitemDrag = pNMTreeView->itemNew.hItem; m_hitemDrop = NULL; m_ScriptTree.SelectItem( m_hitemDrag ); if (!IsDropSource(m_hitemDrag)) return; // get the image list for dragging m_pDragImage = m_ScriptTree.CreateDragImage(m_hitemDrag); // CreateDragImage() returns NULL if no image list // associated with the tree view control if(!m_pDragImage) return; m_bLDragging = TRUE; m_pDragImage->BeginDrag(0, CPoint(0,0)); POINT pt = pNMTreeView->ptDrag; m_ScriptTree.ClientToScreen( &pt ); m_pDragImage->DragEnter(NULL, pt); SetCapture(); *pResult = 0; } void CDallasMainDlg::OnMouseMove(UINT nFlags, CPoint point) { HTREEITEM hitem; UINT flags; if (m_bLDragging) { POINT pt = point; ClientToScreen(&pt); POINT tree_pt = pt; m_ScriptTree.ScreenToClient( &tree_pt ); CImageList::DragMove(pt); if ((hitem = m_ScriptTree.HitTest(tree_pt, &flags)) != NULL) { CImageList::DragShowNolock(FALSE); m_hitemDrop = GetDropTarget(hitem); m_ScriptTree.SelectDropTarget(m_hitemDrop); CImageList::DragShowNolock(TRUE); } else { CImageList::DragShowNolock(FALSE); m_hitemDrop = NULL; m_ScriptTree.SelectDropTarget(m_hitemDrop); CImageList::DragShowNolock(TRUE); } } CDialog::OnMouseMove(nFlags, point); } void CDallasMainDlg::OnLButtonUp(UINT nFlags, CPoint point) { if (m_bLDragging) { m_bLDragging = FALSE; CImageList::DragLeave(this); CImageList::EndDrag(); ReleaseCapture(); delete m_pDragImage; // Remove drop target highlighting m_ScriptTree.SelectDropTarget(NULL); if((m_hitemDrag == m_hitemDrop) || m_hitemDrop==NULL) return; // See if the dragged node is an action if(GetNodeType(m_hitemDrag)==ACTION_STATEMENT_NODE) { HTREEITEM new_action_node, parent; tTreeNodeData *data; data=(tTreeNodeData *)m_ScriptTree.GetItemData(m_hitemDrop); if(data==NULL) return; if(data->type==ACTION_STATEMENT_NODE || (data->type==CONDITIONAL_HEADER_NODE && data->ID==NESTED)) new_action_node=CopyTree(m_ScriptTree.GetParentItem(m_hitemDrop),m_hitemDrop,m_hitemDrag); else if(data->type==ACTIONS_HEADER_NODE) { new_action_node=CopyTree(m_hitemDrop,TVI_LAST,m_hitemDrag); } if(new_action_node==NULL) return; UpdateAllParentNodesText(new_action_node); m_ScriptTree.SelectItem(new_action_node); // Delete the old action parent=m_ScriptTree.GetParentItem(m_hitemDrag); FreeTreeItem(m_hitemDrag); ConfirmAfterDelete(parent); SetModified(TRUE); return; } // Copy the tree to its new location (and select it) HTREEITEM new_script_header=CopyTree(TVI_ROOT,m_hitemDrop,m_hitemDrag); if(new_script_header==NULL) return; UpdateAllParentNodesText(new_script_header); m_ScriptTree.SelectItem(new_script_header); // Delete the old tree FreeTreeItem(m_hitemDrag); SetModified(TRUE); } CDialog::OnLButtonUp(nFlags, point); } /////////////////////////////////////////////////////////////////// // Functions to Handle Highlight Interface /////////////////////////////////////////////////////////////////// void CDallasMainDlg::ClearHighlightRadioButtons(void) { ((CButton *) GetDlgItem(IDC_NONE_RADIO))->SetCheck(0); ((CButton *) GetDlgItem(IDC_SPECIFIC_RADIO))->SetCheck(0); ((CButton *) GetDlgItem(IDC_LEVEL_RADIO))->SetCheck(0); ((CButton *) GetDlgItem(IDC_ALLOBJ_RADIO))->SetCheck(0); ((CButton *) GetDlgItem(IDC_ALLTRIG_RADIO))->SetCheck(0); } void CDallasMainDlg::FillHighlightEventList(void) { int i, index; m_EventList.ResetContent(); // Add the "all events" type index=m_EventList.AddString("All Event Types"); if(index!=LB_ERR) { m_EventList.SetItemData(index,ALL_EVENT_TYPES); } // Fill the list with the event types for (i=0;event_info[i].type>=0;i++) { index=m_EventList.AddString(event_info[i].name); if(index!=LB_ERR) { m_EventList.SetItemData(index,event_info[i].type); } } SetHighlightedEvent(ALL_EVENT_TYPES); } int CDallasMainDlg::GetHighlightedEvent(void) { int index=m_EventList.GetCurSel(); if(index==LB_ERR) return ALL_EVENT_TYPES; return(m_EventList.GetItemData(index)); } void CDallasMainDlg::SetHighlightedEvent(int type) { int index, total; total=m_EventList.GetCount(); for(index=0;index=1) returned_node=ParseScriptNodeLine_v1U(line,linenum,current_parent,skip_children,version,insert_before); else returned_node=ParseScriptNodeLine_v0(line,linenum,current_parent,skip_children,insert_before); if(returned_node!=NULL ) { if(new_script_header==NULL) new_script_header=returned_node; last_node_added=returned_node; last_node_childless=TRUE; UpdateNodeText(last_node_added); } else ScriptFileParseError(INVALID_NODE_ERR,linenum,0,NULL); if(returned_node==NULL || skip_children) { skip_children=TRUE; skip_depth=0; } } } if (!done) ScriptFileParseError(UEOS_ERR,linenum,0,NULL); } } cfclose(infile); // Change the script ID for the new script if(new_script_header!=NULL) { tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(new_script_header); if(data!=NULL && data->type==SCRIPT_HEADER_NODE) { int new_id=GetLowestUnusedScriptID(); data->ID=new_id; UpdateNodeText(new_script_header); HighlightScript(new_script_header); if(new_id==m_NextScriptID) m_NextScriptID++; m_ScriptTree.SelectItem(new_script_header); AssignSpecificValue(); SetModified(TRUE); } } return TRUE; } #define TEMP_EXPORT_FNAME "DExport.tmp" // Adds selected script to specified library file bool CDallasMainDlg::ExportScriptToFile(char *filename, char *script_name) { CFILE *infile; char linebuf[2048]; char *line; int linenum; int valid_lines_read; HTREEITEM selected_node, script_header_node; bool ReplacingScript; bool ScriptReplaced; CurrentParsingFilename=filename; // Make sure the selected item is valid for exporting selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return FALSE; script_header_node=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return FALSE; // Make sure library file can be written to if(_access(filename,0) != -1) { if( (_access( filename, 2 )) == -1 ) { CString msg; msg.Format("The library file \"%s\" is read-only!",filename); MessageBox(msg,"Script Library File Not Writeable!",MB_OK|MB_ICONEXCLAMATION); return FALSE; } } // Try to open the file for reading infile=cfopen (filename,"rt"); // Try to open the temp file for writing CurrentOutputFile = cfopen(TEMP_EXPORT_FNAME,"wt"); if(CurrentOutputFile==NULL) { CString msg, title; msg.Format("ERROR: Unable to open %s for output.",TEMP_EXPORT_FNAME); title.Format("Temp File Save Error!"); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); if(infile!=NULL) cfclose(infile); return FALSE; } // If file doesn't exist, Write out the header info if(infile==NULL) { O(("/////////////////////////////////////////////////////////////////////")); O(("// D.A.L.L.A.S. Generated Script Library File ")); O(("/////////////////////////////////////////////////////////////////////")); O((" ")); } linenum=0; ReplacingScript=FALSE; ScriptReplaced=FALSE; // Read in and parse each line of the file while (infile!=NULL && !cfeof(infile)) { // Clear the buffer strcpy(linebuf,""); // Read in a line from the file cf_ReadString(linebuf, sizeof(linebuf), infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); // Check for Start of Script Block Section if (strncmp(line,SCRIPT_START_TAG,strlen(SCRIPT_START_TAG)) == 0) { bool done = false; // Write out the start tag O(("%s",linebuf)); // Set valid line counter to track whether we're reading header info or tree nodes valid_lines_read=0; // Read all the lines in the block while (!done && !cfeof(infile)) { strcpy(linebuf,""); cf_ReadString(linebuf,sizeof(linebuf),infile); linenum++; // Remove whitespace padding at start and end of line RemoveTrailingWhitespace(linebuf); line=SkipInitialWhitespace(linebuf); // If it's an empty line or a comment, skip it if(strlen(line)==0 || strncmp(line,"//",2)==0) { if(!ReplacingScript) O(("%s",linebuf)); continue; } // Check for End of Script Block Section if (strncmp(line,SCRIPT_END_TAG,strlen(SCRIPT_END_TAG)) == 0) { if(ReplacingScript) { ScriptReplaced=TRUE; ReplacingScript=FALSE; } O(("%s",linebuf)); done=true; continue; } // See if this script's name matches the given name if(valid_lines_read==0) { if(stricmp(line,script_name)==0) { CString msg, title; msg.Format("A script named '%s' already exists in this library.\n\nWould you like to replace it with your new script?",script_name); title.Format("Duplicate Script Name Encountered"); // Prompt user to see if it should be replaced if(MessageBox(msg,title,MB_YESNO|MB_ICONQUESTION)==IDNO) { cfclose(infile); cfclose(CurrentOutputFile); CurrentOutputFile=NULL; ddio_DeleteFile(TEMP_EXPORT_FNAME); return FALSE; } // Copy the new script into it's place O(("%s",script_name)); O(("VERSION %d",DALLAS_SAVE_VERSION)); CurrentTabLevel=0; if(DALLAS_SAVE_VERSION>=1) WriteScriptNodeDump_v1U(script_header_node,TRUE); else WriteScriptNodeDump_v0(script_header_node); WriteScriptChildrenDump(script_header_node,TRUE); ReplacingScript=TRUE; } else O(("%s",linebuf)); valid_lines_read++; continue; } if(!ReplacingScript) O(("%s",linebuf)); } if (!done) ScriptFileParseError(UEOS_ERR,linenum,0,NULL); } else O(("%s",linebuf)); } // If the script wasn't replaced, add it at the end if(!ScriptReplaced) { O(("%s",SCRIPT_START_TAG)); O(("%s",script_name)); O(("VERSION %d",DALLAS_SAVE_VERSION)); CurrentTabLevel=0; if(DALLAS_SAVE_VERSION>=1) WriteScriptNodeDump_v1U(script_header_node,TRUE); else WriteScriptNodeDump_v0(script_header_node); WriteScriptChildrenDump(script_header_node,TRUE); O(("%s",SCRIPT_END_TAG)); O((" ")); } if(infile!=NULL) cfclose(infile); cfclose(CurrentOutputFile); CurrentOutputFile=NULL; // Now delete the library input file, and replace it with the temp file ddio_DeleteFile(filename); if(!CopyFile(TEMP_EXPORT_FNAME,filename,FALSE)) { CString msg, title; msg.Format("ERROR: Could not copy over temporary library file.\n\nThe export failed."); title.Format("Script Export Error!"); MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION); } else { CString msg, title; msg.Format("The script was exported successfully!"); title.Format("Script Export Successful"); MessageBox(msg,title,MB_OK|MB_ICONINFORMATION); } ddio_DeleteFile(TEMP_EXPORT_FNAME); return TRUE; } // Imports a script from a specified Library file void CDallasMainDlg::OnImportButton() { HTREEITEM selected_node, initial_insert_before; CString library_filename; // Make sure the selected item is valid for importing selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; if(GetNodeType(selected_node)==CLIPBOARD_HEADER_NODE) initial_insert_before=selected_node; else { initial_insert_before=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); if(initial_insert_before==NULL) return; if(m_ScriptTree.GetParentItem(initial_insert_before)!=NULL) return; } // Display file selection dlg if(!ScriptLibraryFilePrompt(library_filename,TRUE)) return; // Scan the file and display scripts that can be imported CDallasImportDlg dlg; dlg.m_Filename=library_filename; if(dlg.DoModal()==IDCANCEL) return; if(dlg.m_ScriptName.IsEmpty()) return; // Try to import the selected script ImportScriptFromFile(library_filename.GetBuffer(0),dlg.m_ScriptName.GetBuffer(0)); } // Exports a script to a specified Library file void CDallasMainDlg::OnExportButton() { HTREEITEM selected_node, script_header_node; CString library_filename; // Make sure the selected item is valid for exporting selected_node=m_ScriptTree.GetSelectedItem(); if(selected_node==NULL) return; script_header_node=GetParentNodeOfType(selected_node,SCRIPT_HEADER_NODE); if(script_header_node==NULL) return; // Display the enter name prompt CDallasGenericPromptDlg dlg; dlg.m_DialogTitle="Exported Script Name Prompt"; dlg.m_PromptText="Enter the name for this exported script:"; dlg.m_PromptData=""; dlg.m_MaxDataLength=256; if(dlg.DoModal()==IDCANCEL) return; if(dlg.m_PromptData.IsEmpty()) return; // Display file selection dlg if(!ScriptLibraryFilePrompt(library_filename,FALSE)) return; // Try to export the selected script to the specified library file ExportScriptToFile(library_filename.GetBuffer(0),dlg.m_PromptData.GetBuffer(0)); } CDallasMainDlg *GetDallasDialogPtr(void) { #ifdef NEWEDITOR CNewEditorApp *editor_app; editor_app = (CNewEditorApp *)AfxGetApp(); #else CEditorApp *editor_app; editor_app = &theApp; #endif return editor_app->m_DallasModelessDlgPtr; }