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
|
#pragma once
|
||||||
|
|
||||||
|
#include "Game\GUI\Text.h"
|
||||||
|
|
||||||
#include "Game\combatAI.h"
|
#include "Game\combatAI.h"
|
||||||
#include "Game\inventory.h"
|
#include "Game\inventory.h"
|
||||||
#include "Game\items.h"
|
#include "Game\items.h"
|
||||||
|
|||||||
@@ -293,6 +293,7 @@
|
|||||||
<ClInclude Include="FalloutEngine\Functions.h" />
|
<ClInclude Include="FalloutEngine\Functions.h" />
|
||||||
<ClInclude Include="FalloutEngine\Functions_def.h" />
|
<ClInclude Include="FalloutEngine\Functions_def.h" />
|
||||||
<ClInclude Include="Game\combatAI.h" />
|
<ClInclude Include="Game\combatAI.h" />
|
||||||
|
<ClInclude Include="Game\GUI\Text.h" />
|
||||||
<ClInclude Include="Game\inventory.h" />
|
<ClInclude Include="Game\inventory.h" />
|
||||||
<ClInclude Include="Game\items.h" />
|
<ClInclude Include="Game\items.h" />
|
||||||
<ClInclude Include="Game\objects.h" />
|
<ClInclude Include="Game\objects.h" />
|
||||||
@@ -406,6 +407,7 @@
|
|||||||
<ClCompile Include="FalloutEngine\Variables.cpp" />
|
<ClCompile Include="FalloutEngine\Variables.cpp" />
|
||||||
<ClCompile Include="FalloutEngine\Functions.cpp" />
|
<ClCompile Include="FalloutEngine\Functions.cpp" />
|
||||||
<ClCompile Include="Game\combatAI.cpp" />
|
<ClCompile Include="Game\combatAI.cpp" />
|
||||||
|
<ClCompile Include="Game\GUI\Text.cpp" />
|
||||||
<ClCompile Include="Game\inventory.cpp" />
|
<ClCompile Include="Game\inventory.cpp" />
|
||||||
<ClCompile Include="Game\items.cpp" />
|
<ClCompile Include="Game\items.cpp" />
|
||||||
<ClCompile Include="Game\objects.cpp" />
|
<ClCompile Include="Game\objects.cpp" />
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
<Filter Include="Game">
|
<Filter Include="Game">
|
||||||
<UniqueIdentifier>{eb2be45d-bfdf-4a70-920d-4d616202a597}</UniqueIdentifier>
|
<UniqueIdentifier>{eb2be45d-bfdf-4a70-920d-4d616202a597}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Game\GUI">
|
||||||
|
<UniqueIdentifier>{e19ca1b6-f754-47a9-9a6d-5ce44592d8ab}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="main.h" />
|
<ClInclude Include="main.h" />
|
||||||
@@ -349,6 +352,12 @@
|
|||||||
<ClInclude Include="Modules\EngineTweaks.h">
|
<ClInclude Include="Modules\EngineTweaks.h">
|
||||||
<Filter>Modules</Filter>
|
<Filter>Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="FalloutEngine\VariableOffsets_HRP.h">
|
||||||
|
<Filter>FalloutEngine</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Game\GUI\Text.h">
|
||||||
|
<Filter>Game\GUI</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
@@ -648,6 +657,9 @@
|
|||||||
<ClCompile Include="Modules\EngineTweaks.cpp">
|
<ClCompile Include="Modules\EngineTweaks.cpp">
|
||||||
<Filter>Modules</Filter>
|
<Filter>Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Game\GUI\Text.cpp">
|
||||||
|
<Filter>Game\GUI</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc" />
|
<ResourceCompile Include="version.rc" />
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ DWORD HRPAddress(DWORD addr) {
|
|||||||
char falloutConfigName[65] = {0};
|
char falloutConfigName[65] = {0};
|
||||||
|
|
||||||
void InitReplacementHacks() {
|
void InitReplacementHacks() {
|
||||||
|
game::gui::Text::init();
|
||||||
|
|
||||||
game::CombatAI::init();
|
game::CombatAI::init();
|
||||||
game::Inventory::init();
|
game::Inventory::init();
|
||||||
game::Items::init();
|
game::Items::init();
|
||||||
|
|||||||
Reference in New Issue
Block a user