Changed the implementation of BarBoxes.cpp (from Mr.Stalin)

Added "add_iface_tag" script function.
This commit is contained in:
NovaRain
2019-02-19 21:33:42 +08:00
parent 8613a4fb8b
commit 0980967cee
8 changed files with 162 additions and 108 deletions
+2 -1
View File
@@ -237,7 +237,8 @@
#define party_member_list_critters party_member_list(0) #define party_member_list_critters party_member_list(0)
#define party_member_list_all party_member_list(1) #define party_member_list_all party_member_list(1)
// sfall_funcX macros
#define add_iface_tag sfall_func0("add_iface_tag")
#define art_cache_clear sfall_func0("art_cache_clear") #define art_cache_clear sfall_func0("art_cache_clear")
#define attack_is_aimed sfall_func0("attack_is_aimed") #define attack_is_aimed sfall_func0("attack_is_aimed")
#define car_gas_amount sfall_func0("car_gas_amount") #define car_gas_amount sfall_func0("car_gas_amount")
+6 -2
View File
@@ -498,9 +498,13 @@ Some utility/math functions are available:
> void sfall_func3("set_iface_tag_text", int tag, string text, int color) > void sfall_func3("set_iface_tag_text", int tag, string text, int color)
- sets the text messages and colors for custom notification boxes to the interface without the need to add messages to intrface.msg and set up the font colors in ddraw.ini - sets the text messages and colors for custom notification boxes to the interface without the need to add messages to intrface.msg and set up the font colors in ddraw.ini
- tag value is the same as used in show_iface_tag, hide_iface_tag, and is_iface_tag_active. The valid range is from 5 to (4 + the value of BoxBarCount in ddraw.ini) - tag value is the same as used in show_iface_tag, hide_iface_tag, and is_iface_tag_active. The valid range is from 5 to (4 + the value of BoxBarCount in ddraw.ini) or the number of the last custom box added using the add_ifaca_tag function
- The text is limited to 19 characters - The text is limited to 19 characters
- available colors: 0 - green, 1 - red, 2 - white, 3 - yellow, 4 - dark yellow, 5 - blue, 6 - purple - available colors: 0 - green, 1 - red, 2 - white, 3 - yellow, 4 - dark yellow, 5 - blue, 6 - purple, 7 - dull pink
> int sfall_func0("add_iface_tag")
- adds one custom box to the current boxes, and returns the number of the added tag (-1 if the tags limit is exceeded)
- The maximum number of boxes is limited to 126 tags
> void sfall_func1("inventory_redraw", int invSide) > void sfall_func1("inventory_redraw", int invSide)
- redraws inventory list in the inventory/use inventory item on/loot/barter screens - redraws inventory list in the inventory/use inventory item on/loot/barter screens
+1
View File
@@ -222,6 +222,7 @@
// colors // colors
#define FO_VAR_BlueColor 0x6A38EF #define FO_VAR_BlueColor 0x6A38EF
#define FO_VAR_DarkGreenColor 0x6A3A90 #define FO_VAR_DarkGreenColor 0x6A3A90
#define FO_VAR_DullPinkColor 0x6AB718
#define FO_VAR_GoodColor 0x6AB4EF #define FO_VAR_GoodColor 0x6AB4EF
#define FO_VAR_GreenColor 0x6A3CB0 #define FO_VAR_GreenColor 0x6A3CB0
#define FO_VAR_PeanutButter 0x6A82F3 #define FO_VAR_PeanutButter 0x6A82F3
+140 -101
View File
@@ -25,28 +25,26 @@
namespace sfall namespace sfall
{ {
int BarBoxes::boxCount; // total count box int BarBoxes::boxCount; // current box count
static int actualBoxCount; static int totalBoxCount, actualBoxCount; // total boxes and w/o vanilla
static int sizeBox; static int initCount = 5; // init config counter (5 - vanilla box)
static int sizeBox, setBoxIndex = 5;
#define sSize (12) #define sSize (12)
struct sBox { static struct sBox {
DWORD msg; DWORD msg;
DWORD colour; DWORD colour;
void* mem; void* mem;
}; } *boxes;
#define tSize (25) #define tSize (24)
struct tBox { static struct tBox {
bool hasText; bool hasText;
DWORD color; char color;
char text[tSize - 5]; char cfgColor;
}; bool isActive;
char text[tSize - 4];
static sBox* boxes; } *boxText;
static tBox* boxText;
static bool* boxesEnabled;
static DWORD* colorBakup;
static bool setCustomBoxText; static bool setCustomBoxText;
@@ -58,13 +56,14 @@ static const DWORD DisplayBoxesRet1 = 0x4615A8;
static const DWORD DisplayBoxesRet2 = 0x4615BE; static const DWORD DisplayBoxesRet2 = 0x4615BE;
static void __declspec(naked) DisplayBoxesHack() { static void __declspec(naked) DisplayBoxesHack() {
__asm { __asm {
mov edx, [boxesEnabled]; mov edx, [boxText];
mov ebx, 0; xor ebx, ebx;
start: start:
mov al, byte ptr [edx][ebx]; imul eax, ebx, tSize;
mov al, byte ptr [edx][eax + 3]; // .isActive
test al, al; test al, al;
jz next; jz next;
lea eax, [ebx + 5]; lea eax, [ebx + 5]; // index box
call fo::funcoffs::add_bar_box_; call fo::funcoffs::add_bar_box_;
add esi, eax; add esi, eax;
next: next:
@@ -83,27 +82,27 @@ fail:
static void __declspec(naked) BarBoxesTextHack() { static void __declspec(naked) BarBoxesTextHack() {
__asm { __asm {
push ecx; // ecx = BoxIndex push ecx; // ecx = BoxIndex
sub ecx, 5; sub ecx, 5; // subtract vanilla boxes
imul ecx, tSize; imul ecx, tSize;
mov esi, [boxText]; // boxText addr mov esi, [boxText]; // boxText addr
cmp byte ptr [esi][ecx], 1; // .hasText cmp byte ptr [esi][ecx], 1; // .hasText
jnz end; je customText;
add esp, 4;
jmp fo::funcoffs::getmsg_;
customText:
// get color // get color
mov ebx, dword ptr [esi][ecx + 1]; // .color movzx ebx, byte ptr [esi][ecx + 1]; // .color
// set text // set text
lea eax, [esi + ecx + 5]; // .text lea eax, [esi + ecx + 4]; // .text
// set color // set color
pop ecx; pop ecx; // restore BoxIndex
imul ecx, sSize; imul ecx, sSize;
mov esi, [boxes]; // boxes addr mov esi, [boxes]; // boxes addr
cmp dword ptr [esi][ecx + 4], 2; // .colour cmp dword ptr [esi][ecx + 4], 2; // .colour
jb skip; jb skip;
mov [esp + 0x440 - 0x20], ebx; // Color mov [esp + 0x440 - 0x20], ebx; // set to Color
skip: skip:
retn; retn;
end:
add esp, 4;
jmp fo::funcoffs::getmsg_;
} }
} }
@@ -111,7 +110,7 @@ static const DWORD SetIndexBoxRet = 0x4612E8;
static void __declspec(naked) BarBoxesIndexHack() { static void __declspec(naked) BarBoxesIndexHack() {
__asm { __asm {
mov eax, ds:[0x4612E2]; // fontnum mov eax, ds:[0x4612E2]; // fontnum
mov ecx, 5; // start index mov ecx, setBoxIndex; // start index
mov edx, ecx; mov edx, ecx;
jmp SetIndexBoxRet; jmp SetIndexBoxRet;
} }
@@ -129,9 +128,10 @@ exitLoop:
} }
} }
static void ReconstructBarBoxes() { static void ReconstructBarBoxes(int count) {
SafeWrite8(0x46140B, count);
__asm { __asm {
call fo::funcoffs::refresh_box_bar_win_; //call fo::funcoffs::refresh_box_bar_win_;
call fo::funcoffs::reset_box_bar_win_; call fo::funcoffs::reset_box_bar_win_;
call fo::funcoffs::construct_box_bar_win_; call fo::funcoffs::construct_box_bar_win_;
} }
@@ -139,28 +139,28 @@ static void ReconstructBarBoxes() {
static void ResetBoxes() { static void ResetBoxes() {
for (int i = 0; i < actualBoxCount; i++) { for (int i = 0; i < actualBoxCount; i++) {
boxesEnabled[i] = false; boxText[i].isActive = false;
boxes[i + 5].colour = colorBakup[i]; boxText[i].hasText = false;
boxes[i + 5].colour = boxText[i].cfgColor;
} }
if (setBoxIndex == 5) return;
if (!setCustomBoxText) return; // Restore boxes
setBoxIndex = 5; // set start
//Restore boxes //SafeWrite32(0x461343, 0x00023D05); // call getmsg_
SafeWrite32(0x461343, 0x00023D05); // call getmsg_ ReconstructBarBoxes(totalBoxCount);
ReconstructBarBoxes(); //SafeWrite8(0x461243, 0x31);
SafeWrite8(0x461243, 0x31); //SafeWrite32(0x461244, 0x249489D2);
SafeWrite32(0x461244, 0x249489D2);
setCustomBoxText = false;
} }
void BarBoxes::SetText(int box, const char* text, DWORD color) { void BarBoxes::SetText(int box, const char* text, DWORD color) {
setBoxIndex = box;
boxes[box].colour = color; boxes[box].colour = color;
box -= 5; box -= 5;
boxText[box].hasText = true; boxText[box].hasText = true;
strncpy_s(boxText[box].text, text, _TRUNCATE); strncpy_s(boxText[box].text, text, _TRUNCATE);
DWORD clr; char clr;
switch (color) { switch (color) {
case 2: case 2:
clr = fo::var::WhiteColor; clr = fo::var::WhiteColor;
@@ -177,101 +177,140 @@ void BarBoxes::SetText(int box, const char* text, DWORD color) {
case 6: case 6:
clr = fo::var::GoodColor; clr = fo::var::GoodColor;
break; break;
case 7:
clr = *(BYTE*)FO_VAR_DullPinkColor;
break;
default: default:
clr = fo::var::GreenColor; clr = fo::var::GreenColor;
} }
boxText[box].color = clr; boxText[box].color = clr;
bool* enabled = new bool[actualBoxCount];
for (int i = 0; i < actualBoxCount; i++) {
enabled[i] = boxesEnabled[i];
boxesEnabled[i] = false;
}
if (!setCustomBoxText) { if (!setCustomBoxText) {
setCustomBoxText = true;
MakeCall(0x461342, BarBoxesTextHack); // construct_box_bar_win_ MakeCall(0x461342, BarBoxesTextHack); // construct_box_bar_win_
MakeJump(0x461243, BarBoxesIndexHack); // construct_box_bar_win_ MakeJump(0x461243, BarBoxesIndexHack); // construct_box_bar_win_
setCustomBoxText = true;
} }
ReconstructBarBoxes(setBoxIndex + 1);
ReconstructBarBoxes();
for (int i = 0; i < actualBoxCount; i++) {
boxesEnabled[i] = enabled[i];
}
delete[] enabled;
__asm call fo::funcoffs::refresh_box_bar_win_;
} }
void BarBoxes::init() { static void SetEngine(int count) {
boxCount = 5 + GetConfigInt("Misc", "BoxBarCount", 5);
if (boxCount < 10) boxCount = 10;
if (boxCount > 100) boxCount = 100;
actualBoxCount = boxCount - 5;
sizeBox = sSize * boxCount;
boxes = new sBox[boxCount]();
boxText = new tBox[actualBoxCount]();
boxesEnabled = new bool[actualBoxCount]();
colorBakup = new DWORD[actualBoxCount]();
memcpy(boxes, (void*)0x518FE8, sSize * 5);
for (int i = 5; i < boxCount; i++) {
boxes[i].msg = 100 + i;
}
auto boxBarColors = GetConfigString("Misc", "BoxBarColours", "", actualBoxCount + 1);
int size = boxBarColors.size();
for (int i = 0; i < size; i++) {
if (boxBarColors[i] == '1') {
boxes[i + 5].colour = 1;
colorBakup[i] = 1;
}
}
SafeWriteBatch<DWORD>((DWORD)boxes + 8, bboxMemAddr); //.mem SafeWriteBatch<DWORD>((DWORD)boxes + 8, bboxMemAddr); //.mem
SafeWrite32(0x4612FE, (DWORD)boxes + 4); //.colour SafeWrite32(0x4612FE, (DWORD)boxes + 4); //.colour
SafeWrite32(0x46133C, (DWORD)boxes); //.msg SafeWrite32(0x46133C, (DWORD)boxes); //.msg
SafeWrite8(0x46127C, boxCount); sizeBox = sizeof(sBox) * count;
SafeWrite8(0x46140B, boxCount);
if (boxCount > 10) { static bool onlyOnce = false;
MakeJump(0x461493, BarBoxesSizeHack); if (onlyOnce) return;
if (count > 10) {
MakeJump(0x461493, BarBoxesSizeHack); // deconstruct_box_bar_win_
onlyOnce = true;
} else { } else {
SafeWrite8(0x461495, sizeBox); SafeWrite8(0x461495, sizeBox);
} }
}
void BarBoxes::init() {
initCount += GetConfigInt("Misc", "BoxBarCount", 5);
if (initCount < 5) initCount = 5; // exclude the influence of negative values from the config
if (initCount > 100) initCount = 100;
actualBoxCount = initCount - 5;
boxes = new sBox[initCount]();
boxText = new tBox[actualBoxCount]();
memcpy(boxes, (void*)0x518FE8, sSize * 5);
for (int i = 5; i < initCount; i++) {
boxes[i].msg = 100 + i;
}
auto boxBarColors = GetConfigString("Misc", "BoxBarColours", "", actualBoxCount + 1);
for (size_t i = 0; i < boxBarColors.size(); i++) {
if (boxBarColors[i] == '1') {
boxes[i + 5].colour = 1; // red color
boxText[i].cfgColor = 1;
}
}
SetEngine(initCount);
SafeWrite8(0x46127C, initCount); // for only init
SafeWrite8(0x46140B, initCount);
MakeJump(0x4615A3, DisplayBoxesHack); MakeJump(0x4615A3, DisplayBoxesHack);
LoadGameHook::OnGameReset() += ResetBoxes; totalBoxCount = boxCount = initCount;
LoadGameHook::OnGameReset() += []() {
ResetBoxes();
if (initCount != totalBoxCount) {
boxCount = initCount;
actualBoxCount = initCount - 5;
}
};
}
long BarBoxes::AddExtraBox() {
if (boxCount < totalBoxCount) {
actualBoxCount++;
boxCount++;
return MaxBox(); // just return the number of the previously added box
}
if (totalBoxCount > 126) return -1; // limit is exceeded
void* data;
__asm {
mov eax, 2730;
call fo::funcoffs::mem_malloc_;
mov data, eax;
}
if (data == nullptr) return -1; // error on memory allocation
memcpy(data, boxes[1].mem, 2730); // copy image box to a new allocated memory
sBox* boxes_new = new sBox[totalBoxCount + 1];
memcpy(boxes_new, boxes, sizeof(sBox) * totalBoxCount);
delete[] boxes;
boxes = boxes_new;
boxes[totalBoxCount].mem = data;
boxes[totalBoxCount].msg = 100; // set default text for added box
boxes[totalBoxCount].colour = 0;
boxCount = ++totalBoxCount;
tBox* boxText_new = new tBox[actualBoxCount + 1];
memcpy(boxText_new, boxText, sizeof(tBox) * actualBoxCount);
delete[] boxText;
boxText = boxText_new;
memset((void*)&boxText[actualBoxCount], 0, sizeof(tBox));
actualBoxCount++;
SetEngine(totalBoxCount);
return MaxBox(); // current number of added box
} }
bool BarBoxes::GetBox(int i) { bool BarBoxes::GetBox(int i) {
if (i < 5 || i > BarBoxes::MaxBox()) return false; if (i < 5 || i > BarBoxes::MaxBox()) return false;
return boxesEnabled[i - 5]; return boxText[i - 5].isActive;
} }
void BarBoxes::AddBox(int i) { void BarBoxes::AddBox(int i) {
if (i < 5 || i > BarBoxes::MaxBox()) return; if (i < 5 || i > BarBoxes::MaxBox()) return;
boxesEnabled[i - 5] = 1; boxText[i - 5].isActive = true;
_asm call fo::funcoffs::refresh_box_bar_win_; __asm call fo::funcoffs::refresh_box_bar_win_;
} }
void BarBoxes::RemoveBox(int i) { void BarBoxes::RemoveBox(int i) {
if (i < 5 || i > BarBoxes::MaxBox()) return; if (i < 5 || i > BarBoxes::MaxBox()) return;
boxesEnabled[i - 5] = 0; boxText[i - 5].isActive = false;
_asm call fo::funcoffs::refresh_box_bar_win_; __asm call fo::funcoffs::refresh_box_bar_win_;
} }
void BarBoxes::exit() { void BarBoxes::exit() {
delete[] boxes; delete[] boxes;
delete[] boxText; delete[] boxText;
delete[] boxesEnabled;
delete[] colorBakup;
} }
} }
+2 -2
View File
@@ -12,13 +12,13 @@ public:
void init(); void init();
void exit() override; void exit() override;
static int MaxBox() { return boxCount - 1; } static int MaxBox() { return boxCount - 1; }
static void SetText(int box, const char* text, DWORD color); static void SetText(int box, const char* text, DWORD color);
static bool GetBox(int); static bool GetBox(int);
static void AddBox(int); static void AddBox(int);
static void RemoveBox(int); static void RemoveBox(int);
static long AddExtraBox();
}; };
} }
@@ -303,6 +303,12 @@ end:
} }
} }
void sf_add_iface_tag(OpcodeContext &ctx) {
int result = BarBoxes::AddExtraBox();
if (result == -1) ctx.printOpcodeError("add_iface_tag() - cannot add new tag as the maximum limit of 126 tags has been reached.");
ctx.setReturn(result);
}
void sf_show_iface_tag(OpcodeContext &ctx) { void sf_show_iface_tag(OpcodeContext &ctx) {
int tag = ctx.arg(0).asInt(); int tag = ctx.arg(0).asInt();
if (tag == 3 || tag == 4) { if (tag == 3 || tag == 4) {
@@ -396,10 +402,10 @@ void sf_display_stats(OpcodeContext& ctx) {
void sf_set_iface_tag_text(OpcodeContext& ctx) { void sf_set_iface_tag_text(OpcodeContext& ctx) {
int boxTag = ctx.arg(0).asInt(); int boxTag = ctx.arg(0).asInt();
int maxBox = BarBoxes::MaxBox(); int maxBox = BarBoxes::MaxBox();
if (boxTag > 4 && boxTag <= maxBox) { if (boxTag > 4 && boxTag <= maxBox) {
BarBoxes::SetText(boxTag, ctx.arg(1).asString(), ctx.arg(2).asInt()); BarBoxes::SetText(boxTag, ctx.arg(1).strValue(), ctx.arg(2).asInt());
} else { } else {
ctx.printOpcodeError("set_iface_tag_text() - tag value must be in the range of 5 to %d.", maxBox); ctx.printOpcodeError("set_iface_tag_text() - tag value must be in the range of 5 to %d.", maxBox);
} }
@@ -67,6 +67,8 @@ void __declspec() op_set_viewport_x();
void __declspec() op_set_viewport_y(); void __declspec() op_set_viewport_y();
void sf_add_iface_tag(OpcodeContext&);
void sf_show_iface_tag(OpcodeContext&); void sf_show_iface_tag(OpcodeContext&);
void sf_hide_iface_tag(OpcodeContext&); void sf_hide_iface_tag(OpcodeContext&);
@@ -78,6 +78,7 @@ static const SfallMetarule* currentMetarule;
- arg1, arg2, ... - argument types for automatic validation - arg1, arg2, ... - argument types for automatic validation
*/ */
static const SfallMetarule metarules[] = { static const SfallMetarule metarules[] = {
{"add_iface_tag", sf_add_iface_tag, 0, 0},
{"art_cache_clear", sf_art_cache_flush, 0, 0}, {"art_cache_clear", sf_art_cache_flush, 0, 0},
{"attack_is_aimed", sf_attack_is_aimed, 0, 0}, {"attack_is_aimed", sf_attack_is_aimed, 0, 0},
{"car_gas_amount", sf_car_gas_amount, 0, 0}, {"car_gas_amount", sf_car_gas_amount, 0, 0},