New file: Externals - parsed before Duals:
func int GetModel(var int npc)
{
CALL__thiscall(MEM_InstToPtr(npc), 7571232);
return CALL_RetValAsInt();
};
func int AniIsActive(var c_npc slf, var string aniname)
{
var int ptr; ptr = GetModel(slf);
const int zCModel_AniIsActive = 5727888; //0x00576690
CALL_zStringPtrParam(Str_Upper(aniname));
CALL__thiscall(ptr, zCModel_AniIsActive);
return CALL_RetValAsInt();
};
func int MEM_KeyHold(var int key1, var int key2)
{
if((MEM_KeyState(key1) == KEY_HOLD && key1)
|| (MEM_KeyState(key2) == KEY_HOLD && key2))
{
return true;
};
return false;
};
func oCItem Hlp_GetItem(var int ID)
{
var zCPar_Symbol symb; symb = _^ (MEM_GetSymbolByIndex (ID));
MEM_PtrToInst (symb.offset);
};
func int oCNpc_GetSlotItem(var c_npc slf, var string slot)
{
CALL_zStringPtrParam(STR_Upper(slot));
CALL__thiscall(_@(slf), 7544720);
return CALL_RetValAsPtr();
};
func void Equip_FarWeapon (var C_NPC slf, var int ItemInst) {
if (!Npc_HasItems (slf, ItemInst)) {
CreateInvItems (slf, ItemInst, 1);
};
if (!Npc_GetInvItem(slf, ItemInst)) {
MEM_AssertFail("Unexpected behaviour in EquipWeapon.");
return;
};
if ((item.mainflag == ITEM_KAT_NF) && (Npc_HasReadiedMeleeWeapon(slf)))
|| ((item.mainflag == ITEM_KAT_FF) && (Npc_HasReadiedRangedWeapon(slf))) {
MEM_Warn ("EquipWeapon: Caller wants to equip a weapon while weapon of the same type is readied. Ignoring request.");
return;
};
if (item.flags & ITEM_ACTIVE)
&& (!EquipWeapon_TogglesEquip) {
/* calling EquipWeapon would unequip the weapon. */
MEM_Info ("EquipWeapon: This weapon is already equipped. Ignoring request.");
return;
};
const int oCNpc__EquipFarWeapon = 7578384; // 0x0073A310
CALL_PtrParam(_@(item));
CALL__thiscall(_@(slf), oCNpc__EquipFarWeapon);
};
func void oCNpc_UseItem(var c_npc slf, var int ItemInst)
{
if (!Npc_HasItems (slf, ItemInst)) {
CreateInvItems (slf, ItemInst, 1);
};
if (!Npc_GetInvItem(slf, ItemInst)) {
return;
};
CALL_PtrParam(_@(item));
CALL__thiscall(_@(slf), oCNpc__UseItem);
};
// Redefine MagBook : <
func int oCItem_HasFlag(var c_item ItemInst, var int flag)
{
CALL_PtrParam(flag);
CALL__thiscall(_@(ItemInst), 7415504);//0x007126D0
return CALL_RetValAsInt();
};
func void oCItem_SetFlag(var c_item ItemInst, var int flag)
{
CALL_PtrParam(flag);
CALL__thiscall(_@(ItemInst), 7415568); //0x00712710
};
func void oCItem_ClearFlag(var c_item ItemInst, var int flag)
{
CALL_PtrParam(flag);
CALL__thiscall(_@(ItemInst), 7415536); //0x007126F0
};
//int __thiscall oCMag_Book::DeRegister(oCItem *) 0x00475CC0 0 5 public: int __thiscall oCMag_Book::DeRegister(oCItem
func int oCMagBook_DeRegister(var int it)
{
var oCNpc her; her = Hlp_GetNpc(hero);
var int ptr; ptr = her.mag_book;
if(ptr)
{
CALL_PtrParam(_@(it));
CALL__thiscall(ptr, 4676800);
return CALL_RetValAsInt();
};
};
func int oCMagBook_GetNoOfSpells()
{
var oCNpc her; her = Hlp_GetNpc(hero);
var int ptr; ptr = her.mag_book;
if(ptr)
{
CALL__thiscall(ptr, 4692832); //0x00479B60
return CALL_RetValAsInt();
};
};
func void oCMagBook_Register(var int it)
{
var oCNpc her; her = Hlp_GetNpc(hero);
var int ptr; ptr = her.mag_book;
if(ptr)
{
CALL_PtrParam(_@(it));
CALL__thiscall(ptr, 4676528); //0x00475BB0
};
};
func void Ext_PutInSlot(var c_npc slf, var c_item itm, var string SlotName)
{
CALL_IntParam(1);
CALL_PtrParam(_@(itm));
CALL_zStringPtrParam(SlotName);
CALL__thiscall(MEM_InstToPtr(slf), oCNpc__PutInSlot);
};
func int Ext_RemoveFromSlot(var c_npc slf, var string SlotName)
{
CALL_IntParam(1);
CALL_PtrParam(1);
CALL_zStringPtrParam(SlotName);
CALL__thiscall(MEM_InstToPtr(slf), oCNpc__RemoveFromSlot);
return CALL_RetValAsInt();
};
Duals system:
const int Hero_TalentDuals = 1;
const string Dual_SlotEquip = "ZS_LONGSWORD";
const string Dual_SlotDraw = "ZS_LEFTHAND";
const string Duals_Mds = "Humans_1hSt1.mds";
var int Dual_SwimFix;
var int Duals_Equipped;
//oCNpc_GetSlotItem
//oCItem_SetFlag
//oCItem_ClearFlag
//Ext_PutInSlot(c_npc, c_item, string)
//Ext_RemoveFromSlot(c_npc, string);
func void Dual_Equip()
{
if(!Hero_TalentDuals)
{
return;
};
var c_item it; it = _^(MEM_ReadInt(ESP+324+4));
var c_item old;
//Get action key!
var int k1; k1 = MEM_GetKey("keyParade");
var int k2; k2 = MEM_GetSecondaryKey("keyParade");
if(MEM_KeyState(k1) == KEY_PRESSED && k1)
||(MEM_KeyState(k2) == KEY_PRESSED && k2)
{
if(it.flags & (ITEM_SWD | ITEM_AXE))
&&(oCNpc_GetSlotItem(hero, "ZS_SWORD"))
{
if(!oCNpc_GetSlotItem(hero, Dual_SlotEquip))
{
if(!(it.flags & ITEM_ACTIVE))
{
Ext_PutInSlot(hero, it, Dual_SlotEquip);
oCItem_SetFlag(it, ITEM_ACTIVE);
Mdl_ApplyOverlayMds(hero, Duals_Mds);
Duals_Equipped = true;
};
}
else
{
if(it.flags & ITEM_ACTIVE)
{
if(oCNpc_GetSlotItem(hero, Dual_SlotEquip) == _@(it))
{
old = _^(oCNpc_GetSlotItem(hero, Dual_SlotEquip));
oCItem_ClearFlag(old, ITEM_ACTIVE);
Ext_RemoveFromSlot(hero, Dual_SlotEquip);
Mdl_RemoveOverlayMds(hero, Duals_Mds);
Duals_Equipped = false;
};
}
else
{
if(oCNpc_GetSlotItem(hero, Dual_SlotEquip))
{
old = _^(oCNpc_GetSlotItem(hero, Dual_SlotEquip));
Ext_RemoveFromSlot(hero, Dual_SlotEquip);
oCItem_ClearFlag(old, ITEM_ACTIVE);
Mdl_RemoveOverlayMds(hero, Duals_Mds);
Duals_Equipped = false;
};
//Put new
Ext_PutInSlot(hero, it, Dual_SlotEquip);
oCItem_SetFlag(it, ITEM_ACTIVE);
Mdl_ApplyOverlayMds(hero, Duals_Mds);
Duals_Equipped = true;
};
};
};
};
};
func void Dual_Unequip()
{
if(ECX != _@(hero))
{
return;
};
var c_item it; it = _^(MEM_ReadInt(ESP+4));
if(it.flags & (ITEM_SWD | ITEM_AXE))
{
if(oCNpc_GetSlotItem(hero, Dual_SlotEquip))
{
it = _^(Ext_RemoveFromSlot(hero, Dual_SlotEquip));
oCItem_ClearFlag(it, ITEM_ACTIVE);
Mdl_RemoveOverlayMds(hero, Duals_Mds);
Duals_Equipped = false;
};
};
};
func void Dual_Drop()
{
if(ECX != _@(hero))
{
return;
};
var oCNpc her; her = _^(ECX);
if(her.fmode)
{
return;
};
if(oCNpc_GetSlotItem(hero, "ZS_LEFTHAND"))
{
var c_item it; it = _^(oCNpc_GetSlotItem(hero, Dual_SlotDraw));
oCNpc_UnequipItem(hero, _@(it));
CALL_zStringPtrParam(Dual_SlotDraw);
CALL__thiscall(_@(hero), 7644560);
};
};
func void Dual_Draw()
{
if(ECX != _@(hero))
{
return;
};
if (oCNpc_GetSlotItem(hero, "ZS_RIGHTHAND")
&& !oCNpc_GetSlotItem(hero, Dual_SlotDraw))
{
var c_item it; it = _^(Ext_RemoveFromSlot(hero, Dual_SlotEquip));
Ext_PutInSlot(hero, it, Dual_SlotDraw);
Dual_SwimFix = _@(it);
};
};
func void Dual_UnDraw()
{
if(ECX != _@(hero))
{
return;
};
if (oCNpc_GetSlotItem(hero, "ZS_SWORD")
&& !oCNpc_GetSlotItem(hero, Dual_SlotEquip))
{
var c_item it; it = _^(Ext_RemoveFromSlot(hero, Dual_SlotDraw));
Ext_PutInSlot(hero, it, Dual_SlotEquip);
Dual_SwimFix = 0;
};
};
func void DisableKeys(var int key)
{
if(MEM_ReadInt(ESP+4)==key)
{
MEM_WriteInt(ESP+4,-1);
};
};
func void Duals_RemoveKeys()
{
var int k1; k1 = MEM_GetKey("keyParade");
var int k2; k2 = MEM_GetSecondaryKey("keyParade");
DisableKeys(k1);
DisableKeys(k2);
};
//keyShowMap
func void SwimFix()
{
if(Dual_SwimFix)
{
var c_item d; d = _^(Dual_SwimFix);
if(C_BodyStateContains(hero, BS_SWIM)
|| C_BodyStateContains(hero, BS_DIVE))
{
if(oCNpc_GetSlotItem(hero, Dual_SlotDraw))
{
Ext_RemoveFromSlot(hero, Dual_SlotDraw);
};
Ext_PutInSlot(hero, d, Dual_SlotEquip);
Dual_SwimFix = 0;
};
};
};
func void Duals_Init()
{
const int done = 0;
if(!done)
{
HookEngineF(7546560, 6, Dual_Unequip);
HookEngineF(7397440, 6, Duals_RemoveKeys);
HookEngineF(7369071, 6, Dual_Equip);
HookEngineF(7654416, 6, Dual_Draw);
HookEngineF(7656160, 5, Dual_Draw);
HookEngineF(7656832, 6, Dual_Draw);
HookEngineF(7658272, 7, Dual_UnDraw);
HookEngineF(7660720, 7, Dual_UnDraw);
done = 1;
};
FF_ApplyOnce(SwimFix);
};
Key Parade == Equip left dual.
To fix map you must add fix in function: player_hotkey_screen_map.
That's all, but code don't work with my QuickSlots!