Added an additional mode to SpeedInterfaceCounterAnims (from Mr.Stalin)

Refactored the code of Stats.cpp.
Unified stat_level_ usages in Inventory.cpp, LoadGameHook.cpp and skills.cpp.
This commit is contained in:
NovaRain
2018-11-10 10:08:08 +08:00
parent cce9437d19
commit dcca405b89
9 changed files with 320 additions and 324 deletions
+1
View File
@@ -430,6 +430,7 @@ ExtraSaveSlots=0
;Set to 1 to speed up the HP/AC counter animations
;Set to 2 to update the HP/AC counters instantly
;Set to 3 to update the AC counter instantly when switching to other controlled critters in combat
SpeedInterfaceCounterAnims=0
;These lines allow you to control the karma FRMs displayed on the character screen
+2 -10
View File
@@ -381,16 +381,8 @@ static int __fastcall SuperStimFix2(TGameObj* item, TGameObj* target) {
}
DWORD curr_hp, max_hp;
__asm {
mov eax, target;
mov edx, STAT_current_hp
call stat_level_
mov curr_hp, eax;
mov eax, target;
mov edx, STAT_max_hit_points
call stat_level_
mov max_hp, eax;
}
curr_hp = StatLevel(target, STAT_current_hp);
max_hp = StatLevel(target, STAT_max_hit_points);
if (curr_hp < max_hp) return 0;
DisplayConsoleMessage(SuperStimMsg);
+4 -7
View File
@@ -23,6 +23,7 @@
#include "Bugs.h"
#include "Console.h"
#include "Criticals.h"
#include "Define.h"
#include "Explosions.h"
#include "FalloutEngine.h"
#include "FileSystem.h"
@@ -128,15 +129,11 @@ static DWORD _stdcall combatSaveTest() {
DisplayConsoleMessage(SaveFailMsg);
return 0;
}
DWORD ap;
DWORD bonusmove;
int ap = StatLevel(*ptr_obj_dude, STAT_max_move_points);
int bonusmove;
__asm {
mov edx, 8;
mov edx, PERK_bonus_move;
mov eax, ds:[_obj_dude];
call stat_level_;
mov ap, eax;
mov eax, ds:[_obj_dude];
mov edx, 3;
call perk_level_;
mov bonusmove, eax;
}
+13
View File
@@ -36,6 +36,7 @@
static DWORD Mode;
static int IsControllingNPC = 0;
static bool SkipCounterAnim = false;
static std::vector<WORD> Chars;
static int DelayedExperience;
@@ -103,6 +104,11 @@ static void SaveRealDudeState() {
//real_map_elevation = *ptr_map_elevation;
real_sneak_working = *ptr_sneak_working;
SkillGetTags(real_tag_skill, 4);
if (SkipCounterAnim) {
SafeWrite8(0x4229EC, 0); // no animate
SafeWrite8(0x422BDE, 0);
}
}
// take control of the NPC
@@ -187,6 +193,11 @@ static void RestoreRealDudeState() {
StatPcAddExperience(DelayedExperience);
}
if (SkipCounterAnim) {
SafeWrite8(0x4229EC, 1); // restore
SafeWrite8(0x422BDE, 1);
}
InterfaceRedraw();
SetInventoryCheck(false);
@@ -422,6 +433,8 @@ void PartyControlInit() {
} else
dlogr(" Disabled.", DL_INIT);
SkipCounterAnim = (GetPrivateProfileIntA("Misc", "SpeedInterfaceCounterAnims", 0, ini) == 3);
// display party member's current level & AC & addict flag
if (GetPrivateProfileIntA("Misc", "PartyMemberExtraInfo", 0, ini)) {
dlog("Applying display NPC extra info patch.", DL_INIT);
+10 -7
View File
@@ -1012,19 +1012,20 @@ static void __declspec(naked) SetApAcBonus() {
call interpretPopLong_;
cmp dx, VAR_TYPE_INT;
jnz end;
mov StandardApAcBonus, ax;
mov StandardApAcBonus, eax;
end:
pop edx;
pop ecx;
retn;
}
}
static void __declspec(naked) GetApAcBonus() {
__asm {
push ecx;
push edx;
mov ecx, eax;
movzx edx, StandardApAcBonus;
mov edx, StandardApAcBonus;
call interpretPushLong_;
mov eax, ecx;
mov edx, VAR_TYPE_INT;
@@ -1034,6 +1035,7 @@ static void __declspec(naked) GetApAcBonus() {
retn;
}
}
static void __declspec(naked) SetApAcEBonus() {
__asm {
push ecx;
@@ -1045,19 +1047,20 @@ static void __declspec(naked) SetApAcEBonus() {
call interpretPopLong_;
cmp dx, VAR_TYPE_INT;
jnz end;
mov ExtraApAcBonus, ax;
mov ExtraApAcBonus, eax;
end:
pop edx;
pop ecx;
retn;
}
}
static void __declspec(naked) GetApAcEBonus() {
__asm {
push ecx;
push edx;
mov ecx, eax;
movzx edx, ExtraApAcBonus;
mov edx, ExtraApAcBonus;
call interpretPushLong_;
mov eax, ecx;
mov edx, VAR_TYPE_INT;
@@ -1088,9 +1091,9 @@ next:
//call palette_set_to_;
mov eax, ecx;
call interpretGetString_;
call loadColorTable_
mov eax, _cmap
call palette_set_to_
call loadColorTable_;
mov eax, _cmap;
call palette_set_to_;
end:
pop edx;
pop ecx;
+109 -118
View File
@@ -29,79 +29,73 @@ static DWORD StatMinimumsPC[STAT_max_stat];
static DWORD StatMaximumsNPC[STAT_max_stat];
static DWORD StatMinimumsNPC[STAT_max_stat];
static DWORD cCritter;
static TGameObj* cCritter;
static DWORD xpTable[99];
static int StatFormulas[33 * 2];
static int StatShifts[33 * 7];
static double StatMulti[33 * 7];
static void __declspec(naked) GetCurrentStatHook1() {
DWORD StandardApAcBonus = 4;
DWORD ExtraApAcBonus = 4;
static const DWORD StatLevelHack_Ret = 0x4AEF52;
static void __declspec(naked) stat_level_hack() {
__asm {
mov cCritter, eax;
push ebx;
push ecx;
push esi;
push edi;
push ebp;
push 0x4AEF4D;
retn;
}
}
static void __declspec(naked) GetCurrentStatHook2() {
__asm {
shl esi, 2;
mov eax, cCritter;
cmp eax, dword ptr ds:[_obj_dude];
je pc;
cmp ecx, StatMinimumsNPC[esi];
jg npc1;
mov eax, StatMinimumsNPC[esi];
jmp end;
npc1:
cmp ecx, StatMaximumsNPC[esi];
jl npc2;
mov eax, StatMaximumsNPC[esi];
jmp end;
npc2:
mov eax, ecx;
jmp end;
pc:
cmp ecx, StatMinimumsPC[esi];
jge pc1;
mov eax, StatMinimumsPC[esi];
jmp end;
pc1:
cmp ecx, StatMaximumsPC[esi];
jle pc2;
mov eax, StatMaximumsPC[esi];
jmp end;
pc2:
mov eax, ecx;
end:
push 0x4AF3D7;
retn;
sub esp, 8;
mov ebx, eax;
jmp StatLevelHack_Ret;
}
}
static void __declspec(naked) SetCurrentStatHook() {
static DWORD __fastcall check_stat_level(register DWORD value, DWORD stat) {
DWORD valLimit;
if (cCritter == *ptr_obj_dude) {
valLimit = StatMinimumsPC[stat];
if (value < valLimit) return valLimit;
valLimit = StatMaximumsPC[stat];
if (value > valLimit) return valLimit;
} else {
valLimit = StatMinimumsNPC[stat];
if (value < valLimit) return valLimit;
valLimit = StatMaximumsNPC[stat];
if (value > valLimit) return valLimit;
}
return value;
}
static const DWORD StatLevelHackCheck_Ret = 0x4AF3D7;
static void __declspec(naked) stat_level_hack_check() {
__asm {
mov edx, esi;
call check_stat_level; // ecx - value stat
jmp StatLevelHackCheck_Ret;
}
}
static const DWORD StatSetBaseHack_RetMin = 0x4AF57E;
static const DWORD StatSetBaseHack_RetMax = 0x4AF591;
static const DWORD StatSetBaseHack_Ret = 0x4AF59C;
static void __declspec(naked) stat_set_base_hack_check() {
__asm {
cmp esi, dword ptr ds:[_obj_dude];
je pc;
cmp ebx, StatMinimumsNPC[ecx*4];
jl fail;
cmp ebx, StatMaximumsNPC[ecx*4];
jg fail;
jmp end;
jz pc;
cmp ebx, StatMinimumsNPC[eax];
jl failMin;
cmp ebx, StatMaximumsNPC[eax];
jg failMax;
jmp StatSetBaseHack_Ret;
pc:
cmp ebx, StatMinimumsPC[ecx*4];
jl fail;
cmp ebx, StatMaximumsPC[ecx*4];
jg fail;
jmp end;
fail:
push 0x4AF57E;
retn;
end:
push 0x4AF59C;
retn;
cmp ebx, StatMinimumsPC[eax];
jl failMin;
cmp ebx, StatMaximumsPC[eax];
jg failMax;
jmp StatSetBaseHack_Ret;
failMin:
jmp StatSetBaseHack_RetMin;
failMax:
jmp StatSetBaseHack_RetMax;
}
}
@@ -109,9 +103,10 @@ static void __declspec(naked) GetLevelXPHook() {
__asm {
dec eax;
mov eax, [xpTable + eax * 4];
ret;
retn;
}
}
static void __declspec(naked) GetNextLevelXPHook() {
__asm {
mov eax, ds:[_Level_];
@@ -119,46 +114,29 @@ static void __declspec(naked) GetNextLevelXPHook() {
}
}
unsigned short StandardApAcBonus=4;
unsigned short ExtraApAcBonus=4;
static const DWORD ApAcRetAddr = 0x4AF0A4;
static void __declspec(naked) ApplyApAcBonus() {
static void __declspec(naked) CalcApToAcBonus() {
__asm {
push edi;
push edx;
cmp [esp+12], 2;
jge h2hEvade;
xor edi, edi;
jmp standard;
h2hEvade:
xor eax, eax;
mov edi, [ebx + 0x40];
test edi, edi;
jz end;
cmp [esp + 0x1C - 0x18], 2; // pc have perk h2hEvade (2 - vanilla bonus)
jb standard;
mov edx, PERK_hth_evade_perk;
mov eax, dword ptr ds:[_obj_dude];
call perk_level_;
imul ax, ExtraApAcBonus;
imul ax, [ebx+0x40];
mov edi, eax;
imul eax, ExtraApAcBonus; // bonus = perkLvl * ExtraApBonus
imul eax, edi; // perkBonus = bonus * curAP
standard:
mov eax, [ebx+0x40];
imul ax, StandardApAcBonus;
add eax, edi;
shr eax, 2;
pop edx;
pop edi;
imul edi, StandardApAcBonus; // stdBonus = curAP * StandardApBonus
add eax, edi; // bonus = perkBonus + stdBonus
shr eax, 2; // acBonus = bonus / 4
end:
jmp ApAcRetAddr;
}
}
static int StatFormulas[33*2];
static int StatShifts[33*7];
static double StatMulti[33*7];
static int __declspec(naked) _stdcall StatLevel(void* critter, int id) {
__asm {
mov eax, [esp+4];
mov edx, [esp+8];
call stat_level_;
retn 8;
}
}
static void __declspec(naked) _stdcall ProtoPtr(DWORD pid, int** proto) {
__asm {
mov eax, [esp + 4];
@@ -167,17 +145,19 @@ static void __declspec(naked) _stdcall ProtoPtr(DWORD pid, int** proto) {
retn 8;
}
}
static void _stdcall StatRecalcDerived(DWORD* critter) {
int basestats[7];
for(int i=0;i<7;i++) basestats[i]=StatLevel(critter, i);
int* proto;
ProtoPtr(critter[25], &proto);
for(int i=7;i<=32;i++) {
if(i>=17&&i<=30) continue;
static void _stdcall StatRecalcDerived(TGameObj* critter) {
int basestats[7];
for (int i = STAT_st; i <= STAT_lu; i++) basestats[i] = StatLevel(critter, i);
int* proto;
ProtoPtr(critter->pid, &proto);
for (int i = STAT_max_hit_points; i <= STAT_poison_resist; i++) {
if (i >= STAT_dmg_thresh && i <= STAT_dmg_resist_explosion) continue;
double sum = 0;
for(int j=0;j<7;j++) {
for (int j = STAT_st; j <= STAT_lu; j++) {
sum += (basestats[j] + StatShifts[i * 7 + j]) * StatMulti[i * 7 + j];
}
proto[i + 9] = StatFormulas[i * 2] + (int)floor(sum);
@@ -185,7 +165,7 @@ static void _stdcall StatRecalcDerived(DWORD* critter) {
}
}
static void __declspec(naked) stat_recalc_derived() {
static void __declspec(naked) stat_recalc_derived_hack() {
__asm {
push edx;
push ecx;
@@ -205,16 +185,14 @@ void StatsReset() {
StandardApAcBonus = 4;
ExtraApAcBonus = 4;
}
void StatsInit() {
StatsReset();
SafeWrite8(0x4AEF48, 0xE9);
HookCall(0x4AEF48, GetCurrentStatHook1);
SafeWrite8(0x4AF3AF, 0xE9);
HookCall(0x4AF3AF, GetCurrentStatHook2);
SafeWrite8(0x4AF56A, 0xE9);
HookCall(0x4AF56A, SetCurrentStatHook);
SafeWrite8(0x4AF09C, 0xE9);
HookCall(0x4AF09C, ApplyApAcBonus);
MakeJump(0x4AEF4D, stat_level_hack);
MakeJump(0x4AF3AF, stat_level_hack_check);
MakeJump(0x4AF571, stat_set_base_hack_check);
MakeJump(0x4AF09C, CalcApToAcBonus); // stat_level_
char table[2048];
GetPrivateProfileString("Misc", "XPTable", "", table, 2048, ini);
@@ -242,7 +220,8 @@ void StatsInit() {
GetPrivateProfileStringA("Misc", "DerivedStats", "", table, 2048, ini);
if (strlen(table)) {
MakeJump(0x4AF6FC, stat_recalc_derived);
MakeJump(0x4AF6FC, stat_recalc_derived_hack); // overrides function
memset(StatFormulas, 0, sizeof(StatFormulas));
memset(StatShifts, 0, sizeof(StatShifts));
memset(StatMulti, 0, sizeof(StatMulti));
@@ -250,17 +229,22 @@ void StatsInit() {
StatFormulas[7 * 2] = 15; // max hp
StatMulti[7 * 7 + 0] = 1;
StatMulti[7 * 7 + 2] = 2;
StatFormulas[8 * 2] = 5; // max ap
StatMulti[8 * 7 + 5] = 0.5;
StatMulti[9 * 7 + 5] = 1; // ac
StatFormulas[11 * 2 + 1] = 1; // melee damage
StatShifts[11 * 7 + 0] = -5;
StatMulti[11 * 7 + 0] = 1;
StatFormulas[12 * 2] = 25; // carry weight
StatMulti[12 * 7 + 0] = 25;
StatMulti[13 * 7 + 1] = 2; // sequence
StatFormulas[14 * 2 + 1] = 1; // heal rate
StatMulti[14 * 7 + 2] = 1.0 / 3.0;
StatMulti[15 * 7 + 6] = 1; // critical chance
StatMulti[31 * 7 + 2] = 2; // rad resist
StatMulti[32 * 7 + 2] = 5; // poison resist
@@ -268,13 +252,13 @@ void StatsInit() {
char key[6], buf2[256], buf3[256];
strcpy_s(buf3, table);
sprintf(table, ".\\%s", buf3);
for(int i=7;i<=32;i++) {
if(i>=17&&i<=30) continue;
for (int i = STAT_max_hit_points; i <= STAT_poison_resist; i++) {
if (i >= STAT_dmg_thresh && i <= STAT_dmg_resist_explosion) continue;
_itoa(i, key, 10);
StatFormulas[i * 2] = GetPrivateProfileInt(key, "base", StatFormulas[i * 2], table);
StatFormulas[i * 2 + 1] = GetPrivateProfileInt(key, "min", StatFormulas[i * 2 + 1], table);
for(int j=0;j<7;j++) {
for (int j = 0; j < STAT_max_hit_points; j++) {
sprintf(buf2, "shift%d", j);
StatShifts[i * 7 + j] = GetPrivateProfileInt(key, buf2, StatShifts[i * 7 + 0], table);
sprintf(buf2, "multi%d", j);
@@ -287,18 +271,25 @@ void StatsInit() {
}
void _stdcall SetPCStatMax(int stat, int i) {
if(stat<0||stat>=STAT_max_stat) return;
if (stat >= 0 && stat < STAT_max_stat) {
StatMaximumsPC[stat] = i;
}
}
void _stdcall SetPCStatMin(int stat, int i) {
if(stat<0||stat>=STAT_max_stat) return;
if (stat >= 0 && stat < STAT_max_stat) {
StatMinimumsPC[stat] = i;
}
}
void _stdcall SetNPCStatMax(int stat, int i) {
if(stat<0||stat>=STAT_max_stat) return;
if (stat >= 0 && stat < STAT_max_stat) {
StatMaximumsNPC[stat] = i;
}
}
void _stdcall SetNPCStatMin(int stat, int i) {
if(stat<0||stat>=STAT_max_stat) return;
if (stat >= 0 && stat < STAT_max_stat) {
StatMinimumsNPC[stat] = i;
}
}
+2 -2
View File
@@ -24,5 +24,5 @@ void _stdcall SetPCStatMax(int stat, int i);
void _stdcall SetPCStatMin(int stat, int i);
void _stdcall SetNPCStatMax(int stat, int i);
void _stdcall SetNPCStatMin(int stat, int i);
extern unsigned short StandardApAcBonus;
extern unsigned short ExtraApAcBonus;
extern DWORD StandardApAcBonus;
extern DWORD ExtraApAcBonus;
+1 -1
View File
@@ -1290,7 +1290,7 @@ static void DllMain2() {
break;
case 2:
dlog("Applying SpeedInterfaceCounterAnims patch. (Instant)", DL_INIT);
SafeWrite32(0x460BB6, 0x90DB3190);
SafeWrite32(0x460BB6, 0x90DB3190); // xor ebx, ebx
dlogr(" Done", DL_INIT);
break;
}
+25 -26
View File
@@ -27,24 +27,29 @@
#include "Knockback.h"
struct SkillInfo {
DWORD a, b, c; //Not interested in these at the moment
DWORD image;
DWORD base;
DWORD statMulti;
int statA;
int statB;
DWORD skillPointMulti;
DWORD e, f; //nor these
const char* name;
const char* description;
long attr;
long image;
long base;
long statMulti;
long statA;
long statB;
long skillPointMulti;
// Default experience for using the skill: 25 for Lockpick, Steal, Traps, and First Aid, 50 for Doctor, and 100 for Outdoorsman.
long experience;
// 1 for Lockpick, Steal, Traps; 0 otherwise
long f;
};
struct ChanceModifier {
struct SkillModifier {
DWORD id;
int maximum;
int mod;
};
static std::vector<ChanceModifier> SkillMaxMods;
static ChanceModifier BaseSkillMax;
static std::vector<SkillModifier> SkillMaxMods;
static SkillModifier BaseSkillMax;
static BYTE skillCosts[512 * SKILL_count];
static DWORD basedOnPoints;
@@ -56,6 +61,7 @@ static int _stdcall SkillMaxHook2(int base, DWORD critter) {
}
return min(base, BaseSkillMax.maximum);
}
static void __declspec(naked) SkillHookA() {
__asm {
push ecx;
@@ -65,6 +71,7 @@ static void __declspec(naked) SkillHookA() {
retn;
}
}
static void __declspec(naked) SkillHookB() {
__asm {
push edx;
@@ -87,6 +94,7 @@ win:
retn;
}
}
static const DWORD SkillHookWin = 0x4AA738;
static const DWORD SkillHookFail = 0x4AA72C;
static void __declspec(naked) SkillHookC() {
@@ -117,7 +125,7 @@ void _stdcall SetSkillMax(DWORD critter, DWORD maximum) {
return;
}
}
ChanceModifier cm;
SkillModifier cm;
cm.id = critter;
cm.maximum = maximum;
cm.mod = 0;
@@ -125,29 +133,20 @@ void _stdcall SetSkillMax(DWORD critter, DWORD maximum) {
}
double* multipliers;
static const DWORD StatBonusHookRet=0x4AA5D6;
static int __declspec(naked) _stdcall stat_level(void* critter, int stat) {
__asm {
push edx;
mov eax, [esp+8];
mov edx, [esp+12];
call stat_level_;
pop edx;
ret 8;
}
}
static int _stdcall GetStatBonusHook2(const SkillInfo* info, int skill, int points, void* critter) {
static int _stdcall GetStatBonusHook2(const SkillInfo* info, int skill, int points, TGameObj* critter) {
double result = 0;
for(int i=0;i<7;i++) {
result+=stat_level(critter, i)*multipliers[skill*7+i];
for (int i = STAT_st; i <= STAT_lu; i++) {
result += StatLevel(critter, i) * multipliers[skill * 7 + i];
}
result += points*info->skillPointMulti;
result += info->base;
return (int)result;
}
//On input, ebx contains the skill id, ecx contains the critter, edx contains the skill id, edi contains a SkillInfo*, ebp contains the number of skill points
//On exit ebx, ecx, edi, ebp are preserved, esi contains skill base + stat bonus + skillpoints * multiplier
static const DWORD StatBonusHookRet = 0x4AA5D6;
static void __declspec(naked) GetStatBonusHook() {
__asm {
push edx;