Expanded get/inc_npc_level functions to accept party member PIDs (from Mr.Stalin)

Some code correction in Skills.cpp.
This commit is contained in:
NovaRain
2019-02-24 20:14:36 +08:00
parent 6ab45bbc3c
commit 72e370117e
5 changed files with 89 additions and 135 deletions
+2 -2
View File
@@ -162,8 +162,8 @@
0x81a3 - int eax_available()
0x81a4 - void set_eax_environment(int environment)
0x81a5 - void inc_npc_level(string npc)
0x8241 - int get_npc_level(string npc)
0x81a5 - void inc_npc_level(string npcName/int pid)
0x8241 - int get_npc_level(string npcName/int pid)
0x81a6 - int get_viewport_x()
0x81a7 - int get_viewport_y()
+79 -127
View File
@@ -538,152 +538,104 @@ static void __declspec(naked) EaxAvailable() {
retn;
}
}
static char* NPCToInc;
static void _stdcall IncNPCLevel4(char* npc) {
if (_stricmp(npc, NPCToInc)) {
SafeWrite8(0x495C50, 0xE9);
SafeWrite32(0x495C51, 0x000001FC);
} else {
SafeWrite16(0x495C50, 0x840F); //Want to keep this check intact.
SafeWrite32(0x495C52, 0x000001FB);
//SafeMemSet(0x495C50, 0x90, 6);
SafeMemSet(0x495C77, 0x90, 6); //Check that the player is high enough for the npc to consider this level
//SafeMemSet(0x495C8C, 0x90, 6); //Check that the npc isn't already at its maximum level
SafeMemSet(0x495CEC, 0x90, 6); //Check that the npc hasn't already levelled up recently
if (!npcautolevel) {
SafeMemSet(0x495D22, 0x90, 6); //Random element
static const char* nameNPCToInc;
static long pidNPCToInc;
static bool onceNpcLoop;
static void __cdecl IncNPCLevelFunc(const char* fmt, const char* name) {
TGameObj* mObj;
__asm {
push edx;
mov eax, [ebp + 0x150 - 0x1C + 16]; // ebp <- esp
mov edx, [eax];
mov mObj, edx;
}
if ((pidNPCToInc && (mObj && mObj->pid == pidNPCToInc)) || (!pidNPCToInc && !_stricmp(name, nameNPCToInc))) {
DebugPrintf(fmt, name);
SafeWrite32(0x495C50, 0x01FB840F); // Want to keep this check intact. (restore)
SafeMemSet(0x495C77, 0x90, 6); // Check that the player is high enough for the npc to consider this level
//SafeMemSet(0x495C8C, 0x90, 6); // Check that the npc isn't already at its maximum level
SafeMemSet(0x495CEC, 0x90, 6); // Check that the npc hasn't already levelled up recently
if (!npcAutoLevelEnabled) {
SafeWrite8(0x495CFB, 0xEB); // Disable random element
}
__asm mov [ebp + 0x150 - 0x28 + 16], 255; // set counter for exit loop
} else {
if (!onceNpcLoop) {
SafeWrite32(0x495C50, 0x01FCE9); // set goto next member
onceNpcLoop = true;
}
}
__asm pop edx;
}
static void __declspec(naked) IncNPCLevel3() {
__asm {
pushad;
push eax;
call IncNPCLevel4;
popad;
push 0x495BF9;
retn;
}
}
static void _stdcall IncNPCLevel2(char* npc) {
NPCToInc = npc;
MakeJump(0x495BEB, IncNPCLevel3); //Replace the debug output with a jmp
__asm {
call partyMemberIncLevels_;
}
SafeWrite16(0x495C50, 0x840F);
SafeWrite32(0x495C52, 0x000001FB);
static void _stdcall IncNPCLevel2() {
nameNPCToInc = opHandler.arg(0).asString();
pidNPCToInc = opHandler.arg(0).asInt(); // set to 0 if passing npc name
if (pidNPCToInc == 0 && nameNPCToInc[0] == 0) return;
MakeCall(0x495BF1, IncNPCLevelFunc); // Replace the debug output
__asm call partyMemberIncLevels_;
onceNpcLoop = false;
// restore code
SafeWrite32(0x495C50, 0x01FB840F);
SafeWrite16(0x495C77, 0x8C0F);
SafeWrite32(0x495C79, 0x000001D4);
//SafeWrite16(0x495C8C, 0x8D0F);
//SafeWrite32(0x495C8E, 0x000001BF);
SafeWrite16(0x495CEC, 0x850F);
SafeWrite32(0x495CEE, 0x00000130);
if (!npcautolevel) {
SafeWrite16(0x495D22, 0x8F0F);
SafeWrite32(0x495D24, 0x00000129);
if (!npcAutoLevelEnabled) {
SafeWrite8(0x495CFB, 0x74);
}
}
static void __declspec(naked) IncNPCLevel() {
__asm {
push ebx;
push ecx;
push edx;
push edi;
mov edi, eax;
call interpretPopShort_;
mov edx, eax;
mov eax, edi;
call interpretPopLong_;
cmp dx, VAR_TYPE_STR2;
jz next;
cmp dx, VAR_TYPE_STR;
jnz end;
next:
mov ebx, eax;
mov eax, edi;
call interpretGetString_;
push eax;
call IncNPCLevel2;
end:
pop edi;
pop edx;
pop ecx;
pop ebx;
retn;
}
}
static int _stdcall get_npc_level2(DWORD numMembers, DWORD maxMembers, DWORD* members, DWORD* pids, DWORD* words, const char* name) {
for (DWORD i = 0; i < numMembers; i++) {
const char* name2;
__asm {
mov eax, members;
mov eax, [eax];
call critter_name_
mov name2, eax;
}
if (_stricmp(name, name2)) {
members += 4;
continue;
}
DWORD pid = ((DWORD*)members[0])[25];
DWORD id = -1;
for (DWORD j = 0; j < maxMembers; j++) {
static void __declspec(naked) IncNPCLevel() {
_WRAP_OPCODE(IncNPCLevel2, 1, 0)
}
static void _stdcall get_npc_level2() {
int level = -1;
DWORD pid = opHandler.arg(0).asInt(); // set to 0 if passing npc name
if (!pid) {
const char *critterName, *name = opHandler.arg(0).strValue();
if (name[0] != 0) {
DWORD* members = *(DWORD**)_partyMemberList;
for (DWORD i = 0; i < *(DWORD*)_partyMemberCount; i++) {
__asm {
mov eax, members;
mov eax, [eax];
call critter_name_;
mov critterName, eax;
}
if (!_stricmp(name, critterName)) { // found npc
pid = ((TGameObj*)*members)->pid;
break;
}
members += 4;
}
}
}
if (pid) {
DWORD* pids = *(DWORD**)_partyMemberPidList;
DWORD* lvlUpInfo = *(DWORD**)_partyMemberLevelUpInfoList;
for (DWORD j = 0; j < *(DWORD*)_partyMemberMaxCount; j++) {
if (pids[j] == pid) {
id = j;
level = lvlUpInfo[j * 3];
break;
}
}
if (id == -1) break;
return words[id * 3];
}
return 0;
opHandler.setReturn(level);
}
static void __declspec(naked) get_npc_level() {
__asm {
push ebx;
push ecx;
push edx;
push edi;
mov edi, eax;
call interpretPopShort_;
mov edx, eax;
mov eax, edi;
call interpretPopLong_;
cmp dx, VAR_TYPE_STR2;
jz next;
cmp dx, VAR_TYPE_STR;
jnz fail;
next:
mov ebx, eax;
mov eax, edi;
call interpretGetString_;
push eax;
push ds:[_partyMemberLevelUpInfoList];
push ds:[_partyMemberPidList];
push ds:[_partyMemberList];
push ds:[_partyMemberMaxCount];
push ds:[_partyMemberCount];
call get_npc_level2;
mov edx, eax;
jmp end;
fail:
xor edx, edx;
end:
mov eax, edi;
call interpretPushLong_;
mov eax, edi;
mov edx, VAR_TYPE_INT;
call interpretPushShort_;
pop edi;
pop edx;
pop ecx;
pop ebx;
retn;
}
_WRAP_OPCODE(get_npc_level2, 1, 1)
}
static int ParseIniSetting(const char* iniString, const char* &key, char section[], char file[]) {
@@ -715,7 +667,7 @@ static char IniStrBuffer[128];
static DWORD _stdcall GetIniSetting2(const char* c, DWORD string) {
const char* key;
char section[33], file[67];
if (ParseIniSetting(c, key, section, file) < 0) {
return -1;
}
+3 -3
View File
@@ -83,7 +83,7 @@ char dfModelName[65];
static const char* musicOverridePath = "data\\sound\\music\\";
DWORD AddUnarmedStatToGetYear = 0;
bool npcautolevel;
bool npcAutoLevelEnabled;
static int* scriptDialog = nullptr;
@@ -1134,8 +1134,8 @@ static void DllMain2() {
DebugEditorInit();
npcautolevel = GetPrivateProfileIntA("Misc", "NPCAutoLevel", 0, ini) != 0;
if (npcautolevel) {
npcAutoLevelEnabled = GetPrivateProfileIntA("Misc", "NPCAutoLevel", 0, ini) != 0;
if (npcAutoLevelEnabled) {
dlog("Applying NPC autolevel patch.", DL_INIT);
SafeWrite8(0x495CFB, 0xEB); // jmps 0x495D28 (skip random check)
dlogr(" Done", DL_INIT);
+1 -1
View File
@@ -70,7 +70,7 @@ extern DWORD modifiedIni;
extern char dmModelName[65];
extern char dfModelName[65];
extern bool npcautolevel;
extern bool npcAutoLevelEnabled;
DWORD GetAddedYears(bool isCheck = true);
void SetAddedYears(DWORD years);
+4 -2
View File
@@ -82,7 +82,7 @@ static int __fastcall SkillNegative(TGameObj* critter, int base, int skill) {
}
if (tagged) rawPoints *= 2;
base += rawPoints; // add the negative skill points after calculating the skill level
if (base < -300) return -300;
if (base < 0) return max(-999, base);
}
return CheckSkillMax(critter, base);
}
@@ -330,7 +330,9 @@ void SkillsInit() {
skills[i].base = GetPrivateProfileIntA("Skills", key, skills[i].base, file);
sprintf(key, "SkillMulti%d", i);
skills[i].skillPointMulti = GetPrivateProfileIntA("Skills", key, skills[i].skillPointMulti, file);
int multi = GetPrivateProfileIntA("Skills", key, skills[i].skillPointMulti, file);
if (multi < 1) multi = 1; else if (multi > 10) multi = 10;
skills[i].skillPointMulti = multi;
sprintf(key, "SkillImage%d", i);
skills[i].image = GetPrivateProfileIntA("Skills", key, skills[i].image, file);