-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSource.cpp
More file actions
173 lines (154 loc) · 6.26 KB
/
Source.cpp
File metadata and controls
173 lines (154 loc) · 6.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include "MainHeader.h"
#include "InitHooks.h"
#include <iostream>
#include <sstream>
#include <iomanip>
UInt32 SkillCheckVar = 0;
char newSkillString[516];
char customOffset[8] = "%s[%s] ";
char customOffset1[7] = "%s%s";
char MWString[14] = "Melee Weapons";
char EWString[15] = "Energy Weapons";
namespace DiaCondExtended
{
//Takes the Actor Value Code stored in SkillCheckVar and converts it to a string
const char* GetSkillCheckString()
{
const char* name = nullptr;
if (SkillCheckVar <= eActorVal_FalloutMax)
{
//I'm so, so sorry if you speak another language, I'm lazy AF
//If either MeleeWeapons or EnergyWeapons, changes the string to have a space
if (SkillCheckVar == 0x26)
{
name = MWString;
}
else if (SkillCheckVar == 0x22)
{
name = EWString;
}
else
{
name = GetActorValueString(SkillCheckVar);
}
}
else
{
name = "unknown";
}
return name;
}
//Grabs the AVcode from the ECX register at this address and stores it in SkillCheckVar
_declspec(naked) void __fastcall GetAvCodeHook()
{
static const UInt32 returnAddr = 0x763C40;
_asm
{
mov[ebp - 0x23C], ecx //Rewriting Overwritten Address
mov SkillCheckVar, ecx //ECX = AvCode --> SkillCheckVar
jmp returnAddr
}
}
//Wipes the string buffer before the loop starts, so that the 'AV/Perk' category in the GECK is irrelevant
_declspec(naked) void __fastcall WipeBuffer()
{
static const UInt32 FormatString = 0x406D00;
static const UInt32 returnAddr = 0x763BD9;
_asm
{
mov[ebp - 0x230], eax //Rewriting Overwritten Address
lea edi, [ebp - 0x208]
mov ecx, 0x200
xor eax, eax
rep stosb //Cleared StringBuffer
jmp returnAddr
}
}
//Modifies the construction of the failure string.
_declspec(naked) void __stdcall StringModFail()
{
static const UInt32 FormatString = 0x406D00;
static const UInt32 offsetAddr = 0x01072850;
static const UInt32 returnAddr = 0x763CB7;
_asm
{
call GetSkillCheckString
push eax //eax = AvCode
push offsetAddr //"%s %d/%d"
push 0x200
lea eax, newSkillString
push eax
call FormatString //FormatString(newSkillString, 512, "%s %d/%d", AvCode, ClampedActorValueI, ComparisonValue)
add esp, 0x18 //2 arguments before jump + 4 new arguments = 6 arguments = 24 bits
lea eax, newSkillString //Concatenated String
push eax
lea edx, [ebp - 0x208] //StringBuffer
push edx
push offset customOffset //"%s[%s] "
push 0x200
lea eax, [ebp - 0x208]
push eax
call FormatString //FormatString(StringBuffer, 512, "%s[%s] ", StringBuffer, newSkillString)
add esp, 0x14 //Need to clean 20 bits for 5 arguments
jmp returnAddr
}
}
//Modifies the construction of the success string.
_declspec(naked) void __stdcall StringModPass()
{
static const UInt32 FormatString = 0x406D00;
static const UInt32 offsetAddr = 0x0104700C;
static const UInt32 returnAddr = 0x763CE4;
_asm
{
call GetSkillCheckString
push eax //eax = AvCode
push offsetAddr //"%s %d"
push 0x200
lea eax, newSkillString
push eax
call FormatString //FormatString(newSkillString, 512, "%s %d", AvCode, ComparisonValue)
add esp, 0x14
lea eax, newSkillString //Concatenated String
push eax
lea edx, [ebp - 0x208] //StringBuffer
push edx
push offset customOffset //"%s[%s] "
push 0x200
lea eax, [ebp - 0x208]
push eax
call FormatString //FormatString(StringBuffer, 512, "%s[%s] ", StringBuffer, newSkillString)
jmp returnAddr
}
}
//Removes the appended ']' at the end of the skill tag
_declspec(naked) void __fastcall EndModString()
{
static const UInt32 returnAddr = 0x763D1E;
_asm
{
push offset customOffset1
jmp returnAddr
}
}
//Function to initialize hooks
void InitHooks()
{
UInt32 avHookAddr = 0x763C3A; //This is an Address where the ECX Register = AvCode
UInt32 loopStartAddr = 0x763BD3; //This Address is the start of the For Loop
UInt32 failStrAddr = 0x763C97; //This Address is for the String Buffer right before the string is formatted (Failure Condition)
UInt32 passStrAddr = 0x763CC7; //This Address is for the String Buffer right before the string is formatted (Success Condition)
UInt32 endFormatAddr = 0x763D19; //THis Address pushes the string definition "%s] %s" as an offset to close the Skill Tag up; ']'
ULONG_PTR breakAddr1 = 0x763CE7; //breakAddr1 and 2 are responsible for the break at the end of the for loop
ULONG_PTR breakAddr2 = 0x763CE8;
//Extend Dialogue Conditions
WriteRelJump(avHookAddr, UInt32(GetAvCodeHook));
WriteRelJump(loopStartAddr, UInt32(WipeBuffer));
WriteRelJump(failStrAddr, UInt32(StringModFail));
WriteRelJump(passStrAddr, UInt32(StringModPass));
WriteRelJump(endFormatAddr, UInt32(EndModString));
//Remove loop break
PatchMemoryNop(breakAddr1, 1);
PatchMemoryNop(breakAddr2, 1);
}
}