Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #59 weapon auto-equipping #62

Merged
merged 1 commit into from Jan 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/Ninja/G1CP/Content/Fixes/Session/fix059_FixEquipBestWeapons.d
@@ -0,0 +1,55 @@
/*
* Intercept default equipping of best ranged and melee weapons of NPCs. Best weapons will now only be equipped if no
* weapon of respective type is not already equipped. This will prevent trading NPCs to block the best weapon.
* Source: https://forum.worldofplayers.de/forum/threads/?p=25954713
*
* - Requires Ikarus, LeGo (HookEngine)
* - Compatible with Gothic 1 and Gothic 2
*
* Call FixEquipBestWeapons_Init from Init_Global.
*/
func void FixEquipBestWeapons_Init() {
const int once = 0;
if (!once) {
MEM_InitAll();

const int oCNpc__Enable_equipBestWeapons_G1 = 6955616; //0x6A2260
const int oCNpc__Enable_equipBestWeapons_G2 = 7626662; //0x745FA6
var int addr; addr = MEMINT_SwitchG1G2(oCNpc__Enable_equipBestWeapons_G1, oCNpc__Enable_equipBestWeapons_G2);

// Remove default equipping of best melee and ranged weapon to add more conditions
const int nop20Bytes[5] = { -1869574000, -1869574000, -1869574000, -1869574000, -1869574000 }; //0x90 * 20
MemoryProtectionOverride(addr, 18);
MEM_CopyBytes(_@(nop20Bytes), addr, 18);

HookEngineF(addr, 5, _FixEquipBestWeapons);

once = 1;
};
};

func void NpcEquipBestWeaponByType(var C_Npc npc, var int type) {
const int oCNpc__EquipBestWeapon_G1 = 6988320; //0x6AA220
const int oCNpc__EquipBestWeapon_G2 = 7663408; //0x74EF30
var int npcPtr; npcPtr = _@(npc);
const int call = 0;
if (CALL_Begin(call)) {
CALL_IntParam(_@(type));
CALL__thiscall(_@(npcPtr), MEMINT_SwitchG1G2(oCNpc__EquipBestWeapon_G1, oCNpc__EquipBestWeapon_G2));
call = CALL_End();
};
};

func void _FixEquipBestWeapons() {
var C_Npc npc; npc = _^(ESI);

if (!Npc_HasEquippedMeleeWeapon(npc))
&& (!Npc_HasReadiedMeleeWeapon(npc)) {
NpcEquipBestWeaponByType(npc, ITEM_KAT_NF);
};

if (!Npc_HasEquippedRangedWeapon(npc))
&& (!Npc_HasReadiedRangedWeapon(npc)) {
NpcEquipBestWeaponByType(npc, ITEM_KAT_FF);
};
};
1 change: 1 addition & 0 deletions src/Ninja/G1CP/Content/NinjaInit.d
Expand Up @@ -7,6 +7,7 @@ func void Ninja_G1CP_Menu(var int menuPtr) {
// Initialize one-time-per-session fixes
const int once = 0;
if (!once) {
FixEquipBestWeapons_Init(); // #59

once = 1;
};
Expand Down