mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
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 critterName, eax;
|
||||
}
|
||||
if (!_stricmp(name, critterName)) { // found npc
|
||||
pid = ((fo::GameObject*)*members)->protoId;
|
||||
break;
|
||||
}
|
||||
members += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 fo::funcoffs::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++) {
|
||||
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[]) {
|
||||
@@ -732,7 +669,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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user