mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added support for the newline character '\n' in pro_*.msg files (#401)
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#include "..\..\main.h"
|
||||
#include "..\..\FalloutEngine\Fallout2.h"
|
||||
|
||||
#include "Text.h"
|
||||
|
||||
namespace game
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
namespace sf = sfall;
|
||||
|
||||
// Returns the position of the newline character, or the position of the character within the specified width (implementation from HRP)
|
||||
static long GetPositionWidth(const char* text, long width) {
|
||||
long gapWidth;
|
||||
__asm {
|
||||
call dword ptr ds:[FO_VAR_text_spacing];
|
||||
mov gapWidth, eax;
|
||||
}
|
||||
|
||||
long wordCharCount = 0;
|
||||
long position = 0;
|
||||
long w = 0;
|
||||
|
||||
char c = text[position];
|
||||
while (c) {
|
||||
if (c == '\\' && text[position + 1] == 'n') return position;
|
||||
|
||||
if (c != ' ') wordCharCount++; else wordCharCount = 0;
|
||||
|
||||
w += gapWidth + fo::util::GetCharWidth(c);
|
||||
if (w > width) {
|
||||
// set the position to the beginning of the current word
|
||||
if (wordCharCount > 1 && ((wordCharCount - 1) != position)) {
|
||||
position -= wordCharCount; // position at the space char
|
||||
}
|
||||
break;
|
||||
}
|
||||
c = text[++position];
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
// Replaces the implementation of display_print_ function from HRP with support for the newline control character '\n'
|
||||
// Works with vanilla and HRP 4.1.8
|
||||
static void __fastcall DisplayPrintLineBreak(const char* message) {
|
||||
if (*message == 0 || !fo::var::GetInt(FO_VAR_disp_init)) return;
|
||||
const char* text = message;
|
||||
|
||||
const long max_lines = 100; // aka FO_VAR_max
|
||||
long max_disp_chars = 256; // HRP value (vanilla 80)
|
||||
char* display_string_buf_addr;
|
||||
|
||||
long width = (sf::hrpIsEnabled) ? sf::GetIntHRPValue(HRP_VAR_disp_width) : 0;
|
||||
if (width == 0) {
|
||||
width = 167; // vanilla size
|
||||
max_disp_chars = 80;
|
||||
display_string_buf_addr = (char*)FO_VAR_display_string_buf; // array size 100x80
|
||||
} else {
|
||||
display_string_buf_addr = (char*)sf::HRPAddress(HRP_VAR_display_string_buf); // array size 100x256, allocated by HRP
|
||||
}
|
||||
|
||||
if (!(fo::var::combat_state & 1)) {
|
||||
long time = fo::var::GetInt(FO_VAR_bk_process_time);
|
||||
if ((time - fo::var::GetInt(FO_VAR_lastTime)) >= 500) {
|
||||
*fo::var::SetInt(FO_VAR_lastTime) = time;
|
||||
fo::func::gsound_play_sfx_file((const char*)0x50163C); // "monitor"
|
||||
}
|
||||
}
|
||||
|
||||
long font = fo::var::curr_font_num;
|
||||
fo::func::text_font(101);
|
||||
|
||||
unsigned char bulletChar = 149;
|
||||
long wChar = fo::util::GetCharWidth(bulletChar);
|
||||
width -= (wChar + fo::var::GetInt(FO_VAR_max_disp));
|
||||
|
||||
do {
|
||||
char* display_string_buf = &display_string_buf_addr[max_disp_chars * fo::var::GetInt(FO_VAR_disp_start)];
|
||||
|
||||
long pos = GetPositionWidth(text, width);
|
||||
|
||||
if (bulletChar) {
|
||||
*display_string_buf = bulletChar;
|
||||
display_string_buf++;
|
||||
bulletChar = 0;
|
||||
width += wChar;
|
||||
}
|
||||
|
||||
std::strncpy(display_string_buf, text, pos);
|
||||
display_string_buf[pos] = 0;
|
||||
|
||||
if (text[pos] == ' ') {
|
||||
pos++;
|
||||
} else if (text[pos] == '\\' && text[pos + 1] == 'n') {
|
||||
pos += 2; // position after the 'n' character
|
||||
}
|
||||
text += pos;
|
||||
|
||||
*fo::var::SetInt(FO_VAR_disp_start) = (fo::var::GetInt(FO_VAR_disp_start) + 1) % max_lines;
|
||||
} while (*text);
|
||||
|
||||
*fo::var::SetInt(FO_VAR_disp_curr) = fo::var::GetInt(FO_VAR_disp_start);
|
||||
|
||||
fo::func::text_font(font);
|
||||
__asm call fo::funcoffs::display_redraw_;
|
||||
}
|
||||
|
||||
static void __declspec(naked) sf_display_print() {
|
||||
__asm {
|
||||
push ecx;
|
||||
mov ecx, eax; // message
|
||||
call DisplayPrintLineBreak;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __stdcall SplitPrintMessage(char* message, void* printFunc) {
|
||||
char* text = message;
|
||||
while (*text) {
|
||||
if (text[0] == '\\' && text[1] == 'n') {
|
||||
*text = 0; // set null terminator
|
||||
|
||||
__asm mov eax, message;
|
||||
__asm call printFunc;
|
||||
|
||||
*text = '\\';
|
||||
text += 2; // position after the 'n' character
|
||||
message = text;
|
||||
} else {
|
||||
text++;
|
||||
}
|
||||
}
|
||||
// print the last line or the all text if there was no line break
|
||||
if (message != text) {
|
||||
__asm mov eax, message;
|
||||
__asm call printFunc;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) sf_display_print_alt() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push fo::funcoffs::display_print_;
|
||||
push eax; // message
|
||||
call SplitPrintMessage;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) sf_inven_display_msg() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push fo::funcoffs::inven_display_msg_;
|
||||
push eax; // message
|
||||
call SplitPrintMessage;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::init() {
|
||||
// Support for the newline control character '\n' in the object description in pro_*.msg files
|
||||
void* printFunc = sf_display_print; // for vanilla and HRP 4.1.8
|
||||
if (sf::hrpIsEnabled && !sf::hrpVersionValid) {
|
||||
printFunc = sf_display_print_alt;
|
||||
}
|
||||
sf::SafeWriteBatch<DWORD>((DWORD)printFunc, {0x46ED87, 0x49AD7A}); // setup_inventory_, obj_examine_
|
||||
sf::SafeWrite32(0x472F9A, (DWORD)&sf_inven_display_msg); // inven_obj_examine_func_
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace game
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class Text {
|
||||
public:
|
||||
static void init();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Game\GUI\Text.h"
|
||||
|
||||
#include "Game\combatAI.h"
|
||||
#include "Game\inventory.h"
|
||||
#include "Game\items.h"
|
||||
|
||||
@@ -293,6 +293,7 @@
|
||||
<ClInclude Include="FalloutEngine\Functions.h" />
|
||||
<ClInclude Include="FalloutEngine\Functions_def.h" />
|
||||
<ClInclude Include="Game\combatAI.h" />
|
||||
<ClInclude Include="Game\GUI\Text.h" />
|
||||
<ClInclude Include="Game\inventory.h" />
|
||||
<ClInclude Include="Game\items.h" />
|
||||
<ClInclude Include="Game\objects.h" />
|
||||
@@ -406,6 +407,7 @@
|
||||
<ClCompile Include="FalloutEngine\Variables.cpp" />
|
||||
<ClCompile Include="FalloutEngine\Functions.cpp" />
|
||||
<ClCompile Include="Game\combatAI.cpp" />
|
||||
<ClCompile Include="Game\GUI\Text.cpp" />
|
||||
<ClCompile Include="Game\inventory.cpp" />
|
||||
<ClCompile Include="Game\items.cpp" />
|
||||
<ClCompile Include="Game\objects.cpp" />
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
<Filter Include="Game">
|
||||
<UniqueIdentifier>{eb2be45d-bfdf-4a70-920d-4d616202a597}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Game\GUI">
|
||||
<UniqueIdentifier>{e19ca1b6-f754-47a9-9a6d-5ce44592d8ab}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="main.h" />
|
||||
@@ -349,6 +352,12 @@
|
||||
<ClInclude Include="Modules\EngineTweaks.h">
|
||||
<Filter>Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FalloutEngine\VariableOffsets_HRP.h">
|
||||
<Filter>FalloutEngine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Game\GUI\Text.h">
|
||||
<Filter>Game\GUI</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
@@ -648,6 +657,9 @@
|
||||
<ClCompile Include="Modules\EngineTweaks.cpp">
|
||||
<Filter>Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Game\GUI\Text.cpp">
|
||||
<Filter>Game\GUI</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
||||
@@ -103,6 +103,8 @@ DWORD HRPAddress(DWORD addr) {
|
||||
char falloutConfigName[65] = {0};
|
||||
|
||||
void InitReplacementHacks() {
|
||||
game::gui::Text::init();
|
||||
|
||||
game::CombatAI::init();
|
||||
game::Inventory::init();
|
||||
game::Items::init();
|
||||
|
||||
Reference in New Issue
Block a user