2171 lines
62 KiB
C++
2171 lines
62 KiB
C++
|
//
|
||
|
// Copyright 2020 Electronic Arts Inc.
|
||
|
//
|
||
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
|
||
|
|
||
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
|
||
|
// in the hope that it will be useful, but with permitted additional restrictions
|
||
|
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
|
||
|
// distributed with this program. You should have received a copy of the
|
||
|
// GNU General Public License along with permitted additional restrictions
|
||
|
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||
|
|
||
|
/* $Header: /CounterStrike/MAPEDIT.CPP 2 3/13/97 2:05p Steve_tall $ */
|
||
|
/***************************************************************************
|
||
|
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||
|
***************************************************************************
|
||
|
* *
|
||
|
* Project Name : Command & Conquer *
|
||
|
* *
|
||
|
* File Name : MAPEDIT.CPP *
|
||
|
* *
|
||
|
* Programmer : Bill Randolph *
|
||
|
* *
|
||
|
* Start Date : October 20, 1994 *
|
||
|
* *
|
||
|
* Last Update : February 2, 1995 [BR] *
|
||
|
* *
|
||
|
*-------------------------------------------------------------------------*
|
||
|
* Map Editor overloaded routines & utility routines *
|
||
|
*-------------------------------------------------------------------------*
|
||
|
* Map Editor modules: *
|
||
|
* (Yes, they're all one huge class.) *
|
||
|
* mapedit.cpp: overloaded routines, utility routines *
|
||
|
* mapeddlg.cpp: map editor dialogs, most of the main menu options *
|
||
|
* mapedplc.cpp: object-placing routines *
|
||
|
* mapedsel.cpp: object-selection & manipulation routines *
|
||
|
* mapedtm.cpp: team-editing routines *
|
||
|
*-------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* MapEditClass::AI -- The map editor's main logic *
|
||
|
* MapEditClass::Read_INI -- overloaded Read_INI function *
|
||
|
* MapEditClass::AI_Menu -- menu of AI options *
|
||
|
* MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list *
|
||
|
* MapEditClass::Clear_List -- clears the internal chooseable object list*
|
||
|
* MapEditClass::Cycle_House -- finds next valid house for object type *
|
||
|
* MapEditClass::Draw_It -- overloaded Redraw routine *
|
||
|
* MapEditClass::Fatal -- exits with error message *
|
||
|
* MapEditClass::Main_Menu -- main menu processor for map editor *
|
||
|
* MapEditClass::MapEditClass -- class constructor *
|
||
|
* MapEditClass::Mouse_Moved -- checks for mouse motion *
|
||
|
* MapEditClass::One_Time -- one-time initialization *
|
||
|
* MapEditClass::Verify_House -- sees if given house can own given obj *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#include "function.h"
|
||
|
|
||
|
#ifdef SCENARIO_EDITOR
|
||
|
|
||
|
/*
|
||
|
** Array of all missions supported by the map editor
|
||
|
*/
|
||
|
MissionType MapEditClass::MapEditMissions[] = {
|
||
|
MISSION_GUARD,
|
||
|
MISSION_STICKY,
|
||
|
MISSION_HARMLESS,
|
||
|
MISSION_HARVEST,
|
||
|
MISSION_GUARD_AREA,
|
||
|
MISSION_RETURN,
|
||
|
MISSION_AMBUSH,
|
||
|
MISSION_HUNT,
|
||
|
MISSION_SLEEP,
|
||
|
};
|
||
|
#define NUM_EDIT_MISSIONS (sizeof(MapEditClass::MapEditMissions) / sizeof(MapEditClass::MapEditMissions[0]))
|
||
|
|
||
|
|
||
|
/*
|
||
|
** For menu processing
|
||
|
*/
|
||
|
extern int UnknownKey; // in menus.cpp
|
||
|
|
||
|
char MapEditClass::HealthBuf[20];
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::MapEditClass -- class constructor *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/20/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
MapEditClass::MapEditClass(void)
|
||
|
{
|
||
|
/*
|
||
|
** Init data members.
|
||
|
*/
|
||
|
// ScenVar = SCEN_VAR_A;
|
||
|
ObjCount = 0;
|
||
|
LastChoice = 0;
|
||
|
LastHouse = HOUSE_GOOD;
|
||
|
GrabbedObject = 0;
|
||
|
for (int i=0; i < NUM_EDIT_CLASSES; i++) {
|
||
|
NumType[i] = 0;
|
||
|
TypeOffset[i] = 0;
|
||
|
}
|
||
|
Scen.Waypoint[WAYPT_HOME] = 0;
|
||
|
CurrentCell = 0;
|
||
|
CurTeam = NULL;
|
||
|
CurTrigger = NULL;
|
||
|
Changed = 0;
|
||
|
LMouseDown = 0;
|
||
|
BaseBuilding = false;
|
||
|
// BasePercent = 100;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::One_Time -- one-time initialization *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 02/02/1995 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::One_Time(void)
|
||
|
{
|
||
|
MouseClass::One_Time();
|
||
|
|
||
|
/*
|
||
|
** The map: a single large "button"
|
||
|
*/
|
||
|
#ifdef WIN32
|
||
|
MapArea = new ControlClass(MAP_AREA, 0, 8, 640-8, 400-8, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);
|
||
|
#else
|
||
|
MapArea = new ControlClass(MAP_AREA, 0, 8, 312, 192, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
** House buttons
|
||
|
*/
|
||
|
HouseList = new ListClass(POPUP_HOUSELIST, POPUP_HOUSE_X, POPUP_HOUSE_Y, POPUP_HOUSE_W, POPUP_HOUSE_H,
|
||
|
TPF_EFNT|TPF_NOSHADOW,
|
||
|
MFCD::Retrieve("EBTN-UP.SHP"),
|
||
|
MFCD::Retrieve("EBTN-DN.SHP"));
|
||
|
for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
|
||
|
HouseList->Add_Item(HouseTypeClass::As_Reference(house).IniName);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** The mission list box
|
||
|
*/
|
||
|
MissionList = new ListClass(POPUP_MISSIONLIST,
|
||
|
POPUP_MISSION_X, POPUP_MISSION_Y, POPUP_MISSION_W, POPUP_MISSION_H,
|
||
|
TPF_EFNT|TPF_NOSHADOW,
|
||
|
MFCD::Retrieve("EBTN-UP.SHP"),
|
||
|
MFCD::Retrieve("EBTN-DN.SHP"));
|
||
|
|
||
|
for (int i = 0; i < NUM_EDIT_MISSIONS; i++) {
|
||
|
MissionList->Add_Item(MissionClass::Mission_Name(MapEditMissions[i]));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** The health bar
|
||
|
*/
|
||
|
HealthGauge = new TriColorGaugeClass(POPUP_HEALTHGAUGE,
|
||
|
POPUP_HEALTH_X, POPUP_HEALTH_Y, POPUP_HEALTH_W, POPUP_HEALTH_H);
|
||
|
HealthGauge->Use_Thumb(true);
|
||
|
HealthGauge->Set_Maximum(0x100);
|
||
|
HealthGauge->Set_Red_Limit(0x3f - 1);
|
||
|
HealthGauge->Set_Yellow_Limit(0x7f - 1);
|
||
|
|
||
|
/*
|
||
|
** The health text label
|
||
|
*/
|
||
|
HealthBuf[0] = 0;
|
||
|
HealthText = new TextLabelClass(HealthBuf,
|
||
|
POPUP_HEALTH_X + POPUP_HEALTH_W / 2,
|
||
|
POPUP_HEALTH_Y + POPUP_HEALTH_H + 1,
|
||
|
GadgetClass::Get_Color_Scheme(),
|
||
|
TPF_CENTER | TPF_FULLSHADOW | TPF_EFNT);
|
||
|
|
||
|
/*
|
||
|
** Building attribute buttons.
|
||
|
*/
|
||
|
Sellable = new TextButtonClass(POPUP_SELLABLE, TXT_SELLABLE, TPF_EBUTTON, 320-65, 200-25, 60);
|
||
|
Rebuildable = new TextButtonClass(POPUP_REBUILDABLE, TXT_REBUILD, TPF_EBUTTON, 320-65, 200-15, 60);
|
||
|
|
||
|
/*
|
||
|
** The facing dial
|
||
|
*/
|
||
|
FacingDial = new Dial8Class(POPUP_FACINGDIAL, POPUP_FACEBOX_X,
|
||
|
POPUP_FACEBOX_Y, POPUP_FACEBOX_W, POPUP_FACEBOX_H, (DirType)0);
|
||
|
|
||
|
/*
|
||
|
** The base percent-built slider & its label
|
||
|
*/
|
||
|
BaseGauge = new GaugeClass(POPUP_BASEPERCENT, POPUP_BASE_X, POPUP_BASE_Y, POPUP_BASE_W, POPUP_BASE_H);
|
||
|
BaseLabel = new TextLabelClass ("Base:", POPUP_BASE_X - 3, POPUP_BASE_Y, GadgetClass::Get_Color_Scheme(),
|
||
|
TPF_RIGHT | TPF_NOSHADOW | TPF_EFNT);
|
||
|
BaseGauge->Set_Maximum(100);
|
||
|
BaseGauge->Set_Value(Scen.Percent);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
* MapeditClass::Init_IO -- Reinitializes the radar map at scenario start. *
|
||
|
* *
|
||
|
* INPUT: none *
|
||
|
* *
|
||
|
* OUTPUT: none *
|
||
|
* *
|
||
|
* WARNINGS: none *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 12/22/1994 JLB : Created. *
|
||
|
*=============================================================================================*/
|
||
|
void MapEditClass::Init_IO(void)
|
||
|
{
|
||
|
/*
|
||
|
** For normal game mode, jump to the parent's Init routine.
|
||
|
*/
|
||
|
if (!Debug_Map) {
|
||
|
|
||
|
MouseClass::Init_IO();
|
||
|
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** For editor mode, add the map area to the button input list
|
||
|
*/
|
||
|
Buttons = 0;
|
||
|
Add_A_Button(*BaseGauge);
|
||
|
Add_A_Button(*BaseLabel);
|
||
|
Add_A_Button(*MapArea);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Clear_List -- clears the internal chooseable object list *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/20/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::Clear_List(void)
|
||
|
{
|
||
|
/*
|
||
|
** Set # object type ptrs to 0, set NumType for each type to 0
|
||
|
*/
|
||
|
ObjCount = 0;
|
||
|
for (int i = 0; i < NUM_EDIT_CLASSES; i++) {
|
||
|
NumType[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list *
|
||
|
* *
|
||
|
* Use this routine to add an object to the game object selection list. *
|
||
|
* This list is used by the Add_Object function. All items located in the *
|
||
|
* list will appear and be chooseable by that function. Make sure to *
|
||
|
* clear the list before adding a sequence of items to it. Clearing *
|
||
|
* the list is accomplished by the Clear_List() function. *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* object ptr to ObjectTypeClass to add *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* bool: was the object added to the list? A failure could occur if *
|
||
|
* NULL were passed in or the list is full. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 06/04/1994 JLB : Created. *
|
||
|
*=========================================================================*/
|
||
|
bool MapEditClass::Add_To_List(ObjectTypeClass const * object)
|
||
|
{
|
||
|
/*
|
||
|
** Add the object if there's room.
|
||
|
*/
|
||
|
if (object && ObjCount < MAX_EDIT_OBJECTS) {
|
||
|
Objects[ObjCount++] = object;
|
||
|
|
||
|
/*
|
||
|
** Update type counters.
|
||
|
*/
|
||
|
switch (object->What_Am_I()) {
|
||
|
case RTTI_TEMPLATETYPE:
|
||
|
NumType[0]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_OVERLAYTYPE:
|
||
|
NumType[1]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_SMUDGETYPE:
|
||
|
NumType[2]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_TERRAINTYPE:
|
||
|
NumType[3]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_UNITTYPE:
|
||
|
NumType[4]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_INFANTRYTYPE:
|
||
|
NumType[5]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_VESSELTYPE:
|
||
|
NumType[6]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_BUILDINGTYPE:
|
||
|
NumType[7]++;
|
||
|
break;
|
||
|
|
||
|
case RTTI_AIRCRAFTTYPE:
|
||
|
NumType[8]++;
|
||
|
break;
|
||
|
}
|
||
|
return(true);
|
||
|
}
|
||
|
|
||
|
return(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::AI -- The map editor's main logic *
|
||
|
* *
|
||
|
* This routine overloads the parent's (DisplayClass) AI function. *
|
||
|
* It checks for any input specific to map editing, and calls the parent *
|
||
|
* AI routine to handle scrolling and other mainstream map stuff. *
|
||
|
* *
|
||
|
* If this detects one of its special input keys, it sets 'input' to 0 *
|
||
|
* before calling the parent AI routine; this prevents input conflict. *
|
||
|
* *
|
||
|
* SUPPORTED INPUT: *
|
||
|
* General: *
|
||
|
* F2/RMOUSE: main menu *
|
||
|
* F6: toggles show-passable mode *
|
||
|
* HOME: go to the Home Cell (scenario's start position)*
|
||
|
* SHIFT-HOME: set the Home Cell to the current TacticalCell*
|
||
|
* ESC: exits to DOS *
|
||
|
* Object Placement: *
|
||
|
* INSERT: go into placement mode *
|
||
|
* ESC: exit placement mode *
|
||
|
* LEFT/RIGHT: prev/next placement object *
|
||
|
* PGUP/PGDN: prev/next placement category *
|
||
|
* HOME: 1st placement object (clear template) *
|
||
|
* h/H: toggle house of placement object *
|
||
|
* LMOUSE: place the placement object *
|
||
|
* MOUSE MOTION: "paint" with the placement object *
|
||
|
* Object selection: *
|
||
|
* LMOUSE: select & "grab" current object *
|
||
|
* If no object is present where the mouse is *
|
||
|
* clicked, the current object is de-selected *
|
||
|
* If the same object is clicked on, it stays *
|
||
|
* selected. Also displays the object-editing *
|
||
|
* gadgets. *
|
||
|
* LMOUSE RLSE: release currently-grabbed object *
|
||
|
* MOUSE MOTION: if an object is grabbed, moves the object *
|
||
|
* SHIFT|ALT|ARROW: moves object in that direction *
|
||
|
* DELETE deletes currently-selected object *
|
||
|
* Object-editing controls: *
|
||
|
* POPUP_GDI: makes GDI the owner of this object *
|
||
|
* POPUP_NOD: makes NOD the owner of this object *
|
||
|
* POPUP_MISSIONLIST: sets that mission for this object *
|
||
|
* POPUP_HEALTHGAUGE: sets that health value for this object *
|
||
|
* POPUP_FACINGDIAL: sets the object's facing *
|
||
|
* *
|
||
|
* Changed is set when you: *
|
||
|
* - place an object *
|
||
|
* - move a grabbed object *
|
||
|
* - delete an object *
|
||
|
* - size the map *
|
||
|
* - create a new scenario *
|
||
|
* Changed is cleared when you: *
|
||
|
* - Save the scenario *
|
||
|
* - Load a scenario *
|
||
|
* - Play the scenario *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* input KN_ value, 0 if none *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/20/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::AI(KeyNumType & input, int x, int y)
|
||
|
{
|
||
|
int rc;
|
||
|
MissionType mission;
|
||
|
int strength;
|
||
|
CELL cell;
|
||
|
int i;
|
||
|
int found; // for removing a waypoint label
|
||
|
int waypt_idx; // for labelling a waypoint
|
||
|
BaseNodeClass * node; // for removing from an AI Base
|
||
|
HousesType house;
|
||
|
char wayname[4];
|
||
|
|
||
|
/*
|
||
|
** Trap 'F2' regardless of whether we're in game or editor mode
|
||
|
*/
|
||
|
if (Debug_Flag) {
|
||
|
if ((input == KN_F2 && Session.Type == GAME_NORMAL) || input == (KN_F2 | KN_CTRL_BIT)) {
|
||
|
ScenarioInit = 0;
|
||
|
|
||
|
/*
|
||
|
** If we're in editor mode & Changed is set, prompt for saving changes
|
||
|
*/
|
||
|
if (Debug_Map && Changed) {
|
||
|
rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
|
||
|
/*
|
||
|
** User wants to save
|
||
|
*/
|
||
|
if (rc == 0) {
|
||
|
|
||
|
/*
|
||
|
** If save cancelled, abort game
|
||
|
*/
|
||
|
if (Save_Scenario()!=0) {
|
||
|
input = KN_NONE;
|
||
|
} else {
|
||
|
Changed = 0;
|
||
|
Go_Editor(!Debug_Map);
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** User doesn't want to save
|
||
|
*/
|
||
|
Go_Editor(!Debug_Map);
|
||
|
}
|
||
|
} else {
|
||
|
/*
|
||
|
** If we're in game mode, set Changed to 0 (so if we didn't save our
|
||
|
** changes above, they won't keep coming back to haunt us with continual
|
||
|
** Save Changes? prompts!)
|
||
|
*/
|
||
|
if (!Debug_Map) {
|
||
|
Changed = 0;
|
||
|
}
|
||
|
BaseGauge->Set_Value(Scen.Percent);
|
||
|
Go_Editor(!Debug_Map);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** For normal game mode, jump to the parent's AI routine.
|
||
|
*/
|
||
|
if (!Debug_Map) {
|
||
|
MouseClass::AI(input, x, y);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
::Frame++;
|
||
|
|
||
|
/*
|
||
|
** Do special mouse processing if the mouse is over the map
|
||
|
*/
|
||
|
if (Get_Mouse_X() > TacPixelX && Get_Mouse_X() <
|
||
|
TacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&
|
||
|
Get_Mouse_Y() > TacPixelY && Get_Mouse_Y() <
|
||
|
TacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {
|
||
|
|
||
|
/*
|
||
|
** When the mouse moves over a scrolling edge, ScrollClass changes its
|
||
|
** shape to the appropriate arrow or NO symbol; it's our job to change it
|
||
|
** back to normal (or whatever the shape is set to by Set_Default_Mouse())
|
||
|
** when it re-enters the map area.
|
||
|
*/
|
||
|
if (CurTrigger) {
|
||
|
Override_Mouse_Shape(MOUSE_CAN_MOVE);
|
||
|
} else {
|
||
|
Override_Mouse_Shape(MOUSE_NORMAL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Set 'ZoneCell' to track the mouse cursor around over the map. Do this
|
||
|
** even if the map is scrolling.
|
||
|
*/
|
||
|
if (Get_Mouse_X() >= TacPixelX && Get_Mouse_X() <=
|
||
|
TacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&
|
||
|
Get_Mouse_Y() >= TacPixelY && Get_Mouse_Y() <=
|
||
|
TacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {
|
||
|
|
||
|
cell = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());
|
||
|
if (cell != -1) {
|
||
|
Set_Cursor_Pos(cell);
|
||
|
if (PendingObject) {
|
||
|
Flag_To_Redraw(true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Check for mouse motion while left button is down.
|
||
|
*/
|
||
|
rc = Mouse_Moved();
|
||
|
if (LMouseDown && rc) {
|
||
|
|
||
|
/*
|
||
|
** "Paint" mode: place current object, and restart placement
|
||
|
*/
|
||
|
if (PendingObject) {
|
||
|
Flag_To_Redraw(true);
|
||
|
if (Place_Object() == 0) {
|
||
|
Changed = 1;
|
||
|
Start_Placement();
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** Move the currently-grabbed object
|
||
|
*/
|
||
|
if (GrabbedObject) {
|
||
|
GrabbedObject->Mark(MARK_CHANGE);
|
||
|
if (Move_Grabbed_Object() == 0) {
|
||
|
Changed = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Trap special editing keys; if one is detected, set 'input' to 0 to
|
||
|
** prevent a conflict with parent's AI().
|
||
|
*/
|
||
|
switch (input) {
|
||
|
/*
|
||
|
** F2/RMOUSE = pop up main menu
|
||
|
*/
|
||
|
case KN_RMOUSE:
|
||
|
|
||
|
/*
|
||
|
** Turn off placement mode
|
||
|
*/
|
||
|
if (PendingObject) {
|
||
|
if (BaseBuilding) {
|
||
|
Cancel_Base_Building();
|
||
|
} else {
|
||
|
Cancel_Placement();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Turn off trigger placement mode
|
||
|
*/
|
||
|
if (CurTrigger) {
|
||
|
Stop_Trigger_Placement();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Unselect object & hide popup controls
|
||
|
*/
|
||
|
if (CurrentObject.Count()) {
|
||
|
CurrentObject[0]->Unselect();
|
||
|
Popup_Controls();
|
||
|
}
|
||
|
Main_Menu();
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** F6 = toggle passable/impassable display
|
||
|
*/
|
||
|
case KN_F6:
|
||
|
Debug_Passable = (Debug_Passable == false);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** INSERT = go into object-placement mode
|
||
|
*/
|
||
|
case KN_INSERT:
|
||
|
if (!PendingObject) {
|
||
|
/*
|
||
|
** Unselect current object, hide popup controls
|
||
|
*/
|
||
|
if (CurrentObject.Count()) {
|
||
|
CurrentObject[0]->Unselect();
|
||
|
Popup_Controls();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Go into placement mode
|
||
|
*/
|
||
|
Start_Placement();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** ESC = exit placement mode, or exit to DOS
|
||
|
*/
|
||
|
case KN_ESC:
|
||
|
|
||
|
/*
|
||
|
** Exit object placement mode
|
||
|
*/
|
||
|
if (PendingObject) {
|
||
|
if (BaseBuilding) {
|
||
|
Cancel_Base_Building();
|
||
|
} else {
|
||
|
Cancel_Placement();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** Exit trigger placement mode
|
||
|
*/
|
||
|
if (CurTrigger) {
|
||
|
Stop_Trigger_Placement();
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
} else {
|
||
|
rc = WWMessageBox().Process("Exit Scenario Editor?", TXT_YES, TXT_NO);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
|
||
|
/*
|
||
|
** User doesn't want to exit; return to editor
|
||
|
*/
|
||
|
if (rc==1) {
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** If changed, prompt for saving
|
||
|
*/
|
||
|
if (Changed) {
|
||
|
rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
|
||
|
/*
|
||
|
** User wants to save
|
||
|
*/
|
||
|
if (rc == 0) {
|
||
|
|
||
|
/*
|
||
|
** If save cancelled, abort exit
|
||
|
*/
|
||
|
if (Save_Scenario()!=0) {
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
} else {
|
||
|
Changed = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//Prog_End();
|
||
|
Emergency_Exit(0);
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** LEFT = go to previous placement object
|
||
|
*/
|
||
|
case KN_LEFT:
|
||
|
if (PendingObject) {
|
||
|
Place_Prev();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** RIGHT = go to next placement object
|
||
|
*/
|
||
|
case KN_RIGHT:
|
||
|
if (PendingObject) {
|
||
|
Place_Next();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** PGUP = go to previous placement category
|
||
|
*/
|
||
|
case KN_PGUP:
|
||
|
if (PendingObject) {
|
||
|
Place_Prev_Category();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** PGDN = go to next placement category
|
||
|
*/
|
||
|
case KN_PGDN:
|
||
|
if (PendingObject) {
|
||
|
Place_Next_Category();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** HOME = jump to first placement object, or go to Home Cell
|
||
|
*/
|
||
|
case KN_HOME:
|
||
|
if (PendingObject) {
|
||
|
Place_Home();
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** Set map position
|
||
|
*/
|
||
|
ScenarioInit++;
|
||
|
Set_Tactical_Position(Scen.Waypoint[WAYPT_HOME]);
|
||
|
ScenarioInit--;
|
||
|
|
||
|
/*
|
||
|
** Force map to redraw
|
||
|
*/
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** SHIFT-HOME: set new Home Cell position
|
||
|
*/
|
||
|
case ((int)KN_HOME | (int)KN_SHIFT_BIT):
|
||
|
if (CurrentCell != 0) {
|
||
|
|
||
|
/*
|
||
|
** Unflag the old Home Cell, if there are no other waypoints
|
||
|
** pointing to it
|
||
|
*/
|
||
|
cell = Scen.Waypoint[WAYPT_HOME];
|
||
|
|
||
|
if (cell != -1) {
|
||
|
found = 0;
|
||
|
for (i = 0; i < WAYPT_COUNT; i++) {
|
||
|
if (i != WAYPT_HOME && Scen.Waypoint[i]==cell) {
|
||
|
found = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (found==0) {
|
||
|
(*this)[cell].IsWaypoint = 0;
|
||
|
Flag_Cell(cell);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Now set the new Home cell
|
||
|
*/
|
||
|
// Scen.Waypoint[WAYPT_HOME] = Coord_Cell(TacticalCoord);
|
||
|
// (*this)[TacticalCoord].IsWaypoint = 1;
|
||
|
// Flag_Cell(Coord_Cell(TacticalCoord));
|
||
|
Scen.Waypoint[WAYPT_HOME] = CurrentCell;
|
||
|
(*this)[CurrentCell].IsWaypoint = 1;
|
||
|
Flag_Cell(CurrentCell);
|
||
|
|
||
|
Changed = 1;
|
||
|
input = KN_NONE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** SHIFT-R: set new Reinforcement Cell position. Don't allow setting
|
||
|
** the Reinf. Cell to the same as the Home Cell (for display purposes.)
|
||
|
*/
|
||
|
case ((int)KN_R | (int)KN_SHIFT_BIT):
|
||
|
if (CurrentCell==0 || CurrentCell==Scen.Waypoint[WAYPT_HOME]) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Unflag the old Reinforcement Cell, if there are no other waypoints
|
||
|
** pointing to it
|
||
|
*/
|
||
|
cell = Scen.Waypoint[WAYPT_REINF];
|
||
|
|
||
|
if (cell != -1) {
|
||
|
found = 0;
|
||
|
for (i = 0; i < WAYPT_COUNT; i++) {
|
||
|
if (i != WAYPT_REINF && Scen.Waypoint[i]==cell) {
|
||
|
found = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (found==0) {
|
||
|
(*this)[cell].IsWaypoint = 0;
|
||
|
Flag_Cell(cell);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
/*
|
||
|
** Now set the new Reinforcement cell
|
||
|
*/
|
||
|
Scen.Waypoint[WAYPT_REINF] = CurrentCell;
|
||
|
(*this)[CurrentCell].IsWaypoint = 1;
|
||
|
Flag_Cell(CurrentCell);
|
||
|
Changed = 1;
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** ALT-Letter: Label a waypoint cell
|
||
|
*/
|
||
|
case ((int)KN_A | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_B | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_C | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_D | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_E | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_F | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_G | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_H | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_I | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_J | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_K | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_L | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_M | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_N | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_O | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_P | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_Q | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_R | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_S | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_T | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_U | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_V | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_W | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_X | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_Y | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_Z | (int)KN_ALT_BIT):
|
||
|
if (CurrentCell != 0) {
|
||
|
#ifdef WIN32
|
||
|
waypt_idx = (input & ~KN_ALT_BIT) - KN_A;
|
||
|
#else
|
||
|
waypt_idx = KN_To_KA(input & 0x00ff) - KA_a;
|
||
|
#endif
|
||
|
Update_Waypoint(waypt_idx);
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** ALT-. : Designate an extended (2-letter) waypoint name
|
||
|
*/
|
||
|
case KN_PERIOD:
|
||
|
case ((int)KN_PERIOD | (int)KN_ALT_BIT):
|
||
|
if (CurrentCell != 0 && Get_Waypoint_Name(wayname)) {
|
||
|
int waynm = 0;
|
||
|
if (strlen(wayname)) {
|
||
|
wayname[0] = toupper(wayname[0]);
|
||
|
wayname[1] = toupper(wayname[1]);
|
||
|
if (wayname[0] >= 'A' && wayname[0] <= 'Z') {
|
||
|
waynm = wayname[0] - 'A';
|
||
|
if (wayname[1] >= 'A' && wayname[1] <= 'Z') {
|
||
|
waynm = (waynm+1)*26 + (wayname[1] - 'A');
|
||
|
}
|
||
|
if (waynm < WAYPT_HOME) Update_Waypoint(waynm);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
#ifdef OBSOLETE
|
||
|
/*
|
||
|
** ALT-1-4: Designate a cell as a capture-the-flag cell.
|
||
|
*/
|
||
|
case ((int)KN_1 | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_2 | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_3 | (int)KN_ALT_BIT):
|
||
|
case ((int)KN_4 | (int)KN_ALT_BIT):
|
||
|
|
||
|
/*
|
||
|
** If there's a current cell, place the flag & waypoint there.
|
||
|
*/
|
||
|
if (CurrentCell != 0) {
|
||
|
waypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);
|
||
|
// waypt_idx = (KN_To_KA(input & 0xff) - KA_1);
|
||
|
house = (HousesType)(HOUSE_MULTI1 + waypt_idx);
|
||
|
if (HouseClass::As_Pointer(house)) {
|
||
|
HouseClass::As_Pointer(house)->Flag_Attach(CurrentCell, true);
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** If there's a current object, attach the flag to it and clear the
|
||
|
** waypoint.
|
||
|
*/
|
||
|
if (CurrentObject[0] != 0) {
|
||
|
waypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);
|
||
|
house = (HousesType)(HOUSE_MULTI1 + waypt_idx);
|
||
|
if (HouseClass::As_Pointer(house) && CurrentObject[0]->What_Am_I() == RTTI_UNIT) {
|
||
|
HouseClass::As_Pointer(house)->Flag_Attach((UnitClass *)CurrentObject[0], true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
** ALT-Space: Remove a waypoint designation
|
||
|
*/
|
||
|
case ((int)KN_SPACE | (int)KN_ALT_BIT):
|
||
|
if (CurrentCell != 0) {
|
||
|
|
||
|
/*
|
||
|
** Loop through letter waypoints; if this cell is one of them,
|
||
|
** clear that waypoint.
|
||
|
*/
|
||
|
for (i = 0 ; i < WAYPT_HOME; i++) {
|
||
|
if (Scen.Waypoint[i]==CurrentCell)
|
||
|
Scen.Waypoint[i] = -1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Loop through flag home values; if this cell is one of them, clear
|
||
|
** that waypoint.
|
||
|
*/
|
||
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
||
|
house = (HousesType)(HOUSE_MULTI1 + i);
|
||
|
if (HouseClass::As_Pointer(house) &&
|
||
|
CurrentCell == HouseClass::As_Pointer(house)->FlagHome)
|
||
|
HouseClass::As_Pointer(house)->Flag_Remove(As_Target(CurrentCell), true);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** If there are no more waypoints on this cell, clear the cell's
|
||
|
** waypoint designation.
|
||
|
*/
|
||
|
if (Scen.Waypoint[WAYPT_HOME]!=CurrentCell &&
|
||
|
Scen.Waypoint[WAYPT_REINF]!=CurrentCell)
|
||
|
(*this)[CurrentCell].IsWaypoint = 0;
|
||
|
Changed = 1;
|
||
|
Flag_Cell(CurrentCell);
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** 'H' = toggle current placement object's house
|
||
|
*/
|
||
|
case KN_H:
|
||
|
case ((int)KN_H | (int)KN_SHIFT_BIT):
|
||
|
if (PendingObject) {
|
||
|
Toggle_House();
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Left-mouse click:
|
||
|
** Button DOWN:
|
||
|
** - Toggle LMouseDown
|
||
|
** - If we're in placement mode, try to place the current object
|
||
|
** - If success, re-enter placement mode
|
||
|
** - Otherwise, try to select an object, and "grab" it if there is one
|
||
|
** - If no object, then select that cell as the "current" cell
|
||
|
** Button UP:
|
||
|
** - Toggle LMouseDown
|
||
|
** - release any grabbed object
|
||
|
*/
|
||
|
case ((int)MAP_AREA | (int)KN_BUTTON):
|
||
|
|
||
|
/*
|
||
|
** Left Button DOWN
|
||
|
*/
|
||
|
if (Keyboard->Down(KN_LMOUSE)) {
|
||
|
LMouseDown = 1;
|
||
|
|
||
|
/*
|
||
|
** Placement mode: place an object
|
||
|
*/
|
||
|
if (PendingObject) {
|
||
|
if (Place_Object()==0) {
|
||
|
Changed = 1;
|
||
|
Start_Placement();
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** Place a trigger
|
||
|
*/
|
||
|
if (CurTrigger) {
|
||
|
Place_Trigger();
|
||
|
Changed = 1;
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** Select an object or a cell
|
||
|
** Check for double-click
|
||
|
*/
|
||
|
if (CurrentObject.Count() &&
|
||
|
((TickCount - LastClickTime) < 15)) {
|
||
|
; // stub
|
||
|
|
||
|
} else {
|
||
|
/*
|
||
|
** Single-click: select object
|
||
|
*/
|
||
|
if (Select_Object()==0) {
|
||
|
CurrentCell = 0;
|
||
|
Grab_Object();
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** No object: select the cell
|
||
|
*/
|
||
|
CurrentCell = Click_Cell_Calc(Keyboard->MouseQX, Keyboard->MouseQY);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
LastClickTime = TickCount();
|
||
|
input = KN_NONE;
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** Left Button UP
|
||
|
*/
|
||
|
LMouseDown = 0;
|
||
|
GrabbedObject = 0;
|
||
|
input = KN_NONE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** SHIFT-ALT-Arrow: move the current object
|
||
|
*/
|
||
|
case (int)KN_UP | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
|
||
|
case (int)KN_DOWN | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
|
||
|
case (int)KN_LEFT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
|
||
|
case (int)KN_RIGHT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
|
||
|
if (CurrentObject.Count()) {
|
||
|
CurrentObject[0]->Move(KN_To_Facing(input));
|
||
|
Changed = 1;
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** DELETE: delete currently-selected object
|
||
|
*/
|
||
|
case KN_DELETE:
|
||
|
|
||
|
/*
|
||
|
** Delete currently-selected object's trigger, or the object
|
||
|
*/
|
||
|
if (CurrentObject.Count()) {
|
||
|
|
||
|
/*
|
||
|
** Delete trigger
|
||
|
*/
|
||
|
if (CurrentObject[0]->Trigger.Is_Valid()) {
|
||
|
CurrentObject[0]->Trigger = NULL;
|
||
|
} else {
|
||
|
/*
|
||
|
** If the current object is part of the AI's Base, remove it
|
||
|
** from the Base's Node list.
|
||
|
*/
|
||
|
if (CurrentObject[0]->What_Am_I()==RTTI_BUILDING &&
|
||
|
Base.Is_Node((BuildingClass *)CurrentObject[0])) {
|
||
|
node = Base.Get_Node((BuildingClass *)CurrentObject[0]);
|
||
|
Base.Nodes.Delete(*node);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Delete current object
|
||
|
*/
|
||
|
delete CurrentObject[0];
|
||
|
|
||
|
/*
|
||
|
** Hide the popup controls
|
||
|
*/
|
||
|
Popup_Controls();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Force a redraw
|
||
|
*/
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Changed = 1;
|
||
|
} else {
|
||
|
|
||
|
/*
|
||
|
** Remove trigger from current cell
|
||
|
*/
|
||
|
if (CurrentCell) {
|
||
|
if ((*this)[CurrentCell].Trigger.Is_Valid()) {
|
||
|
(*this)[CurrentCell].Trigger = NULL;
|
||
|
// CellTriggers[CurrentCell] = NULL;
|
||
|
|
||
|
/*
|
||
|
** Force a redraw
|
||
|
*/
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Changed = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** TAB: select next object on the map
|
||
|
*/
|
||
|
case KN_TAB:
|
||
|
Select_Next();
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Object-Editing button: House Button
|
||
|
*/
|
||
|
case POPUP_HOUSELIST|KN_BUTTON:
|
||
|
/*
|
||
|
** Determine the house desired by examining the currently
|
||
|
** selected index in the house list gadget.
|
||
|
*/
|
||
|
house = HousesType(((ListClass *)Buttons->Extract_Gadget(POPUP_HOUSELIST))->Current_Index());
|
||
|
|
||
|
/*
|
||
|
** If that house doesn't own this object, try to transfer it
|
||
|
*/
|
||
|
if (CurrentObject[0]->Owner() != house) {
|
||
|
if (Change_House(house)) {
|
||
|
Changed = 1;
|
||
|
}
|
||
|
}
|
||
|
// Set_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);
|
||
|
HidPage.Clear();
|
||
|
Buttons->Flag_List_To_Redraw();
|
||
|
Flag_To_Redraw(true);
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
// case (POPUP_GDI | KN_BUTTON):
|
||
|
// case (POPUP_NOD | KN_BUTTON):
|
||
|
// case (POPUP_NEUTRAL | KN_BUTTON):
|
||
|
// case (POPUP_MULTI1 | KN_BUTTON):
|
||
|
// case (POPUP_MULTI2 | KN_BUTTON):
|
||
|
// case (POPUP_MULTI3 | KN_BUTTON):
|
||
|
// case (POPUP_MULTI4 | KN_BUTTON):
|
||
|
//
|
||
|
// /*
|
||
|
// ** Convert input value into a house value; assume HOUSE_GOOD is 0
|
||
|
// */
|
||
|
// house = (HousesType)( (input & (~KN_BUTTON)) - POPUP_FIRST);
|
||
|
//
|
||
|
// /*
|
||
|
// ** If that house doesn't own this object, try to transfer it
|
||
|
// */
|
||
|
// if (CurrentObject[0]->Owner()!=house) {
|
||
|
// if (Change_House(house)) {
|
||
|
// Changed = 1;
|
||
|
// }
|
||
|
// }
|
||
|
// Set_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);
|
||
|
// HidPage.Clear();
|
||
|
// Flag_To_Redraw(true);
|
||
|
// input = KN_NONE;
|
||
|
// break;
|
||
|
|
||
|
case POPUP_SELLABLE|KN_BUTTON:
|
||
|
if (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {
|
||
|
BuildingClass * building = (BuildingClass *)CurrentObject[0];
|
||
|
|
||
|
if (building->Class->Level != -1) {
|
||
|
// if (building->Class->IsBuildable) {
|
||
|
building->IsAllowedToSell = (building->IsAllowedToSell == false);
|
||
|
building->Mark(MARK_CHANGE);
|
||
|
}
|
||
|
if (building->IsAllowedToSell) {
|
||
|
Sellable->Turn_On();
|
||
|
} else {
|
||
|
Sellable->Turn_Off();
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case POPUP_REBUILDABLE|KN_BUTTON:
|
||
|
if (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {
|
||
|
BuildingClass * building = (BuildingClass *)CurrentObject[0];
|
||
|
|
||
|
if (building->Class->Level != -1) {
|
||
|
// if (building->Class->IsBuildable) {
|
||
|
building->IsToRebuild = (building->IsToRebuild == false);
|
||
|
building->Mark(MARK_CHANGE);
|
||
|
}
|
||
|
if (building->IsToRebuild) {
|
||
|
Rebuildable->Turn_On();
|
||
|
} else {
|
||
|
Rebuildable->Turn_Off();
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Object-Editing button: Mission
|
||
|
*/
|
||
|
case (POPUP_MISSIONLIST | KN_BUTTON):
|
||
|
if (CurrentObject[0]->Is_Techno()) {
|
||
|
/*
|
||
|
** Set new mission
|
||
|
*/
|
||
|
mission = MapEditMissions[MissionList->Current_Index()];
|
||
|
if (CurrentObject[0]->Get_Mission() != mission) {
|
||
|
((TechnoClass *)CurrentObject[0])->Set_Mission(mission);
|
||
|
Changed = 1;
|
||
|
Buttons->Flag_List_To_Redraw();
|
||
|
Flag_To_Redraw(true);
|
||
|
}
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Object-Editing button: Health
|
||
|
*/
|
||
|
case (POPUP_HEALTHGAUGE | KN_BUTTON):
|
||
|
if (CurrentObject[0]->Is_Techno()) {
|
||
|
|
||
|
/*
|
||
|
** Derive strength from current gauge reading
|
||
|
*/
|
||
|
strength = CurrentObject[0]->Class_Of().MaxStrength * fixed(HealthGauge->Get_Value(), 256);
|
||
|
// strength = Fixed_To_Cardinal((unsigned)CurrentObject[0]->Class_Of().MaxStrength, (unsigned)HealthGauge->Get_Value());
|
||
|
|
||
|
/*
|
||
|
** Clip to 1
|
||
|
*/
|
||
|
if (strength <= 0) {
|
||
|
strength = 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Set new strength
|
||
|
*/
|
||
|
if (strength != CurrentObject[0]->Strength) {
|
||
|
CurrentObject[0]->Strength = strength;
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Changed = 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Update text label
|
||
|
*/
|
||
|
sprintf(HealthBuf, "%d", strength);
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Object-Editing button: Facing
|
||
|
*/
|
||
|
case (POPUP_FACINGDIAL | KN_BUTTON):
|
||
|
if (CurrentObject[0]->Is_Techno()) {
|
||
|
|
||
|
/*
|
||
|
** Set new facing
|
||
|
*/
|
||
|
if (FacingDial->Get_Direction() !=
|
||
|
((TechnoClass *)CurrentObject[0])->PrimaryFacing.Get()) {
|
||
|
|
||
|
/*
|
||
|
** Set body's facing
|
||
|
*/
|
||
|
((TechnoClass *)CurrentObject[0])->PrimaryFacing.Set(FacingDial->Get_Direction());
|
||
|
|
||
|
/*
|
||
|
** Set turret facing, if there is one
|
||
|
*/
|
||
|
if (CurrentObject[0]->What_Am_I()==RTTI_UNIT) {
|
||
|
((UnitClass *)CurrentObject[0])->SecondaryFacing.Set(FacingDial->Get_Direction());
|
||
|
}
|
||
|
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Changed = 1;
|
||
|
}
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Object-Editing button: Facing
|
||
|
*/
|
||
|
case (POPUP_BASEPERCENT | KN_BUTTON):
|
||
|
if (BaseGauge->Get_Value() != Scen.Percent) {
|
||
|
Scen.Percent = BaseGauge->Get_Value();
|
||
|
Build_Base_To(Scen.Percent);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
}
|
||
|
input = KN_NONE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Call parent's AI routine
|
||
|
*/
|
||
|
MouseClass::AI(input, x, y);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Draw_It -- overloaded Redraw routine *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/17/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::Draw_It(bool forced)
|
||
|
{
|
||
|
char const * label;
|
||
|
char buf[40];
|
||
|
char const * tptr;
|
||
|
|
||
|
MouseClass::Draw_It(forced);
|
||
|
|
||
|
if (!Debug_Map) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Display the total value of all Tiberium on the map.
|
||
|
*/
|
||
|
Fancy_Text_Print("Tiberium=%ld ", 0, 0, GadgetClass::Get_Color_Scheme(),
|
||
|
BLACK, TPF_EFNT | TPF_NOSHADOW, TotalValue);
|
||
|
|
||
|
/*
|
||
|
** If there are no object controls displayed, just invoke parent's Redraw
|
||
|
** and return.
|
||
|
*/
|
||
|
if (!Buttons) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Otherwise, if 'display' is set, invoke the parent's Redraw to refresh
|
||
|
** the HIDPAGE; then, update the buttons & text labels onto HIDPAGE;
|
||
|
** then invoke the parent's Redraw to blit the HIDPAGE to SEENPAGE.
|
||
|
*/
|
||
|
if (forced) {
|
||
|
|
||
|
/*
|
||
|
** Update the text labels
|
||
|
*/
|
||
|
if (CurrentObject.Count()) {
|
||
|
/*
|
||
|
** Display the object's name & ID
|
||
|
*/
|
||
|
label = Text_String(CurrentObject[0]->Full_Name());
|
||
|
tptr = label;
|
||
|
sprintf(buf, "%s (%d)", tptr, CurrentObject[0]->As_Target());
|
||
|
|
||
|
/*
|
||
|
** print the label
|
||
|
*/
|
||
|
Fancy_Text_Print (buf, 160, 0,
|
||
|
&ColorRemaps[PCOLOR_BROWN], TBLACK,
|
||
|
TPF_CENTER | TPF_NOSHADOW | TPF_EFNT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Mouse_Moved -- checks for mouse motion *
|
||
|
* *
|
||
|
* Reports whether the mouse has moved or not. This varies based on the *
|
||
|
* type of object currently selected. If there's an infantry object *
|
||
|
* selected, mouse motion counts even within a cell; for all other types,*
|
||
|
* mouse motion counts only if the mouse changes cells. *
|
||
|
* *
|
||
|
* The reason this routine is needed is to prevent Paint-Mode from putting*
|
||
|
* gobs of trees and such into the same cell if the mouse moves just *
|
||
|
* a little bit. *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/08/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
bool MapEditClass::Mouse_Moved(void)
|
||
|
{
|
||
|
static int old_mx = 0;
|
||
|
static int old_my = 0;
|
||
|
static CELL old_zonecell = 0;
|
||
|
const ObjectTypeClass * objtype = NULL;
|
||
|
bool retcode = false;
|
||
|
|
||
|
/*
|
||
|
** Return if no motion
|
||
|
*/
|
||
|
if (old_mx == Get_Mouse_X() && old_my == Get_Mouse_Y()) {
|
||
|
return(false);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Get a ptr to ObjectTypeClass
|
||
|
*/
|
||
|
if (PendingObject) {
|
||
|
objtype = PendingObject;
|
||
|
} else {
|
||
|
if (GrabbedObject) {
|
||
|
objtype = &GrabbedObject->Class_Of();
|
||
|
} else {
|
||
|
old_mx = Get_Mouse_X();
|
||
|
old_my = Get_Mouse_Y();
|
||
|
old_zonecell = ZoneCell;
|
||
|
return(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Infantry: mouse moved if any motion at all
|
||
|
*/
|
||
|
if (objtype->What_Am_I() == RTTI_INFANTRYTYPE) {
|
||
|
retcode = true;
|
||
|
} else {
|
||
|
/*
|
||
|
** Others: mouse moved only if cell changed
|
||
|
*/
|
||
|
if (old_zonecell!=ZoneCell) {
|
||
|
retcode = true;
|
||
|
} else {
|
||
|
retcode = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
old_mx = Get_Mouse_X();
|
||
|
old_my = Get_Mouse_Y();
|
||
|
old_zonecell = ZoneCell;
|
||
|
return(retcode);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Main_Menu -- main menu processor for map editor *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 10/20/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::Main_Menu(void)
|
||
|
{
|
||
|
char const * _menus[MAX_MAIN_MENU_NUM + 1];
|
||
|
int selection; // option the user picks
|
||
|
bool process; // menu stays up while true
|
||
|
int rc;
|
||
|
|
||
|
/*
|
||
|
** Fill in menu items
|
||
|
*/
|
||
|
_menus[0] = "New Scenario";
|
||
|
_menus[1] = "Load Scenario";
|
||
|
_menus[2] = "Save Scenario";
|
||
|
_menus[3] = "Size Map";
|
||
|
_menus[4] = "Add Game Object";
|
||
|
_menus[5] = "Scenario Options";
|
||
|
_menus[6] = "AI Options";
|
||
|
_menus[7] = "Play Scenario";
|
||
|
_menus[8] = NULL;
|
||
|
|
||
|
/*
|
||
|
** Main Menu loop
|
||
|
*/
|
||
|
Override_Mouse_Shape(MOUSE_NORMAL); // display default mouse cursor
|
||
|
process = true;
|
||
|
while (process) {
|
||
|
|
||
|
/*
|
||
|
** Invoke game callback, to update music
|
||
|
*/
|
||
|
Call_Back();
|
||
|
|
||
|
/*
|
||
|
** Invoke menu
|
||
|
*/
|
||
|
Hide_Mouse(); // Do_Menu assumes the mouse is already hidden
|
||
|
selection = Do_Menu(&_menus[0], true);
|
||
|
Show_Mouse();
|
||
|
if (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Process selection
|
||
|
*/
|
||
|
switch (selection) {
|
||
|
|
||
|
/*
|
||
|
** New scenario
|
||
|
*/
|
||
|
case 0:
|
||
|
if (Changed) {
|
||
|
rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
if (rc==0) {
|
||
|
if (Save_Scenario()!=0) {
|
||
|
break;
|
||
|
} else {
|
||
|
Changed = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (New_Scenario()==0) {
|
||
|
Scen.CarryOverMoney = 0;
|
||
|
Changed = 1;
|
||
|
}
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Load scenario
|
||
|
*/
|
||
|
case 1:
|
||
|
if (Changed) {
|
||
|
rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
if (rc==0) {
|
||
|
if (Save_Scenario()!=0) {
|
||
|
break;
|
||
|
} else {
|
||
|
Changed = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (Load_Scenario()==0) {
|
||
|
Scen.CarryOverMoney = 0;
|
||
|
Changed = 0;
|
||
|
}
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Save scenario
|
||
|
*/
|
||
|
case 2:
|
||
|
if (Save_Scenario() == 0) {
|
||
|
Changed = 0;
|
||
|
}
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Edit map size
|
||
|
*/
|
||
|
case 3:
|
||
|
if (Size_Map(MapCellX, MapCellY, MapCellWidth, MapCellHeight)==0) {
|
||
|
process = false;
|
||
|
Changed = 1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Add an object
|
||
|
*/
|
||
|
case 4:
|
||
|
if (Placement_Dialog() == 0) {
|
||
|
Start_Placement();
|
||
|
process = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Scenario options
|
||
|
*/
|
||
|
case 5:
|
||
|
if (Scenario_Dialog() == 0) {
|
||
|
Changed = 1;
|
||
|
process = false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Other options
|
||
|
*/
|
||
|
case 6:
|
||
|
AI_Menu();
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Test-drive this scenario
|
||
|
*/
|
||
|
case 7:
|
||
|
if (Changed) {
|
||
|
rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO, TXT_CANCEL);
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
if (rc == 2) return;
|
||
|
if (rc==0) {
|
||
|
if (Save_Scenario()!=0) {
|
||
|
break;
|
||
|
} else {
|
||
|
Changed = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Changed = 0;
|
||
|
Debug_Map = false;
|
||
|
Start_Scenario(Scen.ScenarioName);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Restore the display:
|
||
|
** - Clear HIDPAGE to erase any spurious drawing done by the menu system
|
||
|
** - Invoke Flag_To_Redraw to tell DisplayClass to re-render the whole screen
|
||
|
** - Invoke Redraw() to update the display
|
||
|
*/
|
||
|
HidPage.Clear();
|
||
|
Flag_To_Redraw(true);
|
||
|
Render();
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::AI_Menu -- menu of AI options *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/29/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::AI_Menu(void)
|
||
|
{
|
||
|
int selection; // option the user picks
|
||
|
bool process; // menu stays up while true
|
||
|
char const * _menus[MAX_AI_MENU_NUM + 1];
|
||
|
|
||
|
/*
|
||
|
** Fill in menu strings
|
||
|
*/
|
||
|
_menus[0] = "Pre-Build a Base";
|
||
|
_menus[1] = "Edit Triggers";
|
||
|
_menus[2] = "Edit Teams";
|
||
|
_menus[3] = NULL;
|
||
|
|
||
|
/*
|
||
|
** Main Menu loop
|
||
|
*/
|
||
|
Override_Mouse_Shape(MOUSE_NORMAL); // display default mouse cursor
|
||
|
process = true;
|
||
|
while (process) {
|
||
|
|
||
|
/*
|
||
|
** Invoke game callback, to update music
|
||
|
*/
|
||
|
Call_Back();
|
||
|
|
||
|
/*
|
||
|
** Invoke menu
|
||
|
*/
|
||
|
Hide_Mouse(); // Do_Menu assumes the mouse is already hidden
|
||
|
selection = Do_Menu(&_menus[0], true);
|
||
|
Show_Mouse();
|
||
|
if (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Process selection
|
||
|
*/
|
||
|
switch (selection) {
|
||
|
/*
|
||
|
** Pre-Build a Base
|
||
|
*/
|
||
|
case 0:
|
||
|
Start_Base_Building();
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Trigger Editing
|
||
|
*/
|
||
|
case 1:
|
||
|
Handle_Triggers();
|
||
|
/*
|
||
|
** Go into trigger placement mode
|
||
|
*/
|
||
|
if (CurTrigger) {
|
||
|
Start_Trigger_Placement();
|
||
|
}
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** Team Editing
|
||
|
*/
|
||
|
case 2:
|
||
|
Handle_Teams("Teams");
|
||
|
process = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Verify_House -- is this objtype ownable by this house? *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* house house to check *
|
||
|
* objtype ObjectTypeClass to check *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* 0 = isn't ownable, 1 = it is *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/16/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
bool MapEditClass::Verify_House(HousesType house, ObjectTypeClass const * objtype)
|
||
|
{
|
||
|
/*
|
||
|
** Verify that new house can own this object
|
||
|
*/
|
||
|
return((objtype->Get_Ownable() & (1 << house)) != 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Cycle_House -- finds next valid house for object type *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* objtype ObjectTypeClass ptr to get house for *
|
||
|
* curhouse current house value to start with *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* HousesType that's valid for this object type *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/23/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
HousesType MapEditClass::Cycle_House(HousesType curhouse, ObjectTypeClass const *)
|
||
|
{
|
||
|
HousesType count; // prevents an infinite loop
|
||
|
|
||
|
/*
|
||
|
** Loop through all house types, starting with the one after 'curhouse';
|
||
|
** return the first one that's valid
|
||
|
*/
|
||
|
count = HOUSE_NONE;
|
||
|
while (1) {
|
||
|
|
||
|
/*
|
||
|
** Go to next house
|
||
|
*/
|
||
|
curhouse++;
|
||
|
if (curhouse == HOUSE_COUNT) {
|
||
|
curhouse = HOUSE_FIRST;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Count # iterations; don't go forever
|
||
|
*/
|
||
|
count++;
|
||
|
if (count == HOUSE_COUNT) {
|
||
|
curhouse = HOUSE_NONE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Break if this is a valid house
|
||
|
*/
|
||
|
// if (HouseClass::As_Pointer(curhouse) && Verify_House(curhouse, objtype)) {
|
||
|
break;
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
return(curhouse);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Fatal -- exits with error message *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* code tells which message to display; this minimizes the *
|
||
|
* use of character strings in the code. *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 12/12/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::Fatal(int txt)
|
||
|
{
|
||
|
//Prog_End();
|
||
|
printf("%s\n", txt);
|
||
|
Emergency_Exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
|
||
|
bool MapEditClass::Scroll_Map(DirType facing, int & distance, bool really)
|
||
|
{
|
||
|
if (Debug_Map) {
|
||
|
/*
|
||
|
** The popup gadgets require the entire map to be redrawn if we scroll.
|
||
|
*/
|
||
|
if (really) {
|
||
|
Flag_To_Redraw(true);
|
||
|
}
|
||
|
}
|
||
|
return(MouseClass::Scroll_Map(facing, distance, really));
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef OBSOLETE
|
||
|
void MapEditClass::Flag_To_Redraw(bool complete)
|
||
|
{
|
||
|
MouseClass::Flag_To_Redraw(complete);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
void MapEditClass::Detach(ObjectClass * object)
|
||
|
{
|
||
|
if (GrabbedObject == object) {
|
||
|
GrabbedObject = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool MapEditClass::Get_Waypoint_Name(char wayptname[])
|
||
|
{
|
||
|
/*
|
||
|
** Dialog & button dimensions
|
||
|
*/
|
||
|
enum {
|
||
|
D_DIALOG_W = 100, // dialog width
|
||
|
D_DIALOG_H = 56, // dialog height
|
||
|
D_DIALOG_X = ((320 - D_DIALOG_W) / 2), // centered x-coord
|
||
|
D_DIALOG_Y = ((200 - D_DIALOG_H) / 2), // centered y-coord
|
||
|
D_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2), // coord of x-center
|
||
|
|
||
|
D_TXT8_H = 11, // ht of 8-pt text
|
||
|
D_MARGIN = 7, // margin width/height
|
||
|
|
||
|
D_EDIT_W = D_DIALOG_W - (D_MARGIN * 2),
|
||
|
D_EDIT_H = 13,
|
||
|
D_EDIT_X = D_DIALOG_X + D_MARGIN,
|
||
|
D_EDIT_Y = D_DIALOG_Y + 20,
|
||
|
|
||
|
D_BUTTON_X = D_DIALOG_X + D_MARGIN,
|
||
|
D_BUTTON_Y = D_DIALOG_Y + 40,
|
||
|
D_BUTTON_W = 40,
|
||
|
D_BUTTON_H = 13,
|
||
|
|
||
|
D_CANCEL_X = D_DIALOG_X + 53,
|
||
|
D_CANCEL_Y = D_DIALOG_Y + 40,
|
||
|
D_CANCEL_W = 40,
|
||
|
D_CANCEL_H = 13,
|
||
|
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
** Button enumerations
|
||
|
*/
|
||
|
enum {
|
||
|
BUTTON_OK = 100,
|
||
|
BUTTON_CANCEL,
|
||
|
BUTTON_EDIT,
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
** Dialog variables
|
||
|
*/
|
||
|
bool cancel = false; // true = user cancels
|
||
|
wayptname[0] = 0;
|
||
|
|
||
|
/*
|
||
|
** Buttons
|
||
|
*/
|
||
|
ControlClass * commands = NULL; // the button list
|
||
|
|
||
|
TextButtonClass button (BUTTON_OK, TXT_OK, TPF_EBUTTON, D_BUTTON_X, D_BUTTON_Y, D_BUTTON_W);
|
||
|
TextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W);
|
||
|
EditClass editbtn (BUTTON_EDIT, wayptname, 3, TPF_EFNT|TPF_NOSHADOW, D_EDIT_X, D_EDIT_Y, D_EDIT_W, -1, EditClass::ALPHANUMERIC);
|
||
|
|
||
|
/*
|
||
|
** Initialize.
|
||
|
*/
|
||
|
Set_Logic_Page(SeenBuff);
|
||
|
|
||
|
/*
|
||
|
** Create the button list.
|
||
|
*/
|
||
|
commands = &button;
|
||
|
cancelbtn.Add_Tail(*commands);
|
||
|
editbtn.Add_Tail(*commands);
|
||
|
editbtn.Set_Focus();
|
||
|
|
||
|
/*
|
||
|
** Main Processing Loop.
|
||
|
*/
|
||
|
bool firsttime = true;
|
||
|
bool display = true;
|
||
|
bool process = true;
|
||
|
while (process) {
|
||
|
|
||
|
/*
|
||
|
** Invoke game callback.
|
||
|
*/
|
||
|
if (Session.Type == GAME_NORMAL) {
|
||
|
Call_Back();
|
||
|
} else if (Main_Loop()) {
|
||
|
process = false;
|
||
|
cancel = true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Refresh display if needed.
|
||
|
*/
|
||
|
if (display) {
|
||
|
|
||
|
/*
|
||
|
** Display the dialog box.
|
||
|
*/
|
||
|
Hide_Mouse();
|
||
|
if (display) {
|
||
|
Dialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);
|
||
|
// Draw_Caption(caption, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Redraw the buttons.
|
||
|
*/
|
||
|
if (display) {
|
||
|
commands->Flag_List_To_Redraw();
|
||
|
}
|
||
|
Show_Mouse();
|
||
|
display = false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Get user input.
|
||
|
*/
|
||
|
KeyNumType input = commands->Input();
|
||
|
|
||
|
/*
|
||
|
** The first time through the processing loop, set the edit
|
||
|
** gadget to have the focus. The
|
||
|
** focus must be set here since the gadget list has changed
|
||
|
** and this change will cause any previous focus setting to be
|
||
|
** cleared by the input processing routine.
|
||
|
*/
|
||
|
if (firsttime) {
|
||
|
firsttime = false;
|
||
|
editbtn.Set_Focus();
|
||
|
editbtn.Flag_To_Redraw();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** If the <RETURN> key was pressed, then default to the appropriate
|
||
|
** action button according to the style of this dialog box.
|
||
|
*/
|
||
|
if (input == KN_RETURN) {
|
||
|
input = (KeyNumType)(BUTTON_OK|KN_BUTTON);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Process input.
|
||
|
*/
|
||
|
switch (input) {
|
||
|
/*
|
||
|
** Load: if load fails, present a message, and stay in the dialog
|
||
|
** to allow the user to try another game
|
||
|
*/
|
||
|
case (BUTTON_OK | KN_BUTTON):
|
||
|
Hide_Mouse();
|
||
|
SeenPage.Clear();
|
||
|
GamePalette.Set();
|
||
|
Show_Mouse();
|
||
|
process = false;
|
||
|
cancel = false;
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
** ESC/Cancel: break
|
||
|
*/
|
||
|
case (KN_ESC):
|
||
|
case (BUTTON_CANCEL | KN_BUTTON):
|
||
|
Hide_Mouse();
|
||
|
SeenPage.Clear();
|
||
|
GamePalette.Set();
|
||
|
Show_Mouse();
|
||
|
cancel = true;
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Map.Flag_To_Redraw(true);
|
||
|
if (cancel) return(false);
|
||
|
|
||
|
return(true);
|
||
|
}
|
||
|
|
||
|
void MapEditClass::Update_Waypoint(int waypt_idx)
|
||
|
{
|
||
|
CELL cell;
|
||
|
|
||
|
/*
|
||
|
** Unflag cell for this waypoint if there is one
|
||
|
*/
|
||
|
cell = Scen.Waypoint[waypt_idx];
|
||
|
if (cell != -1) {
|
||
|
if (Scen.Waypoint[WAYPT_HOME] != cell && Scen.Waypoint[WAYPT_REINF] != cell) {
|
||
|
(*this)[cell].IsWaypoint = 0;
|
||
|
}
|
||
|
Flag_Cell(cell);
|
||
|
}
|
||
|
Scen.Waypoint[waypt_idx] = CurrentCell;
|
||
|
(*this)[CurrentCell].IsWaypoint = 1;
|
||
|
Changed = 1;
|
||
|
Flag_Cell(CurrentCell);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* MapEditClass::Read_INI -- overloaded Read_INI function *
|
||
|
* *
|
||
|
* Overloading this function gives the map editor a chance to initialize *
|
||
|
* certain values every time a new INI is read. *
|
||
|
* *
|
||
|
* INPUT: *
|
||
|
* buffer INI staging area *
|
||
|
* *
|
||
|
* OUTPUT: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* WARNINGS: *
|
||
|
* none. *
|
||
|
* *
|
||
|
* HISTORY: *
|
||
|
* 11/16/1994 BR : Created. *
|
||
|
*=========================================================================*/
|
||
|
void MapEditClass::Read_INI(CCINIClass & ini)
|
||
|
{
|
||
|
/*
|
||
|
** Invoke parent's Read_INI
|
||
|
*/
|
||
|
Mono_Printf("We are in Read_INI\n");
|
||
|
|
||
|
MouseClass::Read_INI(ini);
|
||
|
BaseGauge->Set_Value(Scen.Percent);
|
||
|
|
||
|
Mono_Clear_Screen();
|
||
|
Mono_Printf("Scen.Percent = %d", Scen.Percent);
|
||
|
|
||
|
// BaseGauge->Set_Value(Scen.Percent);
|
||
|
}
|
||
|
|
||
|
|
||
|
void MapEditClass::Write_INI(CCINIClass & ini)
|
||
|
{
|
||
|
MouseClass::Write_INI(ini);
|
||
|
// ini.Put_Int("Basic", "Percent", Scen.Percent);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#include "mapedsel.cpp"
|
||
|
|