Compare commits

...
25 changed files with 2484 additions and 330 deletions
+48 -2
View File
@@ -447,11 +447,57 @@ void artRender(int fid, unsigned char* dest, int width, int height, int pitch)
// mapper2.exe: 0x40A03C
int art_list_str(int fid, char* name)
{
// TODO: Incomplete.
if (fid == -1 || name == nullptr) {
return -1;
}
return -1;
int objectType = (fid & 0xF000000) >> 24;
int index = fid & 0xFFF;
const char* typeName = artGetObjectTypeName(objectType);
if (typeName == nullptr) {
return -1;
}
char path[260];
snprintf(path, sizeof(path), "%s%s%s\\%s.lst", _cd_path_base, "art\\", typeName, typeName);
File* stream = fileOpen(path, "rt");
if (stream == nullptr) {
return -1;
}
char buffer[260];
int line = 0;
bool found = false;
while (fileReadString(buffer, sizeof(buffer), stream) != nullptr) {
if (line == index) {
char* p = buffer;
while (*p) {
if (*p == ' ' || *p == '\n') {
*p = '\0';
break;
}
p++;
}
char* dst = name;
const char* src = buffer;
do {
*dst++ = *src++;
*dst++ = *src++;
} while (dst[-2] != '\0' || dst[-1] != '\0');
found = true;
break;
}
line++;
}
fileClose(stream);
return found ? 0 : -1;
}
// art_list_index
int artListIndex(int objectType, const char* name)
{
if (objectType < 0 || objectType >= OBJ_TYPE_COUNT) return -1;
+1 -2
View File
@@ -86,7 +86,6 @@ namespace fallout {
#define SPLASH_HEIGHT (480)
#define SPLASH_COUNT (10)
static int gameLoadGlobalVars();
static int gameTakeScreenshot(int width, int height, unsigned char* buffer, unsigned char* palette);
static void gameFreeGlobalVars();
static bool tryLoadBaseCEModAtPath(const char* path, bool* found, bool* openFailed);
@@ -1016,7 +1015,7 @@ int gameSetGlobalVar(int var, int value)
// game_load_info
// 0x443CC8
static int gameLoadGlobalVars()
int gameLoadGlobalVars()
{
if (globalVarsRead("data\\vault13.gam", "GAME_GLOBAL_VARS:", &gGameGlobalVarsLength, &gGameGlobalVars) != 0) {
return -1;
+1
View File
@@ -47,6 +47,7 @@ int gameRequestState(int newGameState);
void gameUpdateState();
int showQuitConfirmationDialog();
int gameLoadGlobalVars();
int gameShowDeathDialog(const char* message);
void gameHandleSkilldexResult(int rc);
void* gameGetGlobalPointer(int var);
+22 -1
View File
@@ -313,7 +313,6 @@ Object* gGameMouseHexCursor;
// 0x596C74
static Object* gGameMousePointedObject;
static int _gmouse_get_click_to_scroll();
static void _gmouse_3d_enable_modes();
static int gameMouseSetBouncingCursorFid(int fid);
static int gameMouseRenderAccuracy(const char* string, int color);
@@ -455,6 +454,15 @@ int _gmouse_get_click_to_scroll()
return _gmouse_click_to_scroll;
}
// gmouse_set_click_to_scroll
void _gmouse_set_click_to_scroll(int value)
{
if (value != _gmouse_click_to_scroll) {
_gmouse_click_to_scroll = value;
_gmouse_clicked_on_edge = false;
}
}
// 0x44B54C
int _gmouse_is_scrolling()
{
@@ -2383,6 +2391,19 @@ int gameMouseHandleScrolling(int x, int y, int cursor)
flags |= SCROLLABLE_S;
}
// Click-to-scroll mode (mapper Alt-Z): only scroll while the left button is held at an
// edge. Track this in _gmouse_clicked_on_edge so callers can react (e.g. suppress the
// regular 3D cursor update while an edge-click scroll is active).
// TODO: reconcile with other site where _gmouse_clicked_on_edge is set to true
if (_gmouse_click_to_scroll) {
bool atEdge = flags != 0;
bool leftHeld = (mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_REPEAT) != 0;
_gmouse_clicked_on_edge = atEdge && leftHeld;
if (!_gmouse_clicked_on_edge) {
return -1;
}
}
int dx = 0;
int dy = 0;
+2
View File
@@ -82,6 +82,8 @@ void _gmouse_enable_scrolling();
void _gmouse_disable_scrolling();
bool gmouse_scrolling_is_enabled();
int _gmouse_is_scrolling();
int _gmouse_get_click_to_scroll();
void _gmouse_set_click_to_scroll(int value);
void gameMouseRefresh();
void _gmouse_handle_event(int mouseX, int mouseY, int mouseState);
int gameMouseSetCursor(int cursor);
+1 -1
View File
@@ -82,7 +82,7 @@ static char _aErrorF2[] = "ERROR! F2";
static IsoWindowRefreshProc* _map_scroll_refresh = isoWindowRefreshRectGame;
// 0x519544
static const int _map_data_elev_flags[ELEVATION_COUNT] = {
const int _map_data_elev_flags[ELEVATION_COUNT] = {
2,
4,
8,
+1
View File
@@ -77,6 +77,7 @@ extern int gElevation;
extern MessageList gMapMessageList;
extern MapHeader gMapHeader;
extern TileData* _square[ELEVATION_COUNT];
extern const int _map_data_elev_flags[ELEVATION_COUNT];
extern int gIsoWindow;
int isoInit();
+881 -70
View File
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -17,8 +17,8 @@ bool map_toggle_block_obj_viewing_on();
void map_load_dialog();
void map_save_dialog();
void map_save_as();
void map_info_dialog();
int map_save_as(const char* name);
void map_get_name(char* buf);
void create_spray_tool();
void copy_spray_tile();
// mode = 1 - enable, 0 - disable, -1 - toggle
@@ -32,7 +32,9 @@ int pickHex();
int pickToolbar(int topY);
void placeObject(int pid, int fid);
void placeTile(int pid, int fid);
void copyObject();
// Pass the current toolbar type to filter the region copy by type, or -1 to copy all object
// types in the picked region (mirrors the original mapper's `copy_object(arg1)` arg).
void copyObject(int filterType);
void copyTile();
void eraseObject();
+448 -211
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -18,6 +18,8 @@ extern unsigned char e_num[4][19 * 26];
int mapper_main(int argc, char** argv);
void print_toolbar_name(int object_type);
int mapper_inven_unwield(Object* obj, int right_hand);
void mapperShowTimedMsg(const char* msg);
bool mapperYesNoDialog(const char* msg);
} // namespace fallout
+27
View File
@@ -615,6 +615,13 @@ int proto_build_all_type(int type)
return 0;
}
int proto_build_all_type_binary(int type)
{
// TODO: rebuild binary proto list for given object type.
(void)type;
return 0;
}
int protoEdit(int protoId)
{
// TODO: implement proto editor dialog — load proto, show editor UI
@@ -622,6 +629,26 @@ int protoEdit(int protoId)
return -1;
}
void rebuild_spray_tools()
{
// TODO: rebuild spray tool (create/update pattern protos)
}
void rebuild_binary()
{
// TODO: rebuild binary proto files from text sources
}
void art_to_protos()
{
// TODO: create new proto entries for art files that have no proto yet
}
void swap_protos()
{
// TODO: swap two prototype slots
}
static unsigned char itemIconsBgColor()
{
return _colorTable[21];
+5
View File
@@ -16,6 +16,11 @@ void init_mapper_protos();
const char* proto_wall_light_str(int flags);
int proto_pick_ai_packet(int* value);
int proto_build_all_type(int type);
int proto_build_all_type_binary(int type);
void rebuild_spray_tools();
void rebuild_binary();
void art_to_protos();
void swap_protos();
int protoEdit(int protoId);
int protoChooseMultiPids(int pidType, protoChooseFidCallback fidFunc, protoChooseAddCallback addFunc);
// protoInstEdit moved to mp_instance.h
+19 -5
View File
@@ -330,12 +330,26 @@ int map_scr_add_spatial(int tile, int elevation)
return 0;
}
void map_set_script()
void map_set_script(int scriptIndex)
{
char info[256];
snprintf(info, sizeof(info), "Map SID: %d", gMapSid);
_win_msg(info, 80, 80, 0x10104);
// TODO: full script selection dialog
if (scriptIndex == -1) {
if (gMapSid != -1) {
scriptRemove(gMapSid);
gMapSid = -1;
}
gMapHeader.scriptIndex = -1;
} else {
int idx = scriptIndex - 1;
if (gMapSid == -1) {
scriptAdd(&gMapSid, SCRIPT_TYPE_SYSTEM);
}
Script* script;
if (scriptGetScript(gMapSid, &script) != -1) {
script->index = idx;
gMapHeader.scriptIndex = idx;
_scr_find_str_run_info(idx, nullptr, gMapSid);
}
}
}
void map_show_script()
+1 -1
View File
@@ -8,7 +8,7 @@ int map_scr_remove_all_spatials();
int map_scr_add_spatial(int tile, int elevation);
void map_scr_toggle_hexes();
void map_set_script();
void map_set_script(int scriptIndex);
void map_show_script();
void scr_debug_print_scripts();
int scr_choose(int scriptType);
+771 -2
View File
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -1,10 +1,15 @@
#ifndef FALLOUT_MAPPER_MP_TEXT_H_
#define FALLOUT_MAPPER_MP_TEXT_H_
#include "db.h"
namespace fallout {
int proto_build_all_texts();
void load_all_maps_text();
// mode==0 → rebuild from text; mode==1 → generate text versions from binary maps.
void load_all_maps_text(int mode = 0);
void map_save_text();
int obj_load_text(File* stream);
} // namespace fallout
+41 -7
View File
@@ -31,7 +31,7 @@
namespace fallout {
static int objectLoadAllInternal(File* stream);
static void _object_fix_weapon_ammo(Object* obj);
void _object_fix_weapon_ammo(Object* obj);
static int objectWrite(Object* obj, File* stream);
static int _obj_offset_table_init();
static void _obj_offset_table_exit();
@@ -51,7 +51,7 @@ static void objectDeallocate(Object** objectPtr);
static int objectListNodeCreate(ObjectListNode** nodePtr);
static void objectListNodeDestroy(ObjectListNode** nodePtr);
static int objectGetListNode(Object* obj, ObjectListNode** out_node, ObjectListNode** out_prev_node);
static void _obj_insert(ObjectListNode* ptr);
void _obj_insert(ObjectListNode* ptr);
static int _obj_remove(ObjectListNode* a1, ObjectListNode* a2);
static int _obj_connect_to_tile(ObjectListNode* node, int tile_index, int elev, Rect* rect);
static int _obj_adjust_light(Object* obj, int a2, Rect* rect);
@@ -242,7 +242,7 @@ static Rect gObjectsUpdateAreaPixelBounds;
// Contains objects that are bounded to tiles.
//
// 0x639DA0
static ObjectListNode* gObjectListHeadByTile[HEX_GRID_SIZE];
ObjectListNode* gObjectListHeadByTile[HEX_GRID_SIZE];
// 0x660EA0
static unsigned char _glassGrayTable[256];
@@ -598,7 +598,7 @@ static int objectLoadAllInternal(File* stream)
// Fixes ammo pid and number of charges.
//
// 0x48911C
static void _object_fix_weapon_ammo(Object* obj)
void _object_fix_weapon_ammo(Object* obj)
{
if (PID_TYPE(obj->pid) != OBJ_TYPE_ITEM) {
return;
@@ -2308,7 +2308,7 @@ Object* objectFindNextAtLocation()
return nullptr;
}
// 0x0x48B66C
// 0x48B66C
void objectGetRect(Object* obj, Rect* rect)
{
if (obj == nullptr) {
@@ -3852,7 +3852,7 @@ static int objectGetListNode(Object* object, ObjectListNode** nodePtr, ObjectLis
}
// 0x48D8E8
static void _obj_insert(ObjectListNode* objectListNode)
void _obj_insert(ObjectListNode* objectListNode)
{
ObjectListNode** objectListNodePtr;
@@ -4021,7 +4021,7 @@ static int _obj_adjust_light(Object* obj, int a2, Rect* rect)
obj->lightIntensity = 65536;
}
int(*v70)[36] = _light_offsets[obj->tile & 1];
int (*v70)[36] = _light_offsets[obj->tile & 1];
int v7 = (obj->lightIntensity - 655) / (obj->lightDistance + 1);
int v28[36];
v28[0] = obj->lightIntensity - v7;
@@ -5264,4 +5264,38 @@ int objectCreateWithFidPid(UniqueObject& obj, int fid, int pid)
return rc;
}
int objectCreateEmpty(Object** objectPtr, ObjectListNode** nodePtr)
{
if (objectPtr == nullptr || nodePtr == nullptr) {
return -1;
}
if (objectListNodeCreate(nodePtr) == -1) {
return -1;
}
if (objectAllocate(&((*nodePtr)->obj)) == -1) {
objectListNodeDestroy(nodePtr);
return -1;
}
*objectPtr = (*nodePtr)->obj;
return 0;
}
void objectDestroyEmpty(Object** objectPtr, ObjectListNode** nodePtr)
{
if (objectPtr == nullptr && nodePtr == nullptr) {
return;
}
if (objectPtr != nullptr && *objectPtr != nullptr) {
objectDeallocate(objectPtr);
}
if (nodePtr != nullptr && *nodePtr != nullptr) {
objectListNodeDestroy(nodePtr);
}
}
} // namespace fallout
+5
View File
@@ -20,6 +20,7 @@ extern Object* _moveBlockObj;
extern unsigned char _commonGrayTable[256];
extern Object* gEgg;
extern Object* gDude;
extern ObjectListNode* gObjectListHeadByTile[HEX_GRID_SIZE];
int objectsInit(unsigned char* buf, int width, int height, int pitch);
void objectsReset();
@@ -99,6 +100,10 @@ void _obj_preload_art_cache(int flags);
int _obj_save_dude(File* stream);
int _obj_load_dude(File* stream);
void _obj_fix_violence_settings(int* fid);
void _object_fix_weapon_ammo(Object* obj);
void _obj_insert(ObjectListNode* node);
int objectCreateEmpty(Object** objectPtr, ObjectListNode** nodePtr);
void objectDestroyEmpty(Object** objectPtr, ObjectListNode** nodePtr);
Object* objectTypedFindById(int id, int type);
bool isExitGridAt(int tile, int elevation);
+162
View File
@@ -247,6 +247,74 @@ int _proto_list_str(int pid, char* proto_path)
return 0;
}
// Finds a proto pid by type name and proto name string (e.g., "critter.vault").
// Returns 0 on success, -1 on failure.
int proto_find_str(int pid, const char* name, int* outPid)
{
if (pid == -1) {
if (outPid != nullptr) {
*outPid = -1;
}
return -1;
}
if (name == nullptr || outPid == nullptr) {
return -1;
}
// Parse type name from pid
int type = PID_TYPE(pid);
if (type < 0 || type >= OBJ_TYPE_COUNT) {
return -1;
}
const char* typeName = artGetObjectTypeName(type);
if (typeName == nullptr) {
return -1;
}
// Build path to <type>.lst
char path[COMPAT_MAX_PATH];
proto_make_path(path, pid);
strcat(path, typeName);
strcat(path, ".lst");
File* stream = fileOpen(path, "rt");
if (stream == nullptr) {
return -1;
}
// Search for the name in the lst file
char line[256];
int foundPid = -1;
while (fileReadString(line, sizeof(line), stream) != nullptr) {
// Skip CR/LF
char* pch = strpbrk(line, "\r\n");
if (pch != nullptr) {
*pch = '\0';
}
// Parse "index name" format
int index = 0;
char foundName[256];
if (sscanf(line, "%d %255s", &index, foundName) == 2) {
if (strcmp(foundName, name) == 0) {
foundPid = index << 24 | type;
break;
}
}
}
fileClose(stream);
if (foundPid == -1) {
return -1;
}
*outPid = foundPid;
return 0;
}
// 0x49E984
size_t proto_size(int type)
{
@@ -2194,4 +2262,98 @@ int _ResetPlayer()
return 0;
}
// Parses a FID from text format (numeric value) and validates it.
// Returns 0 on success, -1 on failure.
int proto_read_text_fid(const char* text, int* fidPtr, int pidType)
{
if (text == nullptr || fidPtr == nullptr) {
return -1;
}
int v6 = pidType;
if (pidType == 255) {
v6 = -1;
}
int firstNum;
if (sscanf(text, "%d", &firstNum) != 1) {
return -1;
}
// Skip past the first integer token
const char* p = text;
if (*p != ' ') {
while (*p != ' ' && *p != '\0') {
p++;
}
}
while (*p == ' ') {
p++;
}
int index = artListIndex(FID_TYPE(firstNum), p);
if (index == -1) {
int type = (v6 == -1) ? FID_TYPE(firstNum) : v6;
*fidPtr = buildFid(type, 0, 0, 0, 0);
} else {
int fid = buildFid(
(firstNum & 0xF000000u) >> 24,
index,
(firstNum & 0xFF0000u) >> 16,
static_cast<uint16_t>(firstNum & 0xF000) >> 12,
0);
if (!_art_fid_valid(fid)) {
int type = (v6 == -1) ? FID_TYPE(firstNum) : v6;
fid = buildFid(type, 0, 0, 0, 0);
debugPrint("\nError: proto_read_text_fid: art-check-valid failed: %s!\n", p);
}
*fidPtr = fid;
}
return 0;
}
// Parses a PID from text format and validates it.
// Text format: "number name" (e.g. "16777218 Vault13"). The name is looked up via proto_find_str
// and must match the number's type. No fallback to raw numeric PID if the name isn't found.
// Returns 0 on success, -1 on failure.
int proto_read_text_pid(const char* text, int* pidPtr)
{
if (text == nullptr || pidPtr == nullptr) {
return -1;
}
int firstNum;
if (sscanf(text, "%d", &firstNum) != 1) {
return -1;
}
// Skip past the first integer token
const char* p = text;
if (*p != ' ') {
while (*p != ' ' && *p != '\0') {
p++;
}
}
while (*p == ' ') {
p++;
}
int foundPid;
if (proto_find_str(firstNum, p, &foundPid) == -1) {
return -1;
}
Proto* proto;
if (protoGetProto(foundPid, &proto) == -1) {
return -1;
}
*pidPtr = foundPid;
return 0;
}
} // namespace fallout

Some files were not shown because too many files have changed in this diff Show More