mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
16384 lines
457 KiB
C++
16384 lines
457 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/editor/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 <string.h>
|
|
#include <ctype.h>
|
|
#include <io.h>
|
|
|
|
#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);
|
|
std::vsprintf(buffer,format,marker);
|
|
cf_WriteString(CurrentOutputFile,buffer);
|
|
va_end(marker);
|
|
}
|
|
|
|
#define DALLASFUNCS_FILENAME "dallasfuncs.cpp"
|
|
|
|
#define NOT_SPECIFIED_MSG "<NOT_SPECIFIED>"
|
|
|
|
#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;j<strlen(msgname);j++)
|
|
if(isspace(msgname[j]) || (!isalnum(msgname[j]) && msgname[j]!='_')) {
|
|
MessageBox("That message ID is invalid!\n\nAn ID may only contain letters and numbers","Invalid Message ID Error",MB_OK|MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
// Check if the message name already exists in the list
|
|
if(FindMessageInList(msgname)!=NULL && strcmp(msgname,old_name.GetBuffer(0))!=0) {
|
|
MessageBox("That message ID is already in use!\n\nYou must enter a UNIQUE message ID.","Invalid Message ID Error",MB_OK|MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
// Store the message
|
|
message=msg_entry->message;
|
|
|
|
// 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[_MAX_PATH+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_SCRIPT_ID_RANGE_END)
|
|
AssignScriptID(nID-ASSIGN_SCRIPT_ID_RANGE_START);
|
|
|
|
// Check for the assigning of an execution time
|
|
if(nID>=ASSIGN_EXEC_TIME_ID_RANGE_START && nID<ASSIGN_EXEC_TIME_ID_RANGE_END)
|
|
AssignExecTime(nID-ASSIGN_EXEC_TIME_ID_RANGE_START);
|
|
|
|
// Check for the assigning of a chain option
|
|
if(nID>=ASSIGN_CHAIN_ID_RANGE_START && nID<ASSIGN_CHAIN_ID_RANGE_END)
|
|
AssignChainOption(nID-ASSIGN_CHAIN_ID_RANGE_START);
|
|
|
|
// Check for the entering of a specific value (i.e. popup dialog)
|
|
if(nID==ASSIGN_SPECIFIC_VALUE_ID)
|
|
AssignSpecificValue();
|
|
|
|
// Check for the entering of a specific value (i.e. popup dialog)
|
|
if(nID==ASSIGN_TRUE_ID)
|
|
AssignBooleanValue(TRUE);
|
|
if(nID==ASSIGN_FALSE_ID)
|
|
AssignBooleanValue(FALSE);
|
|
|
|
// Check for the assigning of a message name
|
|
if(nID>=ASSIGN_MESSAGE_ID_RANGE_START && nID<ASSIGN_MESSAGE_ID_RANGE_END)
|
|
AssignMessageName(nID-ASSIGN_MESSAGE_ID_RANGE_START);
|
|
|
|
// Check for the assigning of an event type
|
|
if(nID>=ASSIGN_EVENT_ID_RANGE_START && nID<ASSIGN_EVENT_ID_RANGE_END)
|
|
AssignEventType(nID-ASSIGN_EVENT_ID_RANGE_START);
|
|
|
|
// Check for the assigning of a level owner
|
|
if(nID==ASSIGN_LEVEL_ID)
|
|
AssignNamedValue(LEVEL_TYPE,0x000);
|
|
|
|
// Check for the assigning of a trigger owner
|
|
if(nID>=ASSIGN_TRIGGER_ID_RANGE_START && nID<ASSIGN_TRIGGER_ID_RANGE_END)
|
|
AssignNamedValue(TRIGGER_TYPE,nID-ASSIGN_TRIGGER_ID_RANGE_START);
|
|
|
|
// Check for the assigning of object none
|
|
if(nID==ASSIGN_OBJECT_NONE_ID)
|
|
AssignNamedValue(OBJECT_TYPE,OBJECT_NONE_HANDLE);
|
|
|
|
// Check for the assigning of object IT
|
|
if(nID==ASSIGN_OBJECT_IT_ID)
|
|
AssignNamedValue(OBJECT_TYPE,OBJECT_IT_HANDLE);
|
|
|
|
// Check for the assigning of object ME
|
|
if(nID==ASSIGN_OBJECT_ME_ID)
|
|
AssignNamedValue(OBJECT_TYPE,OBJECT_ME_HANDLE);
|
|
|
|
// Check for the assigning of a named object
|
|
if(nID>=ASSIGN_OBJECT_ID_RANGE_START && nID<ASSIGN_OBJECT_ID_RANGE_END)
|
|
AssignNamedValue(OBJECT_TYPE,nID-ASSIGN_OBJECT_ID_RANGE_START);
|
|
|
|
// Check for the assigning of a named room
|
|
if(nID>=ASSIGN_ROOM_ID_RANGE_START && nID<ASSIGN_ROOM_ID_RANGE_END)
|
|
AssignNamedValue(ROOM_TYPE,nID-ASSIGN_ROOM_ID_RANGE_START);
|
|
|
|
// Check for the assigning of an expression operator
|
|
if(nID>=ASSIGN_EXPOP_ID_RANGE_START && nID<ASSIGN_EXPOP_ID_RANGE_END)
|
|
AssignExpOpType(nID-ASSIGN_EXPOP_ID_RANGE_START);
|
|
|
|
// Check for the assigning of enum GoalID
|
|
if(nID==ASSIGN_ENUM_GOAL_ID)
|
|
AssignEnumValueType(ENUM_GOALID_VALUE);
|
|
|
|
// Check for the assigning of enum TimerID
|
|
if(nID==ASSIGN_ENUM_TIMER_ID)
|
|
AssignEnumValueType(ENUM_TIMERID_VALUE);
|
|
|
|
// Check for the assigning of enum MatcenID
|
|
if(nID==ASSIGN_ENUM_MATCEN_ID)
|
|
AssignEnumValueType(ENUM_MATCENID_VALUE);
|
|
|
|
// Check for the assigning of an enum value
|
|
if(nID>=ASSIGN_ENUM_VALUE_ID_RANGE_START && nID<ASSIGN_ENUM_VALUE_ID_RANGE_END)
|
|
AssignEnumValueType(nID-ASSIGN_ENUM_VALUE_ID_RANGE_START);
|
|
|
|
// Check for the assigning of a path
|
|
if(nID>=ASSIGN_PATH_ID_RANGE_START && nID<ASSIGN_PATH_ID_RANGE_END)
|
|
AssignNamedValue(PATH_TYPE,nID-ASSIGN_PATH_ID_RANGE_START);
|
|
|
|
// Check for the assigning of a matcen
|
|
if(nID==ASSIGN_MATCEN_EVENT_ID)
|
|
AssignNamedValue(MATCEN_TYPE,MATCEN_ID_VALUE);
|
|
|
|
// Check for the assigning of a matcen
|
|
if(nID>=ASSIGN_MATCEN_ID_RANGE_START && nID<ASSIGN_MATCEN_ID_RANGE_END)
|
|
AssignNamedValue(MATCEN_TYPE,nID-ASSIGN_MATCEN_ID_RANGE_START);
|
|
|
|
// Check for the assigning of a level goal
|
|
if(nID==ASSIGN_LEVEL_GOAL_ID)
|
|
AssignNamedValue(LEVEL_GOAL_TYPE,LEVEL_GOAL_ID_VALUE);
|
|
|
|
// Check for the assigning of a level goal
|
|
if(nID>=ASSIGN_LEVEL_GOAL_ID_RANGE_START && nID<ASSIGN_LEVEL_GOAL_ID_RANGE_END)
|
|
AssignNamedValue(LEVEL_GOAL_TYPE,nID-ASSIGN_LEVEL_GOAL_ID_RANGE_START);
|
|
}
|
|
|
|
|
|
// Translates the type of Add being requested
|
|
void CDallasMainDlg::OnMenuSelectionOfTypeAdd(UINT nID)
|
|
{
|
|
// Check for adding of a nested IF-THEN clause
|
|
if(nID==ADD_IF_THEN_CLAUSE_ID)
|
|
AddNestedIfThenClause();
|
|
|
|
// Check for adding of a nested ELSE clause
|
|
if(nID==ADD_ELSE_CLAUSE_ID)
|
|
AddNestedElseClause();
|
|
|
|
// Check for adding of a nested IF-THEN-ELSE clause
|
|
if(nID==ADD_IF_THEN_ELSE_CLAUSE_ID)
|
|
AddNestedIfThenElseClause();
|
|
|
|
// Check for the adding of a DO_NOTHING Action
|
|
if(nID==ADD_DO_NOTHING_ACTION_ID)
|
|
AddActionStatementNode(DO_NOTHING_ID);
|
|
|
|
// Check for the adding of a specific Action
|
|
if(nID>=ADD_ACTION_ID_RANGE_START && nID<ADD_ACTION_ID_RANGE_END)
|
|
AddActionStatementNode(nID-ADD_ACTION_ID_RANGE_START);
|
|
|
|
// Check for the adding of a logical operator
|
|
if(nID>=ADD_LOGOP_ID_RANGE_START && nID<ADD_LOGOP_ID_RANGE_END)
|
|
AddLogicalOperatorNode(nID-ADD_LOGOP_ID_RANGE_START);
|
|
|
|
// Check for the adding of a logical operator
|
|
if(nID>=INSERT_LOGOP_ID_RANGE_START && nID<INSERT_LOGOP_ID_RANGE_END)
|
|
InsertLogicalOperatorNode(nID-INSERT_LOGOP_ID_RANGE_START);
|
|
|
|
// Check for the adding of a condition
|
|
if(nID>=ADD_CONDITION_ID_RANGE_START && nID<ADD_CONDITION_ID_RANGE_END)
|
|
AddConditionalStatementNode(nID-ADD_CONDITION_ID_RANGE_START);
|
|
|
|
// Check for the adding of a binary condition (query)
|
|
if(nID>=ADD_COND_QBIN_ID_RANGE_START && nID<ADD_COND_QBIN_ID_RANGE_END)
|
|
AddConditionalStatementNode(BINARY_STATEMENT,nID-ADD_COND_QBIN_ID_RANGE_START);
|
|
|
|
// Check for the adding of a comparison condition (query)
|
|
if(nID>=ADD_COND_QCOMP_ID_RANGE_START && nID<ADD_COND_QCOMP_ID_RANGE_END)
|
|
AddConditionalStatementNode(COMPARISON_STATEMENT,nID-ADD_COND_QCOMP_ID_RANGE_START);
|
|
}
|
|
|
|
|
|
// Handle replace commands
|
|
void CDallasMainDlg::OnMenuSelectionOfTypeReplace(UINT nID)
|
|
{
|
|
// Check for the replacement of a node with a specific Query
|
|
if(nID>=REPLACE_QUERY_ID_RANGE_START && nID<REPLACE_QUERY_ID_RANGE_END)
|
|
ReplaceWithQueryNode(nID-REPLACE_QUERY_ID_RANGE_START);
|
|
|
|
// Check for the replacement of a node with a Literal
|
|
if(nID>=REPLACE_LITERAL_ID_RANGE_START && nID<REPLACE_LITERAL_ID_RANGE_END)
|
|
ReplaceWithLiteralNode(nID-REPLACE_LITERAL_ID_RANGE_START,0);
|
|
|
|
// Check for the replacement of a node with a Literal enumeration
|
|
if(nID>=REPLACE_LIT_ENUM_ID_RANGE_START && nID<REPLACE_LIT_ENUM_ID_RANGE_END)
|
|
ReplaceWithLiteralNode(ENUM_PARAMETER_TYPE,nID-REPLACE_LIT_ENUM_ID_RANGE_START);
|
|
|
|
// Check for the replacement of a node with a Literal flag
|
|
if(nID>=REPLACE_LIT_FLAG_ID_RANGE_START && nID<REPLACE_LIT_FLAG_ID_RANGE_END)
|
|
ReplaceWithLiteralNode(FLAG_PARAMETER_TYPE,nID-REPLACE_LIT_FLAG_ID_RANGE_START);
|
|
|
|
// Check for the replacement of a node with a DO_NOTHING Action
|
|
if(nID==REPLACE_DO_NOTHING_ACTION_ID)
|
|
ReplaceWithActionNode(DO_NOTHING_ID);
|
|
|
|
// Check for the replacement of a node with an action
|
|
if(nID>=REPLACE_ACTION_ID_RANGE_START && nID<REPLACE_ACTION_ID_RANGE_END)
|
|
ReplaceWithActionNode(nID-REPLACE_ACTION_ID_RANGE_START);
|
|
|
|
// Check for the replacement of a node with a logical operator
|
|
if(nID>=REPLACE_LOGOP_ID_RANGE_START && nID<REPLACE_LOGOP_ID_RANGE_END)
|
|
ReplaceWithLogOpNode(nID-REPLACE_LOGOP_ID_RANGE_START);
|
|
|
|
// Check for the replacement of a node with a condition
|
|
if(nID>=REPLACE_CONDITION_ID_RANGE_START && nID<REPLACE_CONDITION_ID_RANGE_END)
|
|
ReplaceWithConditionNode(nID-REPLACE_CONDITION_ID_RANGE_START);
|
|
|
|
// Check for the replacement of a node with a binary condition (query)
|
|
if(nID>=REPLACE_COND_QBIN_ID_RANGE_START && nID<REPLACE_COND_QBIN_ID_RANGE_END)
|
|
ReplaceWithConditionNode(BINARY_STATEMENT,nID-REPLACE_COND_QBIN_ID_RANGE_START);
|
|
|
|
// Check for the replacement of a node with a comparison condition (query)
|
|
if(nID>=REPLACE_COND_QCOMP_ID_RANGE_START && nID<REPLACE_COND_QCOMP_ID_RANGE_END)
|
|
ReplaceWithConditionNode(COMPARISON_STATEMENT,nID-REPLACE_COND_QCOMP_ID_RANGE_START);
|
|
}
|
|
|
|
|
|
// Handle delete commands
|
|
void CDallasMainDlg::OnMenuSelectionOfTypeDelete(UINT nID)
|
|
{
|
|
HTREEITEM selected_node, parent_node;
|
|
tTreeNodeData *data;
|
|
|
|
// Obtain the currently selected node
|
|
selected_node=m_ScriptTree.GetSelectedItem();
|
|
if(selected_node==NULL) return;
|
|
|
|
// Save the parent of this node
|
|
parent_node=m_ScriptTree.GetParentItem(selected_node);
|
|
|
|
// Get the node's data
|
|
data=(tTreeNodeData *)m_ScriptTree.GetItemData(selected_node);
|
|
if(data==NULL) return;
|
|
|
|
// Handle Delete all's
|
|
if(nID==DELETE_ALL_ID) {
|
|
switch(data->type) {
|
|
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[_MAX_PATH+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[_MAX_PATH+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="<Not a Conditional Statement>";
|
|
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="<Invalid Expression>";
|
|
}
|
|
|
|
|
|
// 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="<Not a Parameter>";
|
|
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="<Message Not Found>";
|
|
|
|
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+="<Invalid Node>";
|
|
|
|
// 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+="<Invalid Node>";
|
|
|
|
// 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+="<Invalid Node>";
|
|
|
|
// 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+="<Invalid Node>";
|
|
|
|
// 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<max_size) {
|
|
list[size]=id;
|
|
size++;
|
|
}
|
|
node=m_ScriptTree.GetNextSiblingItem(node);
|
|
}
|
|
|
|
// Sort and determine the lowest unused ID
|
|
qsort( (void *)list, size, sizeof(int), id_list_compare);
|
|
|
|
// Determine the lowest number
|
|
int j;
|
|
lowest_id=0;
|
|
for(j=0;j<size;j++) {
|
|
if(lowest_id<list[j]) break;
|
|
lowest_id=list[j]+1;
|
|
}
|
|
|
|
/* Debugging output
|
|
CString msg, num;
|
|
msg="";
|
|
for(j=0;j<size;j++) {
|
|
num.Format("%d ",list[j]);
|
|
msg+=num;
|
|
}
|
|
num.Format("-> %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;j<MAX_MESSAGE_LIST_ENTRIES;j++)
|
|
m_MessageEntryList[j]=NULL;
|
|
}
|
|
|
|
// Clears the message list
|
|
void CDallasMainDlg::ClearMessageList(void)
|
|
{
|
|
int j;
|
|
|
|
// Wipeout the list of message entries
|
|
for(j=0;j<MAX_MESSAGE_LIST_ENTRIES;j++)
|
|
if(m_MessageEntryList[j]!=NULL) {
|
|
delete m_MessageEntryList[j];
|
|
m_MessageEntryList[j]=NULL;
|
|
}
|
|
|
|
// Reset the next message ID
|
|
m_NextMessageID=1;
|
|
|
|
// Clear the message list and edit boxes
|
|
m_MessageEdit.SetWindowText("");
|
|
m_MessageList.ResetContent();
|
|
}
|
|
|
|
// Adds a message to the list
|
|
bool CDallasMainDlg::AddToMessageList(char *name, char *message)
|
|
{
|
|
tMessageListEntry *empty_slot;
|
|
int index;
|
|
|
|
// Make sure no duplicate entries exist
|
|
if(FindMessageInList(name)!=NULL) {
|
|
m_MessageListErrorCode=MSG_LIST_DUP_NAME_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
// Search the list for an empty slot, and add the message
|
|
empty_slot=GetEmptyMessageListEntry();
|
|
if(empty_slot==NULL) {
|
|
m_MessageListErrorCode=MSG_LIST_FULL_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
// Set the data
|
|
strncpy(empty_slot->name,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;j<MAX_MESSAGE_LIST_ENTRIES;j++)
|
|
if(m_MessageEntryList[j]!=NULL && strcmp(m_MessageEntryList[j]->name,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;j<MAX_MESSAGE_LIST_ENTRIES;j++)
|
|
if(m_MessageEntryList[j]!=NULL && strcmp(m_MessageEntryList[j]->name,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;j<MAX_MESSAGE_LIST_ENTRIES;j++)
|
|
if(m_MessageEntryList[j]==NULL) {
|
|
m_MessageEntryList[j]=new tMessageListEntry;
|
|
return(m_MessageEntryList[j]);
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Name List functions
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Initialize all the name lists
|
|
void CDallasMainDlg::InitNameLists(void)
|
|
{
|
|
int j;
|
|
|
|
// Init the Door list
|
|
for(j=0;j<MAX_NAMED_DOORS;j++)
|
|
m_DoorList[j]=NULL;
|
|
m_DoorListSize=0;
|
|
|
|
// Init the object list
|
|
for(j=0;j<MAX_NAMED_OBJECTS;j++)
|
|
m_ObjectList[j]=NULL;
|
|
m_ObjectListSize=0;
|
|
|
|
// Init the Room list
|
|
for(j=0;j<MAX_NAMED_ROOMS;j++)
|
|
m_RoomList[j]=NULL;
|
|
m_RoomListSize=0;
|
|
|
|
// Init the Trigger list
|
|
for(j=0;j<MAX_NAMED_TRIGGERS;j++)
|
|
m_TriggerList[j]=NULL;
|
|
m_TriggerListSize=0;
|
|
|
|
// Init the sound list
|
|
for(j=0;j<MAX_NAMED_SOUNDS;j++)
|
|
m_SoundList[j]=NULL;
|
|
m_SoundListSize=0;
|
|
|
|
// Init the Texture list
|
|
for(j=0;j<MAX_NAMED_TEXTURES;j++)
|
|
m_TextureList[j]=NULL;
|
|
m_TextureListSize=0;
|
|
|
|
// Init the Specname list
|
|
for(j=0;j<MAX_SPECNAMES;j++)
|
|
m_SpecnameList[j]=NULL;
|
|
m_SpecnameListSize=0;
|
|
|
|
// Init the Path list
|
|
for(j=0;j<MAX_NAMED_PATHS;j++)
|
|
m_PathList[j]=NULL;
|
|
m_PathListSize=0;
|
|
|
|
// Init the Matcen list
|
|
for(j=0;j<MAX_NAMED_MATCENS;j++)
|
|
m_MatcenList[j]=NULL;
|
|
m_MatcenListSize=0;
|
|
|
|
// Init the Goal list
|
|
for(j=0;j<MAX_NAMED_GOALS;j++)
|
|
m_GoalList[j]=NULL;
|
|
m_GoalListSize=0;
|
|
|
|
// Init the StrmAudio list
|
|
for(j=0;j<MAX_NAMED_STRM_AUDIO;j++)
|
|
m_StrmAudioList[j]=NULL;
|
|
m_StrmAudioListSize=0;
|
|
|
|
// Init the Message name list
|
|
for(j=0;j<MAX_MESSAGE_LIST_ENTRIES;j++)
|
|
m_MessageNameList[j]=NULL;
|
|
m_MessageNameListSize=0;
|
|
}
|
|
|
|
|
|
// Empty the name lists
|
|
void CDallasMainDlg::ClearNameLists(void)
|
|
{
|
|
int j;
|
|
|
|
// Clear the Door list
|
|
for(j=0;j<m_DoorListSize;j++)
|
|
if(m_DoorList[j]!=NULL) {
|
|
mem_free(m_DoorList[j]);
|
|
m_DoorList[j]=NULL;
|
|
}
|
|
m_DoorListSize=0;
|
|
|
|
// Clear the object list
|
|
for(j=0;j<m_ObjectListSize;j++)
|
|
if(m_ObjectList[j]!=NULL) {
|
|
mem_free(m_ObjectList[j]);
|
|
m_ObjectList[j]=NULL;
|
|
}
|
|
m_ObjectListSize=0;
|
|
|
|
// Clear the Room list
|
|
for(j=0;j<m_RoomListSize;j++)
|
|
if(m_RoomList[j]!=NULL) {
|
|
mem_free(m_RoomList[j]);
|
|
m_RoomList[j]=NULL;
|
|
}
|
|
m_RoomListSize=0;
|
|
|
|
// Clear the Trigger list
|
|
for(j=0;j<m_TriggerListSize;j++)
|
|
if(m_TriggerList[j]!=NULL) {
|
|
mem_free(m_TriggerList[j]);
|
|
m_TriggerList[j]=NULL;
|
|
}
|
|
m_TriggerListSize=0;
|
|
|
|
// Clear the sound list
|
|
for(j=0;j<m_SoundListSize;j++)
|
|
if(m_SoundList[j]!=NULL) {
|
|
mem_free(m_SoundList[j]);
|
|
m_SoundList[j]=NULL;
|
|
}
|
|
m_SoundListSize=0;
|
|
|
|
// Clear the Texture list
|
|
for(j=0;j<m_TextureListSize;j++)
|
|
if(m_TextureList[j]!=NULL) {
|
|
mem_free(m_TextureList[j]);
|
|
m_TextureList[j]=NULL;
|
|
}
|
|
m_TextureListSize=0;
|
|
|
|
// Clear the Specname list
|
|
for(j=0;j<m_SpecnameListSize;j++)
|
|
if(m_SpecnameList[j]!=NULL) {
|
|
mem_free(m_SpecnameList[j]);
|
|
m_SpecnameList[j]=NULL;
|
|
}
|
|
m_SpecnameListSize=0;
|
|
|
|
// Clear the Path list
|
|
for(j=0;j<m_PathListSize;j++)
|
|
if(m_PathList[j]!=NULL) {
|
|
mem_free(m_PathList[j]);
|
|
m_PathList[j]=NULL;
|
|
}
|
|
m_PathListSize=0;
|
|
|
|
// Clear the Matcen list
|
|
for(j=0;j<m_MatcenListSize;j++)
|
|
if(m_MatcenList[j]!=NULL) {
|
|
mem_free(m_MatcenList[j]);
|
|
m_MatcenList[j]=NULL;
|
|
}
|
|
m_MatcenListSize=0;
|
|
|
|
// Clear the Goal list
|
|
for(j=0;j<m_GoalListSize;j++)
|
|
if(m_GoalList[j]!=NULL) {
|
|
mem_free(m_GoalList[j]);
|
|
m_GoalList[j]=NULL;
|
|
}
|
|
m_GoalListSize=0;
|
|
|
|
// Clear the StrmAudio list
|
|
for(j=0;j<m_StrmAudioListSize;j++)
|
|
if(m_StrmAudioList[j]!=NULL) {
|
|
mem_free(m_StrmAudioList[j]);
|
|
m_StrmAudioList[j]=NULL;
|
|
}
|
|
m_StrmAudioListSize=0;
|
|
|
|
// Clear the Message Name list
|
|
for(j=0;j<m_MessageNameListSize;j++)
|
|
if(m_MessageNameList[j]!=NULL) {
|
|
mem_free(m_MessageNameList[j]);
|
|
m_MessageNameList[j]=NULL;
|
|
}
|
|
m_MessageNameListSize=0;
|
|
}
|
|
|
|
|
|
// Search the tree, and fill all of the name lists
|
|
// Returns a count of all invalid name fields encountered
|
|
int CDallasMainDlg::FillNameListsFromTree(HTREEITEM parent, bool show_notspec_warnings)
|
|
{
|
|
HTREEITEM child;
|
|
int inv_name_count;
|
|
|
|
if(parent==NULL) return 0;
|
|
|
|
// Search the tree for named things
|
|
inv_name_count=0;
|
|
child=m_ScriptTree.GetChildItem(parent);
|
|
while(child!=NULL) {
|
|
inv_name_count+=FillNameListsFromTree(child,show_notspec_warnings);
|
|
inv_name_count+=AddNameToListFromTreeNode(child,show_notspec_warnings);
|
|
child=m_ScriptTree.GetNextSiblingItem(child);
|
|
}
|
|
|
|
return(inv_name_count);
|
|
}
|
|
|
|
|
|
// Checks to see if the node contains a named thing,
|
|
// and, if it does, adds it to the appropriate name list
|
|
// It returns 1 if an invalid name is found, 0 otherwise
|
|
int CDallasMainDlg::AddNameToListFromTreeNode(HTREEITEM node, bool show_notspec_warnings)
|
|
{
|
|
tTreeNodeData *data;
|
|
int scriptID;
|
|
|
|
if(node==NULL) return 0;
|
|
|
|
data=(tTreeNodeData *)m_ScriptTree.GetItemData(node);
|
|
if(data==NULL) return 0;
|
|
|
|
// Make sure this node isn't in the clipboard
|
|
HTREEITEM script_header_node;
|
|
script_header_node=GetParentNodeOfType(node,SCRIPT_HEADER_NODE);
|
|
if(script_header_node==NULL) return 0;
|
|
if(m_ScriptTree.GetParentItem(script_header_node)!=NULL) return 0;
|
|
|
|
// Get the script ID
|
|
scriptID=GetScriptID(node);
|
|
if(scriptID==-1) return 0;
|
|
|
|
// See if it's an Owner Node
|
|
if(data->type==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<m_DoorListSize;j++)
|
|
if(strcmp(m_DoorList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given object name to the object name list
|
|
int CDallasMainDlg::AddObjectToList(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(FindObjectInList(name)>=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<m_ObjectListSize;j++)
|
|
if(strcmp(m_ObjectList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Room name to the Room name list
|
|
int CDallasMainDlg::AddRoomToList(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(FindRoomInList(name)>=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<m_RoomListSize;j++)
|
|
if(strcmp(m_RoomList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Trigger name to the Trigger name list
|
|
int CDallasMainDlg::AddTriggerToList(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(FindTriggerInList(name)>=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<m_TriggerListSize;j++)
|
|
if(strcmp(m_TriggerList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given sound name to the sound name list
|
|
int CDallasMainDlg::AddSoundToList(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(FindSoundInList(name)>=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<m_SoundListSize;j++)
|
|
if(strcmp(m_SoundList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Texture name to the Texture name list
|
|
int CDallasMainDlg::AddTextureToList(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(FindTextureInList(name)>=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<m_TextureListSize;j++)
|
|
if(strcmp(m_TextureList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Specname name to the Specname name list
|
|
int CDallasMainDlg::AddSpecnameToList(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(FindSpecnameInList(name)>=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<m_SpecnameListSize;j++)
|
|
if(strcmp(m_SpecnameList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Path name to the Path name list
|
|
int CDallasMainDlg::AddPathToList(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(FindPathInList(name)>=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<m_PathListSize;j++)
|
|
if(strcmp(m_PathList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Matcen name to the Matcen name list
|
|
int CDallasMainDlg::AddMatcenToList(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(FindMatcenInList(name)>=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<m_MatcenListSize;j++)
|
|
if(strcmp(m_MatcenList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Goal name to the Goal name list
|
|
int CDallasMainDlg::AddGoalToList(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(FindGoalInList(name)>=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<m_GoalListSize;j++)
|
|
if(strcmp(m_GoalList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given StrmAudio name to the StrmAudio name list
|
|
int CDallasMainDlg::AddStrmAudioToList(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(FindStrmAudioInList(name)>=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<m_StrmAudioListSize;j++)
|
|
if(strcmp(m_StrmAudioList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// Adds the given Message name to the Message name list
|
|
int CDallasMainDlg::AddMessageNameToList(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(FindMessageNameInList(name)>=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;j<m_MessageNameListSize;j++)
|
|
if(strcmp(m_MessageNameList[j],name)==0) return(j);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// User Type Workshop Functions
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Fills drop down box with available user types
|
|
int CDallasMainDlg::FillUserTypeBox(CComboBox *box)
|
|
{
|
|
int j, types_added;
|
|
|
|
types_added=0;
|
|
|
|
// Clear the box
|
|
box->ResetContent();
|
|
|
|
// Add the User Type Names
|
|
for(j=0;j<m_NumEnums;j++) {
|
|
if(m_EnumDatabase[j].is_user_type) {
|
|
box->AddString(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;j<m_EnumDatabase[DBslot].num_values;j++) {
|
|
tEnumValueEntry *value_entry=&m_EnumDatabase[DBslot].values[j];
|
|
if(value_entry->value!=-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;j<entry->num_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;j<entry->num_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;j<entry->num_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;j<MAX_ENUMS;j++) {
|
|
m_EnumDatabase[j].name=NULL;
|
|
for(k=0;k<MAX_ENUM_VALUES;k++) {
|
|
m_EnumDatabase[j].values[k].name=NULL;
|
|
m_EnumDatabase[j].values[k].value=0;
|
|
}
|
|
m_EnumDatabase[j].num_values=0;
|
|
}
|
|
m_NumEnums=0;
|
|
}
|
|
|
|
|
|
// Clears any allocated data for the enums
|
|
void CDallasMainDlg::ClearEnumDatabase(void)
|
|
{
|
|
int j,k;
|
|
|
|
for(j=0;j<m_NumEnums;j++) {
|
|
if(m_EnumDatabase[j].name!=NULL) {
|
|
mem_free(m_EnumDatabase[j].name);
|
|
m_EnumDatabase[j].name=NULL;
|
|
}
|
|
for(k=0;k<m_EnumDatabase[j].num_values;k++) {
|
|
if(m_EnumDatabase[j].values[k].name!=NULL) {
|
|
mem_free(m_EnumDatabase[j].values[k].name);
|
|
m_EnumDatabase[j].values[k].name=NULL;
|
|
}
|
|
m_EnumDatabase[j].values[k].value=0;
|
|
}
|
|
m_EnumDatabase[j].num_values=0;
|
|
}
|
|
m_NumEnums=0;
|
|
}
|
|
|
|
|
|
// Returns the DB slot matching the given enum type name
|
|
int CDallasMainDlg::GetEnumID(char *name)
|
|
{
|
|
int i;
|
|
|
|
if(name==NULL) return INVALID_ENUM;
|
|
|
|
for(i=0;i<m_NumEnums;i++)
|
|
if(strcmp(m_EnumDatabase[i].name,name) == 0)
|
|
return i;
|
|
|
|
return INVALID_ENUM;
|
|
}
|
|
|
|
|
|
// Returns the name bound to an enum value
|
|
char *CDallasMainDlg::GetEnumValueName(char *name, int value)
|
|
{
|
|
int DBslot, j;
|
|
|
|
DBslot=GetEnumID(name);
|
|
if(DBslot==INVALID_ENUM) return NULL;
|
|
|
|
for(j=0;j<m_EnumDatabase[DBslot].num_values;j++)
|
|
if(m_EnumDatabase[DBslot].values[j].value == value)
|
|
return(m_EnumDatabase[DBslot].values[j].name);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// Obtains the value bound to an enum value name,
|
|
// Returns TRUE if value was found, FALSE otherwise
|
|
bool CDallasMainDlg::GetEnumValue(char *name, char *value_name, int &value)
|
|
{
|
|
int DBslot, j;
|
|
|
|
DBslot=GetEnumID(name);
|
|
if(DBslot==INVALID_ENUM) return FALSE;
|
|
|
|
for(j=0;j<m_EnumDatabase[DBslot].num_values;j++)
|
|
if(strcmp(m_EnumDatabase[DBslot].values[j].name,value_name)==0) {
|
|
value=m_EnumDatabase[DBslot].values[j].value;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Fills up the given menu with the available enumeration types
|
|
// NOTE: Command ID's of objects items start at the given command_offset
|
|
int CDallasMainDlg::FillEnumTypesMenu(CMenu *enum_menu, int command_offset, char *valid_name)
|
|
{
|
|
CString name;
|
|
int enum_types_added;
|
|
int i;
|
|
|
|
// Set the counts
|
|
enum_types_added=0;
|
|
|
|
// Fill the menu with names of matching enumeration values
|
|
for (i=0;i<m_NumEnums;i++) {
|
|
name=m_EnumDatabase[i].name;
|
|
if(m_EnumDatabase[i].is_user_type) name+=" (USER TYPE)";
|
|
if(strlen(valid_name)==0 || strcmp(valid_name,m_EnumDatabase[i].name)==0) {
|
|
enum_menu->AppendMenu(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;i<enum_entry->num_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;j<MAX_FLAGS;j++) {
|
|
m_FlagDatabase[j].name=NULL;
|
|
for(k=0;k<MAX_FLAG_VALUES;k++) {
|
|
m_FlagDatabase[j].values[k].name=NULL;
|
|
m_FlagDatabase[j].values[k].value=0;
|
|
}
|
|
m_FlagDatabase[j].num_values=0;
|
|
}
|
|
m_NumFlags=0;
|
|
}
|
|
|
|
|
|
// Clears any allocated data for the Flags
|
|
void CDallasMainDlg::ClearFlagDatabase(void)
|
|
{
|
|
int j,k;
|
|
|
|
for(j=0;j<m_NumFlags;j++) {
|
|
if(m_FlagDatabase[j].name!=NULL) {
|
|
mem_free(m_FlagDatabase[j].name);
|
|
m_FlagDatabase[j].name=NULL;
|
|
}
|
|
for(k=0;k<m_FlagDatabase[j].num_values;k++) {
|
|
if(m_FlagDatabase[j].values[k].name!=NULL) {
|
|
mem_free(m_FlagDatabase[j].values[k].name);
|
|
m_FlagDatabase[j].values[k].name=NULL;
|
|
}
|
|
m_FlagDatabase[j].values[k].value=0;
|
|
}
|
|
m_FlagDatabase[j].num_values=0;
|
|
}
|
|
m_NumFlags=0;
|
|
}
|
|
|
|
|
|
// Returns the DB slot matching the given Flag type name
|
|
int CDallasMainDlg::GetFlagID(char *name)
|
|
{
|
|
int i;
|
|
|
|
if(name==NULL) return INVALID_FLAG;
|
|
|
|
for(i=0;i<m_NumFlags;i++)
|
|
if(strcmp(m_FlagDatabase[i].name,name) == 0)
|
|
return i;
|
|
|
|
return INVALID_FLAG;
|
|
}
|
|
|
|
|
|
// Returns the name bound to an flag value
|
|
char *CDallasMainDlg::GetFlagValueName(char *name, int value)
|
|
{
|
|
int DBslot, j;
|
|
|
|
DBslot=GetFlagID(name);
|
|
if(DBslot==INVALID_FLAG) return NULL;
|
|
|
|
for(j=0;j<m_FlagDatabase[DBslot].num_values;j++)
|
|
if(m_FlagDatabase[DBslot].values[j].value == value)
|
|
return(m_FlagDatabase[DBslot].values[j].name);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// Returns the name bound to an Flag value
|
|
bool CDallasMainDlg::FormatFlagValueNames(char *name, int value, CString &text)
|
|
{
|
|
int DBslot, j;
|
|
bool first_added;
|
|
|
|
DBslot=GetFlagID(name);
|
|
if(DBslot==INVALID_FLAG) return FALSE;
|
|
|
|
first_added=TRUE;
|
|
text="";
|
|
for(j=0;j<m_FlagDatabase[DBslot].num_values;j++) {
|
|
if(m_FlagDatabase[DBslot].values[j].value & value) {
|
|
if(!first_added)
|
|
text+=",";
|
|
else {
|
|
text+='[';
|
|
first_added=FALSE;
|
|
}
|
|
text+=m_FlagDatabase[DBslot].values[j].name;
|
|
}
|
|
}
|
|
|
|
if(text.IsEmpty())
|
|
text="[NO FLAGS SET]";
|
|
else
|
|
text+=']';
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Obtains the value bound to an Flag value name,
|
|
// Returns TRUE if value was found, FALSE otherwise
|
|
bool CDallasMainDlg::GetFlagValue(char *name, char *value_name, int &value)
|
|
{
|
|
int DBslot, j;
|
|
|
|
DBslot=GetFlagID(name);
|
|
if(DBslot==INVALID_FLAG) return FALSE;
|
|
|
|
for(j=0;j<m_FlagDatabase[DBslot].num_values;j++)
|
|
if(strcmp(m_FlagDatabase[DBslot].values[j].name,value_name)==0) {
|
|
value=m_FlagDatabase[DBslot].values[j].value;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Fills up the given menu with the available flag types
|
|
// NOTE: Command ID's of objects items start at the given command_offset
|
|
int CDallasMainDlg::FillFlagTypesMenu(CMenu *flag_menu, int command_offset, char *valid_name)
|
|
{
|
|
int flag_types_added;
|
|
int i;
|
|
|
|
// Set the counts
|
|
flag_types_added=0;
|
|
|
|
// Fill the menu with names of matching Flageration values
|
|
for (i=0;i<m_NumFlags;i++) {
|
|
if(strlen(valid_name)==0 || strcmp(valid_name,m_FlagDatabase[i].name)==0) {
|
|
flag_menu->AppendMenu(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;i<flag_entry->num_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<MAX_CATEGORIES;j++)
|
|
m_FunctionCategories[j]=NULL;
|
|
m_NumFunctionCategories=0;
|
|
|
|
for(j=0;j<MAX_ACTIONS;j++) {
|
|
m_ActionDatabase[j].category=INVALID_CATEGORY;
|
|
m_ActionDatabase[j].desc=NULL;
|
|
m_ActionDatabase[j].func=NULL;
|
|
m_ActionDatabase[j].help=NULL;
|
|
}
|
|
m_NumActions=0;
|
|
|
|
for(j=0;j<MAX_QUERIES;j++) {
|
|
m_QueryDatabase[j].category=INVALID_CATEGORY;
|
|
m_QueryDatabase[j].desc=NULL;
|
|
m_QueryDatabase[j].func=NULL;
|
|
m_QueryDatabase[j].help=NULL;
|
|
}
|
|
m_NumQueries=0;
|
|
}
|
|
|
|
// Frees up any allocated memory
|
|
void CDallasMainDlg::ClearFunctionDatabases(void)
|
|
{
|
|
int j;
|
|
|
|
for(j=0;j<m_NumFunctionCategories;j++)
|
|
mem_free(m_FunctionCategories[j]);
|
|
m_NumFunctionCategories=0;
|
|
|
|
for(j=0;j<m_NumActions;j++) {
|
|
m_ActionDatabase[j].category=INVALID_CATEGORY;
|
|
mem_free(m_ActionDatabase[j].desc);
|
|
m_ActionDatabase[j].desc=NULL;
|
|
mem_free(m_ActionDatabase[j].func);
|
|
m_ActionDatabase[j].func=NULL;
|
|
mem_free(m_ActionDatabase[j].help);
|
|
m_ActionDatabase[j].help=NULL;
|
|
}
|
|
m_NumActions=0;
|
|
|
|
for(j=0;j<m_NumQueries;j++) {
|
|
m_QueryDatabase[j].category=INVALID_CATEGORY;
|
|
mem_free(m_QueryDatabase[j].desc);
|
|
m_QueryDatabase[j].desc=NULL;
|
|
mem_free(m_QueryDatabase[j].func);
|
|
m_QueryDatabase[j].func=NULL;
|
|
mem_free(m_QueryDatabase[j].help);
|
|
m_QueryDatabase[j].help=NULL;
|
|
}
|
|
m_NumQueries=0;
|
|
}
|
|
|
|
// Matches an integer ID to a given category name
|
|
int CDallasMainDlg::GetFunctionCategoryID(char *catname)
|
|
{
|
|
for (int i=0;i<m_NumFunctionCategories;i++)
|
|
if (strcmp(m_FunctionCategories[i],catname) == 0)
|
|
return i;
|
|
|
|
return INVALID_CATEGORY;
|
|
}
|
|
|
|
// Handle Parse Errors
|
|
void CDallasMainDlg::FunctionFileParseError(int error_code, int linenum, const char *filename)
|
|
{
|
|
CString err_msg;
|
|
|
|
switch(error_code) {
|
|
case INV_CAT_ERR:
|
|
err_msg.Format("ERROR: Invalid category assigned in %s, line %d.",filename,linenum);
|
|
break;
|
|
case INV_ENUM_ERR:
|
|
err_msg.Format("ERROR: Invalid or duplicate enumeration name assigned in %s, line %d.",filename,linenum);
|
|
break;
|
|
case INV_ENUM_VALUE_ERR:
|
|
err_msg.Format("ERROR: Invalid or duplicate enumeration value assigned in %s, line %d.",filename,linenum);
|
|
break;
|
|
case MAX_ENUM_ERR:
|
|
err_msg.Format("ERROR: Maximum enumeration limit reached in %s, line %d.",filename,linenum);
|
|
break;
|
|
case MAX_ENUM_VALUES_ERR:
|
|
err_msg.Format("ERROR: Maximum enumeration value limit reached in %s, line %d.",filename,linenum);
|
|
break;
|
|
case INV_FLAG_ERR:
|
|
err_msg.Format("ERROR: Invalid or duplicate flag name assigned in %s, line %d.",filename,linenum);
|
|
break;
|
|
case INV_FLAG_VALUE_ERR:
|
|
err_msg.Format("ERROR: Invalid or duplicate flag value assigned in %s, line %d.",filename,linenum);
|
|
break;
|
|
case MAX_FLAG_ERR:
|
|
err_msg.Format("ERROR: Maximum flag limit reached in %s, line %d.",filename,linenum);
|
|
break;
|
|
case MAX_FLAG_VALUES_ERR:
|
|
err_msg.Format("ERROR: Maximum flag value limit reached in %s, line %d.",filename,linenum);
|
|
break;
|
|
case NO_MEM_ERR:
|
|
err_msg.Format("ERROR: Ran out of memory while parsing %s, line %d.",filename,linenum);
|
|
break;
|
|
case UEOF_ERR:
|
|
err_msg.Format("ERROR: Unexpected end of file while parsing %s, line %d.",filename,linenum);
|
|
break;
|
|
default:
|
|
err_msg.Format("ERROR: An unknown error was detected in %s, line %d.",filename,linenum);
|
|
break;
|
|
}
|
|
|
|
MessageBox(err_msg,"Function Database Parse Error",MB_OK|MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
// Returns a pointer to the action description
|
|
char *CDallasMainDlg::GetActionDesc(int ID)
|
|
{
|
|
if(ID<0 || ID>=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_NumActions;j++)
|
|
if(strcmp(m_ActionDatabase[j].func,func_name)==0) return(j);
|
|
|
|
return INVALID_FUNCTION_ID;
|
|
}
|
|
|
|
// Returns a pointer to the query description
|
|
char *CDallasMainDlg::GetQueryDesc(int ID)
|
|
{
|
|
if(ID<0 || ID>=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;j<m_NumQueries;j++)
|
|
if(strcmp(m_QueryDatabase[j].func,func_name)==0) return(j);
|
|
|
|
return INVALID_FUNCTION_ID;
|
|
}
|
|
|
|
// Returns the Query's return type (parameter type), or UNKNOWN_PARAMETER_TYPE
|
|
int CDallasMainDlg::GetQueryReturnType(int ID, CString &name)
|
|
{
|
|
char *desc;
|
|
int type;
|
|
|
|
name="";
|
|
desc=GetQueryDesc(ID);
|
|
if(desc==NULL) return(UNKNOWN_PARAMETER_TYPE);
|
|
|
|
if(!isalpha(desc[0])) return(UNKNOWN_PARAMETER_TYPE);
|
|
type=ConvertParamCharToType(desc[0]);
|
|
|
|
if(type!=ENUM_PARAMETER_TYPE && type!=FLAG_PARAMETER_TYPE) {
|
|
if(desc[1]!=':') return(UNKNOWN_PARAMETER_TYPE);
|
|
return(type);
|
|
}
|
|
|
|
// If it's an enum or flag, we need to get the name of the enum/flag type as well
|
|
if(desc[1]=='(')
|
|
for(int j=2;(desc[j]!='\0' && desc[j]!=')');j++)
|
|
name+=desc[j];
|
|
|
|
return(type);
|
|
}
|
|
|
|
|
|
// Parses the given text file, adding categories, actions, and queries, as it finds them
|
|
void CDallasMainDlg::ParseFunctionFile(char *filename, bool show_errors/*=TRUE*/)
|
|
{
|
|
CFILE *ifile;
|
|
char linebuf[2048];
|
|
char *line;
|
|
char helpbuf[2048];
|
|
int linenum;
|
|
char fullpath[_MAX_PATH];
|
|
|
|
ddio_MakePath(fullpath,LocalScriptDir,filename,NULL);
|
|
|
|
ifile = cfopen(fullpath,"rt");
|
|
if(ifile==NULL) {
|
|
if(show_errors) {
|
|
CString msg;
|
|
msg.Format("Unable to open \"%s\"!",filename);
|
|
MessageBox(msg,"No Function Database Found!",MB_OK|MB_ICONEXCLAMATION);
|
|
}
|
|
return;
|
|
}
|
|
|
|
linenum = 0;
|
|
|
|
while (! cfeof(ifile)) {
|
|
|
|
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_CAT,strlen(TAG_CAT)) == 0) { // parse a category block
|
|
bool 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(m_NumFunctionCategories<MAX_CATEGORIES) {
|
|
if(GetFunctionCategoryID(line)==INVALID_CATEGORY) { // don't add duplicate categories
|
|
m_FunctionCategories[m_NumFunctionCategories] = (char *) mem_malloc(strlen(line)+1);
|
|
if(m_FunctionCategories[m_NumFunctionCategories]==NULL) {
|
|
FunctionFileParseError(NO_MEM_ERR,linenum,filename);
|
|
cfclose(ifile);
|
|
return;
|
|
}
|
|
strcpy(m_FunctionCategories[m_NumFunctionCategories],line);
|
|
m_NumFunctionCategories++;
|
|
if(m_NumFunctionCategories==MAX_CATEGORIES)
|
|
MessageBox("Warning: The Maximum Category limit has been reached!","Warning!");
|
|
}
|
|
}
|
|
|
|
} while (!done && !cfeof(ifile));
|
|
|
|
if (!done)
|
|
FunctionFileParseError(UEOF_ERR,linenum,filename);
|
|
}
|
|
else if (strncmp(line,TAG_USERTYPE,strlen(TAG_USERTYPE))==0) { // Parse a user type line
|
|
tEnumDBEntry *enum_entry;
|
|
char *enum_name;
|
|
char *max_value_text;
|
|
|
|
// Strip off the name of this user type
|
|
max_value_text=NULL;
|
|
enum_name=strtok(line,WHITESPACE_CHARS);
|
|
if(enum_name!=NULL) enum_name=strtok(NULL,":");
|
|
if(enum_name!=NULL) max_value_text=strtok(NULL,"");
|
|
if(enum_name==NULL || max_value_text==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=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;j<m_NumFunctionCategories;j++) {
|
|
CMenu category_submenu;
|
|
category_submenu.CreatePopupMenu();
|
|
actions_added=0;
|
|
|
|
// Scan the list, adding Actions that match the current category
|
|
for(k=0;k<m_NumActions;k++)
|
|
if(m_ActionDatabase[k].category==j) {
|
|
char *temp_desc = (char *) mem_malloc(strlen(m_ActionDatabase[k].desc)+1);
|
|
if(temp_desc==NULL) {
|
|
MessageBox("Out of memory error in FillActionMenu()!","Memory Error!", MB_OK|MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
ParseOutActionVarTypes(temp_desc,m_ActionDatabase[k].desc);
|
|
category_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, (command_offset+k), temp_desc);
|
|
mem_free(temp_desc);
|
|
actions_added++;
|
|
}
|
|
|
|
// Detach and add this submenu to the action menu
|
|
ColumnizePopupMenu(&category_submenu);
|
|
if(actions_added==0)
|
|
action_menu->AppendMenu(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;j<m_NumFunctionCategories;j++) {
|
|
CMenu category_submenu;
|
|
category_submenu.CreatePopupMenu();
|
|
queries_added=0;
|
|
|
|
// Scan the list, adding queries that match the current category
|
|
for(k=0;k<m_NumActions;k++)
|
|
if(m_QueryDatabase[k].category==j) {
|
|
char *temp_desc = (char *) mem_malloc(strlen(m_QueryDatabase[k].desc)+1);
|
|
if(temp_desc==NULL) {
|
|
MessageBox("Out of memory error in FillQueryMenu()!","Memory Error!", MB_OK|MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
ParseOutQueryVarTypes(temp_desc,m_QueryDatabase[k].desc);
|
|
|
|
query_ret_type=GetQueryReturnType(k,query_ret_name);
|
|
|
|
// See if the types match up
|
|
types_match=FALSE;
|
|
if(valid_return_type==ANY_PARAMETER_TYPE)
|
|
types_match=TRUE;
|
|
else if(valid_return_type==query_ret_type) {
|
|
if(valid_return_type==ENUM_PARAMETER_TYPE || valid_return_type==FLAG_PARAMETER_TYPE) {
|
|
if(strlen(valid_return_name)==0)
|
|
types_match=TRUE;
|
|
else if(strcmp(valid_return_name,query_ret_name.GetBuffer(0))==0)
|
|
types_match=TRUE;
|
|
}
|
|
else
|
|
types_match=TRUE;
|
|
}
|
|
|
|
if(types_match) {
|
|
category_submenu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, (command_offset+k), temp_desc);
|
|
queries_added++;
|
|
}
|
|
else
|
|
category_submenu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING, (command_offset+k), temp_desc);
|
|
mem_free(temp_desc);
|
|
}
|
|
|
|
// Detach and add this submenu to the action menu
|
|
ColumnizePopupMenu(&category_submenu);
|
|
if(queries_added==0)
|
|
query_menu->AppendMenu(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<n;j++)
|
|
if(s!=NULL) {
|
|
s++;
|
|
s=strchr(s,'[');
|
|
}
|
|
|
|
// Make sure the requested section was found
|
|
if(s==NULL) return FALSE;
|
|
|
|
// Parse the parameter block into its different sections
|
|
return(ParseParamBlock(s,name_text,default_text,range_text));
|
|
}
|
|
|
|
|
|
#define NO_SECTION 0
|
|
#define TYPE_SECTION 1
|
|
#define NAME_SECTION 2
|
|
#define DEFAULT_SECTION 3
|
|
#define RANGE_SECTION 4
|
|
|
|
// Parses the next param block encountered, and, if successfull, returns the
|
|
// parameter type (-1 is returned if a parameter block was not found).
|
|
// The name, default, and range strings are also set appropriately, and the
|
|
// line pointer will be set to the first character after the closing bracket.
|
|
int
|
|
CDallasMainDlg::ParseParamBlock
|
|
(
|
|
char_ptr &line,
|
|
CString &name_text,
|
|
CString &default_text,
|
|
CString &range_text
|
|
)
|
|
{
|
|
int param_type_char;
|
|
|
|
// Set all the return data to empty
|
|
name_text="";
|
|
default_text="";
|
|
range_text="";
|
|
param_type_char=-1;
|
|
|
|
// Parse the parameter block
|
|
int currently_parsing=NO_SECTION;
|
|
bool done=FALSE;
|
|
while(!done && (*line)!='\0') {
|
|
|
|
char ch=(*line);
|
|
if(ch=='[') { // Start of parameter block
|
|
currently_parsing=TYPE_SECTION;
|
|
}
|
|
else if(ch==']') { // End of parameter block
|
|
done=TRUE;
|
|
}
|
|
else if(ch==':') { // Start of name section or range section
|
|
if(currently_parsing==NAME_SECTION || currently_parsing==DEFAULT_SECTION)
|
|
currently_parsing=RANGE_SECTION;
|
|
else
|
|
currently_parsing=NAME_SECTION;
|
|
}
|
|
else if(ch=='=') { // Start of default section
|
|
if(currently_parsing==NAME_SECTION)
|
|
currently_parsing=DEFAULT_SECTION;
|
|
}
|
|
else { // It is just a character, so parse it appropriately
|
|
switch(currently_parsing) {
|
|
case NO_SECTION: break;
|
|
case TYPE_SECTION: if(param_type_char==-1) param_type_char=ch; break;
|
|
case NAME_SECTION: name_text+=ch; break;
|
|
case DEFAULT_SECTION: default_text+=ch; break;
|
|
case RANGE_SECTION: range_text+=ch; break;
|
|
}
|
|
}
|
|
|
|
// Get the next character
|
|
line++;
|
|
}
|
|
|
|
// If end of line reached before end of block, return an error value
|
|
if(!done) return (-1);
|
|
|
|
// Otherwise, return what was found
|
|
return(ConvertParamCharToType(param_type_char));
|
|
}
|
|
|
|
|
|
#define RANGE_START_NUM 0
|
|
#define RANGE_END_NUM 1
|
|
|
|
// Returns TRUE if the given integer is in the given range, FALSE otherwise
|
|
bool CDallasMainDlg::VerifyIntegerRange(int value, char *range_desc)
|
|
{
|
|
CString num_text;
|
|
int range_start=0, range_end=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=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;
|
|
}
|
|
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;j<m_NumScriptGroups;j++) {
|
|
for(k=0;k<MAX_EVENT_TYPES;k++) {
|
|
tEventSection *event_section=&m_ScriptGroupingList[j].event_sections[k];
|
|
if(event_section->num_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;j<m_NumScriptGroups;j++) {
|
|
if(m_ScriptGroupingList[j].owner_type != owner_data->ID) 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<MAX_EVENT_TYPES;j++) {
|
|
m_ScriptGroupingList[new_pos].event_sections[j].num_script_nodes=0;
|
|
m_ScriptGroupingList[new_pos].event_sections[j].script_node_list=NULL;
|
|
}
|
|
|
|
// Now add it officially to the grouping list
|
|
return(AddNodeToScriptOwnerGroup(new_pos,script_node));
|
|
}
|
|
|
|
|
|
// Adds every script from the tree to the Grouping List
|
|
int CDallasMainDlg::BuildScriptGroupingList(void)
|
|
{
|
|
HTREEITEM script_header_node;
|
|
|
|
// Clear the grouping list first
|
|
ClearScriptGroupingList();
|
|
|
|
// Group each script header node into the list
|
|
script_header_node=m_ScriptTree.GetChildItem(TVI_ROOT);
|
|
while(script_header_node!=NULL) {
|
|
AddNodeToScriptGroupingList(script_header_node);
|
|
script_header_node=m_ScriptTree.GetNextSiblingItem(script_header_node);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Creates an ID constant name for a given owner node
|
|
char *CDallasMainDlg::CreateScriptConstantName(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("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="<FilenameNotSet>";
|
|
|
|
// 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<m_ObjectListSize) {
|
|
node_data.int_val=osipf_FindObjectName(m_ObjectList[index]);
|
|
if(node_data.int_val != OBJECT_HANDLE_NONE) {
|
|
strcpy(node_data.str_val,m_ObjectList[index]);
|
|
}
|
|
else {
|
|
strcpy(node_data.str_val,"");
|
|
SpecialScriptFileParseError(linenum,scriptID,"Object Script Owner",m_ObjectList[index]);
|
|
}
|
|
}
|
|
else {
|
|
node_data.int_val=OBJECT_HANDLE_NONE;
|
|
strcpy(node_data.str_val,"");
|
|
}
|
|
}
|
|
else if(node_data.ID==TRIGGER_TYPE) {
|
|
if(index>=0 && index<m_TriggerListSize) {
|
|
node_data.int_val=osipf_FindTriggerName(m_TriggerList[index]);
|
|
if(node_data.int_val >= 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<m_DoorListSize) {
|
|
node_data.int_val=osipf_FindDoorName(m_DoorList[index]);
|
|
if(node_data.int_val != OBJECT_HANDLE_NONE) {
|
|
strcpy(node_data.str_val,m_DoorList[index]);
|
|
}
|
|
else {
|
|
strcpy(node_data.str_val,"");
|
|
SpecialScriptFileParseError(linenum,scriptID,"Door",m_DoorList[index]);
|
|
}
|
|
}
|
|
else {
|
|
node_data.int_val=OBJECT_HANDLE_NONE;
|
|
strcpy(node_data.str_val,"");
|
|
}
|
|
}
|
|
else {
|
|
node_data.int_val=OBJECT_HANDLE_NONE;
|
|
strcpy(node_data.str_val,"");
|
|
}
|
|
|
|
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;
|
|
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<m_ObjectListSize) {
|
|
node_data.int_val=osipf_FindObjectName(m_ObjectList[index]);
|
|
if(node_data.int_val != OBJECT_HANDLE_NONE) {
|
|
strcpy(node_data.str_val,m_ObjectList[index]);
|
|
}
|
|
else {
|
|
strcpy(node_data.str_val,"");
|
|
SpecialScriptFileParseError(linenum,scriptID,"Object",m_ObjectList[index]);
|
|
}
|
|
}
|
|
else {
|
|
node_data.int_val=OBJECT_HANDLE_NONE;
|
|
strcpy(node_data.str_val,"");
|
|
}
|
|
}
|
|
else {
|
|
node_data.int_val=OBJECT_HANDLE_NONE;
|
|
strcpy(node_data.str_val,"");
|
|
}
|
|
|
|
add_node=TRUE;
|
|
break;
|
|
case ROOM_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<m_RoomListSize) {
|
|
node_data.int_val=osipf_FindRoomName(m_RoomList[index]);
|
|
if(node_data.int_val >= 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<m_TriggerListSize) {
|
|
node_data.int_val=osipf_FindTriggerName(m_TriggerList[index]);
|
|
if(node_data.int_val >= 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<m_SoundListSize) {
|
|
node_data.int_val=osipf_FindSoundName(m_SoundList[index]);
|
|
if(node_data.int_val >= 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<m_SpecnameListSize)
|
|
strcpy(node_data.str_val,m_SpecnameList[index]);
|
|
else
|
|
strcpy(node_data.str_val,"");
|
|
|
|
add_node=TRUE;
|
|
break;
|
|
case TEXTURE_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<m_TextureListSize) {
|
|
node_data.int_val=osipf_FindTextureName(m_TextureList[index]);
|
|
if(node_data.int_val >= 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<m_PathListSize) {
|
|
node_data.int_val=osipf_FindPathName(m_PathList[index]);
|
|
if(node_data.int_val >= 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<m_MatcenListSize) {
|
|
node_data.int_val=osipf_FindMatcenName(m_MatcenList[index]);
|
|
if(node_data.int_val >= 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<m_GoalListSize) {
|
|
node_data.int_val=osipf_FindLevelGoalName(m_GoalList[index]);
|
|
if(node_data.int_val >= 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 && index<m_StrmAudioListSize) {
|
|
if(GamefileExists(m_StrmAudioList[index])) {
|
|
strcpy(node_data.str_val,m_StrmAudioList[index]);
|
|
}
|
|
else {
|
|
strcpy(node_data.str_val,"");
|
|
SpecialScriptFileParseError(linenum,scriptID,"Streaming Audio File",m_StrmAudioList[index]);
|
|
}
|
|
}
|
|
else {
|
|
strcpy(node_data.str_val,"");
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
// Handle Special Parse Errors (Invalid Named Values)
|
|
void CDallasMainDlg::SpecialScriptFileParseError(int linenum, int script_ID, char *type_name, const char *name)
|
|
{
|
|
CString err_msg;
|
|
|
|
if(name==NULL || type_name==NULL) return;
|
|
|
|
err_msg.Format(
|
|
"ERROR: An invalid %s (%s) was encountered in %s, line %d.\n\n"
|
|
"Hence, Script #%d now contains a %s that needs to be replaced.",
|
|
type_name,name,CurrentParsingFilename.GetBuffer(0),linenum,script_ID,type_name);
|
|
|
|
MessageBox(err_msg,"Script File Parse Error",MB_OK|MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
|
|
// Validates a function node by conforming its parameters to what they should be
|
|
// returns FALSE if node was modified significantly, otherwise TRUE
|
|
bool CDallasMainDlg::ValidateFunctionNode(HTREEITEM node, int linenum)
|
|
{
|
|
tTreeNodeData *data;
|
|
|
|
if(node==NULL) return TRUE;
|
|
|
|
data=(tTreeNodeData *)m_ScriptTree.GetItemData(node);
|
|
if(data==NULL) return TRUE;
|
|
|
|
if(data->type==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;j<m_NumCustomScriptLines;j++) {
|
|
mem_free(m_CustomScriptLines[j]);
|
|
m_CustomScriptLines[j]=NULL;
|
|
}
|
|
|
|
// Clear the array of line pointers
|
|
if(m_CustomScriptLines!=NULL) {
|
|
mem_free(m_CustomScriptLines);
|
|
m_CustomScriptLines=NULL;
|
|
}
|
|
|
|
m_NumCustomScriptLines=0;
|
|
m_MaxNumCustomScriptLines=0;
|
|
}
|
|
|
|
|
|
// Scans the file for the custom script block and count how many lines are in it
|
|
int CDallasMainDlg::CountCustomScriptLines(CFILE *infile)
|
|
{
|
|
int32_t start_pos;
|
|
int line_count;
|
|
char linebuf[2048];
|
|
bool done;
|
|
|
|
line_count=0;
|
|
done = false;
|
|
|
|
// Save the current file position
|
|
start_pos=cftell(infile);
|
|
|
|
// Read all the lines in the block
|
|
while (!done && !cfeof(infile)) {
|
|
|
|
strcpy(linebuf,"");
|
|
cf_ReadString(linebuf,sizeof(linebuf),infile);
|
|
|
|
// 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;
|
|
}
|
|
|
|
// If it's not the end of custom block tag, then it's a line we need to save
|
|
line_count++;
|
|
}
|
|
|
|
// Move file pointer back to the original starting position
|
|
cfseek(infile,start_pos,SEEK_SET);
|
|
|
|
return(line_count);
|
|
}
|
|
|
|
|
|
// Reads in and stores all the lines in the custom script block
|
|
int CDallasMainDlg::ParseCustomScriptFile(char *filename, bool show_errors/*=TRUE*/)
|
|
{
|
|
CFILE *infile;
|
|
char linebuf[2048];
|
|
char *line;
|
|
int linenum;
|
|
char fullpath[_MAX_PATH];
|
|
|
|
CurrentParsingFilename=m_ScriptFilename;
|
|
|
|
ddio_MakePath(fullpath,LocalScriptDir,filename,NULL);
|
|
|
|
// Try to open the file for loading
|
|
infile=cfopen (fullpath,"rt");
|
|
if (!infile)
|
|
{
|
|
if(show_errors) {
|
|
CString msg;
|
|
msg.Format("Unable to open \"%s\"!",filename);
|
|
MessageBox(msg,"No Custom Script Source File Found!",MB_OK|MB_ICONEXCLAMATION);
|
|
}
|
|
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,CUSTOM_SCRIPT_BLOCK_START_TAG,strlen(CUSTOM_SCRIPT_BLOCK_START_TAG)) == 0) {
|
|
bool done = false;
|
|
bool warning_issued = false;
|
|
|
|
// Count the number of lines in the file, and allocate room for them
|
|
ClearCustomScriptStorage();
|
|
m_MaxNumCustomScriptLines=CountCustomScriptLines(infile);
|
|
if(m_MaxNumCustomScriptLines>0) {
|
|
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;j<m_NumCustomScriptLines;j++)
|
|
O(("%s",m_CustomScriptLines[j]));
|
|
}
|
|
|
|
O(("%s",CUSTOM_SCRIPT_BLOCK_END_TAG));
|
|
O(("// ============================================================"));
|
|
O(("// End of Custom Script Block - DO NOT EDIT ANYTHING AFTER THIS"));
|
|
O(("// ============================================================"));
|
|
O((" "));
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// File Creation Functions
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Writes message list to file
|
|
int CDallasMainDlg::CreateMsgTableFile(char *filename)
|
|
{
|
|
CFILE *outfile;
|
|
CString buffer;
|
|
int count, j;
|
|
tMessageListEntry *msg_data;
|
|
char fullpath[_MAX_PATH];
|
|
|
|
ddio_MakePath(fullpath,LocalScriptDir,filename,NULL);
|
|
|
|
// Try to open the file for writing
|
|
outfile=cfopen (fullpath,"wt");
|
|
if (!outfile)
|
|
{
|
|
CString msg;
|
|
msg.Format("Unable to open \"%s\"!",filename);
|
|
MessageBox(msg,"Script Message File Error!",MB_OK|MB_ICONEXCLAMATION);
|
|
return FALSE;
|
|
}
|
|
|
|
// Write out comment header
|
|
buffer.Format("//////////////////////////////////////////////");
|
|
cf_WriteString(outfile,buffer.GetBuffer(0));
|
|
buffer.Format("// D.A.L.L.A.S. Generated Message Table File");
|
|
cf_WriteString(outfile,buffer.GetBuffer(0));
|
|
buffer.Format("//////////////////////////////////////////////");
|
|
cf_WriteString(outfile,buffer.GetBuffer(0));
|
|
cf_WriteString(outfile,"");
|
|
|
|
// Write out the next message ID number
|
|
buffer.Format("%s %d",NEXT_MSG_ID_NUM_KEYWORD,m_NextMessageID);
|
|
cf_WriteString(outfile,buffer.GetBuffer(0));
|
|
cf_WriteString(outfile,"");
|
|
|
|
// Write out the message list comment header
|
|
buffer.Format("// Message List");
|
|
cf_WriteString(outfile,buffer.GetBuffer(0));
|
|
|
|
// Write out each message
|
|
count=m_MessageList.GetCount();
|
|
for(j=0;j<count;j++) {
|
|
msg_data=(tMessageListEntry *)m_MessageList.GetItemData(j);
|
|
if(msg_data) {
|
|
buffer.Format("%s=%s",msg_data->name,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<CurrentTabLevel;j++)
|
|
cfprintf(CurrentOutputFile,"\t");
|
|
}
|
|
|
|
|
|
// Create the source script CPP file
|
|
int CDallasMainDlg::CreateScriptFile(char *filename)
|
|
{
|
|
char fullpath[_MAX_PATH];
|
|
int j, counter, num_CO_scripts;
|
|
|
|
// Fill the name lists (and check for any invalid/not selected fields)
|
|
ClearNameLists();
|
|
if(FillNameListsFromTree(TVI_ROOT,TRUE)!=0) {
|
|
int ret_val;
|
|
ret_val=MessageBox("Due to invalid script data, it is probably unsafe to save and compile.\n\nDo you wish to proceed anyway?","Script Problems Encountered!",MB_YESNO|MB_ICONQUESTION);
|
|
if(ret_val==IDNO) return FALSE;
|
|
}
|
|
|
|
// Build the organized list of scripts
|
|
BuildScriptGroupingList();
|
|
|
|
// Open the file for writing
|
|
ddio_MakePath(fullpath,LocalScriptDir,filename,NULL);
|
|
CurrentOutputFile = cfopen(fullpath,"wt");
|
|
if(CurrentOutputFile==NULL) {
|
|
CString msg, title;
|
|
msg.Format("ERROR: Unable to open %s for output.",fullpath);
|
|
title.Format("Script Save Error!");
|
|
MessageBox(msg,title,MB_OK|MB_ICONEXCLAMATION);
|
|
return FALSE;
|
|
}
|
|
|
|
// Write out the header info
|
|
O(("/////////////////////////////////////////////////////////////////////"));
|
|
O(("// D.A.L.L.A.S. Generated Level Script - DLL Source File"));
|
|
O(("// "));
|
|
O(("// Filename: %s",filename));
|
|
O(("// Version: %d",DALLAS_SAVE_VERSION));
|
|
O(("/////////////////////////////////////////////////////////////////////"));
|
|
O(("#include <stdio.h>"));
|
|
O(("#include <stdlib.h>"));
|
|
O(("#include <string.h>"));
|
|
O(("#include <ctype.h>"));
|
|
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;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE) {
|
|
O(("#define %s 0x%03x",CreateScriptConstantName(j),counter++));
|
|
num_CO_scripts++;
|
|
}
|
|
O((""));
|
|
|
|
// Write out the trigger ID's
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==TRIGGER_TYPE)
|
|
O(("#define %s 0x%03x",CreateScriptConstantName(j),counter++));
|
|
O((""));
|
|
|
|
// Write out the base script class definition
|
|
O(("// ========================"));
|
|
O(("// Script Class Definitions"));
|
|
O(("// ========================"));
|
|
O((""));
|
|
O(("class BaseScript {"));
|
|
O(("public:"));
|
|
O((" BaseScript();"));
|
|
O((" ~BaseScript();"));
|
|
O((" virtual int16_t CallEvent(int event, tOSIRISEventInfo *data);"));
|
|
O(("};"));
|
|
O((""));
|
|
|
|
// Write out the level script class definition
|
|
O(("class %s : public BaseScript {",LEVEL_CLASS_NAME));
|
|
O(("public:"));
|
|
O((" int16_t CallEvent(int event, tOSIRISEventInfo *data);"));
|
|
O(("};"));
|
|
O((""));
|
|
|
|
// Write out the custom object class definitions
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE) {
|
|
O(("class %s : public BaseScript {",CreateScriptClassName(j)));
|
|
O(("public:"));
|
|
O((" int16_t CallEvent(int event, tOSIRISEventInfo *data);"));
|
|
O(("};"));
|
|
O((""));
|
|
}
|
|
|
|
// Write out the trigger class definitions
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==TRIGGER_TYPE) {
|
|
O(("class %s : public BaseScript {",CreateScriptClassName(j)));
|
|
O(("public:"));
|
|
O((" int16_t CallEvent(int event, tOSIRISEventInfo *data);"));
|
|
O(("};"));
|
|
O((""));
|
|
}
|
|
|
|
// Write out the global script action counters
|
|
O(("// ======================"));
|
|
O(("// Global Action Counters"));
|
|
O(("// ======================"));
|
|
O((""));
|
|
O(("#define MAX_ACTION_CTR_VALUE 100000"));
|
|
O((""));
|
|
|
|
// Loop through all the scripts, write one global for each script
|
|
HTREEITEM script_node;
|
|
tTreeNodeData *data;
|
|
|
|
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(("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(("struct tScriptMessage {"));
|
|
O((" char *name; // the name of the message"));
|
|
O((" char *message; // the actual message text"));
|
|
O(("};"));
|
|
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;j<MAX_SCRIPT_MESSAGES;j++)"));
|
|
O((" message_list[j]=NULL;"));
|
|
O((" num_messages=0;"));
|
|
O(("}"));
|
|
O((" "));
|
|
O(("// Clear the Message List"));
|
|
O(("void ClearMessageList(void)"));
|
|
O(("{"));
|
|
O((" for(int j=0;j<num_messages;j++) {"));
|
|
O((" free(message_list[j]->name);"));
|
|
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;j<num_messages;j++)"));
|
|
O((" if(strcmp(message_list[j]->name,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;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE) {
|
|
O((" case %s:",CreateScriptConstantName(j)));
|
|
O((" return new %s;",CreateScriptClassName(j)));
|
|
O((" break;"));
|
|
}
|
|
|
|
// Trigger Cases
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==TRIGGER_TYPE) {
|
|
O((" case %s:",CreateScriptConstantName(j)));
|
|
O((" return new %s;",CreateScriptClassName(j)));
|
|
O((" break;"));
|
|
}
|
|
|
|
O((" default:"));
|
|
O((" mprintf(0,\"SCRIPT: Illegal ID (%%d)\\n\",id);"));
|
|
O((" break;"));
|
|
|
|
O((" }"));
|
|
O((" return NULL;"));
|
|
O(("}"));
|
|
O((""));
|
|
|
|
O(("// ================="));
|
|
O(("// DestroyInstance()"));
|
|
O(("// ================="));
|
|
O(("void STDCALL DestroyInstance(int id,void *ptr)"));
|
|
O(("{"));
|
|
O((" switch(id) {"));
|
|
|
|
// Level Case
|
|
O((" case %s:",LEVEL_ID_NAME));
|
|
O((" delete ((%s *)ptr);",LEVEL_CLASS_NAME));
|
|
|
|
// Custom object Cases
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE) {
|
|
O((" case %s:",CreateScriptConstantName(j)));
|
|
O((" delete ((%s *)ptr);",CreateScriptClassName(j)));
|
|
O((" break;"));
|
|
}
|
|
|
|
// Trigger Cases
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==TRIGGER_TYPE) {
|
|
O((" case %s:",CreateScriptConstantName(j)));
|
|
O((" delete ((%s *)ptr);",CreateScriptClassName(j)));
|
|
O((" break;"));
|
|
}
|
|
|
|
O((" default:"));
|
|
O((" mprintf(0,\"SCRIPT: Illegal ID (%%d)\\n\",id);"));
|
|
O((" break;"));
|
|
|
|
O((" }"));
|
|
O(("}"));
|
|
O((""));
|
|
|
|
O(("// ==================="));
|
|
O(("// CallInstanceEvent()"));
|
|
O(("// ==================="));
|
|
O(("int16_t STDCALL CallInstanceEvent(int id,void *ptr,int event,tOSIRISEventInfo *data)"));
|
|
O(("{"));
|
|
O((" switch(id) {"));
|
|
|
|
// Level Case
|
|
O((" case %s:",LEVEL_ID_NAME));
|
|
|
|
// Custom object Cases
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE)
|
|
O((" case %s:",CreateScriptConstantName(j)));
|
|
|
|
// Trigger Cases
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==TRIGGER_TYPE)
|
|
O((" case %s:",CreateScriptConstantName(j)));
|
|
|
|
O((" return ((BaseScript *)ptr)->CallEvent(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<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==TRIGGER_TYPE) {
|
|
CString troom_text, tface_text;
|
|
troom_text="-1";
|
|
tface_text="-1";
|
|
int t=m_ScriptGroupingList[j].owner_handle;
|
|
if(t>=0 && t<Num_triggers && t<MAX_NAMED_TRIGGERS && strlen(Triggers[t].name)!=0) {
|
|
int index=FindTriggerInList(Triggers[t].name);
|
|
if(index>=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;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE) {
|
|
counter++;
|
|
if(counter<num_CO_scripts)
|
|
O((" %s,",CreateScriptConstantName(j)));
|
|
else
|
|
O((" %s",CreateScriptConstantName(j)));
|
|
}
|
|
|
|
O((" };"));
|
|
}
|
|
|
|
// Fill in the custom object handles array
|
|
O((" "));
|
|
counter=0;
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE) {
|
|
|
|
// Obtain the handle text
|
|
CString handle_text;
|
|
|
|
handle_text.Format("0x%04x",OBJECT_HANDLE_NONE);
|
|
object *objp=ObjGet(m_ScriptGroupingList[j].owner_handle);
|
|
if(objp!=NULL && objp->type!=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;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==LEVEL_TYPE)
|
|
owner_group=&m_ScriptGroupingList[j];
|
|
|
|
// Create the event cases for the level script
|
|
CreateLevelEventCases(owner_group);
|
|
|
|
O((" }"));
|
|
O((" return CONTINUE_CHAIN|CONTINUE_DEFAULT;"));
|
|
O(("}"));
|
|
O((""));
|
|
|
|
// Create the CallEvent() methods for each custom object script class
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==OBJECT_TYPE) {
|
|
O(("int16_t %s::CallEvent(int event,tOSIRISEventInfo *data)",CreateScriptClassName(j)));
|
|
O(("{"));
|
|
O((" switch(event) { "));
|
|
|
|
// Create the event cases for the custom object script
|
|
owner_group=&m_ScriptGroupingList[j];
|
|
CreateEventCases(owner_group);
|
|
|
|
O((" }"));
|
|
O((" return CONTINUE_CHAIN|CONTINUE_DEFAULT;"));
|
|
O(("}"));
|
|
O((""));
|
|
}
|
|
|
|
// Create the CallEvent() methods for each trigger script class
|
|
for(j=0;j<m_NumScriptGroups;j++)
|
|
if(m_ScriptGroupingList[j].owner_type==TRIGGER_TYPE) {
|
|
O(("int16_t %s::CallEvent(int event,tOSIRISEventInfo *data)",CreateScriptClassName(j)));
|
|
O(("{"));
|
|
O((" switch(event) { "));
|
|
|
|
// Create the event cases for the trigger script
|
|
owner_group=&m_ScriptGroupingList[j];
|
|
CreateEventCases(owner_group);
|
|
|
|
O((" }"));
|
|
O((" return CONTINUE_CHAIN|CONTINUE_DEFAULT;"));
|
|
O(("}"));
|
|
O((""));
|
|
}
|
|
|
|
// Create the Script Save Block
|
|
WriteScriptSaveBlock();
|
|
|
|
cfclose(CurrentOutputFile);
|
|
CurrentOutputFile=NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Creates the level event cases
|
|
// NOTE: Some level events must always be handled to perform init/load/save/etc.
|
|
void CDallasMainDlg::CreateLevelEventCases(tScriptOwnerGroup *owner_group)
|
|
{
|
|
int j,k;
|
|
|
|
if(CurrentOutputFile==NULL) return;
|
|
|
|
// Handle the saving event
|
|
O((" case EVT_SAVESTATE:"));
|
|
O((" {"));
|
|
O((" tOSIRISEVTSAVESTATE *event_data=&data->evt_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;j<MAX_EVENT_TYPES;j++) {
|
|
tEventSection *event_section;
|
|
if(owner_group!=NULL)
|
|
event_section=&owner_group->event_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;k<event_section->num_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;j<MAX_EVENT_TYPES;j++) {
|
|
tEventSection *event_section=&owner_group->event_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;k<event_section->num_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;j<m_NumEnums;j++) {
|
|
if(m_EnumDatabase[j].is_user_type) {
|
|
O(("%s %s",USERTYPE_VALS_START_TAG,m_EnumDatabase[j].name));
|
|
for(k=0;k<m_EnumDatabase[j].num_values;k++) {
|
|
tEnumValueEntry *value_entry=&m_EnumDatabase[j].values[k];
|
|
if(value_entry->value!=-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;j<m_DoorListSize;j++)
|
|
O(("%s",m_DoorList[j]));
|
|
O(("%s",DOOR_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the object list
|
|
O(("%s",OBJECT_LIST_START_TAG));
|
|
for(j=0;j<m_ObjectListSize;j++)
|
|
O(("%s",m_ObjectList[j]));
|
|
O(("%s",OBJECT_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the room list
|
|
O(("%s",ROOM_LIST_START_TAG));
|
|
for(j=0;j<m_RoomListSize;j++)
|
|
O(("%s",m_RoomList[j]));
|
|
O(("%s",ROOM_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the trigger list
|
|
O(("%s",TRIGGER_LIST_START_TAG));
|
|
for(j=0;j<m_TriggerListSize;j++)
|
|
O(("%s",m_TriggerList[j]));
|
|
O(("%s",TRIGGER_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the sound list
|
|
O(("%s",SOUND_LIST_START_TAG));
|
|
for(j=0;j<m_SoundListSize;j++)
|
|
O(("%s",m_SoundList[j]));
|
|
O(("%s",SOUND_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the texture list
|
|
O(("%s",TEXTURE_LIST_START_TAG));
|
|
for(j=0;j<m_TextureListSize;j++)
|
|
O(("%s",m_TextureList[j]));
|
|
O(("%s",TEXTURE_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the specname list
|
|
O(("%s",SPECNAME_LIST_START_TAG));
|
|
for(j=0;j<m_SpecnameListSize;j++)
|
|
O(("%s",m_SpecnameList[j]));
|
|
O(("%s",SPECNAME_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the Path list
|
|
O(("%s",PATH_LIST_START_TAG));
|
|
for(j=0;j<m_PathListSize;j++)
|
|
O(("%s",m_PathList[j]));
|
|
O(("%s",PATH_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the Matcen list
|
|
O(("%s",MATCEN_LIST_START_TAG));
|
|
for(j=0;j<m_MatcenListSize;j++)
|
|
O(("%s",m_MatcenList[j]));
|
|
O(("%s",MATCEN_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the Goal list
|
|
O(("%s",GOAL_LIST_START_TAG));
|
|
for(j=0;j<m_GoalListSize;j++)
|
|
O(("%s",m_GoalList[j]));
|
|
O(("%s",GOAL_LIST_END_TAG));
|
|
O((" "));
|
|
|
|
// Write out the StrmAudio list
|
|
O(("%s",STRM_AUDIO_LIST_START_TAG));
|
|
for(j=0;j<m_StrmAudioListSize;j++)
|
|
O(("%s",m_StrmAudioList[j]));
|
|
O(("%s",STRM_AUDIO_LIST_END_TAG));
|
|
O((" "));
|
|
}
|
|
|
|
|
|
// Writes out the name list arrays in the code
|
|
void CDallasMainDlg::WriteNameListArrays(void)
|
|
{
|
|
int j;
|
|
|
|
if(CurrentOutputFile==NULL) return;
|
|
|
|
O((" "));
|
|
O(("//======================"));
|
|
O(("// Name List Arrays "));
|
|
O(("//======================"));
|
|
O((" "));
|
|
|
|
// Write out the door list
|
|
O(("#define NUM_DOOR_NAMES %d",m_DoorListSize));
|
|
if(m_DoorListSize>0) {
|
|
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;j<NUM_DOOR_NAMES;j++) "));
|
|
O((" Door_handles[j]=Scrpt_FindDoorName(Door_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Object Index lookups"));
|
|
O((" for(j=0;j<NUM_OBJECT_NAMES;j++) "));
|
|
O((" Object_handles[j]=Scrpt_FindObjectName(Object_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Room Index lookups"));
|
|
O((" for(j=0;j<NUM_ROOM_NAMES;j++) "));
|
|
O((" Room_indexes[j]=Scrpt_FindRoomName(Room_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Trigger Index lookups"));
|
|
O((" for(j=0;j<NUM_TRIGGER_NAMES;j++) {"));
|
|
O((" Trigger_indexes[j]=Scrpt_FindTriggerName(Trigger_names[j]);"));
|
|
O((" Trigger_faces[j]=Scrpt_GetTriggerFace(Trigger_indexes[j]);"));
|
|
O((" Trigger_rooms[j]=Scrpt_GetTriggerRoom(Trigger_indexes[j]);"));
|
|
O((" }"));
|
|
O((" "));
|
|
O((" // Do Sound Index lookups"));
|
|
O((" for(j=0;j<NUM_SOUND_NAMES;j++) "));
|
|
O((" Sound_indexes[j]=Scrpt_FindSoundName(Sound_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Texture Index lookups"));
|
|
O((" for(j=0;j<NUM_TEXTURE_NAMES;j++) "));
|
|
O((" Texture_indexes[j]=Scrpt_FindTextureName(Texture_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Path Index lookups"));
|
|
O((" for(j=0;j<NUM_PATH_NAMES;j++) "));
|
|
O((" Path_indexes[j]=Scrpt_FindPathName(Path_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Matcen Index lookups"));
|
|
O((" for(j=0;j<NUM_MATCEN_NAMES;j++) "));
|
|
O((" Matcen_indexes[j]=Scrpt_FindMatcenName(Matcen_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Goal Index lookups"));
|
|
O((" for(j=0;j<NUM_GOAL_NAMES;j++) "));
|
|
O((" Goal_indexes[j]=Scrpt_FindLevelGoalName(Goal_names[j]);"));
|
|
O((" "));
|
|
O((" // Do Message Name lookups"));
|
|
O((" for(j=0;j<NUM_MESSAGE_NAMES;j++) "));
|
|
O((" Message_strings[j]=GetMessage(Message_names[j]);"));
|
|
}
|
|
|
|
|
|
// Writes out a coded version of all the script nodes in the tree
|
|
void CDallasMainDlg::WriteScriptTreeDump(void)
|
|
{
|
|
HTREEITEM node;
|
|
tTreeNodeData *data;
|
|
|
|
if(CurrentOutputFile==NULL) return;
|
|
|
|
CurrentTabLevel=0;
|
|
|
|
// Write out each script node (and any children)
|
|
node=m_ScriptTree.GetChildItem(TVI_ROOT);
|
|
while(node!=NULL) {
|
|
data=(tTreeNodeData *)m_ScriptTree.GetItemData(node);
|
|
if(data!=NULL && data->type==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;(t<Num_triggers && t<MAX_NAMED_TRIGGERS);t++,tp++) {
|
|
if(strlen(tp->name)>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;p<MAX_GAME_PATHS;p++) {
|
|
if(GamePaths[p].used && strlen(GamePaths[p].name)>0) {
|
|
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;p<MAX_MATCENS;p++) {
|
|
if(MatcenValid(p)) {
|
|
char matcen_name[MAX_MATCEN_NAME_LEN+1];
|
|
Matcen[p]->GetName(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<num_goals;p++) {
|
|
char goal_name[_MAX_PATH+1];
|
|
if(Level_goals.GoalGetName(p,goal_name,_MAX_PATH)>=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;j<num_msgs;j++) {
|
|
CString msg_name;
|
|
m_MessageList.GetText(j,msg_name);
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING, ASSIGN_MESSAGE_ID_RANGE_START+j, msg_name.GetBuffer(0));
|
|
}
|
|
}
|
|
break;
|
|
case PERCENTAGE_PARAMETER_TYPE:
|
|
{
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter Percentage Value...");
|
|
main_menu.AppendMenu(MF_SEPARATOR, 0, "");
|
|
}
|
|
break;
|
|
case ENUM_PARAMETER_TYPE:
|
|
{
|
|
if(strcmp(param_name,"GoalID")==0) {
|
|
if(has_a_goalID)
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_ENUM_GOAL_ID, "GOAL ID");
|
|
else
|
|
main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_ENUM_GOAL_ID, "GOAL ID");
|
|
main_menu.AppendMenu(MF_SEPARATOR, 0, "");
|
|
}
|
|
|
|
if(strcmp(param_name,"TimerID")==0) {
|
|
if(has_a_timerID)
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_ENUM_TIMER_ID, "TIMER ID");
|
|
else
|
|
main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_ENUM_TIMER_ID, "TIMER ID");
|
|
main_menu.AppendMenu(MF_SEPARATOR, 0, "");
|
|
}
|
|
|
|
if(strcmp(param_name,"MatcenID")==0) {
|
|
if(has_a_matcenID)
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_ENUM_MATCEN_ID, "MATCEN ID");
|
|
else
|
|
main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_ENUM_MATCEN_ID, "MATCEN ID");
|
|
main_menu.AppendMenu(MF_SEPARATOR, 0, "");
|
|
}
|
|
|
|
FillEnumValuesMenu(&main_menu,ASSIGN_ENUM_VALUE_ID_RANGE_START,param_name);
|
|
}
|
|
break;
|
|
case SCRIPT_PARAMETER_TYPE:
|
|
{
|
|
FillScriptMenu(&main_menu,ASSIGN_SCRIPT_ID_RANGE_START);
|
|
}
|
|
break;
|
|
case SOUND_PARAMETER_TYPE:
|
|
{
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Select a Different Sound...");
|
|
}
|
|
break;
|
|
case SPECNAME_PARAMETER_TYPE:
|
|
{
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Enter a Specific Name...");
|
|
}
|
|
break;
|
|
case TEXTURE_PARAMETER_TYPE:
|
|
{
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Select a Different Texture...");
|
|
}
|
|
break;
|
|
case FLAG_PARAMETER_TYPE:
|
|
{
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Select the Flags to Set...");
|
|
}
|
|
break;
|
|
case PATH_PARAMETER_TYPE:
|
|
{
|
|
FillPathMenu(&main_menu,ASSIGN_PATH_ID_RANGE_START);
|
|
}
|
|
break;
|
|
case MATCEN_PARAMETER_TYPE:
|
|
{
|
|
if(has_a_matcenID)
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_MATCEN_EVENT_ID, "MATCEN ID");
|
|
else
|
|
main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_MATCEN_EVENT_ID, "MATCEN ID");
|
|
main_menu.AppendMenu(MF_SEPARATOR, 0, "");
|
|
FillMatcenMenu(&main_menu,ASSIGN_MATCEN_ID_RANGE_START);
|
|
}
|
|
break;
|
|
case LEVEL_GOAL_PARAMETER_TYPE:
|
|
{
|
|
if(has_a_levgoalID)
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_LEVEL_GOAL_ID, "LEVEL GOAL ID");
|
|
else
|
|
main_menu.AppendMenu(MF_GRAYED | MF_UNCHECKED | MF_STRING,ASSIGN_LEVEL_GOAL_ID, "LEVEL GOAL ID");
|
|
main_menu.AppendMenu(MF_SEPARATOR, 0, "");
|
|
FillLevelGoalMenu(&main_menu,ASSIGN_LEVEL_GOAL_ID_RANGE_START);
|
|
}
|
|
break;
|
|
case STRM_AUDIO_PARAMETER_TYPE:
|
|
{
|
|
main_menu.AppendMenu(MF_ENABLED | MF_UNCHECKED | MF_STRING,ASSIGN_SPECIFIC_VALUE_ID, "Select the Streaming Audio File...");
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
main_menu.AppendMenu(MF_SEPARATOR, 0, "");
|
|
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();
|
|
}
|
|
|
|
|
|
// 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(pos<item_count) {
|
|
CString name;
|
|
UINT id;
|
|
UINT flags;
|
|
UINT state;
|
|
|
|
// Get the name of the item
|
|
menu->GetMenuString(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_val<MAX_SOUNDS && Sounds[data->int_val].used)
|
|
dlg.m_SoundName=Sounds[data->int_val].name;
|
|
|
|
if(dlg.DoModal()==IDCANCEL) return;
|
|
|
|
if(dlg.m_SoundIndex>=0 && dlg.m_SoundIndex<MAX_SOUNDS && Sounds[dlg.m_SoundIndex].used) {
|
|
data->int_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_val<MAX_TEXTURES && GameTextures[data->int_val].used)
|
|
dlg.m_TextureName=GameTextures[data->int_val].name;
|
|
|
|
if(dlg.DoModal()==IDCANCEL) return;
|
|
|
|
if(dlg.m_TextureIndex>=0 && dlg.m_TextureIndex<MAX_TEXTURES && GameTextures[dlg.m_TextureIndex].used) {
|
|
data->int_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;j<strlen(newname);j++)
|
|
if(newname[j]=='"' || newname[j]==':') {
|
|
MessageBox("That specific name is invalid!\n\nNo quotes or colons are allowed.","Invalid Message ID Error",MB_OK|MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
// Copy in the new name
|
|
strncpy(data->str_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_id<MAX_QUERIES) {
|
|
|
|
// Get the node's data
|
|
tTreeNodeData *data=(tTreeNodeData *)m_ScriptTree.GetItemData(first_parm_node);
|
|
|
|
// Make sure this node is valid for adding a query
|
|
if(data!=NULL && (data->type==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<total;index++) {
|
|
int data=m_EventList.GetItemData(index);
|
|
if(data==type) {
|
|
m_EventList.SetCurSel(index);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDallasMainDlg::OnAllobjRadio()
|
|
{
|
|
m_ScriptOwnerType=ALL_OBJECTS_TYPE;
|
|
m_ScriptOwnerHandle=0;
|
|
//SetHighlightedEvent(ALL_EVENT_TYPES);
|
|
|
|
HighlightAllScripts();
|
|
}
|
|
|
|
void CDallasMainDlg::OnAlltrigRadio()
|
|
{
|
|
m_ScriptOwnerType=ALL_TRIGGERS_TYPE;
|
|
m_ScriptOwnerHandle=0;
|
|
|
|
HighlightAllScripts();
|
|
}
|
|
|
|
void CDallasMainDlg::OnNoneRadio()
|
|
{
|
|
m_ScriptOwnerType=NONE_TYPE;
|
|
m_ScriptOwnerHandle=0;
|
|
|
|
HighlightAllScripts();
|
|
}
|
|
|
|
void CDallasMainDlg::OnSpecificRadio()
|
|
{
|
|
OnHighlightButton();
|
|
}
|
|
|
|
void CDallasMainDlg::OnLevelRadio()
|
|
{
|
|
m_ScriptOwnerType=LEVEL_TYPE;
|
|
m_ScriptOwnerHandle=0;
|
|
|
|
HighlightAllScripts();
|
|
}
|
|
|
|
void CDallasMainDlg::OnEventRadio()
|
|
{
|
|
m_ScriptOwnerType=ALL_OWNERS_TYPE;
|
|
m_ScriptOwnerHandle=0;
|
|
|
|
HighlightAllScripts();
|
|
}
|
|
|
|
void CDallasMainDlg::OnSelchangeEventCombo()
|
|
{
|
|
HighlightAllScripts();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Functions to Handle Import/Export
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Display a script library file selection dialog
|
|
bool CDallasMainDlg::ScriptLibraryFilePrompt(CString &filename, bool use_import_msg)
|
|
{
|
|
static CString last_path="";
|
|
CString filter;
|
|
char *default_fname;
|
|
CString title;
|
|
bool dlg_type;
|
|
|
|
if(use_import_msg) {
|
|
title="Import Script from what Library File?";
|
|
dlg_type=TRUE;
|
|
}
|
|
else {
|
|
title="Export Script to what Library File?";
|
|
dlg_type=FALSE;
|
|
}
|
|
|
|
if(last_path.IsEmpty())
|
|
default_fname=NULL;
|
|
else
|
|
default_fname=last_path.GetBuffer(0);
|
|
|
|
filename="";
|
|
filter = "Dallas Script Library Files (*.dsl)|*.dsl|All Files (*.*)|*.*||";
|
|
CFileDialog dlg_open(dlg_type, NULL, default_fname, OFN_FILEMUSTEXIST, (LPCTSTR)filter, this);
|
|
dlg_open.m_ofn.lpstrTitle=title.GetBuffer(0);
|
|
if (dlg_open.DoModal() == IDCANCEL) {
|
|
return FALSE;
|
|
}
|
|
|
|
filename=dlg_open.GetPathName();
|
|
if(filename.Find('.')<0)
|
|
filename+=".dsl";
|
|
last_path=filename;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Scans given .dsl file for given name, and imports it
|
|
bool CDallasMainDlg::ImportScriptFromFile(char *filename, char *script_name)
|
|
{
|
|
CFILE *infile;
|
|
char linebuf[2048];
|
|
char tempbuf[256];
|
|
char *line;
|
|
int linenum;
|
|
int valid_lines_read, version;
|
|
int rc;
|
|
|
|
HTREEITEM last_node_added, current_parent, insert_before, returned_node;
|
|
HTREEITEM selected_node, initial_insert_before, new_script_header;
|
|
bool skip_children;
|
|
int skip_depth;
|
|
bool last_node_childless;
|
|
bool ScriptToImportFound;
|
|
|
|
// Determine the initial insert before script header node
|
|
selected_node=m_ScriptTree.GetSelectedItem();
|
|
if(selected_node==NULL) return FALSE;
|
|
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 FALSE;
|
|
if(m_ScriptTree.GetParentItem(initial_insert_before)!=NULL) return FALSE;
|
|
}
|
|
|
|
CurrentParsingFilename=filename;
|
|
new_script_header=NULL;
|
|
|
|
// Try to open the file for loading
|
|
infile=cfopen (filename,"rt");
|
|
if (!infile)
|
|
{
|
|
CString msg;
|
|
msg.Format("Unable to open \"%s\"!",filename);
|
|
MessageBox(msg,"Script Library File Not Found!",MB_OK|MB_ICONEXCLAMATION);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
linenum=0;
|
|
ScriptToImportFound=FALSE;
|
|
|
|
// Read in and parse each line of the file
|
|
while (!cfeof(infile) && !ScriptToImportFound) {
|
|
|
|
// 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;
|
|
|
|
// 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_END_TAG,strlen(SCRIPT_END_TAG)) == 0) {
|
|
done=true;
|
|
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 script name line
|
|
if(valid_lines_read==0) {
|
|
if(stricmp(line,script_name)==0)
|
|
ScriptToImportFound=TRUE;
|
|
else
|
|
ScriptToImportFound=FALSE;
|
|
valid_lines_read++;
|
|
continue;
|
|
}
|
|
|
|
// See if it should be the save version line
|
|
if(valid_lines_read==1) {
|
|
rc=sscanf(line,"%s %d",tempbuf,&version);
|
|
if(rc==2 && strcmp(tempbuf,"VERSION")==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 && ScriptToImportFound) {
|
|
|
|
if(initial_insert_before!=NULL) {
|
|
insert_before=initial_insert_before;
|
|
initial_insert_before=NULL;
|
|
}
|
|
else
|
|
insert_before=TVI_LAST;
|
|
|
|
if(version>=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;
|
|
}
|