Added displaying terrain types on the world map

(from Rotators repo)
This commit is contained in:
NovaRain
2020-01-03 10:12:03 +08:00
parent fad2928fbf
commit 756356dbf2
8 changed files with 189 additions and 29 deletions
+5 -5
View File
@@ -123,11 +123,11 @@ ActionPointsBar=0
WorldTravelMarkers=0
;Uncomment these lines to change the appearance of the markers
;The color index in Fallout default palette (valid range: 1..255; default is 133)
;MarkerColor=133
;The lengh in pixels of the dots (valid range: 1..10)
;MarkerLength=1
;The spacing in pixels between the dots (valid range: 1..10)
;MarkerSpaces=2
;TravelMarkerColor=133
;The lengh of the dots in pixels (valid range: 1..10)
;TravelMarkerLength=1
;The spacing between the dots in pixels (valid range: 1..10)
;TravelMarkerSpaces=2
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Input]
+69 -8
View File
@@ -212,23 +212,77 @@ void GetObjectsTileRadius(std::vector<fo::GameObject*> &objs, long sourceTile, l
}
}
// Returns the name of the terrain type in the position of the player's marker on the world map
const char* wmGetCurrentTerrainName() {
long* terrainId = *(long**)FO_VAR_world_subtile;
if (terrainId == nullptr) {
__asm {
lea ebx, terrainId;
mov edx, dword ptr ds:[FO_VAR_world_ypos];
mov eax, dword ptr ds:[FO_VAR_world_xpos];
call fo::funcoffs::wmFindCurSubTileFromPos_;
}
}
return GetMessageStr(&fo::var::wmMsgFile, 1000 + *terrainId);
}
//---------------------------------------------------------
//print text to surface
void PrintText(char *DisplayText, BYTE ColourIndex, DWORD Xpos, DWORD Ypos, DWORD TxtWidth, DWORD ToWidth, BYTE *ToSurface) {
DWORD posOffset = Ypos * ToWidth + Xpos;
// copy the area from the interface buffer to the data array
void RectCopyToMemory(long fromX, long fromY, long width, long height, long fromWidth, BYTE* fromBuff, BYTE* toMem) {
fromBuff += fromY * fromWidth + fromX;
long i = 0;
for (long h = 0; h < height; h++) {
for (long w = 0; w < width; w++) {
toMem[i++] = fromBuff[w];
}
fromBuff += fromWidth;
}
}
// copy data from memory to the area of the interface buffer
void MemCopyToWinBuffer(long toX, long toY, long width, long height, long toWidth, BYTE* toBuff, BYTE* fromMem) {
toBuff += toY * toWidth + toX;
long i = 0;
for (long h = 0; h < height; h++) {
for (long w = 0; w < width; w++) {
toBuff[w] = fromMem[i++];
}
toBuff += toWidth;
}
}
//---------------------------------------------------------
// print text to surface
void PrintText(char* displayText, BYTE colourIndex, DWORD xPos, DWORD yPos, DWORD txtWidth, DWORD toWidth, BYTE* toSurface) {
DWORD posOffset = yPos * toWidth + xPos;
__asm {
xor eax, eax;
mov al, ColourIndex;
mov al, colourIndex;
mov edx, displayText;
push eax;
mov edx, DisplayText;
mov ebx, TxtWidth;
mov ecx, ToWidth;
mov eax, ToSurface;
mov ebx, txtWidth;
mov eax, toSurface;
mov ecx, toWidth;
add eax, posOffset;
call dword ptr ds:[FO_VAR_text_to_buf];
}
}
void PrintTextFM(char* displayText, BYTE colorIndex, DWORD xPos, DWORD yPos, DWORD txtWidth, DWORD toWidth, BYTE* toSurface) {
DWORD posOffset = yPos * toWidth + xPos;
__asm {
xor eax, eax;
mov al, colorIndex;
mov edx, displayText;
push eax;
mov ebx, txtWidth;
mov eax, toSurface;
mov ecx, toWidth;
add eax, posOffset;
call fo::funcoffs::FMtext_to_buf_;
}
}
//---------------------------------------------------------
//gets the height of the currently selected font
DWORD GetTextHeight() {
@@ -249,6 +303,13 @@ DWORD GetTextWidth(const char *TextMsg) {
}
}
DWORD GetTextWidthFM(const char *TextMsg) {
__asm {
mov eax, TextMsg;
call fo::funcoffs::FMtext_width_; //get text width
}
}
//---------------------------------------------------------
//get width of Char for current font
DWORD GetCharWidth(char CharVal) {
+9 -1
View File
@@ -80,12 +80,20 @@ long __fastcall GetTopWindowID(long xPos, long yPos);
void GetObjectsTileRadius(std::vector<fo::GameObject*> &objs, long sourceTile, long radius, long elev, long type);
const char* wmGetCurrentTerrainName();
void RectCopyToMemory(long fromX, long fromY, long width, long height, long fromWidth, BYTE* fromBuff, BYTE* toMem);
void MemCopyToWinBuffer(long toX, long toY, long width, long height, long toWidth, BYTE* toBuff, BYTE* fromMem);
// Print text to surface
void PrintText(char *displayText, BYTE colorIndex, DWORD x, DWORD y, DWORD textWidth, DWORD destWidth, BYTE *surface);
void PrintText(char* displayText, BYTE colorIndex, DWORD x, DWORD y, DWORD textWidth, DWORD destWidth, BYTE* surface);
void PrintTextFM(char* displayText, BYTE colorIndex, DWORD x, DWORD y, DWORD textWidth, DWORD destWidth, BYTE* surface);
// gets the height of the currently selected font
DWORD GetTextHeight();
// gets the length of a string using the currently selected font
DWORD GetTextWidth(const char *textMsg);
DWORD GetTextWidthFM(const char *textMsg);
// get width of Char for current font
DWORD GetCharWidth(char charVal);
// get maximum string length for current font - if all characters were maximum width
+2
View File
@@ -25,6 +25,7 @@ WRAP_WATCOM_FFUNC3(FrmFrameData*, frame_ptr, FrmHeaderData*, frm, long, frame, l
WRAP_WATCOM_FFUNC3(void, intface_update_items, long, animate, long, modeLeft,long, modeRight)
WRAP_WATCOM_FFUNC3(long, item_add_force, GameObject*, critter, GameObject*, item, long, count)
WRAP_WATCOM_FFUNC7(void, make_straight_path_func, GameObject*, objFrom, DWORD, tileFrom, DWORD, tileTo, void*, rotationPtr, DWORD*, result, long, flags, void*, func)
WRAP_WATCOM_FFUNC3(long, message_find, DWORD*, msgFile, long, msgNumber, DWORD*, outBuf)
WRAP_WATCOM_FFUNC4(long, mouse_click_in, long, x, long, y, long, x_end, long, y_end)
WRAP_WATCOM_FFUNC3(GameObject*, obj_blocking_at, GameObject*, object, long, tile, long, elevation)
WRAP_WATCOM_FFUNC4(long, obj_move_to_tile, GameObject*, object, long, tile, long, elevation, RECT*, rect)
@@ -172,6 +173,7 @@ WRAP_WATCOM_FUNC1(void, win_show, DWORD, winRef)
WRAP_WATCOM_FUNC1(void, win_hide, DWORD, winRef)
WRAP_WATCOM_FUNC1(BYTE*, win_get_buf, DWORD, winRef)
WRAP_WATCOM_FUNC1(void, win_draw, DWORD, winRef)
WRAP_WATCOM_FUNC2(void, win_draw_rect, DWORD, winRef, RECT*, rect)
WRAP_WATCOM_FUNC1(void, win_delete, DWORD, winRef)
WRAP_WATCOM_FUNC0(long, windowWidth)
WRAP_WATCOM_FUNC1(void, wmCarUseGas, long, gasAmount)
+3
View File
@@ -239,16 +239,19 @@
#define FO_VAR_wd_obj 0x59E98C
#define FO_VAR_window 0x6ADE58
#define FO_VAR_wmAreaInfoList 0x51DDF8
#define FO_VAR_wmBkWin 0x51DE14
#define FO_VAR_wmBkWinBuf 0x51DE24
#define FO_VAR_wmLastRndTime 0x51DEA0
#define FO_VAR_wmMaxMapNum 0x51DE10
#define FO_VAR_wmMaxTileNum 0x51DDF0
#define FO_VAR_wmMsgFile 0x672FB0
#define FO_VAR_wmNumHorizontalTiles 0x51DDF4
#define FO_VAR_wmViewportRightScrlLimit 0x672EFC
#define FO_VAR_wmViewportBottomtScrlLimit 0x672F00
#define FO_VAR_wmWorldOffsetX 0x51DE2C
#define FO_VAR_wmWorldOffsetY 0x51DE30
#define FO_VAR_wmYesNoStrs 0x51DD90
#define FO_VAR_world_subtile 0x672E14
#define FO_VAR_world_xpos 0x672E0C
#define FO_VAR_world_ypos 0x672E10
#define FO_VAR_WorldMapCurrArea 0x672E08
+2 -1
View File
@@ -79,7 +79,7 @@ VAR_(i_rhand, GameObject*)
VAR_(i_wid, DWORD)
VAR_(i_worn, GameObject*)
VAR_(idle_func, DWORD)
VAR_(In_WorldMap, DWORD)
VAR_(In_WorldMap, DWORD) // moving on WorldMap
VAR_(info_line, DWORD)
VAR_(interfaceWindow, DWORD)
VAR_(intfaceEnabled, DWORD)
@@ -209,6 +209,7 @@ VAR_(WhiteColor, BYTE)
VAR_(wmAreaInfoList, DWORD)
VAR_(wmLastRndTime, DWORD)
VAR_(wmMaxTileNum, DWORD)
VAR_(wmMsgFile, MessageList)
VAR_(wmNumHorizontalTiles, DWORD)
VAR_(wmViewportRightScrlLimit, DWORD)
VAR_(wmViewportBottomtScrlLimit, DWORD)
+91 -6
View File
@@ -16,10 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <array>
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "..\FalloutEngine\EngineUtils.h"
#include "Graphics.h"
#include "LoadGameHook.h"
//#include "Worldmap.h"
#include "Interface.h"
@@ -459,6 +463,8 @@ static void WorldmapViewportPatch() {
dlogr(" Done", DL_INIT);
}
////////////////////////////// FALLOUT 1 FEATURES //////////////////////////////
struct DotPosition {
long x;
long y;
@@ -468,7 +474,7 @@ static std::vector<DotPosition> dots;
static long optionLenDot = 1;
static long optionSpaceDot = 2;
static unsigned char colorDot = 133; // color index in palette: R = 252, G = 0, B = 0
static unsigned char colorDot = 0; // color index in palette: R = 252, G = 0, B = 0
static long spaceLen = 2;
static long dotLen = 1;
static long dot_xpos = 0;
@@ -529,8 +535,31 @@ static void __declspec(naked) DrawingDots() {
}
}
static std::array<unsigned char, 15 * 100> wmTmpBuffer;
static bool hoveringHotspot = false;
static bool backImageIsCopy = false;
static void PrintTerrainType(long x, long y) {
char* terrainText = (char*)fo::wmGetCurrentTerrainName();
long txtWidth = fo::GetTextWidthFM(terrainText);
if (txtWidth > 100) txtWidth = 100;
// offset position
y += 4;
x += 25 - (txtWidth / 2);
fo::PrintTextFM(terrainText, 228, x, y, txtWidth, wmapWinWidth, *(BYTE**)FO_VAR_wmBkWinBuf); // text shadow
fo::PrintTextFM(terrainText, 215, x - 1, y - 1, txtWidth, wmapWinWidth, *(BYTE**)FO_VAR_wmBkWinBuf);
}
static void PrintTerrainType() {
long y = fo::var::world_ypos - fo::var::wmWorldOffsetY;
long x = fo::var::world_xpos - fo::var::wmWorldOffsetX;
PrintTerrainType(x, y);
}
static void __declspec(naked) wmInterfaceRefresh_hook() {
if (fo::var::target_xpos != -1) {
if (colorDot && fo::var::target_xpos != -1) {
if (fo::var::In_WorldMap) {
DrawingDots();
} else if (!fo::var::target_xpos && !fo::var::target_ypos) {
@@ -540,9 +569,63 @@ static void __declspec(naked) wmInterfaceRefresh_hook() {
spaceLen = optionSpaceDot;
}
}
if (hoveringHotspot && !fo::var::In_WorldMap) {
PrintTerrainType();
hoveringHotspot = backImageIsCopy = false;
}
__asm jmp fo::funcoffs::wmDrawCursorStopped_;
}
static long __fastcall wmDetectHotspotHover(long wmMouseX, long wmMouseY) {
long deltaX = abs((long)fo::var::world_xpos - (wmMouseX - 20 + fo::var::wmWorldOffsetX));
long deltaY = abs((long)fo::var::world_ypos - (wmMouseY - 20 + fo::var::wmWorldOffsetY));
bool hovered = hoveringHotspot;
hoveringHotspot = deltaX < 6 && deltaY < 6;
if (hoveringHotspot != hovered) { // if value has changed
// upper left corner
long y = fo::var::world_ypos - fo::var::wmWorldOffsetY;
long x = fo::var::world_xpos - fo::var::wmWorldOffsetX;
long x_offset = x - 25;
if (!backImageIsCopy) {
backImageIsCopy = true;
// copy image to memory (size 100 x 15)
fo::RectCopyToMemory(x_offset, y, 100, 15, wmapWinWidth, *(BYTE**)FO_VAR_wmBkWinBuf, wmTmpBuffer.data());
PrintTerrainType(x, y);
} else {
// restore saved image
fo::MemCopyToWinBuffer(x_offset, y, 100, 15, wmapWinWidth, *(BYTE**)FO_VAR_wmBkWinBuf, wmTmpBuffer.data());
backImageIsCopy = false;
}
// redraw worldmap interface rectangle
RECT rect;
rect.top = y;
rect.left = x_offset;
rect.right = x + 100;
rect.bottom = y + 15;
fo::func::win_draw_rect(*(long*)FO_VAR_wmBkWin, &rect);
}
return fo::var::wmWorldOffsetY; // overwritten code
}
static void __declspec(naked) wmWorldMap_hack() {
__asm {
cmp ds:[FO_VAR_In_WorldMap], 1; // player is moving
jne checkHover;
mov eax, dword ptr ds:[FO_VAR_wmWorldOffsetY];
retn;
checkHover:
push ecx;
mov ecx, [esp + 0x38 - 0x30 + 8]; // x
mov edx, [esp + 0x38 - 0x34 + 8]; // y
call wmDetectHotspotHover;
pop ecx;
retn;
}
}
////////////////////////////////////////////////////////////////////////////////
static void __declspec(naked) wmInterfaceRefreshCarFuel_hack_empty() {
__asm {
mov byte ptr [eax - 1], 13;
@@ -606,21 +689,23 @@ static void WorldMapInterfacePatch() {
}
if (GetConfigInt("Interface", "WorldTravelMarkers", 0)) {
optionLenDot = GetConfigInt("Interface", "MarkerLength", optionLenDot);
optionSpaceDot = GetConfigInt("Interface", "MarkerSpaces", optionSpaceDot);
int color = GetConfigInt("Interface", "MarkerColor", colorDot);
optionLenDot = GetConfigInt("Interface", "TravelMarkerLength", optionLenDot);
optionSpaceDot = GetConfigInt("Interface", "TravelMarkerSpaces", optionSpaceDot);
int color = GetConfigInt("Interface", "TravelMarkerColor", 133);
if (color > 255) color = 255; else if (color < 1) color = 1;
colorDot = color;
if (optionLenDot > 10) optionLenDot = 10; else if (optionLenDot < 1) optionLenDot = 1;
if (optionSpaceDot > 10) optionSpaceDot = 10; else if (optionSpaceDot < 1) optionSpaceDot = 1;
HookCall(0x4C3C7E, wmInterfaceRefresh_hook); // when calling wmDrawCursorStopped_
dots.reserve(512);
LoadGameHook::OnGameReset() += []() {
dots.clear();
};
}
// Fallout 1 features, travel markers and displaying terrain type
HookCall(0x4C3C7E, wmInterfaceRefresh_hook); // when calling wmDrawCursorStopped_
MakeCall(0x4BFE84, wmWorldMap_hack);
// Car fuel gauge graphics patch
MakeCall(0x4C528A, wmInterfaceRefreshCarFuel_hack_empty);
+8 -8
View File
@@ -58,6 +58,10 @@ static float scriptMapMulti = 1.0;
static bool addYear = false; // used as additional years indicator
static DWORD addedYears = 0;
static void __stdcall WorldmapLoopHook() {
onWorldmapLoop.invoke();
}
static __declspec(naked) void TimeDateFix() {
__asm {
test edi, edi; // year buf
@@ -120,10 +124,6 @@ end:
}
}
static void __stdcall WorldmapLoopHook() {
onWorldmapLoop.invoke();
}
static void __declspec(naked) WorldMapFpsPatch() {
__asm {
push dword ptr ds:[FO_VAR_last_buttons];
@@ -177,9 +177,9 @@ subLoop:
// Only used if the world map speed patch is disabled, so that world map scripts are still run
static void __declspec(naked) wmWorldMap_hook() {
__asm {
pushadc;
//pushadc;
call WorldmapLoopHook;
popadc;
//popadc;
jmp fo::funcoffs::get_input_;
}
}
@@ -223,7 +223,7 @@ static void __declspec(naked) wmTownMapFunc_hack() {
mov [esi], edx
retn;
end:
add esp, 4; // destroy the return address
add esp, 4; // destroy the return address
mov eax, 0x4C4976;
jmp eax;
}
@@ -315,8 +315,8 @@ end:
static void RestRestore() {
if (!restMode) return;
restMode = false;
SafeWrite8(0x49952C, 0x85);
SafeWrite8(0x497557, 0x85);
SafeWrite8(0x42E587, 0xC7);