2022-05-19 01:51:26 -07:00
|
|
|
#include "map.h"
|
|
|
|
|
|
|
|
#include "animation.h"
|
2022-06-19 04:27:29 -07:00
|
|
|
#include "art.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "automap.h"
|
|
|
|
#include "character_editor.h"
|
|
|
|
#include "color.h"
|
|
|
|
#include "combat.h"
|
|
|
|
#include "core.h"
|
|
|
|
#include "critter.h"
|
|
|
|
#include "cycle.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "draw.h"
|
2022-08-03 02:34:13 -07:00
|
|
|
#include "elevator.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "game.h"
|
|
|
|
#include "game_config.h"
|
|
|
|
#include "game_mouse.h"
|
|
|
|
#include "game_movie.h"
|
|
|
|
#include "game_sound.h"
|
|
|
|
#include "interface.h"
|
|
|
|
#include "item.h"
|
|
|
|
#include "light.h"
|
|
|
|
#include "loadsave.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "object.h"
|
|
|
|
#include "palette.h"
|
2022-06-19 02:00:14 -07:00
|
|
|
#include "party_member.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "pipboy.h"
|
|
|
|
#include "proto.h"
|
|
|
|
#include "proto_instance.h"
|
|
|
|
#include "queue.h"
|
|
|
|
#include "random.h"
|
|
|
|
#include "scripts.h"
|
|
|
|
#include "text_object.h"
|
|
|
|
#include "tile.h"
|
|
|
|
#include "window_manager.h"
|
2022-07-29 06:04:05 -07:00
|
|
|
#include "window_manager_private.h"
|
2022-09-14 23:00:11 -07:00
|
|
|
#include "worldmap.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
#include <stdio.h>
|
2022-05-29 14:29:05 -07:00
|
|
|
#include <string.h>
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-06-19 10:14:17 -07:00
|
|
|
static char* mapBuildPath(char* name);
|
|
|
|
static int mapLoad(File* stream);
|
|
|
|
static int _map_age_dead_critters();
|
|
|
|
static void _map_fix_critter_combat_data();
|
|
|
|
static int _map_save();
|
|
|
|
static int _map_save_file(File* stream);
|
|
|
|
static void mapMakeMapsDirectory();
|
|
|
|
static void isoWindowRefreshRect(Rect* rect);
|
|
|
|
static void isoWindowRefreshRectGame(Rect* rect);
|
|
|
|
static void isoWindowRefreshRectMapper(Rect* rect);
|
|
|
|
static void mapGlobalVariablesFree();
|
|
|
|
static void mapLocalVariablesFree();
|
|
|
|
static void _map_place_dude_and_mouse();
|
|
|
|
static void _square_reset();
|
|
|
|
static int _square_load(File* stream, int a2);
|
|
|
|
static int mapHeaderWrite(MapHeader* ptr, File* stream);
|
|
|
|
static int mapHeaderRead(MapHeader* ptr, File* stream);
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x50B058
|
2022-06-19 10:14:17 -07:00
|
|
|
static char byte_50B058[] = "";
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x50B30C
|
2022-06-19 10:14:17 -07:00
|
|
|
static char _aErrorF2[] = "ERROR! F2";
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x519540
|
2022-06-19 10:14:17 -07:00
|
|
|
static IsoWindowRefreshProc* _map_scroll_refresh = isoWindowRefreshRectGame;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x519544
|
2022-06-19 10:14:17 -07:00
|
|
|
static const int _map_data_elev_flags[ELEVATION_COUNT] = {
|
2022-05-19 01:51:26 -07:00
|
|
|
2,
|
|
|
|
4,
|
|
|
|
8,
|
|
|
|
};
|
|
|
|
|
|
|
|
// 0x519550
|
2022-06-19 10:14:17 -07:00
|
|
|
static unsigned int gIsoWindowScrollTimestamp = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x519554
|
2022-06-19 10:14:17 -07:00
|
|
|
static bool gIsoEnabled = false;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x519558
|
2022-06-19 10:14:17 -07:00
|
|
|
static int gEnteringElevation = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x51955C
|
2022-06-19 10:14:17 -07:00
|
|
|
static int gEnteringTile = -1;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x519560
|
2022-06-19 10:14:17 -07:00
|
|
|
static int gEnteringRotation = ROTATION_NE;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x519564
|
|
|
|
int gMapSid = -1;
|
|
|
|
|
|
|
|
// local_vars
|
|
|
|
// 0x519568
|
|
|
|
int* gMapLocalVars = NULL;
|
|
|
|
|
|
|
|
// map_vars
|
|
|
|
// 0x51956C
|
2022-06-19 10:14:17 -07:00
|
|
|
static int* gMapGlobalVars = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// local_vars_num
|
|
|
|
// 0x519570
|
|
|
|
int gMapLocalVarsLength = 0;
|
|
|
|
|
|
|
|
// map_vars_num
|
|
|
|
// 0x519574
|
2022-06-19 10:14:17 -07:00
|
|
|
static int gMapGlobalVarsLength = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// Current elevation.
|
|
|
|
//
|
|
|
|
// 0x519578
|
|
|
|
int gElevation = 0;
|
|
|
|
|
|
|
|
// 0x51957C
|
2022-06-19 10:14:17 -07:00
|
|
|
static char* _errMapName = byte_50B058;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x519584
|
2022-06-19 10:14:17 -07:00
|
|
|
static int _wmMapIdx = -1;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x614868
|
2022-06-19 10:14:17 -07:00
|
|
|
static TileData _square_data[ELEVATION_COUNT];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x631D28
|
2022-06-19 10:14:17 -07:00
|
|
|
static MapTransition gMapTransition;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x631D38
|
2022-06-19 10:14:17 -07:00
|
|
|
static Rect gIsoWindowRect;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// map.msg
|
|
|
|
//
|
|
|
|
// map_msg_file
|
|
|
|
// 0x631D48
|
|
|
|
MessageList gMapMessageList;
|
|
|
|
|
|
|
|
// 0x631D50
|
2022-06-19 10:14:17 -07:00
|
|
|
static unsigned char* gIsoWindowBuffer;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x631D54
|
|
|
|
MapHeader gMapHeader;
|
|
|
|
|
|
|
|
// 0x631E40
|
|
|
|
TileData* _square[ELEVATION_COUNT];
|
|
|
|
|
|
|
|
// 0x631E4C
|
|
|
|
int gIsoWindow;
|
|
|
|
|
|
|
|
// 0x631E50
|
2022-06-19 10:14:17 -07:00
|
|
|
static char _scratchStr[40];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// Last map file name.
|
|
|
|
//
|
|
|
|
// 0x631E78
|
2022-06-19 10:14:17 -07:00
|
|
|
static char _map_path[COMPAT_MAX_PATH];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// iso_init
|
|
|
|
// 0x481CA0
|
|
|
|
int isoInit()
|
|
|
|
{
|
2022-05-23 15:37:46 -07:00
|
|
|
tileScrollLimitingDisable();
|
|
|
|
tileScrollBlockingDisable();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
|
|
|
|
_square[elevation] = &(_square_data[elevation]);
|
|
|
|
}
|
|
|
|
|
2022-05-21 11:30:25 -07:00
|
|
|
gIsoWindow = windowCreate(0, 0, screenGetWidth(), screenGetVisibleHeight(), 256, 10);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (gIsoWindow == -1) {
|
|
|
|
debugPrint("win_add failed in iso_init\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gIsoWindowBuffer = windowGetBuffer(gIsoWindow);
|
|
|
|
if (gIsoWindowBuffer == NULL) {
|
|
|
|
debugPrint("win_get_buf failed in iso_init\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (windowGetRect(gIsoWindow, &gIsoWindowRect) != 0) {
|
|
|
|
debugPrint("win_get_rect failed in iso_init\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (artInit() != 0) {
|
|
|
|
debugPrint("art_init failed in iso_init\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
debugPrint(">art_init\t\t");
|
|
|
|
|
2022-05-21 11:30:25 -07:00
|
|
|
if (tileInit(_square, SQUARE_GRID_WIDTH, SQUARE_GRID_HEIGHT, HEX_GRID_WIDTH, HEX_GRID_HEIGHT, gIsoWindowBuffer, screenGetWidth(), screenGetVisibleHeight(), screenGetWidth(), isoWindowRefreshRect) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
debugPrint("tile_init failed in iso_init\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
debugPrint(">tile_init\t\t");
|
|
|
|
|
2022-05-21 11:30:25 -07:00
|
|
|
if (objectsInit(gIsoWindowBuffer, screenGetWidth(), screenGetVisibleHeight(), screenGetWidth()) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
debugPrint("obj_init failed in iso_init\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
debugPrint(">obj_init\t\t");
|
|
|
|
|
|
|
|
colorCycleInit();
|
|
|
|
debugPrint(">cycle_init\t\t");
|
|
|
|
|
2022-05-23 15:37:46 -07:00
|
|
|
tileScrollBlockingEnable();
|
|
|
|
tileScrollLimitingEnable();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (interfaceInit() != 0) {
|
|
|
|
debugPrint("intface_init failed in iso_init\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
debugPrint(">intface_init\t\t");
|
|
|
|
|
2022-08-03 02:34:13 -07:00
|
|
|
// SFALL
|
|
|
|
elevatorsInit();
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
mapMakeMapsDirectory();
|
|
|
|
|
|
|
|
gEnteringElevation = -1;
|
|
|
|
gEnteringTile = -1;
|
|
|
|
gEnteringRotation = -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x481ED4
|
|
|
|
void isoReset()
|
|
|
|
{
|
|
|
|
if (gMapGlobalVars != NULL) {
|
|
|
|
internal_free(gMapGlobalVars);
|
|
|
|
gMapGlobalVars = NULL;
|
|
|
|
gMapGlobalVarsLength = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMapLocalVars != NULL) {
|
|
|
|
internal_free(gMapLocalVars);
|
|
|
|
gMapLocalVars = NULL;
|
|
|
|
gMapLocalVarsLength = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
artReset();
|
|
|
|
tileReset();
|
|
|
|
objectsReset();
|
|
|
|
colorCycleReset();
|
|
|
|
interfaceReset();
|
|
|
|
gEnteringElevation = -1;
|
|
|
|
gEnteringTile = -1;
|
|
|
|
gEnteringRotation = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x481F48
|
|
|
|
void isoExit()
|
|
|
|
{
|
|
|
|
interfaceFree();
|
|
|
|
colorCycleFree();
|
|
|
|
objectsExit();
|
|
|
|
tileExit();
|
|
|
|
artExit();
|
|
|
|
|
|
|
|
if (gMapGlobalVars != NULL) {
|
|
|
|
internal_free(gMapGlobalVars);
|
|
|
|
gMapGlobalVars = NULL;
|
|
|
|
gMapGlobalVarsLength = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMapLocalVars != NULL) {
|
|
|
|
internal_free(gMapLocalVars);
|
|
|
|
gMapLocalVars = NULL;
|
|
|
|
gMapLocalVarsLength = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x481FB4
|
|
|
|
void _map_init()
|
|
|
|
{
|
|
|
|
char* executable;
|
|
|
|
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, "executable", &executable);
|
2022-05-28 01:57:32 -07:00
|
|
|
if (compat_stricmp(executable, "mapper") == 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
_map_scroll_refresh = isoWindowRefreshRectMapper;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (messageListInit(&gMapMessageList)) {
|
2022-05-28 02:34:49 -07:00
|
|
|
char path[COMPAT_MAX_PATH];
|
2022-05-19 01:51:26 -07:00
|
|
|
sprintf(path, "%smap.msg", asc_5186C8);
|
|
|
|
|
|
|
|
if (!messageListLoad(&gMapMessageList, path)) {
|
|
|
|
debugPrint("\nError loading map_msg_file!");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
debugPrint("\nError initing map_msg_file!");
|
|
|
|
}
|
|
|
|
|
|
|
|
_map_new_map();
|
|
|
|
tickersAdd(gameMouseRefresh);
|
|
|
|
_gmouse_disable(0);
|
|
|
|
windowUnhide(gIsoWindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482084
|
|
|
|
void _map_exit()
|
|
|
|
{
|
|
|
|
windowHide(gIsoWindow);
|
|
|
|
gameMouseSetCursor(MOUSE_CURSOR_ARROW);
|
|
|
|
tickersRemove(gameMouseRefresh);
|
|
|
|
if (!messageListFree(&gMapMessageList)) {
|
|
|
|
debugPrint("\nError exiting map_msg_file!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4820C0
|
|
|
|
void isoEnable()
|
|
|
|
{
|
|
|
|
if (!gIsoEnabled) {
|
|
|
|
textObjectsEnable();
|
|
|
|
if (!gameUiIsDisabled()) {
|
|
|
|
_gmouse_enable();
|
|
|
|
}
|
|
|
|
tickersAdd(_object_animate);
|
|
|
|
tickersAdd(_dude_fidget);
|
|
|
|
_scr_enable_critters();
|
|
|
|
gIsoEnabled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482104
|
|
|
|
bool isoDisable()
|
|
|
|
{
|
|
|
|
if (!gIsoEnabled) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_scr_disable_critters();
|
|
|
|
tickersRemove(_dude_fidget);
|
|
|
|
tickersRemove(_object_animate);
|
|
|
|
_gmouse_disable(0);
|
|
|
|
textObjectsDisable();
|
|
|
|
|
|
|
|
gIsoEnabled = false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482148
|
|
|
|
bool isoIsDisabled()
|
|
|
|
{
|
|
|
|
return gIsoEnabled == false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// map_set_elevation
|
|
|
|
// 0x482158
|
|
|
|
int mapSetElevation(int elevation)
|
|
|
|
{
|
|
|
|
if (!elevationIsValid(elevation)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool gameMouseWasVisible = false;
|
|
|
|
if (gameMouseGetCursor() != MOUSE_CURSOR_WAIT_PLANET) {
|
|
|
|
gameMouseWasVisible = gameMouseObjectsIsVisible();
|
|
|
|
gameMouseObjectsHide();
|
|
|
|
gameMouseSetCursor(MOUSE_CURSOR_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (elevation != gElevation) {
|
2022-09-15 01:42:02 -07:00
|
|
|
wmMapMarkMapEntranceState(gMapHeader.field_34, elevation, 1);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
gElevation = elevation;
|
|
|
|
|
|
|
|
reg_anim_clear(gDude);
|
|
|
|
_dude_stand(gDude, gDude->rotation, gDude->fid);
|
|
|
|
_partyMemberSyncPosition();
|
|
|
|
|
|
|
|
if (gMapSid != -1) {
|
|
|
|
scriptsExecMapUpdateProc();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gameMouseWasVisible) {
|
|
|
|
gameMouseObjectsShow();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482220
|
|
|
|
int mapSetGlobalVar(int var, int value)
|
|
|
|
{
|
|
|
|
if (var < 0 || var >= gMapGlobalVarsLength) {
|
|
|
|
debugPrint("ERROR: attempt to reference map var out of range: %d", var);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMapGlobalVars[var] = value;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482250
|
|
|
|
int mapGetGlobalVar(int var)
|
|
|
|
{
|
|
|
|
if (var < 0 || var >= gMapGlobalVarsLength) {
|
|
|
|
debugPrint("ERROR: attempt to reference map var out of range: %d", var);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gMapGlobalVars[var];
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482280
|
|
|
|
int mapSetLocalVar(int var, int value)
|
|
|
|
{
|
|
|
|
if (var < 0 || var >= gMapLocalVarsLength) {
|
|
|
|
debugPrint("ERROR: attempt to reference local var out of range: %d", var);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMapLocalVars[var] = value;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4822B0
|
|
|
|
int mapGetLocalVar(int var)
|
|
|
|
{
|
|
|
|
if (var < 0 || var >= gMapLocalVarsLength) {
|
|
|
|
debugPrint("ERROR: attempt to reference local var out of range: %d", var);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gMapLocalVars[var];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make a room to store more local variables.
|
|
|
|
//
|
|
|
|
// 0x4822E0
|
|
|
|
int _map_malloc_local_var(int a1)
|
|
|
|
{
|
|
|
|
int oldMapLocalVarsLength = gMapLocalVarsLength;
|
|
|
|
gMapLocalVarsLength += a1;
|
|
|
|
|
2022-05-21 08:22:03 -07:00
|
|
|
int* vars = (int*)internal_realloc(gMapLocalVars, sizeof(*vars) * gMapLocalVarsLength);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (vars == NULL) {
|
|
|
|
debugPrint("\nError: Ran out of memory!");
|
|
|
|
}
|
|
|
|
|
|
|
|
gMapLocalVars = vars;
|
|
|
|
memset((unsigned char*)vars + sizeof(*vars) * oldMapLocalVarsLength, 0, sizeof(*vars) * a1);
|
|
|
|
|
|
|
|
return oldMapLocalVarsLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x48234C
|
|
|
|
void mapSetStart(int tile, int elevation, int rotation)
|
|
|
|
{
|
|
|
|
gMapHeader.enteringTile = tile;
|
|
|
|
gMapHeader.enteringElevation = elevation;
|
|
|
|
gMapHeader.enteringRotation = rotation;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4824CC
|
|
|
|
char* mapGetName(int map, int elevation)
|
|
|
|
{
|
2022-09-15 01:42:02 -07:00
|
|
|
if (map < 0 || map >= wmMapMaxCount()) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!elevationIsValid(elevation)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageListItem messageListItem;
|
|
|
|
return getmsg(&gMapMessageList, &messageListItem, map * 3 + elevation + 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Check, probably returns true if map1 and map2 represents the same city.
|
|
|
|
//
|
|
|
|
// 0x482528
|
|
|
|
bool _is_map_idx_same(int map1, int map2)
|
|
|
|
{
|
2022-09-15 01:42:02 -07:00
|
|
|
if (map1 < 0 || map1 >= wmMapMaxCount()) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
if (map2 < 0 || map2 >= wmMapMaxCount()) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
if (!wmMapIdxIsSaveable(map1)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
if (!wmMapIdxIsSaveable(map2)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int city1;
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMatchAreaContainingMapIdx(map1, &city1) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int city2;
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMatchAreaContainingMapIdx(map2, &city2) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return city1 == city2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4825CC
|
|
|
|
int _get_map_idx_same(int map1, int map2)
|
|
|
|
{
|
|
|
|
int city1 = -1;
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMatchAreaContainingMapIdx(map1, &city1) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int city2 = -2;
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMatchAreaContainingMapIdx(map2, &city2) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (city1 != city2) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return city1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x48261C
|
|
|
|
char* mapGetCityName(int map)
|
|
|
|
{
|
|
|
|
int city;
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMatchAreaContainingMapIdx(map, &city) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return _aErrorF2;
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageListItem messageListItem;
|
|
|
|
char* name = getmsg(&gMapMessageList, &messageListItem, 1500 + city);
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x48268C
|
|
|
|
char* _map_get_description_idx_(int map)
|
|
|
|
{
|
|
|
|
int city;
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMatchAreaContainingMapIdx(map, &city) == 0) {
|
|
|
|
wmGetAreaIdxName(city, _scratchStr);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
|
|
|
strcpy(_scratchStr, _errMapName);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _scratchStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4826B8
|
|
|
|
int mapGetCurrentMap()
|
|
|
|
{
|
|
|
|
return gMapHeader.field_34;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4826C0
|
|
|
|
int mapScroll(int dx, int dy)
|
|
|
|
{
|
|
|
|
if (getTicksSince(gIsoWindowScrollTimestamp) < 33) {
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
gIsoWindowScrollTimestamp = _get_time();
|
|
|
|
|
|
|
|
int screenDx = dx * 32;
|
|
|
|
int screenDy = dy * 24;
|
|
|
|
|
|
|
|
if (screenDx == 0 && screenDy == 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gameMouseObjectsHide();
|
|
|
|
|
|
|
|
int centerScreenX;
|
|
|
|
int centerScreenY;
|
|
|
|
tileToScreenXY(gCenterTile, ¢erScreenX, ¢erScreenY, gElevation);
|
|
|
|
centerScreenX += screenDx + 16;
|
|
|
|
centerScreenY += screenDy + 8;
|
|
|
|
|
|
|
|
int newCenterTile = tileFromScreenXY(centerScreenX, centerScreenY, gElevation);
|
|
|
|
if (newCenterTile == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tileSetCenter(newCenterTile, 0) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Rect r1;
|
|
|
|
rectCopy(&r1, &gIsoWindowRect);
|
|
|
|
|
|
|
|
Rect r2;
|
|
|
|
rectCopy(&r2, &r1);
|
|
|
|
|
2022-05-21 11:30:25 -07:00
|
|
|
int width = screenGetWidth();
|
2022-05-19 01:51:26 -07:00
|
|
|
int pitch = width;
|
2022-05-21 11:30:25 -07:00
|
|
|
int height = screenGetVisibleHeight();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (screenDx != 0) {
|
|
|
|
width -= 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (screenDy != 0) {
|
|
|
|
height -= 24;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (screenDx < 0) {
|
|
|
|
r2.right = r2.left - screenDx;
|
|
|
|
} else {
|
|
|
|
r2.left = r2.right - screenDx;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char* src;
|
|
|
|
unsigned char* dest;
|
|
|
|
int step;
|
|
|
|
if (screenDy < 0) {
|
|
|
|
r1.bottom = r1.top - screenDy;
|
|
|
|
src = gIsoWindowBuffer + pitch * (height - 1);
|
2022-05-21 11:30:25 -07:00
|
|
|
dest = gIsoWindowBuffer + pitch * (screenGetVisibleHeight() - 1);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (screenDx < 0) {
|
|
|
|
dest -= screenDx;
|
|
|
|
} else {
|
|
|
|
src += screenDx;
|
|
|
|
}
|
|
|
|
step = -pitch;
|
|
|
|
} else {
|
|
|
|
r1.top = r1.bottom - screenDy;
|
|
|
|
dest = gIsoWindowBuffer;
|
|
|
|
src = gIsoWindowBuffer + pitch * screenDy;
|
|
|
|
|
|
|
|
if (screenDx < 0) {
|
|
|
|
dest -= screenDx;
|
|
|
|
} else {
|
|
|
|
src += screenDx;
|
|
|
|
}
|
|
|
|
step = pitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int y = 0; y < height; y++) {
|
|
|
|
memmove(dest, src, width);
|
|
|
|
dest += step;
|
|
|
|
src += step;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (screenDx != 0) {
|
|
|
|
_map_scroll_refresh(&r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (screenDy != 0) {
|
|
|
|
_map_scroll_refresh(&r1);
|
|
|
|
}
|
|
|
|
|
|
|
|
windowRefresh(gIsoWindow);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482900
|
2022-06-19 10:14:17 -07:00
|
|
|
static char* mapBuildPath(char* name)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (*name != '\\') {
|
2022-06-18 00:58:15 -07:00
|
|
|
// NOTE: Uppercased from "maps".
|
|
|
|
sprintf(_map_path, "MAPS\\%s", name);
|
2022-05-19 01:51:26 -07:00
|
|
|
return _map_path;
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482924
|
|
|
|
int mapSetEnteringLocation(int elevation, int tile_num, int orientation)
|
|
|
|
{
|
|
|
|
gEnteringElevation = elevation;
|
|
|
|
gEnteringTile = tile_num;
|
|
|
|
gEnteringRotation = orientation;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482938
|
|
|
|
void _map_new_map()
|
|
|
|
{
|
|
|
|
mapSetElevation(0);
|
|
|
|
tileSetCenter(20100, TILE_SET_CENTER_FLAG_0x02);
|
|
|
|
memset(&gMapTransition, 0, sizeof(gMapTransition));
|
|
|
|
gMapHeader.enteringElevation = 0;
|
|
|
|
gMapHeader.enteringRotation = 0;
|
|
|
|
gMapHeader.localVariablesCount = 0;
|
|
|
|
gMapHeader.version = 20;
|
|
|
|
gMapHeader.name[0] = '\0';
|
|
|
|
gMapHeader.enteringTile = 20100;
|
|
|
|
_obj_remove_all();
|
2022-07-07 01:28:21 -07:00
|
|
|
animationStop();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (gMapGlobalVars != NULL) {
|
|
|
|
internal_free(gMapGlobalVars);
|
|
|
|
gMapGlobalVars = NULL;
|
|
|
|
gMapGlobalVarsLength = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMapLocalVars != NULL) {
|
|
|
|
internal_free(gMapLocalVars);
|
|
|
|
gMapLocalVars = NULL;
|
|
|
|
gMapLocalVarsLength = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_square_reset();
|
|
|
|
_map_place_dude_and_mouse();
|
|
|
|
tileWindowRefresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482A68
|
|
|
|
int mapLoadByName(char* fileName)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2022-05-28 01:57:32 -07:00
|
|
|
compat_strupr(fileName);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
char* extension = strstr(fileName, ".MAP");
|
|
|
|
if (extension != NULL) {
|
|
|
|
strcpy(extension, ".SAV");
|
|
|
|
|
|
|
|
const char* filePath = mapBuildPath(fileName);
|
|
|
|
|
|
|
|
File* stream = fileOpen(filePath, "rb");
|
|
|
|
|
|
|
|
strcpy(extension, ".MAP");
|
|
|
|
|
|
|
|
if (stream != NULL) {
|
|
|
|
fileClose(stream);
|
|
|
|
rc = mapLoadSaved(fileName);
|
2022-09-15 01:42:02 -07:00
|
|
|
wmMapMusicStart();
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc == -1) {
|
|
|
|
const char* filePath = mapBuildPath(fileName);
|
|
|
|
File* stream = fileOpen(filePath, "rb");
|
|
|
|
if (stream != NULL) {
|
|
|
|
rc = mapLoad(stream);
|
|
|
|
fileClose(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc == 0) {
|
|
|
|
strcpy(gMapHeader.name, fileName);
|
|
|
|
gDude->data.critter.combat.whoHitMe = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482B34
|
|
|
|
int mapLoadById(int map)
|
|
|
|
{
|
|
|
|
scriptSetFixedParam(gMapSid, map);
|
|
|
|
|
|
|
|
char name[16];
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMapIdxToName(map, name) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_wmMapIdx = map;
|
|
|
|
|
|
|
|
int rc = mapLoadByName(name);
|
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
wmMapMusicStart();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x482B74
|
2022-06-19 10:14:17 -07:00
|
|
|
static int mapLoad(File* stream)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
_map_save_in_game(true);
|
|
|
|
backgroundSoundLoad("wind2", 12, 13, 16);
|
|
|
|
isoDisable();
|
|
|
|
_partyMemberPrepLoad();
|
|
|
|
_gmouse_disable_scrolling();
|
|
|
|
|
|
|
|
int savedMouseCursorId = gameMouseGetCursor();
|
|
|
|
gameMouseSetCursor(MOUSE_CURSOR_WAIT_PLANET);
|
|
|
|
fileSetReadProgressHandler(gameMouseRefresh, 32768);
|
|
|
|
tileDisable();
|
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
windowFill(gIsoWindow, 0, 0, _scr_size.right - _scr_size.left + 1, _scr_size.bottom - _scr_size.top - 99, _colorTable[0]);
|
|
|
|
windowRefresh(gIsoWindow);
|
2022-07-07 01:28:21 -07:00
|
|
|
animationStop();
|
2022-05-19 01:51:26 -07:00
|
|
|
scriptsDisable();
|
|
|
|
|
|
|
|
gMapSid = -1;
|
|
|
|
|
|
|
|
const char* error = NULL;
|
|
|
|
|
|
|
|
error = "Invalid file handle";
|
|
|
|
if (stream == NULL) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Error reading header";
|
|
|
|
if (mapHeaderRead(&gMapHeader, stream) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Invalid map version";
|
|
|
|
if (gMapHeader.version != 19 && gMapHeader.version != 20) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gEnteringElevation == -1) {
|
|
|
|
gEnteringElevation = gMapHeader.enteringElevation;
|
|
|
|
gEnteringTile = gMapHeader.enteringTile;
|
|
|
|
gEnteringRotation = gMapHeader.enteringRotation;
|
|
|
|
}
|
|
|
|
|
|
|
|
_obj_remove_all();
|
|
|
|
|
|
|
|
if (gMapHeader.globalVariablesCount < 0) {
|
|
|
|
gMapHeader.globalVariablesCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMapHeader.localVariablesCount < 0) {
|
|
|
|
gMapHeader.localVariablesCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Error loading global vars";
|
|
|
|
mapGlobalVariablesFree();
|
|
|
|
|
|
|
|
if (gMapHeader.globalVariablesCount != 0) {
|
2022-05-21 08:22:03 -07:00
|
|
|
gMapGlobalVars = (int*)internal_malloc(sizeof(*gMapGlobalVars) * gMapHeader.globalVariablesCount);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (gMapGlobalVars == NULL) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMapGlobalVarsLength = gMapHeader.globalVariablesCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fileReadInt32List(stream, gMapGlobalVars, gMapGlobalVarsLength) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Error loading local vars";
|
|
|
|
mapLocalVariablesFree();
|
|
|
|
|
|
|
|
if (gMapHeader.localVariablesCount != 0) {
|
2022-05-21 08:22:03 -07:00
|
|
|
gMapLocalVars = (int*)internal_malloc(sizeof(*gMapLocalVars) * gMapHeader.localVariablesCount);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (gMapLocalVars == NULL) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMapLocalVarsLength = gMapHeader.localVariablesCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fileReadInt32List(stream, gMapLocalVars, gMapLocalVarsLength) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_square_load(stream, gMapHeader.flags) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Error reading scripts";
|
|
|
|
if (scriptLoadAll(stream) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Error reading objects";
|
|
|
|
if (objectLoadAll(stream) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((gMapHeader.flags & 1) == 0) {
|
|
|
|
_map_fix_critter_combat_data();
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Error setting map elevation";
|
|
|
|
if (mapSetElevation(gEnteringElevation) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = "Error setting tile center";
|
|
|
|
if (tileSetCenter(gEnteringTile, TILE_SET_CENTER_FLAG_0x02) != 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
lightSetLightLevel(LIGHT_LEVEL_MAX, false);
|
|
|
|
objectSetLocation(gDude, gCenterTile, gElevation, NULL);
|
|
|
|
objectSetRotation(gDude, gEnteringRotation, NULL);
|
2022-09-15 01:42:02 -07:00
|
|
|
gMapHeader.field_34 = wmMapMatchNameToIdx(gMapHeader.name);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if ((gMapHeader.flags & 1) == 0) {
|
2022-05-28 02:34:49 -07:00
|
|
|
char path[COMPAT_MAX_PATH];
|
2022-05-19 01:51:26 -07:00
|
|
|
sprintf(path, "maps\\%s", gMapHeader.name);
|
|
|
|
|
|
|
|
char* extension = strstr(path, ".MAP");
|
|
|
|
if (extension == NULL) {
|
|
|
|
extension = strstr(path, ".map");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (extension != NULL) {
|
|
|
|
*extension = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
strcat(path, ".GAM");
|
|
|
|
globalVarsRead(path, "MAP_GLOBAL_VARS:", &gMapGlobalVarsLength, &gMapGlobalVars);
|
|
|
|
gMapHeader.globalVariablesCount = gMapGlobalVarsLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
scriptsEnable();
|
|
|
|
|
|
|
|
if (gMapHeader.scriptIndex > 0) {
|
|
|
|
error = "Error creating new map script";
|
|
|
|
if (scriptAdd(&gMapSid, SCRIPT_TYPE_SYSTEM) == -1) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object* object;
|
2022-07-29 06:04:05 -07:00
|
|
|
int fid = buildFid(OBJ_TYPE_MISC, 12, 0, 0, 0);
|
2022-05-19 01:51:26 -07:00
|
|
|
objectCreateWithFidPid(&object, fid, -1);
|
2022-06-08 10:38:46 -07:00
|
|
|
object->flags |= (OBJECT_LIGHT_THRU | OBJECT_TEMPORARY | OBJECT_HIDDEN);
|
2022-05-19 01:51:26 -07:00
|
|
|
objectSetLocation(object, 1, 0, NULL);
|
|
|
|
object->sid = gMapSid;
|
|
|
|
scriptSetFixedParam(gMapSid, (gMapHeader.flags & 1) == 0);
|
|
|
|
|
|
|
|
Script* script;
|
|
|
|
scriptGetScript(gMapSid, &script);
|
|
|
|
script->field_14 = gMapHeader.scriptIndex - 1;
|
|
|
|
script->flags |= SCRIPT_FLAG_0x08;
|
|
|
|
object->id = scriptsNewObjectId();
|
|
|
|
script->field_1C = object->id;
|
|
|
|
script->owner = object;
|
|
|
|
_scr_spatials_disable();
|
|
|
|
scriptExecProc(gMapSid, SCRIPT_PROC_MAP_ENTER);
|
|
|
|
_scr_spatials_enable();
|
|
|
|
|
|
|
|
error = "Error Setting up random encounter";
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmSetupRandomEncounter() == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
error = NULL;
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
|
|
|
if (error != NULL) {
|
|
|
|
char message[100]; // TODO: Size is probably wrong.
|
|
|
|
sprintf(message, "%s while loading map.", error);
|
|
|
|
debugPrint(message);
|
|
|
|
_map_new_map();
|
|
|
|
rc = -1;
|
|
|
|
} else {
|
|
|
|
_obj_preload_art_cache(gMapHeader.flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
_partyMemberRecoverLoad();
|
|
|
|
_intface_show();
|
|
|
|
_proto_dude_update_gender();
|
|
|
|
_map_place_dude_and_mouse();
|
|
|
|
fileSetReadProgressHandler(NULL, 0);
|
|
|
|
isoEnable();
|
|
|
|
_gmouse_disable_scrolling();
|
|
|
|
gameMouseSetCursor(MOUSE_CURSOR_WAIT_PLANET);
|
|
|
|
|
|
|
|
if (scriptsExecStartProc() == -1) {
|
|
|
|
debugPrint("\n Error: scr_load_all_scripts failed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
scriptsExecMapEnterProc();
|
|
|
|
scriptsExecMapUpdateProc();
|
|
|
|
tileEnable();
|
|
|
|
|
|
|
|
if (gMapTransition.map > 0) {
|
|
|
|
if (gMapTransition.rotation >= 0) {
|
|
|
|
objectSetRotation(gDude, gMapTransition.rotation, NULL);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tileWindowRefresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
gameTimeScheduleUpdateEvent();
|
|
|
|
|
|
|
|
if (_gsound_sfx_q_start() == -1) {
|
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
wmMapMarkVisited(gMapHeader.field_34);
|
|
|
|
wmMapMarkMapEntranceState(gMapHeader.field_34, gElevation, 1);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmCheckGameAreaEvents() != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fileSetReadProgressHandler(NULL, 0);
|
|
|
|
|
|
|
|
if (gameUiIsDisabled() == 0) {
|
|
|
|
_gmouse_enable_scrolling();
|
|
|
|
}
|
|
|
|
|
|
|
|
gameMouseSetCursor(savedMouseCursorId);
|
|
|
|
|
|
|
|
gEnteringElevation = -1;
|
|
|
|
gEnteringTile = -1;
|
|
|
|
gEnteringRotation = -1;
|
|
|
|
|
|
|
|
gameMovieFadeOut();
|
|
|
|
|
|
|
|
gMapHeader.version = 20;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483188
|
|
|
|
int mapLoadSaved(char* fileName)
|
|
|
|
{
|
|
|
|
debugPrint("\nMAP: Loading SAVED map.");
|
|
|
|
|
|
|
|
char mapName[16]; // TODO: Size is probably wrong.
|
|
|
|
_strmfe(mapName, fileName, "SAV");
|
|
|
|
|
|
|
|
int rc = mapLoadByName(mapName);
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
if (gameTimeGetTime() >= gMapHeader.lastVisitTime) {
|
|
|
|
if (((gameTimeGetTime() - gMapHeader.lastVisitTime) / GAME_TIME_TICKS_PER_HOUR) >= 24) {
|
2022-05-19 01:51:26 -07:00
|
|
|
objectUnjamAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_map_age_dead_critters() == -1) {
|
|
|
|
debugPrint("\nError: Critter aging failed on map load!");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
if (!wmMapIsSaveable()) {
|
2022-05-19 01:51:26 -07:00
|
|
|
debugPrint("\nDestroying RANDOM encounter map.");
|
|
|
|
|
|
|
|
char v15[16];
|
|
|
|
strcpy(v15, gMapHeader.name);
|
|
|
|
|
|
|
|
_strmfe(gMapHeader.name, v15, "SAV");
|
|
|
|
|
|
|
|
_MapDirEraseFile_("MAPS\\", gMapHeader.name);
|
|
|
|
|
|
|
|
strcpy(gMapHeader.name, v15);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x48328C
|
2022-06-19 10:14:17 -07:00
|
|
|
static int _map_age_dead_critters()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
2022-09-15 01:42:02 -07:00
|
|
|
if (!wmMapDeadBodiesAge()) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
int hoursSinceLastVisit = (gameTimeGetTime() - gMapHeader.lastVisitTime) / GAME_TIME_TICKS_PER_HOUR;
|
|
|
|
if (hoursSinceLastVisit == 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object* obj = objectFindFirst();
|
|
|
|
while (obj != NULL) {
|
2022-07-29 06:04:05 -07:00
|
|
|
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER
|
2022-05-19 01:51:26 -07:00
|
|
|
&& obj != gDude
|
|
|
|
&& !objectIsPartyMember(obj)
|
|
|
|
&& !critterIsDead(obj)) {
|
2022-07-29 06:04:05 -07:00
|
|
|
obj->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING;
|
|
|
|
if (critterGetKillType(obj) != KILL_TYPE_ROBOT && _critter_flag_check(obj->pid, CRITTER_FLAG_0x200) == 0) {
|
|
|
|
_critter_heal_hours(obj, hoursSinceLastVisit);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
obj = objectFindNext();
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
int agingType;
|
|
|
|
if (hoursSinceLastVisit > 6 * 24) {
|
|
|
|
agingType = 1;
|
|
|
|
} else if (hoursSinceLastVisit > 14 * 24) {
|
|
|
|
agingType = 2;
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int capacity = 100;
|
|
|
|
int count = 0;
|
2022-05-21 08:22:03 -07:00
|
|
|
Object** objects = (Object**)internal_malloc(sizeof(*objects) * capacity);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
obj = objectFindFirst();
|
|
|
|
while (obj != NULL) {
|
2022-07-29 06:04:05 -07:00
|
|
|
int type = PID_TYPE(obj->pid);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (type == OBJ_TYPE_CRITTER) {
|
|
|
|
if (obj != gDude && critterIsDead(obj)) {
|
2022-07-29 06:04:05 -07:00
|
|
|
if (critterGetKillType(obj) != KILL_TYPE_ROBOT && _critter_flag_check(obj->pid, CRITTER_FLAG_0x200) == 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
objects[count++] = obj;
|
|
|
|
|
|
|
|
if (count >= capacity) {
|
|
|
|
capacity *= 2;
|
2022-05-21 08:22:03 -07:00
|
|
|
objects = (Object**)internal_realloc(objects, sizeof(*objects) * capacity);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (objects == NULL) {
|
|
|
|
debugPrint("\nError: Out of Memory!");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-29 06:04:05 -07:00
|
|
|
} else if (agingType == 2 && type == OBJ_TYPE_MISC && obj->pid == 0x500000B) {
|
2022-05-19 01:51:26 -07:00
|
|
|
objects[count++] = obj;
|
|
|
|
if (count >= capacity) {
|
|
|
|
capacity *= 2;
|
2022-05-21 08:22:03 -07:00
|
|
|
objects = (Object**)internal_realloc(objects, sizeof(*objects) * capacity);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (objects == NULL) {
|
|
|
|
debugPrint("\nError: Out of Memory!");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
obj = objectFindNext();
|
|
|
|
}
|
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
for (int index = 0; index < count; index++) {
|
|
|
|
Object* obj = objects[index];
|
2022-07-29 06:04:05 -07:00
|
|
|
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
|
|
|
|
if (_critter_flag_check(obj->pid, CRITTER_FLAG_0x40) == 0) {
|
2022-08-17 22:41:15 -07:00
|
|
|
itemDropAll(obj, obj->tile);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
Object* blood;
|
|
|
|
if (objectCreateWithPid(&blood, 0x5000004) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
rc = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
objectSetLocation(blood, obj->tile, obj->elevation, NULL);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
Proto* proto;
|
|
|
|
protoGetProto(obj->pid, &proto);
|
|
|
|
|
|
|
|
int frame = randomBetween(0, 3);
|
|
|
|
if ((proto->critter.flags & 0x800)) {
|
|
|
|
frame += 6;
|
|
|
|
} else {
|
|
|
|
if (critterGetKillType(obj) != KILL_TYPE_RAT
|
|
|
|
&& critterGetKillType(obj) != KILL_TYPE_MANTIS) {
|
|
|
|
frame += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
objectSetFrame(blood, frame, NULL);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
reg_anim_clear(obj);
|
|
|
|
objectDestroy(obj, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal_free(objects);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x48358C
|
|
|
|
int _map_target_load_area()
|
|
|
|
{
|
|
|
|
int city = -1;
|
2022-09-15 01:42:02 -07:00
|
|
|
if (wmMatchAreaContainingMapIdx(gMapHeader.field_34, &city) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
city = -1;
|
|
|
|
}
|
|
|
|
return city;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4835B4
|
|
|
|
int mapSetTransition(MapTransition* transition)
|
|
|
|
{
|
|
|
|
if (transition == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&gMapTransition, transition, sizeof(gMapTransition));
|
|
|
|
|
|
|
|
if (gMapTransition.map == 0) {
|
|
|
|
gMapTransition.map = -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isInCombat()) {
|
|
|
|
_game_user_wants_to_quit = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4835F8
|
|
|
|
int mapHandleTransition()
|
|
|
|
{
|
|
|
|
if (gMapTransition.map == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
gameMouseObjectsHide();
|
|
|
|
|
|
|
|
gameMouseSetCursor(MOUSE_CURSOR_NONE);
|
|
|
|
|
|
|
|
if (gMapTransition.map == -1) {
|
|
|
|
if (!isInCombat()) {
|
2022-07-07 01:28:21 -07:00
|
|
|
animationStop();
|
2022-09-15 01:42:02 -07:00
|
|
|
wmTownMap();
|
2022-05-19 01:51:26 -07:00
|
|
|
memset(&gMapTransition, 0, sizeof(gMapTransition));
|
|
|
|
}
|
|
|
|
} else if (gMapTransition.map == -2) {
|
|
|
|
if (!isInCombat()) {
|
2022-07-07 01:28:21 -07:00
|
|
|
animationStop();
|
2022-09-15 01:42:02 -07:00
|
|
|
wmWorldMap();
|
2022-05-19 01:51:26 -07:00
|
|
|
memset(&gMapTransition, 0, sizeof(gMapTransition));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!isInCombat()) {
|
|
|
|
if (gMapTransition.map != gMapHeader.field_34 || gElevation == gMapTransition.elevation) {
|
|
|
|
mapLoadById(gMapTransition.map);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMapTransition.tile != -1 && gMapTransition.tile != 0
|
|
|
|
&& gMapHeader.field_34 != MAP_MODOC_BEDNBREAKFAST && gMapHeader.field_34 != MAP_THE_SQUAT_A
|
|
|
|
&& elevationIsValid(gMapTransition.elevation)) {
|
|
|
|
objectSetLocation(gDude, gMapTransition.tile, gMapTransition.elevation, NULL);
|
|
|
|
mapSetElevation(gMapTransition.elevation);
|
|
|
|
objectSetRotation(gDude, gMapTransition.rotation, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tileSetCenter(gDude->tile, TILE_SET_CENTER_FLAG_0x01) == -1) {
|
|
|
|
debugPrint("\nError: map: attempt to center out-of-bounds!");
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&gMapTransition, 0, sizeof(gMapTransition));
|
|
|
|
|
|
|
|
int city;
|
2022-09-15 01:42:02 -07:00
|
|
|
wmMatchAreaContainingMapIdx(gMapHeader.field_34, &city);
|
|
|
|
if (wmTeleportToArea(city) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
debugPrint("\nError: couldn't make jump on worldmap for map jump!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483784
|
2022-06-19 10:14:17 -07:00
|
|
|
static void _map_fix_critter_combat_data()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
for (Object* object = objectFindFirst(); object != NULL; object = objectFindNext()) {
|
|
|
|
if (object->pid == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
|
2022-05-19 01:51:26 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (object->data.critter.combat.whoHitMeCid == -1) {
|
|
|
|
object->data.critter.combat.whoHitMe = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// map_save
|
|
|
|
// 0x483850
|
2022-06-19 10:14:17 -07:00
|
|
|
static int _map_save()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
char temp[80];
|
|
|
|
temp[0] = '\0';
|
|
|
|
|
|
|
|
char* masterPatchesPath;
|
|
|
|
if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &masterPatchesPath)) {
|
|
|
|
strcat(temp, masterPatchesPath);
|
2022-05-29 08:08:55 -07:00
|
|
|
compat_mkdir(temp);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
strcat(temp, "\\MAPS");
|
2022-05-29 08:08:55 -07:00
|
|
|
compat_mkdir(temp);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int rc = -1;
|
|
|
|
if (gMapHeader.name[0] != '\0') {
|
|
|
|
char* mapFileName = mapBuildPath(gMapHeader.name);
|
|
|
|
File* stream = fileOpen(mapFileName, "wb");
|
|
|
|
if (stream != NULL) {
|
|
|
|
rc = _map_save_file(stream);
|
|
|
|
fileClose(stream);
|
|
|
|
} else {
|
|
|
|
sprintf(temp, "Unable to open %s to write!", gMapHeader.name);
|
|
|
|
debugPrint(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc == 0) {
|
|
|
|
sprintf(temp, "%s saved.", gMapHeader.name);
|
|
|
|
debugPrint(temp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
debugPrint("\nError: map_save: map header corrupt!");
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483980
|
2022-06-19 10:14:17 -07:00
|
|
|
static int _map_save_file(File* stream)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (stream == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
scriptsDisable();
|
|
|
|
|
|
|
|
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
|
|
|
|
int tile;
|
|
|
|
for (tile = 0; tile < SQUARE_GRID_SIZE; tile++) {
|
|
|
|
int fid;
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
fid = buildFid(OBJ_TYPE_TILE, _square[elevation]->field_0[tile] & 0xFFF, 0, 0, 0);
|
|
|
|
if (fid != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
fid = buildFid(OBJ_TYPE_TILE, (_square[elevation]->field_0[tile] >> 16) & 0xFFF, 0, 0, 0);
|
|
|
|
if (fid != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile == SQUARE_GRID_SIZE) {
|
|
|
|
Object* object = objectFindFirstAtElevation(elevation);
|
|
|
|
if (object != NULL) {
|
|
|
|
// TODO: Implementation is slightly different, check in debugger.
|
|
|
|
while (object != NULL && (object->flags & OBJECT_TEMPORARY)) {
|
|
|
|
object = objectFindNextAtElevation();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (object != NULL) {
|
|
|
|
gMapHeader.flags &= ~_map_data_elev_flags[elevation];
|
|
|
|
} else {
|
|
|
|
gMapHeader.flags |= _map_data_elev_flags[elevation];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gMapHeader.flags |= _map_data_elev_flags[elevation];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gMapHeader.flags &= ~_map_data_elev_flags[elevation];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gMapHeader.localVariablesCount = gMapLocalVarsLength;
|
|
|
|
gMapHeader.globalVariablesCount = gMapGlobalVarsLength;
|
|
|
|
gMapHeader.darkness = 1;
|
|
|
|
|
|
|
|
mapHeaderWrite(&gMapHeader, stream);
|
|
|
|
|
|
|
|
if (gMapHeader.globalVariablesCount != 0) {
|
|
|
|
fileWriteInt32List(stream, gMapGlobalVars, gMapHeader.globalVariablesCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gMapHeader.localVariablesCount != 0) {
|
|
|
|
fileWriteInt32List(stream, gMapLocalVars, gMapHeader.localVariablesCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
|
|
|
|
if ((gMapHeader.flags & _map_data_elev_flags[elevation]) == 0) {
|
|
|
|
_db_fwriteLongCount(stream, _square[elevation]->field_0, SQUARE_GRID_SIZE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char err[80];
|
|
|
|
|
|
|
|
if (scriptSaveAll(stream) == -1) {
|
|
|
|
sprintf(err, "Error saving scripts in %s", gMapHeader.name);
|
2022-07-29 06:04:05 -07:00
|
|
|
_win_msg(err, 80, 80, _colorTable[31744]);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (objectSaveAll(stream) == -1) {
|
|
|
|
sprintf(err, "Error saving objects in %s", gMapHeader.name);
|
2022-07-29 06:04:05 -07:00
|
|
|
_win_msg(err, 80, 80, _colorTable[31744]);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
scriptsEnable();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483C98
|
|
|
|
int _map_save_in_game(bool a1)
|
|
|
|
{
|
|
|
|
if (gMapHeader.name[0] == '\0') {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-07-07 01:28:21 -07:00
|
|
|
animationStop();
|
2022-05-19 01:51:26 -07:00
|
|
|
_partyMemberSaveProtos();
|
|
|
|
|
|
|
|
if (a1) {
|
|
|
|
_queue_leaving_map();
|
|
|
|
_partyMemberPrepLoad();
|
|
|
|
_partyMemberPrepItemSaveAll();
|
|
|
|
scriptsExecMapExitProc();
|
|
|
|
|
|
|
|
if (gMapSid != -1) {
|
|
|
|
Script* script;
|
|
|
|
scriptGetScript(gMapSid, &script);
|
|
|
|
}
|
|
|
|
|
|
|
|
gameTimeScheduleUpdateEvent();
|
|
|
|
_obj_reset_roof();
|
|
|
|
}
|
|
|
|
|
|
|
|
gMapHeader.flags |= 0x01;
|
2022-07-29 06:04:05 -07:00
|
|
|
gMapHeader.lastVisitTime = gameTimeGetTime();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
char name[16];
|
|
|
|
|
2022-09-15 01:42:02 -07:00
|
|
|
if (a1 && !wmMapIsSaveable()) {
|
2022-05-19 01:51:26 -07:00
|
|
|
debugPrint("\nNot saving RANDOM encounter map.");
|
|
|
|
|
|
|
|
strcpy(name, gMapHeader.name);
|
|
|
|
_strmfe(gMapHeader.name, name, "SAV");
|
|
|
|
_MapDirEraseFile_("MAPS\\", gMapHeader.name);
|
|
|
|
strcpy(gMapHeader.name, name);
|
|
|
|
} else {
|
|
|
|
debugPrint("\n Saving \".SAV\" map.");
|
|
|
|
|
|
|
|
strcpy(name, gMapHeader.name);
|
|
|
|
_strmfe(gMapHeader.name, name, "SAV");
|
|
|
|
if (_map_save() == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(gMapHeader.name, name);
|
|
|
|
|
|
|
|
automapSaveCurrent();
|
|
|
|
|
|
|
|
if (a1) {
|
|
|
|
gMapHeader.name[0] = '\0';
|
|
|
|
_obj_remove_all();
|
|
|
|
_proto_remove_all();
|
|
|
|
_square_reset();
|
|
|
|
gameTimeScheduleUpdateEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483E28
|
2022-06-19 10:14:17 -07:00
|
|
|
static void mapMakeMapsDirectory()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
2022-05-28 02:34:49 -07:00
|
|
|
char path[COMPAT_MAX_PATH];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
char* masterPatchesPath;
|
|
|
|
if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &masterPatchesPath)) {
|
|
|
|
strcpy(path, masterPatchesPath);
|
|
|
|
} else {
|
|
|
|
strcpy(path, "DATA");
|
|
|
|
}
|
|
|
|
|
2022-05-29 08:08:55 -07:00
|
|
|
compat_mkdir(path);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
strcat(path, "\\MAPS");
|
2022-05-29 08:08:55 -07:00
|
|
|
compat_mkdir(path);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483ED0
|
2022-06-19 10:14:17 -07:00
|
|
|
static void isoWindowRefreshRect(Rect* rect)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
windowRefreshRect(gIsoWindow, rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483EE4
|
2022-06-19 10:14:17 -07:00
|
|
|
static void isoWindowRefreshRectGame(Rect* rect)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
Rect clampedDirtyRect;
|
|
|
|
if (rectIntersection(rect, &gIsoWindowRect, &clampedDirtyRect) == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tileRenderFloorsInRect(&clampedDirtyRect, gElevation);
|
|
|
|
_grid_render(&clampedDirtyRect, gElevation);
|
|
|
|
_obj_render_pre_roof(&clampedDirtyRect, gElevation);
|
|
|
|
tileRenderRoofsInRect(&clampedDirtyRect, gElevation);
|
|
|
|
_obj_render_post_roof(&clampedDirtyRect, gElevation);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x483F44
|
2022-06-19 10:14:17 -07:00
|
|
|
static void isoWindowRefreshRectMapper(Rect* rect)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
Rect clampedDirtyRect;
|
|
|
|
if (rectIntersection(rect, &gIsoWindowRect, &clampedDirtyRect) == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bufferFill(gIsoWindowBuffer + clampedDirtyRect.top * (_scr_size.right - _scr_size.left + 1) + clampedDirtyRect.left,
|
|
|
|
clampedDirtyRect.right - clampedDirtyRect.left + 1,
|
|
|
|
clampedDirtyRect.bottom - clampedDirtyRect.top + 1,
|
|
|
|
_scr_size.right - _scr_size.left + 1,
|
|
|
|
0);
|
|
|
|
tileRenderFloorsInRect(&clampedDirtyRect, gElevation);
|
|
|
|
_grid_render(&clampedDirtyRect, gElevation);
|
|
|
|
_obj_render_pre_roof(&clampedDirtyRect, gElevation);
|
|
|
|
tileRenderRoofsInRect(&clampedDirtyRect, gElevation);
|
|
|
|
_obj_render_post_roof(&clampedDirtyRect, gElevation);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x484038
|
2022-06-19 10:14:17 -07:00
|
|
|
static void mapGlobalVariablesFree()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (gMapGlobalVars != NULL) {
|
|
|
|
internal_free(gMapGlobalVars);
|
|
|
|
gMapGlobalVars = NULL;
|
|
|
|
gMapGlobalVarsLength = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4840D4
|
2022-06-19 10:14:17 -07:00
|
|
|
static void mapLocalVariablesFree()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (gMapLocalVars != NULL) {
|
|
|
|
internal_free(gMapLocalVars);
|
|
|
|
gMapLocalVars = NULL;
|
|
|
|
gMapLocalVarsLength = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x48411C
|
2022-06-19 10:14:17 -07:00
|
|
|
static void _map_place_dude_and_mouse()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
_obj_clear_seen();
|
|
|
|
|
|
|
|
if (gDude != NULL) {
|
2022-07-29 06:04:05 -07:00
|
|
|
if (FID_ANIM_TYPE(gDude->fid) != ANIM_STAND) {
|
2022-05-19 01:51:26 -07:00
|
|
|
objectSetFrame(gDude, 0, 0);
|
2022-07-29 06:04:05 -07:00
|
|
|
gDude->fid = buildFid(OBJ_TYPE_CRITTER, gDude->fid & 0xFFF, ANIM_STAND, (gDude->fid & 0xF000) >> 12, gDude->rotation + 1);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gDude->tile == -1) {
|
|
|
|
objectSetLocation(gDude, gCenterTile, gElevation, NULL);
|
|
|
|
objectSetRotation(gDude, gMapHeader.enteringRotation, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
objectSetLight(gDude, 4, 0x10000, 0);
|
|
|
|
gDude->flags |= OBJECT_TEMPORARY;
|
|
|
|
|
|
|
|
_dude_stand(gDude, gDude->rotation, gDude->fid);
|
|
|
|
_partyMemberSyncPosition();
|
|
|
|
}
|
|
|
|
|
|
|
|
gameMouseResetBouncingCursorFid();
|
|
|
|
gameMouseObjectsShow();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x484210
|
2022-06-19 10:14:17 -07:00
|
|
|
static void _square_reset()
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
|
|
|
|
int* p = _square[elevation]->field_0;
|
|
|
|
for (int y = 0; y < SQUARE_GRID_HEIGHT; y++) {
|
|
|
|
for (int x = 0; x < SQUARE_GRID_WIDTH; x++) {
|
|
|
|
// TODO: Strange math, initially right, but need to figure it out and
|
|
|
|
// check subsequent calls.
|
|
|
|
int fid = *p;
|
|
|
|
fid &= ~0xFFFF;
|
2022-08-01 09:47:09 -07:00
|
|
|
*p = (((buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0) & 0xFFF) | (((fid >> 16) & 0xF000) >> 12)) << 16) | (fid & 0xFFFF);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
fid = *p;
|
|
|
|
int v3 = (fid & 0xF000) >> 12;
|
2022-07-29 06:04:05 -07:00
|
|
|
int v4 = (buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0) & 0xFFF) | v3;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
fid &= ~0xFFFF;
|
|
|
|
|
|
|
|
*p = v4 | ((fid >> 16) << 16);
|
|
|
|
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x48431C
|
2022-06-19 10:14:17 -07:00
|
|
|
static int _square_load(File* stream, int flags)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
int v6;
|
|
|
|
int v7;
|
|
|
|
int v8;
|
|
|
|
int v9;
|
|
|
|
|
|
|
|
_square_reset();
|
|
|
|
|
|
|
|
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
|
|
|
|
if ((flags & _map_data_elev_flags[elevation]) == 0) {
|
|
|
|
int* arr = _square[elevation]->field_0;
|
|
|
|
if (_db_freadIntCount(stream, arr, SQUARE_GRID_SIZE) != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int tile = 0; tile < SQUARE_GRID_SIZE; tile++) {
|
|
|
|
v6 = arr[tile];
|
|
|
|
v6 &= ~(0xFFFF);
|
|
|
|
v6 >>= 16;
|
|
|
|
|
|
|
|
v7 = (v6 & 0xF000) >> 12;
|
|
|
|
v7 &= ~(0x01);
|
|
|
|
|
|
|
|
v8 = v6 & 0xFFF;
|
|
|
|
v9 = arr[tile] & 0xFFFF;
|
|
|
|
arr[tile] = ((v8 | (v7 << 12)) << 16) | v9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4843B8
|
2022-06-19 10:14:17 -07:00
|
|
|
static int mapHeaderWrite(MapHeader* ptr, File* stream)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (fileWriteInt32(stream, ptr->version) == -1) return -1;
|
|
|
|
if (fileWriteFixedLengthString(stream, ptr->name, 16) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->enteringTile) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->enteringElevation) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->enteringRotation) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->localVariablesCount) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->scriptIndex) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->flags) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->darkness) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->globalVariablesCount) == -1) return -1;
|
|
|
|
if (fileWriteInt32(stream, ptr->field_34) == -1) return -1;
|
2022-07-29 06:04:05 -07:00
|
|
|
if (fileWriteInt32(stream, ptr->lastVisitTime) == -1) return -1;
|
2022-05-19 01:51:26 -07:00
|
|
|
if (fileWriteInt32List(stream, ptr->field_3C, 44) == -1) return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4844B4
|
2022-06-19 10:14:17 -07:00
|
|
|
static int mapHeaderRead(MapHeader* ptr, File* stream)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (fileReadInt32(stream, &(ptr->version)) == -1) return -1;
|
|
|
|
if (fileReadFixedLengthString(stream, ptr->name, 16) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->enteringTile)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->enteringElevation)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->enteringRotation)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->localVariablesCount)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->scriptIndex)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->flags)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->darkness)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->globalVariablesCount)) == -1) return -1;
|
|
|
|
if (fileReadInt32(stream, &(ptr->field_34)) == -1) return -1;
|
2022-07-29 06:04:05 -07:00
|
|
|
if (fileReadInt32(stream, &(ptr->lastVisitTime)) == -1) return -1;
|
2022-05-19 01:51:26 -07:00
|
|
|
if (fileReadInt32List(stream, ptr->field_3C, 44) == -1) return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|