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 19:26:42 +08:00
parent fb31357e3d
commit ae3d4fcb69
6 changed files with 79 additions and 141 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()
+2 -2
View File
@@ -130,10 +130,10 @@ VAR_(optionsButtonUpKey, DWORD)
VAR_(outlined_object, GameObject*)
VAR_(partyMemberAIOptions, DWORD)
VAR_(partyMemberCount, DWORD)
VAR_(partyMemberLevelUpInfoList, DWORD)
VAR_(partyMemberLevelUpInfoList, DWORD*)
VAR_(partyMemberList, DWORD*) // each struct - 4 integers, first integer - objPtr
VAR_(partyMemberMaxCount, DWORD)
VAR_(partyMemberPidList, DWORD)
VAR_(partyMemberPidList, DWORD*)
VAR_(patches, char*)
VAR_(paths, PathNode*) // array
VAR2(pc_crit_succ_eff, CritInfo, 9, 6) // 9 body parts, 6 effects
+60 -123
View File
@@ -550,44 +550,51 @@ void __declspec(naked) op_eax_available() {
}
}
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);
static const char* nameNPCToInc;
static long pidNPCToInc;
static bool onceNpcLoop;
//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
static void __cdecl IncNPCLevel(const char* fmt, const char* name) {
fo::GameObject* mObj;
__asm {
push edx;
mov eax, [ebp + 0x150 - 0x1C + 16]; // ebp <- esp
mov edx, [eax];
mov mObj, edx;
}
if ((pidNPCToInc && (mObj && mObj->protoId == pidNPCToInc)) || (!pidNPCToInc && !_stricmp(name, nameNPCToInc))) {
fo::func::debug_printf(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) {
SafeMemSet(0x495D22, 0x90, 6); //Random element
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;
}
}
void sf_inc_npc_level(OpcodeContext& ctx) {
nameNPCToInc = ctx.arg(0).asString();
pidNPCToInc = ctx.arg(0).asInt(); // set to 0 if passing npc name
if (pidNPCToInc == 0 && nameNPCToInc[0] == 0) return;
static void _stdcall IncNPCLevel2(char* npc) {
NPCToInc = npc;
MakeJump(0x495BEB, IncNPCLevel3); //Replace the debug output with a jmp
__asm {
call fo::funcoffs::partyMemberIncLevels_;
}
SafeWrite16(0x495C50, 0x840F);
SafeWrite32(0x495C52, 0x000001FB);
MakeCall(0x495BF1, IncNPCLevel); // Replace the debug output
__asm call fo::funcoffs::partyMemberIncLevels_;
onceNpcLoop = false;
// restore code
SafeWrite32(0x495C50, 0x01FB840F);
SafeWrite16(0x495C77, 0x8C0F);
SafeWrite32(0x495C79, 0x000001D4);
//SafeWrite16(0x495C8C, 0x8D0F);
@@ -595,112 +602,42 @@ static void _stdcall IncNPCLevel2(char* npc) {
SafeWrite16(0x495CEC, 0x850F);
SafeWrite32(0x495CEE, 0x00000130);
if (!npcAutoLevelEnabled) {
SafeWrite16(0x495D22, 0x8F0F);
SafeWrite32(0x495D24, 0x00000129);
SafeWrite8(0x495CFB, 0x74);
}
}
void __declspec(naked) op_inc_npc_level() {
__asm {
push ebx;
push ecx;
push edx;
push edi;
mov edi, eax;
call fo::funcoffs::interpretPopShort_;
mov edx, eax;
mov eax, edi;
call fo::funcoffs::interpretPopLong_;
cmp dx, VAR_TYPE_STR2;
jz next;
cmp dx, VAR_TYPE_STR;
jnz end;
next:
mov ebx, eax;
mov eax, edi;
call fo::funcoffs::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;
void sf_get_npc_level(OpcodeContext& ctx) {
int level = -1;
DWORD pid = ctx.arg(0).asInt(); // set to 0 if passing npc name
if (!pid) {
const char *critterName, *name = ctx.arg(0).strValue();
if (name[0] != 0) {
DWORD* members = fo::var::partyMemberList;
for (DWORD i = 0; i < fo::var::partyMemberCount; i++) {
__asm {
mov eax, members;
mov eax, [eax];
call fo::funcoffs::critter_name_
mov name2, eax;
call fo::funcoffs::critter_name_;
mov critterName, eax;
}
if (!_stricmp(name, critterName)) { // found npc
pid = ((fo::GameObject*)*members)->protoId;
break;
}
if (_stricmp(name, name2)) {
members += 4;
continue;
}
DWORD pid = ((DWORD*)members[0])[25];
DWORD id = -1;
for (DWORD j = 0; j < maxMembers; j++) {
}
}
if (pid) {
DWORD* pids = fo::var::partyMemberPidList;
for (DWORD j = 0; j < fo::var::partyMemberMaxCount; j++) {
if (pids[j] == pid) {
id = j;
level = fo::var::partyMemberLevelUpInfoList[j * 3];
break;
}
}
if (id == -1) break;
return words[id * 3];
}
return 0;
}
void __declspec(naked) op_get_npc_level() {
__asm {
push ebx;
push ecx;
push edx;
push edi;
mov edi, eax;
call fo::funcoffs::interpretPopShort_;
mov edx, eax;
mov eax, edi;
call fo::funcoffs::interpretPopLong_;
cmp dx, VAR_TYPE_STR2;
jz next;
cmp dx, VAR_TYPE_STR;
jnz fail;
next:
mov ebx, eax;
mov eax, edi;
call fo::funcoffs::interpretGetString_;
push eax;
push ds:[FO_VAR_partyMemberLevelUpInfoList];
push ds:[FO_VAR_partyMemberPidList];
push ds:[FO_VAR_partyMemberList];
push ds:[FO_VAR_partyMemberMaxCount];
push ds:[FO_VAR_partyMemberCount];
call get_npc_level2;
mov edx, eax;
jmp end;
fail:
xor edx, edx;
end:
mov eax, edi;
call fo::funcoffs::interpretPushLong_;
mov eax, edi;
mov edx, VAR_TYPE_INT;
call fo::funcoffs::interpretPushShort_;
pop edi;
pop edx;
pop ecx;
pop ebx;
retn;
}
ctx.setReturn(level);
}
static int ParseIniSetting(const char* iniString, const char* &key, char section[], char file[]) {
+2 -2
View File
@@ -72,9 +72,9 @@ void __declspec() op_toggle_active_hand();
void __declspec() op_eax_available();
void __declspec() op_inc_npc_level();
void sf_inc_npc_level(OpcodeContext&);
void __declspec() op_get_npc_level();
void sf_get_npc_level(OpcodeContext&);
void __declspec() op_get_ini_setting();
+2 -2
View File
@@ -68,6 +68,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = {
{0x19d, "set_sfall_global", sf_set_sfall_global, 2, false, {ARG_INTSTR, ARG_NUMBER}},
{0x19e, "get_sfall_global_int", sf_get_sfall_global_int, 1, true, {ARG_INTSTR}},
{0x19f, "get_sfall_global_float", sf_get_sfall_global_float, 1, true, {ARG_INTSTR}},
{0x1a5, "inc_npc_level", sf_inc_npc_level, 1, false, {ARG_INTSTR}},
{0x1dc, "show_iface_tag", sf_show_iface_tag, 1, false, {ARG_INT}},
{0x1dd, "hide_iface_tag", sf_hide_iface_tag, 1, false, {ARG_INT}},
@@ -130,6 +131,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = {
{0x237, "atoi", sf_atoi, 1, true, {ARG_STRING}},
{0x238, "atof", sf_atof, 1, true, {ARG_STRING}},
{0x239, "scan_array", sf_scan_array, 2, true, {ARG_OBJECT, ARG_ANY}},
{0x241, "get_npc_level", sf_get_npc_level, 1, true, {ARG_INTSTR}},
{0x24e, "substr", sf_substr, 3, true, {ARG_STRING, ARG_INT, ARG_INT}},
{0x24f, "strlen", sf_strlen, 1, true, {ARG_STRING}},
@@ -302,7 +304,6 @@ void InitNewOpcodes() {
opcodes[0x1a2] = op_set_skill_max;
opcodes[0x1a3] = op_eax_available;
//opcodes[0x1a4] = op_set_eax_environment;
opcodes[0x1a5] = op_inc_npc_level;
opcodes[0x1a6] = op_get_viewport_x;
opcodes[0x1a7] = op_get_viewport_y;
opcodes[0x1a8] = op_set_viewport_x;
@@ -398,7 +399,6 @@ void InitNewOpcodes() {
opcodes[0x23e] = op_force_aimed_shots;
opcodes[0x23f] = op_disable_aimed_shots;
opcodes[0x240] = op_mark_movie_played;
opcodes[0x241] = op_get_npc_level;
opcodes[0x242] = op_set_critter_skill_points;
opcodes[0x243] = op_get_critter_skill_points;
opcodes[0x244] = op_set_available_skill_points;
+5 -4
View File
@@ -100,11 +100,10 @@ static int __fastcall SkillNegative(fo::GameObject* critter, int base, int skill
int rawPoints = skillNegPoints;
if (rawPoints) {
if (rawPoints < SKILL_MIN_LIMIT) rawPoints = SKILL_MIN_LIMIT;
fo::SkillInfo *skills = fo::var::skill_data;
rawPoints *= skills[skill].skillPointMulti;
rawPoints *= fo::var::skill_data[skill].skillPointMulti;
if (fo::func::skill_is_tagged(skill)) 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);
}
@@ -373,7 +372,9 @@ void Skills::init() {
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);