1537 lines
37 KiB
C++
1537 lines
37 KiB
C++
// WSpace.cpp
|
|
// Guy Simmons, 11th August 1998.
|
|
|
|
#include <MFStdLib.h>
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <ddlib.h>
|
|
#include <commctrl.h>
|
|
#include "resource.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "GEdit.h"
|
|
#include "Mission.h"
|
|
#include "SubClass.h"
|
|
#include "WSpace.h"
|
|
#include "MapView.h"
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL workspace_changed = FALSE;
|
|
CBYTE map_default_dir[_MAX_PATH],
|
|
map_file_name[_MAX_PATH],
|
|
map_path_name[_MAX_PATH],
|
|
mission_name[_MAX_PATH],
|
|
workspace_dir[_MAX_PATH],
|
|
workspace_name[_MAX_PATH],
|
|
workspace_path[_MAX_PATH];
|
|
HANDLE image_list;
|
|
HWND ws_tree,wpt_tree;
|
|
HTREEITEM last_clicked, selected_mission_doohickey=0;
|
|
WSElement root_item;
|
|
|
|
extern HINSTANCE GEDIT_hinstance;
|
|
|
|
extern BOOL map_valid;
|
|
|
|
// The camera.
|
|
extern SLONG cam_x,
|
|
cam_y,
|
|
cam_z,
|
|
cam_yaw,
|
|
cam_pitch,
|
|
cam_focus_x,
|
|
cam_focus_z,
|
|
cam_focus_dist,
|
|
cam_matrix[9],
|
|
cam_forward[3],
|
|
cam_left[3];
|
|
|
|
// The mouse.
|
|
extern SLONG mouse_valid,
|
|
mouse_over,
|
|
mouse_world_x,
|
|
mouse_world_y,
|
|
mouse_world_z,
|
|
mouse_waypoint;
|
|
|
|
void calc_camera_pos(void);
|
|
void remove_children(HTREEITEM parent);
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL init_workspace(HWND parent)
|
|
{
|
|
TV_INSERTSTRUCT tv_is;
|
|
|
|
|
|
// Subclass the tree control windproc.
|
|
ws_tree = GetDlgItem(parent,IDC_WORKSPACE_TREE);
|
|
tree_proc = (WNDPROC)SetWindowLong(ws_tree,GWL_WNDPROC,(long)sc_tree_proc);
|
|
|
|
// Set up the trees image list.
|
|
image_list = ImageList_LoadBitmap(
|
|
GEDIT_hinstance,
|
|
MAKEINTRESOURCE(IDB_WORKSPACE),
|
|
16,
|
|
1,
|
|
RGB (255, 0, 255)
|
|
);
|
|
|
|
/* image_list = ImageList_LoadImage(GEDIT_hinstance,MAKEINTRESOURCE(IDB_WORKSPACE2),16,1,
|
|
RGB(255,0,255),IMAGE_BITMAP,LR_DEFAULTCOLOR);*/
|
|
|
|
TreeView_SetImageList(ws_tree,image_list,TVSIL_NORMAL);
|
|
|
|
// Setup working directories.
|
|
sprintf(workspace_dir,"c:\\Fallen\\Editor");
|
|
sprintf(map_default_dir,"c:\\Fallen\\Data");
|
|
|
|
// Set up the tree root.
|
|
tv_is.hParent = TVI_ROOT;
|
|
tv_is.hInsertAfter = TVI_FIRST;
|
|
tv_is.item.mask = TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.pszText = "Workspace : NONE";
|
|
tv_is.item.lParam = (LPARAM)&root_item;
|
|
root_item.TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
root_item.ElementType = ET_NONE;
|
|
|
|
// Set the workspace state & corresponding menus.
|
|
workspace_changed = FALSE;
|
|
menu_no_workspace();
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void fini_workspace(void)
|
|
{
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL get_element_at_point(POINT *click_point,WSElement **the_element)
|
|
{
|
|
HTREEITEM item_handle;
|
|
TV_HITTESTINFO hit_test;
|
|
TV_ITEM the_item;
|
|
|
|
|
|
// Validate the parameters.
|
|
if(click_point && the_element)
|
|
{
|
|
// Check to see if we clicked on a tree item.
|
|
hit_test.pt = *click_point;
|
|
ScreenToClient(ws_tree,&hit_test.pt);
|
|
item_handle = TreeView_HitTest(ws_tree,&hit_test);
|
|
if(item_handle && hit_test.flags&TVHT_ONITEM)
|
|
{
|
|
// Yes, so get a pointer to its WSElement structure.
|
|
the_item.hItem = item_handle;
|
|
the_item.mask = TVIF_PARAM;
|
|
if(TreeView_GetItem(ws_tree,&the_item))
|
|
{
|
|
*the_element = (WSElement*)the_item.lParam;
|
|
if(*the_element) {
|
|
last_clicked=item_handle;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void handle_ws_context(POINT *click_point)
|
|
{
|
|
HMENU ws_menu;
|
|
WSElement *the_element;
|
|
|
|
|
|
// Validate the parameters.
|
|
if(ws_tree && click_point)
|
|
{
|
|
if(get_element_at_point(click_point,&the_element))
|
|
{
|
|
// Select the item.
|
|
TreeView_Select(ws_tree,the_element->TreeItem,TVGN_CARET);
|
|
|
|
if (the_element->ElementType==ET_LMAP) return;
|
|
|
|
// Bring up the relevent context menu.
|
|
ws_menu = GetSubMenu(LoadMenu(GEDIT_hinstance,MAKEINTRESOURCE(IDR_GEDIT_POPUPS)),the_element->ElementType-1);
|
|
TrackPopupMenu (
|
|
ws_menu,
|
|
TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
|
|
click_point->x,click_point->y,
|
|
0,ws_tree,NULL
|
|
);
|
|
DestroyMenu(ws_menu);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL handle_ws_dblclk(POINT *click_point)
|
|
{
|
|
// CBYTE item_text[_MAX_PATH];
|
|
// TV_ITEM the_item;
|
|
WSElement *the_element;
|
|
HTREEITEM next;
|
|
|
|
// Validate the parameters.
|
|
if(ws_tree && click_point)
|
|
{
|
|
if(get_element_at_point(click_point,&the_element))
|
|
{
|
|
switch(the_element->ElementType)
|
|
{
|
|
case ET_NONE:
|
|
break;
|
|
case ET_ROOT:
|
|
break;
|
|
case ET_MAP:
|
|
|
|
// Expand the workspace
|
|
TreeView_Expand(ws_tree,last_clicked,TVE_EXPAND);
|
|
|
|
// Set the 'busy' cursor.
|
|
SetCursor(GEDIT_busy);
|
|
|
|
// Try to open the map.
|
|
SetCurrentDirectory("c:\\Fallen");
|
|
//GI_init();
|
|
map_valid = GI_load_map(current_map->MapName);
|
|
if(map_valid)
|
|
{
|
|
// Default setup for map view.
|
|
cam_focus_x = 64 << 8;
|
|
cam_focus_z = 64 << 8;
|
|
cam_focus_dist = 14 << 8;
|
|
cam_pitch = 1600;
|
|
cam_yaw = 0;
|
|
calc_camera_pos();
|
|
GI_render_view_into_backbuffer (
|
|
cam_x,
|
|
cam_y,
|
|
cam_z,
|
|
cam_yaw,
|
|
cam_pitch,
|
|
0
|
|
);
|
|
}
|
|
// Set the 'arrow' cursor.
|
|
SetCursor(GEDIT_arrow);
|
|
|
|
// Select the first mission (if present)
|
|
next=TreeView_GetChild(ws_tree,last_clicked);
|
|
if (next) TreeView_SelectItem(ws_tree,next);
|
|
|
|
|
|
return TRUE;
|
|
|
|
case ET_MISSION:
|
|
break;
|
|
case ET_LMAP:
|
|
break;
|
|
case ET_WAYPOINT:
|
|
break;
|
|
case ET_BRIEF:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void handle_ws_select(WSElement *the_element)
|
|
{
|
|
switch(the_element->ElementType)
|
|
{
|
|
case ET_NONE:
|
|
break;
|
|
|
|
case ET_ROOT:
|
|
break;
|
|
|
|
case ET_MAP:
|
|
current_map = &game_maps[the_element->MapRef];
|
|
break;
|
|
|
|
case ET_MISSION:
|
|
if (
|
|
current_map &&
|
|
MAP_NUMBER(current_map)==TO_MISSION(the_element->MissionRef)->MapIndex
|
|
)
|
|
{
|
|
TVITEM item;
|
|
// clear old bold
|
|
item.mask=TVIF_STATE|TVIF_HANDLE;
|
|
item.stateMask=TVIS_BOLD;
|
|
if (selected_mission_doohickey) {
|
|
item.hItem=selected_mission_doohickey;
|
|
item.state=0;
|
|
TreeView_SetItem(ws_tree,&item);
|
|
}
|
|
// set new bold
|
|
item.hItem=the_element->TreeItem;
|
|
item.state=TVIS_BOLD;
|
|
TreeView_SetItem(ws_tree,&item);
|
|
current_mission = &mission_pool[the_element->MissionRef];
|
|
selected_mission_doohickey = the_element->TreeItem;
|
|
reset_wptlist();
|
|
fill_wptlist(current_mission);
|
|
}
|
|
else
|
|
{
|
|
// We probably need to prompt here, to open the missions associated map.
|
|
// current_mission = NULL;
|
|
current_mission = &mission_pool[the_element->MissionRef];
|
|
}
|
|
break;
|
|
|
|
case ET_LMAP:
|
|
break;
|
|
|
|
case ET_WAYPOINT:
|
|
break;
|
|
|
|
case ET_BRIEF:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void ws_add_map(void)
|
|
{
|
|
CBYTE *text_buffer;
|
|
UWORD item_count,
|
|
new_map;
|
|
HTREEITEM map_item;
|
|
OPENFILENAME open_map;
|
|
TV_INSERTSTRUCT tv_is;
|
|
TV_ITEM map_info;
|
|
WSElement *new_element;
|
|
|
|
|
|
// Set up the open file structure.
|
|
ZeroMemory(&open_map,sizeof(OPENFILENAME));
|
|
open_map.lStructSize = sizeof(OPENFILENAME);
|
|
open_map.hwndOwner = NULL;
|
|
open_map.lpstrFilter = "Game map files\0*.iam\0\0";
|
|
open_map.lpstrFile = map_path_name;
|
|
open_map.nMaxFile = _MAX_PATH;
|
|
open_map.lpstrFileTitle = map_file_name;
|
|
open_map.nMaxFileTitle = _MAX_PATH;
|
|
open_map.lpstrInitialDir = map_default_dir;
|
|
open_map.lpstrTitle = "Load a game map";
|
|
open_map.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
|
|
open_map.lpstrDefExt = "iam";
|
|
|
|
if(GetOpenFileName(&open_map))
|
|
{
|
|
// Check to see if this map is part of the workspace.
|
|
text_buffer = (CBYTE*)malloc(_MAX_PATH);
|
|
map_item = TreeView_GetChild(ws_tree,root_item.TreeItem);
|
|
while(map_item)
|
|
{
|
|
map_info.mask = TVIF_TEXT;
|
|
map_info.hItem = map_item;
|
|
map_info.pszText = text_buffer;
|
|
map_info.cchTextMax = _MAX_PATH;
|
|
TreeView_GetItem(ws_tree,&map_info);
|
|
|
|
if(!strcmp(map_file_name,text_buffer))
|
|
{
|
|
// Yes, so show a message & get outta here.
|
|
MessageBox (
|
|
NULL,
|
|
"This map is already part of the workspace",
|
|
"DOH!!",
|
|
MB_OK
|
|
);
|
|
free(text_buffer);
|
|
return;
|
|
}
|
|
|
|
// Get next sibling.
|
|
map_item = TreeView_GetNextSibling(ws_tree,map_item);
|
|
}
|
|
free(text_buffer);
|
|
|
|
// No, so find a spare map structure.
|
|
new_map = alloc_map();
|
|
if(new_map)
|
|
{
|
|
// Set up the new map structure.
|
|
strcpy(game_maps[new_map].MapName,"Data\\");
|
|
strcat(game_maps[new_map].MapName,map_file_name);
|
|
|
|
// Now add it to the workspace root.
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = root_item.TreeItem;
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_MAP;
|
|
tv_is.item.iSelectedImage = IM_MAP;
|
|
tv_is.item.pszText = map_file_name;
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_MAP;
|
|
new_element->MapRef = new_map;
|
|
|
|
// Expand the root if this is the first map to be added.
|
|
item_count = TreeView_GetCount(ws_tree);
|
|
if(item_count<=2)
|
|
TreeView_Expand(ws_tree,root_item.TreeItem,TVE_EXPAND);
|
|
|
|
// Update the window.
|
|
InvalidateRect(ws_tree, NULL, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Error no more maps.
|
|
MessageBox (
|
|
NULL,
|
|
"Run out of Map structures.\n\nClick OK, save your work & then tell Guy.",
|
|
"Oh bugger!!",
|
|
MB_OK
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL CALLBACK new_mish_proc (
|
|
HWND hWnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch(message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
// Make sure the edit control has the focus.
|
|
SetFocus(GetDlgItem(hWnd,IDC_EDIT_MNAME));
|
|
return FALSE;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
EndDialog(hWnd,TRUE);
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hWnd,FALSE);
|
|
return TRUE;
|
|
|
|
case IDC_EDIT_MNAME:
|
|
if(HIWORD(wParam)==EN_CHANGE)
|
|
{
|
|
// The user has changed the text, if there's any
|
|
// text in the control enable the 'Ok' button else
|
|
// disable it.
|
|
if(GetWindowText((HWND)lParam,mission_name,_MAX_PATH))
|
|
EnableWindow(GetDlgItem(hWnd,IDOK),TRUE);
|
|
else
|
|
EnableWindow(GetDlgItem(hWnd,IDOK),FALSE);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void ws_new_mission(void)
|
|
{
|
|
UWORD new_mission;
|
|
HTREEITEM map_handle;
|
|
TV_INSERTSTRUCT tv_is;
|
|
TV_ITEM map_item;
|
|
WSElement *map_element,
|
|
*new_element;
|
|
|
|
|
|
// First get the parent map info.
|
|
map_handle = TreeView_GetSelection(ws_tree);
|
|
map_item.hItem = map_handle;
|
|
map_item.mask = TVIF_PARAM;
|
|
TreeView_GetItem(ws_tree,&map_item);
|
|
map_element = (WSElement*)map_item.lParam;
|
|
|
|
// Now find a spare mission structure.
|
|
new_mission = alloc_mission(map_element->MapRef);
|
|
if(new_mission)
|
|
{
|
|
// Bring up a dialog box for the user to enter the mission name.
|
|
if (
|
|
DialogBox (
|
|
GEDIT_hinstance,
|
|
MAKEINTRESOURCE(IDD_NEWMISSION),
|
|
ws_tree,
|
|
(DLGPROC)new_mish_proc
|
|
)
|
|
)
|
|
{
|
|
// Set up the mission structure.
|
|
init_mission(new_mission,mission_name);
|
|
|
|
// Now create the new mission.
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = map_handle;
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_MISSION;
|
|
tv_is.item.iSelectedImage = IM_MISSION;
|
|
tv_is.item.pszText = mission_name;
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_MISSION;
|
|
new_element->MapRef = map_element->MapRef;
|
|
new_element->MissionRef = new_mission;
|
|
|
|
// Update the window.
|
|
InvalidateRect(ws_tree, NULL, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Error no more missions.
|
|
MessageBox (
|
|
NULL,
|
|
"Run out of Mission structures.\n\nClick OK, save your work & then tell Guy.",
|
|
"Oh bugger!!",
|
|
MB_OK
|
|
);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void ws_del_mission(void) {
|
|
HTREEITEM current = TreeView_GetSelection(ws_tree);
|
|
SLONG c1;
|
|
|
|
for(c1=0;c1<MAX_EVENTPOINTS;c1++)
|
|
if (current_mission->EventPoints[c1].Used)
|
|
free_eventpoint(¤t_mission->EventPoints[c1]);
|
|
|
|
ZeroMemory(current_mission,sizeof(Mission));
|
|
current_mission=NULL; // hmm
|
|
|
|
remove_children(current);
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void ws_add_light_map(void)
|
|
{
|
|
CBYTE temp[_MAX_PATH];
|
|
OPENFILENAME open_map;
|
|
TV_INSERTSTRUCT tv_is;
|
|
WSElement *new_element;
|
|
|
|
|
|
// Set up the open file structure.
|
|
sprintf(current_mission->LightMapName,"*.lgt");
|
|
ZeroMemory(&open_map,sizeof(OPENFILENAME));
|
|
open_map.lStructSize = sizeof(OPENFILENAME);
|
|
open_map.hwndOwner = NULL;
|
|
open_map.lpstrFilter = "Light Map files\0*.lgt\0\0";
|
|
// open_map.lpstrFile = current_mission->LightMapName;
|
|
// open_map.nMaxFile = _MAX_PATH;
|
|
open_map.lpstrFileTitle = temp;
|
|
open_map.nMaxFileTitle = _MAX_PATH;
|
|
open_map.lpstrInitialDir = map_default_dir;
|
|
open_map.lpstrTitle = "Load a light map";
|
|
open_map.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
|
|
open_map.lpstrDefExt = "lgt";
|
|
|
|
if(GetOpenFileName(&open_map))
|
|
{
|
|
strcpy(current_mission->LightMapName,"Data\\Lighting\\");
|
|
strcat(current_mission->LightMapName,temp);
|
|
|
|
// Add it to the mission root.
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = TreeView_GetSelection(ws_tree);
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_LMAP;
|
|
tv_is.item.iSelectedImage = IM_LMAP;
|
|
tv_is.item.pszText = temp;
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_LMAP;
|
|
|
|
// Update the window.
|
|
InvalidateRect(ws_tree, NULL, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void ws_add_citsez_map(void)
|
|
{
|
|
CBYTE temp[_MAX_PATH];
|
|
OPENFILENAME open_map;
|
|
TV_INSERTSTRUCT tv_is;
|
|
WSElement *new_element;
|
|
|
|
|
|
// Set up the open file structure.
|
|
sprintf(current_mission->CitSezMapName,"*.txt");
|
|
ZeroMemory(&open_map,sizeof(OPENFILENAME));
|
|
open_map.lStructSize = sizeof(OPENFILENAME);
|
|
open_map.hwndOwner = NULL;
|
|
open_map.lpstrFilter = "Text files\0*.txt\0\0";
|
|
open_map.lpstrFile = current_mission->CitSezMapName;
|
|
open_map.nMaxFile = _MAX_PATH;
|
|
open_map.lpstrFileTitle = temp;
|
|
open_map.nMaxFileTitle = _MAX_PATH;
|
|
open_map.lpstrInitialDir = "c:\\fallen\\text\\";
|
|
open_map.lpstrTitle = "Load a Citizen-Sez text file";
|
|
open_map.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
|
|
open_map.lpstrDefExt = "txt";
|
|
|
|
if(GetOpenFileName(&open_map))
|
|
{
|
|
strcpy(current_mission->CitSezMapName,"Text\\");
|
|
strcat(current_mission->CitSezMapName,temp);
|
|
|
|
// Add it to the mission root.
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = TreeView_GetSelection(ws_tree);
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_SEWER;
|
|
tv_is.item.iSelectedImage = IM_SEWER;
|
|
tv_is.item.pszText = temp;
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_LMAP;
|
|
|
|
// Update the window.
|
|
InvalidateRect(ws_tree, NULL, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL create_workspace(void)
|
|
{
|
|
int result;
|
|
CBYTE temp[_MAX_PATH];
|
|
OPENFILENAME save_workspace;
|
|
TV_ITEM set_item;
|
|
|
|
|
|
if(workspace_changed)
|
|
{
|
|
// Ask the user to save etc.
|
|
result = MessageBox (
|
|
NULL,
|
|
"Changes have been made to the current workspace.\nDo you want to save?",
|
|
"Urban Chaos Mission Editor",
|
|
MB_ICONQUESTION|MB_YESNOCANCEL
|
|
);
|
|
if(result==IDCANCEL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else if(result==IDYES)
|
|
{
|
|
// save_workspace();
|
|
}
|
|
}
|
|
|
|
// Set up the default directory & file name.
|
|
sprintf(workspace_path,"*.ucw");
|
|
|
|
// Set up the save file structure.
|
|
ZeroMemory(&save_workspace,sizeof(OPENFILENAME));
|
|
save_workspace.lStructSize = sizeof(OPENFILENAME);
|
|
save_workspace.hwndOwner = NULL;
|
|
save_workspace.lpstrFilter = "Editor Workspace Files\0*.ucw\0\0";
|
|
save_workspace.lpstrFile = workspace_path;
|
|
save_workspace.nMaxFile = _MAX_PATH;
|
|
save_workspace.lpstrFileTitle = workspace_name;
|
|
save_workspace.nMaxFileTitle = _MAX_PATH;
|
|
save_workspace.lpstrInitialDir = workspace_dir;
|
|
save_workspace.lpstrTitle = "Create a new Workspace";
|
|
save_workspace.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
|
|
save_workspace.lpstrDefExt = "ucw";
|
|
|
|
if(GetOpenFileName(&save_workspace))
|
|
{
|
|
// Change the root item.
|
|
sprintf(temp,"Workspace : %s",workspace_name);
|
|
set_item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT;
|
|
set_item.hItem = root_item.TreeItem;
|
|
set_item.pszText = temp;
|
|
set_item.iImage = IM_ROOT;
|
|
set_item.iSelectedImage = IM_ROOT;
|
|
root_item.ElementType = ET_ROOT;
|
|
TreeView_SetItem(ws_tree,&set_item);
|
|
|
|
// Set the workspace state & corresponding menus.
|
|
workspace_changed = TRUE;
|
|
menu_has_workspace();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL close_workspace(void)
|
|
{
|
|
int result;
|
|
UWORD c0,c1;
|
|
Mission *the_mission;
|
|
TV_ITEM set_item;
|
|
|
|
|
|
if(workspace_changed)
|
|
{
|
|
// Ask the user to save etc.
|
|
result = MessageBox (
|
|
NULL,
|
|
"Changes have been made to the workspace.\nDo you want to save?",
|
|
"Urban Chaos Mission Editor",
|
|
MB_ICONQUESTION|MB_YESNOCANCEL
|
|
);
|
|
if(result==IDCANCEL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else if(result==IDYES)
|
|
{
|
|
save_workspace();
|
|
}
|
|
}
|
|
|
|
// Remove eveything from the tree.
|
|
remove_children(TreeView_GetRoot(ws_tree));
|
|
|
|
// Go thru' the missions & clear out ep data.
|
|
for(c0=0;c0<MAX_MISSIONS;c0++)
|
|
{
|
|
if(mission_pool[c0].Flags & MISSION_FLAG_USED)
|
|
{
|
|
the_mission = &mission_pool[c0];
|
|
for(c1=0;c1<MAX_EVENTPOINTS;c1++)
|
|
if (the_mission->EventPoints[c1].Used)
|
|
free_eventpoint(&the_mission->EventPoints[c1]);
|
|
}
|
|
}
|
|
MISSION_init();
|
|
|
|
// Reset the root item.
|
|
set_item.mask = TVIF_TEXT;
|
|
set_item.hItem = root_item.TreeItem;
|
|
set_item.pszText = "Workspace : NONE";
|
|
root_item.ElementType = ET_NONE;
|
|
TreeView_SetItem(ws_tree,&set_item);
|
|
|
|
// Setup the workspace state & corresponding menus.
|
|
workspace_changed = FALSE;
|
|
menu_no_workspace();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
BOOL load_workspace(BOOL try_loading_default)
|
|
{
|
|
int result;
|
|
CBYTE temp[_MAX_PATH];
|
|
UBYTE gm_vers;
|
|
UWORD item_count;
|
|
ULONG c0,c1,
|
|
count,
|
|
ep_count,
|
|
size;
|
|
FILE *file_handle;
|
|
HTREEITEM current_item,
|
|
map_handle,
|
|
mission_handle;
|
|
OPENFILENAME load_workspace;
|
|
TV_INSERTSTRUCT tv_is;
|
|
TV_ITEM set_item;
|
|
WSElement *map_element,
|
|
*new_element;
|
|
|
|
|
|
if(workspace_changed)
|
|
{
|
|
// Ask the user to save etc.
|
|
result = MessageBox (
|
|
NULL,
|
|
"Changes have been made to the current workspace.\nDo you want to save?",
|
|
"Urban Chaos Mission Editor",
|
|
MB_ICONQUESTION|MB_YESNOCANCEL
|
|
);
|
|
if(result==IDCANCEL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else if(result==IDYES)
|
|
{
|
|
save_workspace();
|
|
}
|
|
}
|
|
|
|
// Clean up.
|
|
close_workspace();
|
|
|
|
workspace_path[0] = '\000';
|
|
|
|
CBYTE curr_directory[_MAX_PATH];
|
|
|
|
GetCurrentDirectory(_MAX_PATH, curr_directory);
|
|
|
|
if (try_loading_default)
|
|
{
|
|
FILE *handle = fopen("last_workspace.ini", "rb");
|
|
|
|
if (handle)
|
|
{
|
|
fread(workspace_path, 1, _MAX_PATH, handle);
|
|
|
|
fclose(handle);
|
|
}
|
|
}
|
|
|
|
if (workspace_path[0] == '\000')
|
|
{
|
|
// Set up the default directory & file name.
|
|
sprintf(workspace_path,"*.ucw");
|
|
|
|
// Set up the save file structure.
|
|
ZeroMemory(&load_workspace,sizeof(OPENFILENAME));
|
|
load_workspace.lStructSize = sizeof(OPENFILENAME);
|
|
load_workspace.hwndOwner = NULL;
|
|
load_workspace.lpstrFilter = "Editor Workspace Files\0*.ucw\0\0";
|
|
load_workspace.lpstrFile = workspace_path;
|
|
load_workspace.nMaxFile = _MAX_PATH;
|
|
load_workspace.lpstrFileTitle = workspace_name;
|
|
load_workspace.nMaxFileTitle = _MAX_PATH;
|
|
load_workspace.lpstrInitialDir = workspace_dir;
|
|
load_workspace.lpstrTitle = "Open a Workspace";
|
|
load_workspace.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
|
|
load_workspace.lpstrDefExt = "ucw";
|
|
|
|
if (!GetOpenFileName(&load_workspace))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Load the workspace.
|
|
|
|
SetCurrentDirectory(curr_directory);
|
|
|
|
{
|
|
file_handle = fopen(workspace_path,"rb");
|
|
|
|
if(file_handle)
|
|
{
|
|
{
|
|
//
|
|
// Make this the default workspace to load next time.
|
|
//
|
|
|
|
FILE *handle = fopen("last_workspace.ini", "wb");
|
|
|
|
if (handle)
|
|
{
|
|
fwrite(workspace_path, 1, _MAX_PATH, handle);
|
|
|
|
fclose(handle);
|
|
}
|
|
}
|
|
|
|
// Read the file version.
|
|
fread(&gm_vers,sizeof(gm_vers),1,file_handle);
|
|
|
|
// Read the number of game maps & the structure size.
|
|
fread(&count,sizeof(count),1,file_handle);
|
|
fread(&size,sizeof(size),1,file_handle);
|
|
|
|
// Read in the maps.
|
|
for(c0=0;c0<count;c0++)
|
|
{
|
|
fread(&game_maps[c0],size,1,file_handle);
|
|
|
|
// If map exists add it to the workspace tree.
|
|
if(game_maps[c0].Used)
|
|
{
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = root_item.TreeItem;
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_MAP;
|
|
tv_is.item.iSelectedImage = IM_MAP;
|
|
tv_is.item.pszText = &game_maps[c0].MapName[5]; // Assumes name always has 'Data\' preceding it.
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_MAP;
|
|
new_element->MapRef = (UWORD)c0;
|
|
|
|
// Expand the root if this is the first map to be added.
|
|
item_count = TreeView_GetCount(ws_tree);
|
|
if(item_count<=2)
|
|
TreeView_Expand(ws_tree,root_item.TreeItem,TVE_EXPAND);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Read the number of missions, number of event points & the structure size.
|
|
fread(&count,sizeof(count),1,file_handle);
|
|
fread(&ep_count,sizeof(ep_count),1,file_handle);
|
|
fread(&size,sizeof(size),1,file_handle);
|
|
|
|
// Read the missions.
|
|
for(c0=0;c0<count;c0++)
|
|
{
|
|
// Suck in the mission. Blank it first as 'old' missions are shorter
|
|
ZeroMemory(&mission_pool[c0],sizeof(mission_pool[c0]));
|
|
fread(&mission_pool[c0],size,1,file_handle);
|
|
|
|
ResetFreelist(&mission_pool[c0]);
|
|
ResetUsedlist(&mission_pool[c0]);
|
|
ResetFreepoint(&mission_pool[c0]);
|
|
ResetUsedpoint(&mission_pool[c0]);
|
|
|
|
// If mission is used then do some additional stuff.
|
|
if(mission_pool[c0].Flags & MISSION_FLAG_USED)
|
|
{
|
|
// Fix changed stuff:
|
|
if (gm_vers<4) {
|
|
EventPoint *ep;
|
|
for (c1=0,ep=mission_pool[c0].EventPoints;c1<ep_count;c1++,ep++) {
|
|
if (ep->WaypointType==WPT_CREATE_ENEMIES) {
|
|
ep->Data[0]=MAKELONG(ep->Data[0],ep->Data[1]);
|
|
ep->Data[1]=0;
|
|
}
|
|
}
|
|
}
|
|
// if (gm_vers<10) mission_pool[c0].BoredomRate=4;
|
|
if (!mission_pool[c0].BoredomRate) mission_pool[c0].BoredomRate=4;
|
|
// Set up eventpoint data areas.
|
|
for(c1=0;c1<ep_count;c1++)
|
|
read_event_extra(file_handle,&mission_pool[c0].EventPoints[c1],mission_pool[c0].EventPoints,gm_vers);
|
|
|
|
// Find the map tree item that's going to be the missions parent.
|
|
map_handle = NULL;
|
|
current_item = TreeView_GetChild(ws_tree,TreeView_GetRoot(ws_tree));
|
|
while(current_item)
|
|
{
|
|
set_item.hItem = current_item;
|
|
set_item.mask = TVIF_PARAM;
|
|
TreeView_GetItem(ws_tree,&set_item);
|
|
map_element = (WSElement*)set_item.lParam;
|
|
if(map_element && mission_pool[c0].MapIndex==map_element->MapRef)
|
|
{
|
|
map_handle = current_item;
|
|
break;
|
|
}
|
|
current_item = TreeView_GetNextSibling(ws_tree,current_item);
|
|
}
|
|
|
|
// Now add it to the tree.
|
|
if(map_element && map_handle)
|
|
{
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = map_handle;
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_MISSION;
|
|
tv_is.item.iSelectedImage = IM_MISSION;
|
|
tv_is.item.pszText = mission_pool[c0].MissionName;
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_MISSION;
|
|
new_element->MapRef = map_element->MapRef;
|
|
new_element->MissionRef = (UWORD)c0;
|
|
mission_handle = new_element->TreeItem;
|
|
}
|
|
|
|
// Add the light map.
|
|
if(mission_pool[c0].LightMapName[0])
|
|
{
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = mission_handle;
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_LMAP;
|
|
tv_is.item.iSelectedImage = IM_LMAP;
|
|
tv_is.item.pszText = &mission_pool[c0].LightMapName[5]; // Assumes name always has 'Data\' preceding it.
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_LMAP;
|
|
}
|
|
}
|
|
|
|
// Add the sewer map.
|
|
if(mission_pool[c0].CitSezMapName[0])
|
|
{
|
|
new_element = new WSElement;
|
|
if(new_element)
|
|
{
|
|
tv_is.hParent = mission_handle;
|
|
tv_is.hInsertAfter = TVI_LAST;
|
|
tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
|
|
tv_is.item.iImage = IM_SEWER;
|
|
tv_is.item.iSelectedImage = IM_SEWER;
|
|
tv_is.item.pszText = &mission_pool[c0].CitSezMapName[5];
|
|
tv_is.item.lParam = (LPARAM)new_element;
|
|
new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is);
|
|
new_element->ElementType = ET_LMAP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gm_vers>=3) { // includes zoning info
|
|
fread(MissionZones[c0],128*128,1,file_handle);
|
|
}
|
|
}
|
|
|
|
// Force a redraw on the workspace tree.
|
|
InvalidateRect(ws_tree, NULL, FALSE);
|
|
|
|
// Change the root item.
|
|
sprintf(temp,"Workspace : %s",workspace_name);
|
|
set_item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT;
|
|
set_item.hItem = root_item.TreeItem;
|
|
set_item.pszText = temp;
|
|
set_item.iImage = IM_ROOT;
|
|
set_item.iSelectedImage = IM_ROOT;
|
|
root_item.ElementType = ET_ROOT;
|
|
TreeView_SetItem(ws_tree,&set_item);
|
|
|
|
// Set the workspace state & corresponding menus.
|
|
workspace_changed = FALSE;
|
|
menu_has_workspace();
|
|
|
|
fclose(file_handle);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
#define GM_VERSION 8
|
|
|
|
BOOL save_workspace(void)
|
|
{
|
|
UBYTE gm_vers;
|
|
ULONG c0,c1,
|
|
data;
|
|
FILE *file_handle;
|
|
// EventPoint *ep_base;
|
|
|
|
|
|
// Set the 'busy' cursor.
|
|
SetCursor(GEDIT_busy);
|
|
|
|
|
|
// Save the workspace.
|
|
file_handle = fopen(workspace_path,"wb");
|
|
|
|
if(file_handle)
|
|
{
|
|
// Save the file version.
|
|
gm_vers = GM_VERSION;
|
|
fwrite(&gm_vers,sizeof(gm_vers),1,file_handle);
|
|
|
|
// Save the number of game maps & the structure size.
|
|
data = MAX_MAPS;
|
|
fwrite(&data,sizeof(data),1,file_handle);
|
|
data = sizeof(GameMap);
|
|
fwrite(&data,sizeof(data),1,file_handle);
|
|
|
|
// Save the maps.
|
|
fwrite(&game_maps,sizeof(GameMap),MAX_MAPS,file_handle);
|
|
|
|
// Save the number of missions, the number of event points & the structure size.
|
|
data = MAX_MISSIONS;
|
|
fwrite(&data,sizeof(data),1,file_handle);
|
|
data = MAX_EVENTPOINTS;
|
|
fwrite(&data,sizeof(data),1,file_handle);
|
|
data = sizeof(Mission);
|
|
fwrite(&data,sizeof(data),1,file_handle);
|
|
|
|
// Save the missions.
|
|
for(c0=0;c0<MAX_MISSIONS;c0++)
|
|
{
|
|
// Spit out the mission.
|
|
fwrite(&mission_pool[c0],sizeof(Mission),1,file_handle);
|
|
|
|
// Save out the text.
|
|
for(c1=0;c1<MAX_EVENTPOINTS;c1++)
|
|
write_event_extra(file_handle,&mission_pool[c0].EventPoints[c1]);
|
|
|
|
// Write out the zoning information
|
|
fwrite((void*)MissionZones[c0],128*128,1,file_handle);
|
|
|
|
}
|
|
|
|
fclose(file_handle);
|
|
}
|
|
|
|
// Set the 'arrow' cursor.
|
|
SetCursor(GEDIT_arrow);
|
|
|
|
workspace_changed = FALSE;
|
|
menu_workspace_saved();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void remove_children(HTREEITEM parent)
|
|
{
|
|
HTREEITEM current_item,
|
|
next_item;
|
|
TVITEM item_info;
|
|
|
|
|
|
if(parent)
|
|
{
|
|
// Sort out its children.
|
|
current_item = TreeView_GetChild(ws_tree,parent);
|
|
while(current_item)
|
|
{
|
|
next_item = TreeView_GetNextSibling(ws_tree,current_item);
|
|
remove_children(current_item);
|
|
current_item = next_item;
|
|
}
|
|
|
|
// Delete the parent only if it isn't the root.
|
|
if(parent!=TreeView_GetRoot(ws_tree))
|
|
{
|
|
// Get the items WSElement.
|
|
item_info.hItem = parent;
|
|
item_info.mask = TVIF_PARAM;
|
|
TreeView_GetItem(ws_tree,&item_info);
|
|
|
|
// Delete the WSElement.
|
|
delete (WSElement*)item_info.lParam;
|
|
|
|
// Delete the tree item.
|
|
TreeView_DeleteItem(ws_tree,parent);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
// Waypointy stuff
|
|
|
|
|
|
BOOL init_wptlist(HWND parent)
|
|
{
|
|
|
|
// Subclass the tree control windproc.
|
|
wpt_tree = GetDlgItem(parent,IDC_WORKSPACE_TREE2);
|
|
// tree_proc = (WNDPROC)SetWindowLong(ws_tree,GWL_WNDPROC,(long)sc_tree_proc);
|
|
|
|
// Set up the trees image list.
|
|
/* image_list = ImageList_LoadBitmap(
|
|
GEDIT_hinstance,
|
|
MAKEINTRESOURCE(IDB_WORKSPACE),
|
|
16,
|
|
1,
|
|
RGB (255, 0, 255)
|
|
);
|
|
*/
|
|
TreeView_SetImageList(wpt_tree,image_list,TVSIL_NORMAL);
|
|
TreeView_SetImageList(wpt_tree,image_list,TVSIL_STATE);
|
|
|
|
reset_wptlist();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void reset_wptlist(void) {
|
|
|
|
// Set up the tree roots.
|
|
TreeView_DeleteAllItems(wpt_tree);
|
|
/* ws_root_waypoint("Map exits", IM_MAPEXIT,6);
|
|
ws_root_waypoint("Misc", IM_WAYPOINT,5);
|
|
ws_root_waypoint("Traps", IM_TRAP,4);
|
|
ws_root_waypoint("Cameras", IM_CAMERA,3);
|
|
ws_root_waypoint("Items", IM_ITEM,2);
|
|
ws_root_waypoint("Enemies", IM_COP,1);
|
|
ws_root_waypoint("Create Player", IM_PLAYER,0);
|
|
*/
|
|
}
|
|
|
|
|
|
void fill_wptlist(Mission *mish) {
|
|
SLONG ndx=mish->UsedEPoints;
|
|
EventPoint *ep_base = mish->EventPoints;
|
|
|
|
EventPoint *ep;
|
|
|
|
while(ndx) {
|
|
ep = TO_EVENTPOINT(ep_base,ndx);
|
|
ws_add_waypoint(ep);
|
|
ndx= ep->Next;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void fini_wptlist(void)
|
|
{
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
HTREEITEM ws_root_waypoint(CBYTE *msg, SLONG type, LPARAM param) {
|
|
TV_INSERTSTRUCT tv_is;
|
|
|
|
if (msg[0]==0) {
|
|
switch(param) {
|
|
case 0:
|
|
strcpy(msg,"Create Player");
|
|
type=IM_PLAYER;
|
|
break;
|
|
case 1:
|
|
strcpy(msg,"Enemies");
|
|
type=IM_COP;
|
|
break;
|
|
case 2:
|
|
strcpy(msg,"Items");
|
|
type=IM_ITEM;
|
|
break;
|
|
case 3:
|
|
strcpy(msg,"Traps");
|
|
type=IM_TRAP;
|
|
break;
|
|
case 4:
|
|
strcpy(msg,"Cameras");
|
|
type=IM_CAMERA;
|
|
break;
|
|
case 5:
|
|
strcpy(msg,"Misc");
|
|
type=IM_WAYPOINT;
|
|
break;
|
|
case 6:
|
|
strcpy(msg,"Map exits");
|
|
type=IM_MAPEXIT;
|
|
break;
|
|
case 7:
|
|
strcpy(msg,"Text messages");
|
|
type=IM_MESSAGE;
|
|
break;
|
|
}
|
|
}
|
|
tv_is.hParent = TVI_ROOT;
|
|
tv_is.hInsertAfter = TVI_SORT;
|
|
tv_is.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE;
|
|
tv_is.item.stateMask = TVIS_STATEIMAGEMASK;
|
|
tv_is.item.state = 0;
|
|
tv_is.item.pszText = msg;
|
|
tv_is.item.lParam = param;
|
|
tv_is.item.iImage =
|
|
tv_is.item.iSelectedImage = type;
|
|
return TreeView_InsertItem(wpt_tree,&tv_is);
|
|
}
|
|
|
|
HTREEITEM ws_find_child(HTREEITEM parent, LPARAM param) {
|
|
HTREEITEM kid;
|
|
TVITEM item;
|
|
|
|
if (parent)
|
|
kid=TreeView_GetChild(wpt_tree,parent);
|
|
else
|
|
kid=TreeView_GetRoot(wpt_tree);
|
|
while (kid) {
|
|
item.mask=TVIF_HANDLE;
|
|
item.hItem=kid;
|
|
TreeView_GetItem(wpt_tree,&item);
|
|
if (item.lParam==param) return kid;
|
|
kid=TreeView_GetNextSibling(wpt_tree,kid);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
SLONG ws_image_from_type(EventPoint *ep) {
|
|
switch(ep->WaypointType) {
|
|
case WPT_NONE:
|
|
case WPT_SIMPLE:
|
|
case WPT_CREATE_VEHICLE:
|
|
case WPT_VISUAL_EFFECT:
|
|
case WPT_END_GAME_LOSE:
|
|
case WPT_END_GAME_WIN:
|
|
case WPT_SHOUT:
|
|
case WPT_NAV_BEACON:
|
|
case WPT_CUT_SCENE:
|
|
case WPT_TELEPORT:
|
|
case WPT_TELEPORT_TARGET:
|
|
case WPT_ACTIVATE_PRIM:
|
|
case WPT_LINK_PLATFORM:
|
|
case WPT_BURN_PRIM:
|
|
case WPT_SPOT_EFFECT:
|
|
case WPT_INTERESTING:
|
|
case WPT_MAKE_SEARCHABLE:
|
|
case WPT_LOCK_VEHICLE:
|
|
case WPT_STALL_CAR:
|
|
case WPT_EXTEND:
|
|
case WPT_MOVE_THING:
|
|
case WPT_CONE_PENALTIES:
|
|
case WPT_SIGN:
|
|
case WPT_NO_FLOOR:
|
|
case WPT_SHAKE_CAMERA:
|
|
return IM_WAYPOINT;
|
|
|
|
case WPT_CREATE_PLAYER:
|
|
return IM_PLAYER;
|
|
|
|
case WPT_CREATE_ENEMIES:
|
|
case WPT_ADJUST_ENEMY:
|
|
case WPT_CREATE_CREATURE:
|
|
return IM_COP;
|
|
|
|
case WPT_MESSAGE:
|
|
case WPT_CONVERSATION:
|
|
return IM_MESSAGE;
|
|
|
|
case WPT_CREATE_ITEM:
|
|
case WPT_CREATE_BARREL:
|
|
return IM_ITEM;
|
|
|
|
case WPT_CREATE_CAMERA:
|
|
case WPT_CREATE_TARGET:
|
|
case WPT_CAMERA_WAYPOINT:
|
|
case WPT_TARGET_WAYPOINT:
|
|
return IM_CAMERA;
|
|
|
|
case WPT_CREATE_MAP_EXIT:
|
|
return IM_MAPEXIT;
|
|
|
|
case WPT_SOUND_EFFECT:
|
|
case WPT_WAREFX:
|
|
return IM_SOUND;
|
|
|
|
case WPT_CREATE_TRAP:
|
|
case WPT_KILL_WAYPOINT:
|
|
return IM_TRAP;
|
|
|
|
case WPT_CREATE_BOMB:
|
|
return IM_BOMB;
|
|
|
|
default:
|
|
return IM_WAYPOINT;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
SLONG ws_category_from_type(EventPoint *ep) {
|
|
switch(ep->WaypointType) {
|
|
// misc
|
|
case WPT_NONE:
|
|
case WPT_SIMPLE:
|
|
case WPT_CREATE_VEHICLE:
|
|
case WPT_VISUAL_EFFECT:
|
|
case WPT_END_GAME_WIN:
|
|
case WPT_END_GAME_LOSE:
|
|
case WPT_SHOUT:
|
|
case WPT_CUT_SCENE:
|
|
case WPT_TELEPORT:
|
|
case WPT_TELEPORT_TARGET:
|
|
case WPT_ACTIVATE_PRIM:
|
|
case WPT_SOUND_EFFECT:
|
|
case WPT_SPOT_EFFECT:
|
|
case WPT_DYNAMIC_LIGHT:
|
|
case WPT_LINK_PLATFORM:
|
|
case WPT_NAV_BEACON:
|
|
case WPT_BURN_PRIM:
|
|
case WPT_KILL_WAYPOINT:
|
|
case WPT_GROUP_LIFE:
|
|
case WPT_GROUP_DEATH:
|
|
case WPT_INTERESTING:
|
|
case WPT_GOTHERE_DOTHIS:
|
|
case WPT_MAKE_SEARCHABLE:
|
|
case WPT_LOCK_VEHICLE:
|
|
case WPT_GROUP_RESET:
|
|
case WPT_COUNT_UP_TIMER:
|
|
case WPT_CREATE_MIST:
|
|
case WPT_STALL_CAR:
|
|
case WPT_MOVE_THING:
|
|
case WPT_EXTEND:
|
|
case WPT_CONE_PENALTIES:
|
|
case WPT_SIGN:
|
|
case WPT_WAREFX:
|
|
case WPT_SHAKE_CAMERA:
|
|
case WPT_NO_FLOOR:
|
|
return 5;
|
|
// texty things
|
|
case WPT_MESSAGE:
|
|
case WPT_CONVERSATION:
|
|
return 7;
|
|
// player
|
|
case WPT_CREATE_PLAYER:
|
|
case WPT_AUTOSAVE:
|
|
return 0;
|
|
// enemies
|
|
case WPT_CREATE_ENEMIES:
|
|
case WPT_ADJUST_ENEMY:
|
|
case WPT_CREATE_CREATURE:
|
|
case WPT_ENEMY_FLAGS:
|
|
return 1;
|
|
// items
|
|
case WPT_CREATE_ITEM:
|
|
case WPT_CREATE_BARREL:
|
|
case WPT_CREATE_TREASURE:
|
|
case WPT_BONUS_POINTS:
|
|
return 2;
|
|
// cam stuff
|
|
case WPT_CREATE_CAMERA:
|
|
case WPT_CREATE_TARGET:
|
|
case WPT_CAMERA_WAYPOINT:
|
|
case WPT_TARGET_WAYPOINT:
|
|
return 4;
|
|
// exits
|
|
case WPT_CREATE_MAP_EXIT:
|
|
return 6;
|
|
// traps
|
|
case WPT_CREATE_TRAP:
|
|
case WPT_CREATE_BOMB:
|
|
return 3;
|
|
default:
|
|
return 5; // misc
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void ws_add_waypoint(EventPoint *ep) {
|
|
HTREEITEM parent;
|
|
SLONG code;
|
|
TV_INSERTSTRUCT tv_is;
|
|
CBYTE msg[800];
|
|
|
|
if (!ep->Used) return;
|
|
|
|
msg[0]=0;
|
|
parent=ws_find_child(0,code=ws_category_from_type(ep));
|
|
if (code==-1) return;
|
|
if (!parent) parent=ws_root_waypoint(msg, 0, code);
|
|
tv_is.hParent = parent;
|
|
tv_is.hInsertAfter = TVI_SORT;
|
|
tv_is.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE;
|
|
tv_is.item.stateMask = TVIS_STATEIMAGEMASK;
|
|
if (ep->Flags&WPT_FLAGS_SUCKS)
|
|
tv_is.item.state = INDEXTOSTATEIMAGEMASK(IM_BROKEN);
|
|
else
|
|
tv_is.item.state = 0;
|
|
tv_is.item.pszText = WaypointTitle(ep, msg);
|
|
tv_is.item.lParam = (LPARAM)ep;
|
|
tv_is.item.iImage =
|
|
tv_is.item.iSelectedImage = ws_image_from_type(ep);
|
|
TreeView_InsertItem(wpt_tree,&tv_is);
|
|
|
|
// double check -- if this one sucks, it's parent sucks too, to help find suckage.
|
|
if (ep->Flags&WPT_FLAGS_SUCKS) {
|
|
tv_is.item.hItem = parent;
|
|
tv_is.item.mask = TVIF_HANDLE|TVIF_STATE;
|
|
tv_is.item.stateMask = TVIS_STATEIMAGEMASK;
|
|
tv_is.item.state = INDEXTOSTATEIMAGEMASK(IM_BROKEN);
|
|
TreeView_SetItem(wpt_tree,&tv_is.item);
|
|
}
|
|
|
|
}
|
|
|
|
void ws_set_waypoint(EventPoint *ep, CBYTE ndx) {
|
|
// HTREEITEM item;
|
|
|
|
// item=ws_find_child(0,ws_category_from_type(ep));
|
|
if (ep->WaypointType!=ndx) {
|
|
ws_del_waypoint(ep);
|
|
ep->WaypointType=ndx;
|
|
ws_add_waypoint(ep);
|
|
}
|
|
/* if (item) {
|
|
item=ws_find_child(item,(LPARAM)ep);
|
|
if (ep->WaypointType!=ndx) {
|
|
ep->WaypointType=ndx;
|
|
TreeView_DeleteItem(wpt_tree,item);
|
|
ws_add_waypoint(ep);
|
|
}
|
|
}*/
|
|
}
|
|
|
|
void ws_sel_waypoint(EventPoint *ep) {
|
|
HTREEITEM item;
|
|
if (!ep) {
|
|
TreeView_SelectItem(wpt_tree,0);
|
|
return;
|
|
}
|
|
item=ws_find_child(0,ws_category_from_type(ep));
|
|
if (item) {
|
|
item=ws_find_child(item,(LPARAM)ep);
|
|
TreeView_SelectItem(wpt_tree,item);
|
|
}
|
|
}
|
|
|
|
void ws_del_waypoint(EventPoint *ep) {
|
|
HTREEITEM parent,item;
|
|
parent=ws_find_child(0,ws_category_from_type(ep));
|
|
if (parent) {
|
|
item=ws_find_child(parent,(LPARAM)ep);
|
|
if (item) TreeView_DeleteItem(wpt_tree,item);
|
|
item=TreeView_GetChild(wpt_tree,parent);
|
|
if (!item) TreeView_DeleteItem(wpt_tree,parent);
|
|
}
|
|
}
|
|
|