diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index dc93ab28..337f8999 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -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 diff --git a/sfall/Inventory.cpp b/sfall/Inventory.cpp index fa3cf153..d26e0169 100644 --- a/sfall/Inventory.cpp +++ b/sfall/Inventory.cpp @@ -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); diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index 81ddac7d..be8fb5cb 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -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; } diff --git a/sfall/PartyControl.cpp b/sfall/PartyControl.cpp index b964a4c1..0e1fc182 100644 --- a/sfall/PartyControl.cpp +++ b/sfall/PartyControl.cpp @@ -36,6 +36,7 @@ static DWORD Mode; static int IsControllingNPC = 0; +static bool SkipCounterAnim = false; static std::vector 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); diff --git a/sfall/ScriptOps/MiscOps.hpp b/sfall/ScriptOps/MiscOps.hpp index 867bfe3e..283d2acc 100644 --- a/sfall/ScriptOps/MiscOps.hpp +++ b/sfall/ScriptOps/MiscOps.hpp @@ -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; diff --git a/sfall/Stats.cpp b/sfall/Stats.cpp index 2ba44150..b03eb7c6 100644 --- a/sfall/Stats.cpp +++ b/sfall/Stats.cpp @@ -29,89 +29,84 @@ 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; } } static void __declspec(naked) GetLevelXPHook() { __asm { dec eax; - mov eax, [xpTable+eax*4]; - ret; + mov eax, [xpTable + eax * 4]; + retn; } } + static void __declspec(naked) GetNextLevelXPHook() { __asm { mov eax, ds:[_Level_]; @@ -119,186 +114,182 @@ static void __declspec(naked) GetNextLevelXPHook() { } } -unsigned short StandardApAcBonus=4; -unsigned short ExtraApAcBonus=4; -static const DWORD ApAcRetAddr=0x4AF0A4; -static void __declspec(naked) ApplyApAcBonus() { +static const DWORD ApAcRetAddr = 0x4AF0A4; +static void __declspec(naked) CalcApToAcBonus() { __asm { - push edi; - push edx; - cmp [esp+12], 2; - jge h2hEvade; - xor edi, edi; - jmp standard; -h2hEvade: - mov edx, PERK_hth_evade_perk; - mov eax, dword ptr ds:[_obj_dude]; + 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; - jmp ApAcRetAddr; + 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]; - mov edx, [esp+8]; + mov eax, [esp + 4]; + mov edx, [esp + 8]; call proto_ptr_; 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; - - double sum=0; - for(int j=0;j<7;j++) { - sum+=(basestats[j]+StatShifts[i*7+j])*StatMulti[i*7+j]; +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 = 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); - if(proto[i+9]0) { - char *ptr=table, *ptr2; - DWORD level=0; - + if (strlen(table) > 0) { + char *ptr = table, *ptr2; + DWORD level = 0; + HookCall(0x434AA7, GetNextLevelXPHook); HookCall(0x439642, GetNextLevelXPHook); HookCall(0x4AFB22, GetNextLevelXPHook); HookCall(0x496C8D, GetLevelXPHook); HookCall(0x4AFC53, GetLevelXPHook); - while((ptr2=strstr(ptr, ","))&&level<99) { - ptr2[0]='\0'; - xpTable[level++]=atoi(ptr); - ptr=ptr2+1; + while ((ptr2 = strstr(ptr, ",")) && level < 99) { + ptr2[0] = '\0'; + xpTable[level++] = atoi(ptr); + ptr = ptr2 + 1; } - if(level<99&&ptr[0]!='\0') { - xpTable[level++]=atoi(ptr); + if (level < 99 && ptr[0] != '\0') { + xpTable[level++] = atoi(ptr); } - for(int i=level;i<99;i++) xpTable[i]=-1; - SafeWrite8(0x4AFB1B, (BYTE)(level+1)); + for (int i = level; i < 99; i++) xpTable[i] = -1; + SafeWrite8(0x4AFB1B, (BYTE)(level + 1)); } GetPrivateProfileStringA("Misc", "DerivedStats", "", table, 2048, ini); - if(strlen(table)) { - MakeJump(0x4AF6FC, stat_recalc_derived); + if (strlen(table)) { + MakeJump(0x4AF6FC, stat_recalc_derived_hack); // overrides function + memset(StatFormulas, 0, sizeof(StatFormulas)); memset(StatShifts, 0, sizeof(StatShifts)); memset(StatMulti, 0, sizeof(StatMulti)); - 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 + 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 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++) { + 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 < STAT_max_hit_points; j++) { sprintf(buf2, "shift%d", j); - StatShifts[i*7+j]=GetPrivateProfileInt(key, buf2, StatShifts[i*7+0], table); + StatShifts[i * 7 + j] = GetPrivateProfileInt(key, buf2, StatShifts[i * 7 + 0], table); sprintf(buf2, "multi%d", j); - _gcvt(StatMulti[i*7+j], 16, buf3); + _gcvt(StatMulti[i * 7 + j], 16, buf3); GetPrivateProfileStringA(key, buf2, buf3, buf2, 256, table); - StatMulti[i*7+j]=atof(buf2); + StatMulti[i * 7 + j] = atof(buf2); } } } } void _stdcall SetPCStatMax(int stat, int i) { - if(stat<0||stat>=STAT_max_stat) return; - StatMaximumsPC[stat]=i; + 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; - StatMinimumsPC[stat]=i; + 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; - StatMaximumsNPC[stat]=i; + 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; - StatMinimumsNPC[stat]=i; -} \ No newline at end of file + if (stat >= 0 && stat < STAT_max_stat) { + StatMinimumsNPC[stat] = i; + } +} diff --git a/sfall/Stats.h b/sfall/Stats.h index 8b8b0004..afeb03e8 100644 --- a/sfall/Stats.h +++ b/sfall/Stats.h @@ -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; \ No newline at end of file +extern DWORD StandardApAcBonus; +extern DWORD ExtraApAcBonus; diff --git a/sfall/main.cpp b/sfall/main.cpp index ea216dbc..b44ae21a 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -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; } diff --git a/sfall/skills.cpp b/sfall/skills.cpp index 818a374e..e45f8f1f 100644 --- a/sfall/skills.cpp +++ b/sfall/skills.cpp @@ -27,127 +27,126 @@ #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 SkillMaxMods; -static ChanceModifier BaseSkillMax; -static BYTE skillCosts[512*SKILL_count]; +static std::vector SkillMaxMods; +static SkillModifier BaseSkillMax; +static BYTE skillCosts[512 * SKILL_count]; static DWORD basedOnPoints; static int _stdcall SkillMaxHook2(int base, DWORD critter) { - for(DWORD i=0;iskillPointMulti; - result+=info->base; + 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 +//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; @@ -164,7 +163,7 @@ static void __declspec(naked) GetStatBonusHook() { } } -static const DWORD SkillIncCostRet=0x4AA7C1; +static const DWORD SkillIncCostRet = 0x4AA7C1; static void __declspec(naked) SkillIncCostHook() { __asm { //eax - current skill level, ebx - current skill, ecx - num free skill points @@ -184,7 +183,7 @@ next: } } -static const DWORD SkillDecCostRet=0x4AA98D; +static const DWORD SkillDecCostRet = 0x4AA98D; static void __declspec(naked) SkillDecCostHook() { __asm { //eax - current skill level, ebx - current skill, ecx - num free skill points @@ -223,65 +222,65 @@ void SkillsInit() { MakeJump(0x4AA725, SkillHookC); char buf[512], key[16], file[64]; - if(GetPrivateProfileStringA("Misc", "SkillsFile", "", buf, 62, ini)>0) { - SkillInfo *skills=(SkillInfo*)_skill_data; + if (GetPrivateProfileStringA("Misc", "SkillsFile", "", buf, 62, ini) > 0) { + SkillInfo *skills = (SkillInfo*)_skill_data; sprintf(file, ".\\%s", buf); - multipliers=new double[7*SKILL_count]; - memset(multipliers, 0, 7*SKILL_count*sizeof(double)); + multipliers = new double[7 * SKILL_count]; + memset(multipliers, 0, 7 * SKILL_count * sizeof(double)); - for(int i=0;i=2) { - double m=atof(&tok[1]); - switch(tok[0]) { - case 's': multipliers[i*7+0]=m; break; - case 'p': multipliers[i*7+1]=m; break; - case 'e': multipliers[i*7+2]=m; break; - case 'c': multipliers[i*7+3]=m; break; - case 'i': multipliers[i*7+4]=m; break; - case 'a': multipliers[i*7+5]=m; break; - case 'l': multipliers[i*7+6]=m; break; + if (GetPrivateProfileStringA("Skills", key, "", buf, 64, file)) { + char* tok = strtok(buf, "|"); + while (tok) { + if (strlen(tok) >= 2) { + double m = atof(&tok[1]); + switch (tok[0]) { + case 's': multipliers[i * 7 + 0] = m; break; + case 'p': multipliers[i * 7 + 1] = m; break; + case 'e': multipliers[i * 7 + 2] = m; break; + case 'c': multipliers[i * 7 + 3] = m; break; + case 'i': multipliers[i * 7 + 4] = m; break; + case 'a': multipliers[i * 7 + 5] = m; break; + case 'l': multipliers[i * 7 + 6] = m; break; default: continue; } } - tok=strtok(0, "|"); + tok = strtok(0, "|"); } } else { - multipliers[i*7+skills[i].statA]=skills[i].statMulti; - if(skills[i].statB>=0) multipliers[i*7+skills[i].statB]=skills[i].statMulti; + multipliers[i * 7 + skills[i].statA] = skills[i].statMulti; + if (skills[i].statB >= 0) multipliers[i * 7 + skills[i].statB] = skills[i].statMulti; } sprintf(key, "SkillCost%d", i); - if(GetPrivateProfileStringA("Skills", key, "", buf, 512, file)) { - char* tok=strtok(buf, "|"); - DWORD upto=0; - BYTE price=1; - while(tok && upto<512) { - if(strlen(tok)) { - DWORD next=atoi(tok); - while(upto