Descent3/editor/WorldObjectsDoorDialog.cpp
2024-09-03 13:26:51 +02:00

1025 lines
28 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/WorldObjectsDoorDialog.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003-08-26 03:57:39 $
* $Author: kevinb $
*
* WorldObjectsDoorDialog.cpp : implementation file
*
* $Log: not supported by cvs2svn $
*
* 26 2/04/99 2:05p Matt
* Added blastable doors
*
* 25 1/21/99 11:15p Jeff
* pulled out some structs and defines from header files and moved them
* into separate header files so that multiplayer dlls don't require major
* game headers, just those new headers. Side effect is a shorter build
* time. Also cleaned up some header file #includes that weren't needed.
* This affected polymodel.h, object.h, player.h, vecmat.h, room.h,
* manage.h and multi.h
*
* 24 1/08/99 2:56p Samir
* Ripped out OSIRIS1.
*
* 23 12/21/98 5:27p Jeff
* added osiris module information to door page. Fixed up dialogs for
* objects and doors for script interface (added a browse button)
*
* 22 11/06/98 12:34p Jason
* more speedups for manage system
*
* 21 10/14/98 12:08p Jason
* fixed some long standing name problems
*
* 20 10/08/98 4:24p Kevin
* Changed code to comply with memory library usage. Always use mem_malloc
* , mem_free and mem_strdup
*
* 19 6/23/98 2:43p Matt
* Changed calls to OutrageMessageBox() & Debug_MessageBox() to deal with
* int return value (instead of bool).
*
* 18 6/15/98 4:00p Jason
* replaced monochromatic polymodel lighting with rgb lighting
*
* 17 5/22/98 8:50p Matt
* Added sounds for doors
*
* 16 4/17/98 1:53p Matt
* Reinitialize all objects when leaving the editor dialogs for generic
* objects (robots, powerps), doors, and player ships.
*
* 15 4/06/98 4:53p Jason
* got pageable polymodels working correctly with editor
*
* 14 4/02/98 3:54p Jason
* first pass in getting polymodel paging to work
*
* 13 2/02/98 7:07p Matt
* Added support for doors that can be seen through even when closed
*
* 12 1/25/98 5:17p Matt
* Changed the door dialog to be more like the generic dialog
*
* 11 1/23/98 5:39p Matt
* Added validity checking for door models.
*
* 10 12/19/97 11:25a Samir
* g3_StartFrame and g3_EndFrame replaced by EditorStartFrame and
* EditorEndFrame
*
* 9 12/01/97 6:06p Samir
* Implemented new FileDialog tracker system.
*
* 8 10/06/97 3:24p Jason
* fixed checkin problem
*
* 7 10/06/97 1:01p Jason
* made doors work with scripts (sort of)
*
* 6 9/11/97 5:38p Jason
* initial door coding for room engine
*
* 5 8/08/97 2:25p Matt
* Took out error messages which are now handled by mng_MakeLocker()
*
* 4 8/07/97 12:42p Jason
* fixed potential memory problem
*
* 3 7/24/97 6:11p Matt
* Created symbolic constant for default zoom, and used it every place
* that specifies zoom
*
* $NoKeywords: $
*/
#include <filesystem>
#include "mfc_compatibility.h"
#include "editor.h"
#include "WorldObjectsDoorDialog.h"
#include "manage.h"
#include "doorpage.h"
#include "mono.h"
#include "vclip.h"
#include "polymodel.h"
#include "door.h"
#include "ddio.h"
#include "EditLineDialog.h"
#include "objinit.h"
#include "soundload.h"
#include "mem.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWorldObjectsDoorDialog dialog
CWorldObjectsDoorDialog::CWorldObjectsDoorDialog(CWnd *pParent /*=NULL*/)
: CDialog(CWorldObjectsDoorDialog::IDD, pParent) {
//{{AFX_DATA_INIT(CWorldObjectsDoorDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CWorldObjectsDoorDialog::DoDataExchange(CDataExchange *pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CWorldObjectsDoorDialog)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CWorldObjectsDoorDialog, CDialog)
//{{AFX_MSG_MAP(CWorldObjectsDoorDialog)
ON_BN_CLICKED(IDC_ADD_DOOR, OnAddDoor)
ON_BN_CLICKED(IDC_CHECKIN_DOOR, OnCheckinDoor)
ON_EN_KILLFOCUS(IDC_CLOSE_TIME, OnKillfocusCloseTime)
ON_BN_CLICKED(IDC_DELETE_DOOR, OnDeleteDoor)
ON_BN_CLICKED(IDC_DOOR_NEXT, OnDoorNext)
ON_EN_KILLFOCUS(IDC_DOOR_OPEN_TIME, OnKillfocusDoorOpenTime)
ON_BN_CLICKED(IDC_DOOR_PREV, OnDoorPrev)
ON_EN_KILLFOCUS(IDC_DOOR_STAYS_OPEN, OnKillfocusDoorStaysOpen)
ON_BN_CLICKED(IDC_DOORS_OUT, OnDoorsOut)
ON_BN_CLICKED(IDC_LOAD_DOOR_MODEL, OnLoadDoorModel)
ON_BN_CLICKED(IDC_LOCK_DOOR, OnLockDoor)
ON_WM_TIMER()
ON_CBN_SELENDOK(IDC_DOOR_PULLDOWN, OnSelendokDoorPulldown)
ON_WM_HELPINFO()
ON_BN_CLICKED(IDC_DOOR_CHANGE_NAME, OnDoorChangeName)
ON_BN_CLICKED(IDC_TRANSPARENCY, OnTransparency)
ON_WM_DESTROY()
ON_CBN_SELENDOK(IDC_DOOR_CLOSE_SOUND, OnSelendokDoorCloseSound)
ON_CBN_SELENDOK(IDC_DOOR_OPEN_SOUND, OnSelendokDoorOpenSound)
ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
ON_EN_KILLFOCUS(IDC_SCRIPTNAME, OnKillfocusScriptname)
ON_BN_CLICKED(IDC_DOOR_BLASTABLE, OnDoorBlastable)
ON_EN_KILLFOCUS(IDC_DOOR_HITPOINTS_EDIT, OnKillfocusDoorHitpointsEdit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWorldObjectsDoorDialog message handlers
#include "room.h"
// Makes sure a door model is ok. If not ok, brings up messagebox to tell the user
// Parameter: handle - the handle for the polymodel
// Returns: true if ok, else false
bool VerifyDoorModel(int handle) {
poly_model *pm = GetPolymodelPointer(handle);
int s;
bool found_frontface = 0, found_shell = 0;
for (s = 0; s < pm->n_models; s++) {
bsp_info *sm = &pm->submodel[s];
if (sm->flags & SOF_FRONTFACE) {
if (sm->num_faces != 1) {
OutrageMessageBox("Invalid door model: Frontface has %d faces; must have 1.", sm->num_faces);
return 0;
}
if (sm->num_children != 0) {
OutrageMessageBox("Invalid door model: Frontface cannot have submodels.");
return 0;
}
found_frontface = 1;
}
if (sm->flags & SOF_SHELL) {
if (sm->num_children != 0) {
OutrageMessageBox("Invalid door model: Shell cannot have submodels.");
return 0;
}
// check polygons in the shell. we do this by copying the poly face into a room
room check_room;
face check_face;
check_room.verts = sm->verts;
check_room.faces = &check_face;
for (int f = 0; f < sm->num_faces; f++) {
polyface *polyface = &sm->faces[f];
// copy polygon face into the room face
check_face.num_verts = polyface->nverts;
check_face.face_verts = polyface->vertnums;
if (!ComputeFaceNormal(&check_room, 0)) {
OutrageMessageBox("Invalid door model: Face %d in shell has bad normal.", f);
return 0;
}
}
found_shell = 1;
}
}
if (!found_frontface) {
OutrageMessageBox("Invalid door model: Missing Frontface.");
return 0;
}
if (!found_shell) {
OutrageMessageBox("Invalid door model: Missing Shell.");
return 0;
}
return 1;
}
void CWorldObjectsDoorDialog::OnAddDoor() {
char filename[256], pathname[256], dir[256], ext[32];
char cur_name[100];
int img_handle;
int door_handle;
int c = 1, finding_name = 1;
if (!Network_up) {
OutrageMessageBox("Sorry babe, the network is down. This action is a no-no.\n");
return;
}
// Get the filename of the representing image
CString filter = "Descent III files (*.pof,*.oof)|*.pof;*.oof||";
if (!OpenFileDialog(this, (LPCSTR)filter, pathname, Current_model_dir, sizeof(Current_model_dir)))
return;
// Okay, we selected a file. Lets do what needs to be done here.
img_handle = LoadDoorImage(pathname, 0);
ddio_SplitPath(pathname, dir, filename, ext);
if (!VerifyDoorModel(img_handle)) {
FreePolyModel(img_handle);
return;
}
if (img_handle < 0) {
OutrageMessageBox("Couldn't open that model file.");
return;
}
// Alloc a door and give a name not already taken by some other door
door_handle = AllocDoor();
while (finding_name) {
if (c == 1)
sprintf(cur_name, "%s", filename);
else
sprintf(cur_name, "%s%d", filename, c);
if (FindDoorName(cur_name) != -1)
c++;
else
finding_name = 0;
}
strcpy(Doors[door_handle].name, cur_name);
Doors[door_handle].model_handle = img_handle;
// Finally, save a local copy of the model/anim and alloc a tracklock
mprintf(0, "Making a copy of this model locally...\n");
std::filesystem::path destname = LocalModelsDir / Poly_models[Doors[door_handle].model_handle].name;
cf_CopyFile(destname, pathname);
mng_AllocTrackLock(cur_name, PAGETYPE_DOOR);
D3EditState.current_door = door_handle;
UpdateDialog();
}
#define NULL_NAME "<none>"
void CWorldObjectsDoorDialog::UpdateDialog() {
CEdit *ebox;
CButton *bbox;
int n = D3EditState.current_door;
char str[50];
if (Num_doors < 1) {
bbox = (CButton *)GetDlgItem(IDC_DOOR_NEXT);
bbox->EnableWindow(FALSE);
bbox = (CButton *)GetDlgItem(IDC_DOOR_PREV);
bbox->EnableWindow(FALSE);
return;
} else {
bbox = (CButton *)GetDlgItem(IDC_DOOR_NEXT);
bbox->EnableWindow(TRUE);
bbox = (CButton *)GetDlgItem(IDC_DOOR_PREV);
bbox->EnableWindow(TRUE);
}
if (!Doors[n].used)
n = D3EditState.current_door = GetNextDoor(n);
// ebox=(CEdit *) GetDlgItem (IDC_DOOR_NAME_EDIT);
// ebox->SetWindowText (Doors[n].name);
bbox = (CButton *)GetDlgItem(IDC_TRANSPARENCY);
bbox->SetCheck(Doors[n].flags & DF_SEETHROUGH);
bool blastable = ((Doors[n].flags & DF_BLASTABLE) != 0);
bbox = (CButton *)GetDlgItem(IDC_DOOR_BLASTABLE);
bbox->SetCheck(blastable);
ebox = (CEdit *)GetDlgItem(IDC_DOOR_MODEL_NAME_EDIT);
ebox->SetWindowText(Poly_models[Doors[n].model_handle].name);
ebox = (CEdit *)GetDlgItem(IDC_DOOR_OPEN_TIME);
sprintf(str, "%f", Doors[n].total_open_time);
ebox->SetWindowText(str);
ebox = (CEdit *)GetDlgItem(IDC_DOOR_STAYS_OPEN);
sprintf(str, "%f", Doors[n].total_time_open);
ebox->SetWindowText(str);
ebox = (CEdit *)GetDlgItem(IDC_CLOSE_TIME);
sprintf(str, "%f", Doors[n].total_close_time);
ebox->SetWindowText(str);
// Update hitpoint editing controls
GetDlgItem(IDC_DOOR_HITPOINTS_TEXT)->EnableWindow(blastable);
ebox = (CEdit *)GetDlgItem(IDC_DOOR_HITPOINTS_EDIT);
sprintf(str, "%d", Doors[n].hit_points);
ebox->SetWindowText(str);
ebox->EnableWindow(blastable);
bbox = (CButton *)GetDlgItem(IDC_CHECKIN_DOOR);
if (mng_FindTrackLock(Doors[n].name, PAGETYPE_DOOR) == -1) {
bbox->EnableWindow(FALSE);
bbox = (CButton *)GetDlgItem(IDC_LOCK_DOOR);
bbox->EnableWindow(TRUE);
} else {
bbox->EnableWindow(TRUE);
bbox = (CButton *)GetDlgItem(IDC_LOCK_DOOR);
bbox->EnableWindow(FALSE);
}
SendDlgItemMessage(IDC_DOOR_PULLDOWN, CB_RESETCONTENT, 0, 0);
for (int i = 0; i < MAX_DOORS; i++) {
if (Doors[i].used)
SendDlgItemMessage(IDC_DOOR_PULLDOWN, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)Doors[i].name);
}
SendDlgItemMessage(IDC_DOOR_PULLDOWN, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)Doors[n].name);
// Update script
ebox = (CEdit *)GetDlgItem(IDC_SCRIPTNAME);
if (!Doors[n].module_name[0])
ebox->SetWindowText("null");
else
ebox->SetWindowText(Doors[n].module_name);
// Update sounds lists
SendDlgItemMessage(IDC_DOOR_OPEN_SOUND, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage(IDC_DOOR_OPEN_SOUND, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)NULL_NAME);
for (auto & Sound : Sounds) {
if (Sound.used)
SendDlgItemMessage(IDC_DOOR_OPEN_SOUND, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)Sound.name);
}
if (Doors[n].open_sound == -1)
SendDlgItemMessage(IDC_DOOR_OPEN_SOUND, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)NULL_NAME);
else
SendDlgItemMessage(IDC_DOOR_OPEN_SOUND, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)Sounds[Doors[n].open_sound].name);
SendDlgItemMessage(IDC_DOOR_CLOSE_SOUND, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage(IDC_DOOR_CLOSE_SOUND, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)NULL_NAME);
for (auto & Sound : Sounds) {
if (Sound.used)
SendDlgItemMessage(IDC_DOOR_CLOSE_SOUND, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)Sound.name);
}
if (Doors[n].close_sound == -1)
SendDlgItemMessage(IDC_DOOR_CLOSE_SOUND, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)NULL_NAME);
else
SendDlgItemMessage(IDC_DOOR_CLOSE_SOUND, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)Sounds[Doors[n].close_sound].name);
UpdateDoorView();
}
#define NUM_ANIM_FRAMES 30
void CWorldObjectsDoorDialog::UpdateDoorView(void) {
int n = D3EditState.current_door;
CWnd *doorwnd;
RECT rect;
int x, y, bm_handle, w, h;
static int frame = 0, spin_frame = 0;
static int last_door = -1;
static int last_model_handle = -1;
static int door_dir = 0;
if (Num_doors < 1)
return;
if (door_dir == 0) {
frame++;
if (frame == NUM_ANIM_FRAMES) {
frame = NUM_ANIM_FRAMES - 1;
door_dir = 1;
}
} else {
frame--;
if (frame == -1) {
frame = 0;
door_dir = 0;
}
}
doorwnd = GetDlgItem(IDC_DOORVIEW);
doorwnd->GetWindowRect(&rect);
ScreenToClient(&rect);
Desktop_surf->attach_to_window((unsigned)m_hWnd);
w = rect.right - rect.left;
h = rect.bottom - rect.top;
if (last_door != n || last_model_handle != Doors[n].model_handle) {
Desktop_surf->clear(rect.left, rect.top, w, h);
last_door = n;
last_model_handle = Doors[n].model_handle;
}
bm_handle = GetDoorImage(n);
vector zero_vector;
vector view_vector = {0, 0, -20};
matrix id_matrix, rot_matrix;
poly_model *pm = GetPolymodelPointer(bm_handle);
vm_MakeZero(&zero_vector);
vm_MakeIdentity(&id_matrix);
float norm_angles[30];
for (int i = 0; i < 30; i++)
norm_angles[i] = (float)frame / (float)NUM_ANIM_FRAMES;
spin_frame++;
vm_AnglesToMatrix(&rot_matrix, 0, spin_frame * 400, 0);
m_DoorSurf.create(128, 128, BPP_16);
grViewport *vport = new grViewport(&m_DoorSurf);
StartEditorFrame(vport, &view_vector, &id_matrix, D3_DEFAULT_ZOOM);
DrawPolygonModel(&zero_vector, &rot_matrix, bm_handle, norm_angles, 0, 1.0, 1.0, 1.0);
EndEditorFrame();
x = rect.left + ((rect.right - rect.left) / 2) - m_DoorSurf.width() / 2;
y = rect.top + ((rect.bottom - rect.top) / 2) - m_DoorSurf.height() / 2;
Desktop_surf->blt(x, y, &m_DoorSurf);
delete vport;
m_DoorSurf.free();
}
void CWorldObjectsDoorDialog::OnCheckinDoor() {
int n = D3EditState.current_door;
mngs_Pagelock temp_pl;
int r;
if (Num_doors < 1)
return;
if (!mng_MakeLocker())
return;
// Make sure we own this door
strcpy(temp_pl.name, Doors[n].name);
temp_pl.pagetype = PAGETYPE_DOOR;
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(Doors[n].name, Doors[n].name, n, PAGETYPE_DOOR, 0))
OutrageMessageBox(ErrorString);
else {
// Save this door anim/model to the network for all
std::filesystem::path srcname = LocalModelsDir / Poly_models[Doors[n].model_handle].name;
std::filesystem::path destname = NetModelsDir / Poly_models[Doors[n].model_handle].name;
cf_CopyFile(destname, srcname);
OutrageMessageBox("Door checked in.");
// Delete it from local pagefile if it is there
int dret = mng_DeletePage(Doors[n].name, PAGETYPE_DOOR, 1);
ASSERT(dret == 1);
mng_EraseLocker();
// Free the tracklock
int p = mng_FindTrackLock(Doors[n].name, PAGETYPE_DOOR);
ASSERT(p != -1);
mng_FreeTrackLock(p);
UpdateDialog();
}
}
}
mng_EraseLocker();
}
void CWorldObjectsDoorDialog::OnKillfocusCloseTime() {
CEdit *ebox;
char str[20];
int n = D3EditState.current_door;
ebox = (CEdit *)GetDlgItem(IDC_CLOSE_TIME);
ebox->GetWindowText(str, 20);
Doors[n].total_close_time = atof(str);
}
void CWorldObjectsDoorDialog::OnDeleteDoor() {
int answer, tl;
mngs_Pagelock pl;
int n = D3EditState.current_door;
if (Num_doors < 1)
return;
// Check to see if we even have it locked
if ((tl = mng_FindTrackLock(Doors[n].name, PAGETYPE_DOOR)) == -1) {
OutrageMessageBox("This door is not yours to delete. Lock first.");
return;
}
// Make sure it is to be deleted
answer = MessageBox("Are you sure you want to delete this door?", Doors[n].name, MB_YESNO);
if (answer == IDNO)
return;
if (!mng_MakeLocker())
return;
strcpy(pl.name, Doors[n].name);
pl.pagetype = PAGETYPE_DOOR;
// Check to see if this is a local door only. If so, only delete it locally
if (mng_CheckIfPageOwned(&pl, TableUser) != 1) {
mng_FreeTrackLock(tl);
if (!mng_DeletePage(Doors[n].name, PAGETYPE_DOOR, 1)) {
mprintf(0, ErrorString);
Int3();
}
} else // if it is network, delete it from both the net and local drives
{
mng_FreeTrackLock(tl);
mng_DeletePage(Doors[n].name, PAGETYPE_DOOR, 1);
mng_DeletePage(Doors[n].name, PAGETYPE_DOOR, 0);
mng_DeletePagelock(Doors[n].name, PAGETYPE_DOOR);
}
// Advance to the next door
D3EditState.current_door = GetNextDoor(n);
FreePolyModel(Doors[n].model_handle);
FreeDoor(n);
mng_EraseLocker();
OutrageMessageBox("Door deleted.");
UpdateDialog();
}
// Gets a name from the user, making sure it's unique
// Returns true if got new name, false if cancelled.
// the data in buf not changed if cancel is pressed
bool InputDoorName(char *buf, int len, char *title, char *prompt, CWnd *wnd) {
char *tempbuf = (char *)mem_malloc(len);
strcpy(tempbuf, buf);
try_again:
if (!InputString(tempbuf, len, title, prompt, wnd)) {
mem_free(tempbuf);
return 0;
}
if (FindDoorName(tempbuf) != -1) {
OutrageMessageBox("The name you specified is already in use. Enter another name.");
goto try_again;
}
strcpy(buf, tempbuf);
mem_free(tempbuf);
return 1;
}
void CWorldObjectsDoorDialog::OnDoorChangeName() {
int n = D3EditState.current_door;
char name[PAGENAME_LEN];
mngs_Pagelock pl;
// Make sure we have this door locked, if not reset name and bail
int p = mng_FindTrackLock(Doors[n].name, PAGETYPE_DOOR);
if (p == -1) {
OutrageMessageBox("You must lock this door if you wish to change its name.");
return;
}
// Get new name
strcpy(name, Doors[n].name);
if (!InputDoorName(name, sizeof(name), "Door name", "Enter a new name for this door:", this))
return;
if (!mng_MakeLocker())
return;
// Check to see if this page exists on the network. If so, we have to
// rename it so we can prevent havoc
strcpy(pl.name, Doors[n].name);
pl.pagetype = PAGETYPE_DOOR;
int ret = mng_CheckIfPageOwned(&pl, TableUser);
if (ret < 0)
OutrageMessageBox(ErrorString);
else if (ret == 1)
mng_RenamePage(Doors[n].name, name, PAGETYPE_DOOR);
else if (ret == 2) {
// This page has never been checked in, replace only local copy
char oldname[PAGENAME_LEN];
strcpy(oldname, Doors[n].name);
strcpy(Doors[n].name, name);
mng_ReplacePage(oldname, Doors[n].name, n, PAGETYPE_DOOR, 1);
} else if (ret == 0) {
OutrageMessageBox("You don't own this page. Get Jason now!");
mng_FreeTrackLock(p);
return;
}
// Finally, copy our new name to the appropriate arrays
strcpy(GlobalTrackLocks[p].name, name);
strcpy(Doors[n].name, name);
UpdateDialog();
mng_EraseLocker();
}
void CWorldObjectsDoorDialog::OnDoorNext() {
D3EditState.current_door = GetNextDoor(D3EditState.current_door);
UpdateDialog();
}
void CWorldObjectsDoorDialog::OnKillfocusDoorOpenTime() {
CEdit *ebox;
char str[20];
int n = D3EditState.current_door;
ebox = (CEdit *)GetDlgItem(IDC_DOOR_OPEN_TIME);
ebox->GetWindowText(str, 20);
Doors[n].total_open_time = atof(str);
}
void CWorldObjectsDoorDialog::OnDoorPrev() {
D3EditState.current_door = GetPrevDoor(D3EditState.current_door);
UpdateDialog();
}
void CWorldObjectsDoorDialog::OnKillfocusDoorStaysOpen() {
// TODO: Add your control notification handler code here
CEdit *ebox;
char str[20];
int n = D3EditState.current_door;
ebox = (CEdit *)GetDlgItem(IDC_DOOR_STAYS_OPEN);
ebox->GetWindowText(str, 20);
Doors[n].total_time_open = atof(str);
}
void CWorldObjectsDoorDialog::OnDoorsOut() {
char str[10000];
int total = 0;
mng_DisplayLockList(TableUser);
sprintf(str, "User %s has these doors held locally:\n\n", TableUser);
for (int i = 0; i < MAX_TRACKLOCKS; i++) {
if (GlobalTrackLocks[i].used && GlobalTrackLocks[i].pagetype == PAGETYPE_DOOR) {
char temp[90];
sprintf(temp, "%s", GlobalTrackLocks[i].name);
strcat(str, temp);
strcat(str, "\n");
total++;
}
}
if (total != 0) {
// Display that string
MessageBox(str, "Doors", MB_OK);
}
}
void CWorldObjectsDoorDialog::OnLoadDoorModel() {
char filename[255];
int img_handle;
int door_handle;
int c = 1, finding_name = 1;
int model = 0;
// Get the filename of the representing image
CString filter = "Descent III files (*.pof,*.oof)|*.pof;*.oof||";
if (!OpenFileDialog(this, (LPCSTR)filter, filename, Current_model_dir, sizeof(Current_model_dir)))
return;
// Okay, we selected a file. Lets do what needs to be done here.
img_handle = LoadDoorImage(filename, 0);
if (img_handle < 0) {
OutrageMessageBox("Couldn't open that animation/model file.");
return;
}
door_handle = D3EditState.current_door;
Doors[door_handle].model_handle = img_handle;
// Finally, save a local copy of the model
std::filesystem::path curname = LocalModelsDir / Poly_models[Doors[door_handle].model_handle].name;
cf_CopyFile(curname, filename);
UpdateDialog();
}
void CWorldObjectsDoorDialog::OnLockDoor() {
int n = D3EditState.current_door;
mngs_Pagelock temp_pl;
mngs_door_page doorpage;
int r;
if (Num_doors < 1)
return;
if (!mng_MakeLocker())
return;
// Make sure it can be locked
strcpy(temp_pl.name, Doors[n].name);
temp_pl.pagetype = PAGETYPE_DOOR;
r = mng_CheckIfPageLocked(&temp_pl);
if (r == 2) {
int answer;
answer = OutrageMessageBox(MBOX_YESNO, "This page 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_FindSpecificDoorPage(temp_pl.name, &doorpage)) {
if (mng_AssignDoorPageToDoor(&doorpage, n)) {
if (!mng_ReplacePage(Doors[n].name, Doors[n].name, n, PAGETYPE_DOOR, 1)) {
OutrageMessageBox("There was problem writing that page locally!");
mng_EraseLocker();
return;
}
OutrageMessageBox("Door locked.");
} else
OutrageMessageBox(
"There was a problem loading this door. You might encounter problems in dealing with it. Good luck!");
mng_AllocTrackLock(Doors[n].name, PAGETYPE_DOOR);
UpdateDialog();
} else
OutrageMessageBox("Couldn't find that door in the table file!");
}
}
mng_EraseLocker();
}
BOOL CWorldObjectsDoorDialog::OnInitDialog() {
CDialog::OnInitDialog();
CWnd::SetTimer(1, 50, NULL);
UpdateDialog();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CWorldObjectsDoorDialog::OnTimer(UINT nIDEvent) {
UpdateDoorView();
CDialog::OnTimer(nIDEvent);
}
// When closing, save all our checked out doors locally so we know
// what stuff to flag as "checked out" the next time we start up
void CWorldObjectsDoorDialog::SaveDoorsOnClose() {
int i, t;
if (!Network_up)
return; // don't save a damn thing if the network is down
for (i = 0; i < MAX_TRACKLOCKS; i++) {
if (GlobalTrackLocks[i].used == 1 && GlobalTrackLocks[i].pagetype == PAGETYPE_DOOR) {
t = FindDoorName(GlobalTrackLocks[i].name);
ASSERT(t != -1);
mng_ReplacePage(Doors[t].name, Doors[t].name, t, PAGETYPE_DOOR, 1);
}
}
}
BOOL CWorldObjectsDoorDialog::DestroyWindow() {
SaveDoorsOnClose();
return CDialog::DestroyWindow();
}
void CWorldObjectsDoorDialog::OnSelendokDoorPulldown() {
int i, cur;
char name[200];
cur = SendDlgItemMessage(IDC_DOOR_PULLDOWN, CB_GETCURSEL, 0, 0);
SendDlgItemMessage(IDC_DOOR_PULLDOWN, CB_GETLBTEXT, cur, (LPARAM)(LPCTSTR)name);
i = FindDoorName(name);
if (i == -1) {
mprintf(0, "Possible corrupted door list, but probably nothing.");
UpdateDialog();
}
D3EditState.current_door = i;
UpdateDialog();
}
BOOL CWorldObjectsDoorDialog::OnHelpInfo(HELPINFO *pHelpInfo) {
// TODO: Add your message handler code here and/or call default
WinHelp(HID_DOORSDLG, HELP_CONTEXT);
return TRUE;
// return CDialog::OnHelpInfo(pHelpInfo);
}
void CWorldObjectsDoorDialog::OnTransparency() {
int n = D3EditState.current_door;
CButton *btn;
btn = (CButton *)GetDlgItem(IDC_TRANSPARENCY);
if (btn->GetCheck())
Doors[n].flags |= DF_SEETHROUGH;
else
Doors[n].flags &= ~DF_SEETHROUGH;
}
void CWorldObjectsDoorDialog::OnDestroy() {
CDialog::OnDestroy();
ObjReInitAll();
}
void CWorldObjectsDoorDialog::OnSelendokDoorOpenSound() {
int cur;
char name[200];
int n = D3EditState.current_door;
cur = SendDlgItemMessage(IDC_DOOR_OPEN_SOUND, CB_GETCURSEL, 0, 0);
SendDlgItemMessage(IDC_DOOR_OPEN_SOUND, CB_GETLBTEXT, cur, (LPARAM)(LPCTSTR)name);
Doors[n].open_sound = FindSoundName(name);
}
void CWorldObjectsDoorDialog::OnSelendokDoorCloseSound() {
int cur;
char name[200];
int n = D3EditState.current_door;
cur = SendDlgItemMessage(IDC_DOOR_CLOSE_SOUND, CB_GETCURSEL, 0, 0);
SendDlgItemMessage(IDC_DOOR_CLOSE_SOUND, CB_GETLBTEXT, cur, (LPARAM)(LPCTSTR)name);
Doors[n].close_sound = FindSoundName(name);
}
void CWorldObjectsDoorDialog::OnBrowse() {
CString filter = "D3 Compiled Scripts (*.dll)|*.dll||";
char filename[_MAX_PATH];
char pathname[_MAX_PATH], name[_MAX_PATH];
strcpy(pathname, LocalScriptDir);
if (!OpenFileDialog(this, (LPCTSTR)filter, filename, pathname, sizeof(pathname)))
return;
ddio_SplitPath(filename, NULL, name, NULL);
sprintf(filename, "%s.dll", name);
int n = D3EditState.current_door;
strcpy(Doors[n].module_name, filename);
UpdateDialog();
}
void CWorldObjectsDoorDialog::OnKillfocusScriptname() {
char str[MAX_MODULENAME_LEN];
((CEdit *)GetDlgItem(IDC_SCRIPTNAME))->GetWindowText(str, MAX_MODULENAME_LEN);
strcpy(Doors[D3EditState.current_door].module_name, str);
UpdateDialog();
}
void CWorldObjectsDoorDialog::OnDoorBlastable() {
int n = D3EditState.current_door;
CButton *btn;
btn = (CButton *)GetDlgItem(IDC_DOOR_BLASTABLE);
if (btn->GetCheck())
Doors[n].flags |= DF_BLASTABLE;
else
Doors[n].flags &= ~DF_BLASTABLE;
UpdateDialog();
}
void CWorldObjectsDoorDialog::OnKillfocusDoorHitpointsEdit() {
char str[256];
int n = D3EditState.current_door;
CEdit *ebox = (CEdit *)GetDlgItem(IDC_DOOR_HITPOINTS_EDIT);
ebox->GetWindowText(str, sizeof(str));
Doors[n].hit_points = atoi(str);
UpdateDialog();
}