/* * Descent 3 * Copyright (C) 2024 Parallax Software * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/editor/ScriptWizard.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003-08-26 03:57:39 $ * $Author: kevinb $ * * Script Wizard * * $Log: not supported by cvs2svn $ * * 20 11/06/98 12:34p Jason * more speedups for manage system * * 19 10/08/98 4:24p Kevin * Changed code to comply with memory library usage. Always use mem_malloc * , mem_free and mem_strdup * * 18 8/31/98 4:12p Samir * select level script by default in listbox. * * 17 6/23/98 3:04p Samir * sped up script list generation. * * 16 6/23/98 2:43p Matt * Changed calls to OutrageMessageBox() & Debug_MessageBox() to deal with * int return value (instead of bool). * * 15 4/14/98 7:31p Matt * Changed code to use ddio_MakePath() instead of sprintf() to create file * spec * * 14 1/23/98 4:45p Samir * Make level.scr be the default. * * 13 9/26/97 4:15p Samir * Mostly working system to go to a certain script in a file. * * 12 9/25/97 5:28p Samir * Even newer script code due to more changes in ObjCScript.cpp * * 11 9/24/97 6:18p Samir * Fix some memory leakage probs. * * 10 9/24/97 2:57p Samir * New ScriptWizard functionality, without extra commenting in files. * * 9 9/22/97 5:59p Samir * Changed ObjCScript system, so everything is broken, but it shouldn't * crash the game. * * 8 9/10/97 1:58p Samir * Fixed up some code to select multiple script files. * * 7 9/04/97 4:39p Matt * Added includes needed as a result of removing includes from d3edit.h * * 6 9/02/97 3:28p Matt * Got rid of warnings * * 5 8/21/97 6:00p Samir * A whole lot of script editing stuff added for ScriptWizard. * * 4 8/20/97 3:35p Samir * Enhanced ScriptStudio to use tabs! Use new ScriptStudio instead of * ScriptEditor. * * $NoKeywords: $ */ // ScriptWizard.cpp : implementation file // #include "stdafx.h" #include "editor.h" #include "ScriptWizard.h" #include "ObjCScript.h" #include "manage.h" #include "EditLineDialog.h" #include "ScriptEditorDlg.h" #include "gamefile.h" #include "manage\gamefilepage.h" #include "ScriptStudio.h" #include "AddScriptDialog.h" #include "pserror.h" #include "ddio.h" #include "mem.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CScriptWizard dialog CScriptWizard::CScriptWizard(CWnd* pParent /*=NULL*/) : CDialog(CScriptWizard::IDD, pParent) { //{{AFX_DATA_INIT(CScriptWizard) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT m_ScriptSource = NULL; m_ScriptCode = NULL; } void CScriptWizard::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CScriptWizard) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CScriptWizard, CDialog) //{{AFX_MSG_MAP(CScriptWizard) ON_BN_CLICKED(IDC_ADDSCRIPT, OnAddScript) ON_BN_CLICKED(IDC_LOCK, OnLock) ON_BN_CLICKED(IDC_UNLOCK, OnUnlock) ON_BN_CLICKED(IDC_EDITSCRIPT, OnEditScript) ON_LBN_SELCHANGE(IDC_SCR_LISTBOX, OnSelChangeScrListbox) ON_BN_CLICKED(IDC_ADDEVENT, OnAddEvent) ON_LBN_SELCHANGE(IDC_SCREVT_LISTBOX, OnSelchangeScrevtListbox) ON_CBN_SELCHANGE(IDC_SCRMOD_BOX, OnSelchangeScrmodBox) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CScriptWizard message handlers BOOL CScriptWizard::OnInitDialog() { CDialog::OnInitDialog(); // Place all valid script files into the module combo box, then // place all script names relating to the current script file into the script // listbox. CComboBox *modcbox = (CComboBox *)GetDlgItem(IDC_SCRMOD_BOX); m_ScriptCode = D3XReallocProgram(NULL, 0, 0, 0); ResetScriptList(); // place all filenames of scripts into combo box char scrfilename[64]; char *filename; scrfilename[0] = 0; filename = StartScriptFileList(); while (filename) { strcpy(scrfilename, filename); modcbox->AddString(filename); filename = GetNextScriptFile(); } EndScriptFileList(); modcbox->SelectString(-1, LEVEL_SCRIPT_NAME); // update listboxes accordingly to current script module ScriptFileName[0] = 0; ScriptCodeName[0] = 0; CScriptWizard::LoadCurrentModule(); // Updates the buttons UpdateDialogButtons(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CScriptWizard::OnDestroy() { CDialog::OnDestroy(); if (m_ScriptCode) D3XFreeProgram(m_ScriptCode); ResetScriptList(); } // We save whatever was added to the script. This does not include text added via edit // (that's done in the internal script editor.) It does include text added from operations like // Add Script, Add Event, etc. void CScriptWizard::OnOK() { SaveScript(ScriptFileName, m_ScriptSource); FreeScript(m_ScriptSource); CDialog::OnOK(); } // We just don't save anything. We free the script, if there is one void CScriptWizard::OnCancel() { FreeScript(m_ScriptSource); CDialog::OnCancel(); } // Adds a script to the current editable script. We will not allow this if the script is not locked, // so we should allow then to unlock it at this point. void CScriptWizard::OnAddScript() { char scrname[MAX_SCRNAME]; scrname[0] = 0; if (strlen(ScriptFileName) == 0) { OutrageMessageBox("There is no script file to add a script to! You must make one."); return; } // check if current module is locked by us. if (mng_FindTrackLock(ScriptFileName, PAGETYPE_GAMEFILE) == -1) OutrageMessageBox("Warning: This script is not locked by you.\nAny changes you make will not be permanent."); // request a name for this new script! CAddScriptDialog dlg(this); if (dlg.DoModal() == IDOK) { // add script to listbox, then select it, then run editor CListBox *lb = (CListBox *)GetDlgItem(IDC_SCR_LISTBOX); char *tempstr = AddScriptBlockToScript(m_ScriptSource, (LPCSTR)dlg.m_Name, (LPCSTR)dlg.m_TypeName); mem_free(m_ScriptSource); m_ScriptSource = tempstr; UpdateScriptListbox(); lb->SelectString(-1, (LPCSTR)dlg.m_Name); OnEditScript(); } else { OutrageMessageBox("A script name is required to continue. Cancelling action."); } } void CScriptWizard::OnAddEvent() { CListBox *listbox = (CListBox *)GetDlgItem(IDC_SCREVT_LISTBOX); CListBox *scrlb = (CListBox *)GetDlgItem(IDC_SCR_LISTBOX); char *tempstr; char evtname[MAX_EVTNAME]; char scrname[MAX_SCRNAME]; ASSERT(listbox->GetCurSel() != LB_ERR); ASSERT(scrlb->GetCurSel() != LB_ERR); scrlb->GetText(scrlb->GetCurSel(), scrname); listbox->GetText(listbox->GetCurSel(), evtname); tempstr = AddEventBlockToScript(m_ScriptSource, evtname, scrname); if (!tempstr) { OutrageMessageBox("Failed to add event to script.\nScript text possibly corrupted."); return; } mem_free(m_ScriptSource); m_ScriptSource = tempstr; } // This code invokes the original OSIRIS editor dialog with the currently loaded script file. void CScriptWizard::OnEditScript() { CScriptStudio studio; CScriptEditorDlg editor; if (strlen(ScriptFileName) == 0) { OutrageMessageBox("There is no script file to add a script to! You must make one."); return; } // check if current module is locked by us. if (FindGamefileName(ScriptFileName) != -1) { if (mng_FindTrackLock(ScriptFileName, PAGETYPE_GAMEFILE) == -1) { OutrageMessageBox("Warning: This script is not locked by you.\nAny changes you make will not be permanent."); } } //@@** //@@**// Do default external editor stuff. Jeff Slutter's code. //@@** if(strlen(Default_external_editor)==0) //@@** { //@@** char buffer[256]; //@@** CString default_path; //@@** int size=GetWindowsDirectory(buffer,256); //@@** ASSERT(size<256); //@@** buffer[size]='\\'; //@@** buffer[size+1]='\0'; //@@** //@@** default_path=buffer; //@@** default_path+="Notepad.exe"; //@@** editor.SetExternalEditor(default_path.GetBuffer(1)); //@@** } //@@** else //@@** { //@@** editor.SetExternalEditor(Default_external_editor); //@@** } // Now just set the current source loaded as the editor's source // Also create a program so that the compiler can char buf[64]; CListBox *scrlistbox = (CListBox *)GetDlgItem(IDC_SCR_LISTBOX); scrlistbox->GetText(scrlistbox->GetCurSel(), buf); studio.SelectText(buf); studio.SetD3XObject(m_ScriptCode); studio.SetText(CString(m_ScriptSource)); if (studio.DoModal() == IDOK) { //Try and compile now CString tempstr; FreeScript(m_ScriptSource); studio.GetText(tempstr); m_ScriptSource = (char *) mem_malloc(tempstr.GetLength()+1); if(m_ScriptSource) { strcpy(m_ScriptSource, (LPCSTR)tempstr); SaveScript(ScriptFileName, m_ScriptSource); FreeScript(m_ScriptSource); m_ScriptSource = LoadScript(ScriptFileName); // After this, Source_script has new edited script. if (!CompileScript(studio.GetD3XObject(), m_ScriptSource)) { OutrageMessageBox("Your script did not compile. Unless you fix it, the script will not work."); } else { SaveScriptCode(ScriptCodeName, studio.GetD3XObject()); } } else { OutrageMessageBox("Couldn't allocate memory to save script!"); } } m_ScriptCode = studio.GetD3XObject(); // rebuild list of scripts from changes in source code that may have happened. ResetScriptList(); if (stricmp(ScriptFileName, DEFAULT_SCRIPT_NAME) == 0) GenerateScriptWizardInfo(m_ScriptSource, false); else GenerateScriptWizardInfo(m_ScriptSource, true); UpdateScriptListbox(); //@@** if(strcmp(editor.m_ExternalEditor,Default_external_editor)) //@@** { //@@** strcpy(Default_external_editor,editor.m_ExternalEditor.GetBuffer(1)); //@@** } } // Uses gamefile locking code! // This is taken from FilePageDialog.cpp, with some modifications to the outputted text, but uses the GameFile // page scheme, emulating a script page. void CScriptWizard::OnLock() { int n, r; mngs_Pagelock temp_pl; mngs_gamefile_page gamefilepage; n = FindGamefileName(ScriptFileName); if (n == -1) { OutrageMessageBox("Unable to find script file page in the table file.\nOperation can't be completed."); return; } // start the really involved locking process. if (!mng_MakeLocker()) return; // Make sure it can be locked strcpy (temp_pl.name,Gamefiles[n].name); temp_pl.pagetype=PAGETYPE_GAMEFILE; r=mng_CheckIfPageLocked (&temp_pl); if (r==2) { int answer = OutrageMessageBox (MBOX_YESNO, "This script is not even in the table file, or the database maybe corrupt. Override to 'Unlocked'? (Select NO if you don't know what you're doing)"); if (answer==IDYES) { strcpy (temp_pl.holder,"UNLOCKED"); if (!mng_ReplacePagelock (temp_pl.name,&temp_pl)) MessageBox (ErrorString,"Error!"); } } else if (r<0) OutrageMessageBox (ErrorString); else if (r==1) OutrageMessageBox (InfoString); else { // Everything is ok. Tell the network we're locking it and get a copy to // our local drive strcpy (temp_pl.holder,TableUser); if (!mng_ReplacePagelock (temp_pl.name,&temp_pl)) { MessageBox (ErrorString,"Error!"); mng_EraseLocker(); return; } else { // Search thru the net pagefile and get a new copy in RAM in case anyone // changed it since we started the editor if ( mng_FindSpecificGamefilePage (temp_pl.name,&gamefilepage,0)) { if (mng_AssignGamefilePageToGamefile (&gamefilepage,n)) { if (!mng_ReplacePage (Gamefiles[n].name,Gamefiles[n].name,n,PAGETYPE_GAMEFILE,1)) { OutrageMessageBox ("There was problem writing that page locally!"); mng_EraseLocker(); return; } OutrageMessageBox ("Script locked."); } else OutrageMessageBox ("There was a problem loading this script. You might encounter problems in dealing with it. Good luck!"); mng_AllocTrackLock(Gamefiles[n].name,PAGETYPE_GAMEFILE); UpdateDialogButtons(); } else OutrageMessageBox ("Couldn't find that script in the table file!"); } } mng_EraseLocker(); } // Uses gamefile unlocking code! void CScriptWizard::OnUnlock() { int n, r; mngs_Pagelock temp_pl; n = FindGamefileName(ScriptFileName); if (n == -1) { OutrageMessageBox("Unable to find script file page in the table file.\nOperation can't be completed."); return; } if (!mng_MakeLocker()) return; // Make sure we own this gamefile strcpy (temp_pl.name,Gamefiles[n].name); temp_pl.pagetype=PAGETYPE_GAMEFILE; r=mng_CheckIfPageOwned (&temp_pl,TableUser); if (r<0) OutrageMessageBox (ErrorString); else if (r==0) OutrageMessageBox (InfoString); else { // Change the pagelock state to UNLOCKED strcpy (temp_pl.holder,"UNLOCKED"); if (!mng_ReplacePagelock (temp_pl.name,&temp_pl)) { MessageBox (ErrorString,"Error!"); mng_EraseLocker(); return; } else { // Now actually replace the copy on the net with our local one if (!mng_ReplacePage (Gamefiles[n].name,Gamefiles[n].name,n,PAGETYPE_GAMEFILE,0)) OutrageMessageBox (ErrorString); else { // Save this gamefile file to the network for all // Force the save of the current script file so this actually works char destname[100],srcname[100]; SaveScript(ScriptFileName, m_ScriptSource); ddio_MakePath(srcname,LocalD3Dir,"data",Gamefiles[n].dir_name,Gamefiles[n].name,NULL); ddio_MakePath(destname,NetD3Dir,"data",Gamefiles[n].dir_name,Gamefiles[n].name,NULL); cf_CopyFile (destname,srcname); OutrageMessageBox ("Script checked in."); // Delete it from local pagefile if its there int dret=mng_DeletePage (Gamefiles[n].name,PAGETYPE_GAMEFILE,1); ASSERT (dret==1); mng_EraseLocker(); // Free the tracklock int p=mng_FindTrackLock (Gamefiles[n].name,PAGETYPE_GAMEFILE); ASSERT (p!=-1); mng_FreeTrackLock (p); UpdateDialogButtons(); } } } } void CScriptWizard::OnSelChangeScrListbox() { CListBox *lb = (CListBox *)GetDlgItem(IDC_SCR_LISTBOX); m_CurScriptSel = lb->GetCurSel(); if (m_CurScriptSel == LB_ERR) m_CurScriptSel = -1; } void CScriptWizard::OnSelchangeScrevtListbox() { CListBox *lb = (CListBox *)GetDlgItem(IDC_SCREVT_LISTBOX); m_CurEventSel = lb->GetCurSel(); UpdateDialogButtons(); } // User Interface Update Controllers // ListBox // ComboBox void CScriptWizard::LoadCurrentModule() { CComboBox *modcbox = (CComboBox *)GetDlgItem(IDC_SCRMOD_BOX); char str[MAX_SCRNAME]; // Get current module select and load it in. if (m_ScriptSource) FreeScript(m_ScriptSource); m_ScriptSource = NULL; if (modcbox->GetLBText(modcbox->GetCurSel(), str) != CB_ERR) { char *ptr; m_ScriptSource = LoadScript(str); strcpy(ScriptFileName, str); strcpy(ScriptCodeName, str); ptr = strtok(ScriptCodeName, "."); strcat(ptr, ".d3x"); } // new script file, set current script to 0 m_CurScriptSel = 0; // compile and generate list of script names. ResetScriptList(); if (m_ScriptSource) { if (stricmp(ScriptFileName, DEFAULT_SCRIPT_NAME) == 0) GenerateScriptWizardInfo(m_ScriptSource, false); else GenerateScriptWizardInfo(m_ScriptSource, true); } UpdateScriptListbox(); } void CScriptWizard::UpdateScriptListbox() { CListBox *scrlistbox = (CListBox *)GetDlgItem(IDC_SCR_LISTBOX); int i; // Add script names to list box scrlistbox->ResetContent(); for (i = 0; i < MAX_SCRIPTS; i++) { if (Script_names[i].used) if (!stricmp(ScriptFileName, DEFAULT_SCRIPT_NAME) && !Script_names[i].iscustom) scrlistbox->AddString(Script_names[i].name); else if (stricmp(ScriptFileName, DEFAULT_SCRIPT_NAME) && Script_names[i].iscustom) scrlistbox->AddString(Script_names[i].name); } // make sure we reselect the current string. if (scrlistbox->GetCount() > 0) scrlistbox->SetCurSel(m_CurScriptSel); else m_CurScriptSel = -1; m_CurEventSel = 0; UpdateEventListbox(); } void CScriptWizard::UpdateEventListbox() { CListBox *listbox = (CListBox *)GetDlgItem(IDC_SCREVT_LISTBOX); CListBox *scrlistbox = (CListBox *)GetDlgItem(IDC_SCR_LISTBOX); int i, id; char scrname[MAX_SCRNAME]; // Add script names to list box listbox->ResetContent(); if (m_CurScriptSel > -1) { // get text from listbox, then get script ID from that name, since names are sorted alphabetically // in the listbox. scrlistbox->GetText(m_CurScriptSel, scrname); id = FindScriptIDFromName(scrname); for (i = 0; i < MAX_SCREVTS; i++) listbox->AddString(Script_evt_names[i]); listbox->SetCurSel(m_CurEventSel); } } void CScriptWizard::OnSelchangeScrmodBox() { LoadCurrentModule(); UpdateDialogButtons(); } void CScriptWizard::UpdateDialogButtons() { CButton *btnunlock = (CButton *) GetDlgItem (IDC_UNLOCK); CButton *btnlock = (CButton *)GetDlgItem(IDC_LOCK); CButton *btnedit = (CButton *)GetDlgItem(IDC_EDITSCRIPT); CButton *btnevt = (CButton *)GetDlgItem(IDC_ADDEVENT); CButton *btnundolock = (CButton *)GetDlgItem(IDC_UNDOLOCK); CListBox *evtlb = (CListBox *)GetDlgItem(IDC_SCREVT_LISTBOX); int n; char str[128]; // take care of script locking and unlocking buttons if (stricmp(ScriptFileName, DEFAULT_SCRIPT_NAME) == 0) n = FindGamefileName(ScriptFileName); else n = -1; if (n == -1) { btnunlock->EnableWindow(FALSE); btnlock->EnableWindow(FALSE); btnundolock->EnableWindow(FALSE); } else if (mng_FindTrackLock (Gamefiles[n].name,PAGETYPE_GAMEFILE)==-1) { btnunlock->EnableWindow (FALSE); btnlock->EnableWindow (TRUE); btnundolock->EnableWindow(FALSE); } else { btnunlock->EnableWindow(TRUE); btnlock->EnableWindow (FALSE); btnundolock->EnableWindow(TRUE); } // take care of Editing buttons if (evtlb->GetCurSel() == LB_ERR) btnevt->EnableWindow(FALSE); else { evtlb->GetText(m_CurEventSel, str); btnevt->EnableWindow(TRUE); } if (strlen(ScriptFileName) > 0) btnedit->EnableWindow(TRUE); else btnedit->EnableWindow(FALSE); }