|
-
Fackel via Tastendruck in die Hand
Moin zusammen,
ich möchte per Tastendruck die Benutzung der Fackel vereinfachen. Hierzu wird dir Fackel automatisch in die Hand gelegt. Problem: Die Fackel brennt nicht
Habe schon viel versucht aber ich bekomme sie nicht zum leuchten. Vielleicht könnt ihr mir ja helfen.
Beste Grüße
Aebo
Hier das Script
Code:
func void FACKEL_INIT_Loop()
{
keystate_Fackel = MEM_KeyState (KEY_L);
if (keystate_Fackel == KEY_PRESSED)
&& (C_BodyStateContains(hero, BS_STAND))
{
if (Hatfackelinderhand == TRUE)
{
Print("FACKEL geht aus");
RemoveSlotItem(hero, "ZS_LEFTHAND");
Mdl_RemoveOverlayMDS (hero, "Humans_Torch.mds");
Npc_RemoveInvItems (hero, ItLsTorch, 2);
Hatfackelinderhand = FALSE;
}
else
{
if (Npc_HasItems(hero, ItLsTorch) >= 1)
{
Print("Held macht Fackel an");
CreateSlotItem(hero, "ZS_LEFTHAND", ItLsTorchburning);
Mdl_ApplyOverlayMds (hero, "Humans_Torch.mds");
Hatfackelinderhand = TRUE;
}
else
{
AI_PlayAni (hero, "T_DONTKNOW");
B_Say_Overlay (hero, hero, "$MISSINGITEM");
};
};
};
};
Das Wappen -Eine fantastische Spielwelt erwartet dich- -bis zu 100 Stunden Spielzeit-
-
Apprentice
Try this:
Code:
Npc_GetInvItem(hero, ItLsTorch);
CALL_PtrParam(_@(item));
CALL__thiscall(_@(hero), oCNpc__UseItem);
-
G1 Torch on-off
Zitat von Rayzer
Try this:
Code:
Npc_GetInvItem(hero, ItLsTorch);
CALL_PtrParam(_@(item));
CALL__thiscall(_@(hero), oCNpc__UseItem);
Tested with G1 - works, however, it's tricky, seems like you have to remove item afterwards, otherwise there will be equipped empty slot in inventory (not sure if G2A behaves differently)
Code:
/***
These functions will fill global variable item 'pointing' to specific item in inventory
NPC_Get_Inventory_Category_Item - inv_category only
NPC_Get_Inventory_Item - all inv_category
***/
FUNC INT NPC_Get_Inventory_Category_Item (var C_NPC slf, var int inv_category, var int itm)
{
var int p;
var int itm_count;
var int itm_instance;
var int itm_slot;
itm_slot = 0;
//Loop
p = MEM_StackPos.position;
//Is there an item in this slot?
if (NPC_GetInvItemBySlot (slf, inv_category, itm_slot) > 0)
{
itm_instance = Hlp_GetInstanceID (item);
if (itm == itm_instance)
{
return TRUE;
} else
{
itm_slot = itm_slot + 1;
MEM_StackPos.position = p;
};
};
return FALSE;
};
FUNC INT NPC_Get_Inventory_Item (var int slfInstance, var int itm)
{
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
if (NPC_Get_Inventory_Category_Item (slf, INV_WEAPON, itm) == FALSE)
{
if (NPC_Get_Inventory_Category_Item (slf, INV_ARMOR, itm) == FALSE)
{
if (NPC_Get_Inventory_Category_Item (slf, INV_RUNE, itm) == FALSE)
{
if (NPC_Get_Inventory_Category_Item (slf, INV_MAGIC, itm) == FALSE)
{
if (NPC_Get_Inventory_Category_Item (slf, INV_FOOD, itm) == FALSE)
{
if (NPC_Get_Inventory_Category_Item (slf, INV_POTION, itm) == FALSE)
{
if (NPC_Get_Inventory_Category_Item (slf, INV_DOC, itm) == FALSE)
{
if (NPC_Get_Inventory_Category_Item (slf, INV_MISC, itm) == FALSE)
{
return FALSE;
};
};
};
};
};
};
};
};
return TRUE;
};
/***
Returns pointer to item in slotName
***/
FUNC INT NPC_GetSlotItem (var int slfInstance, var string slotName)
{
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
//0068F4F0 .text Debug data ?GetSlotItem@oCNpc@@QAEPAVoCItem@@ABVzSTRING@@@Z
const int oCNPC__GetSlotItem = 6878448;
CALL_zStringPtrParam (slotName);
CALL__thiscall (_@ (slf), oCNPC__GetSlotItem);
return CALL_RetValAsPtr ();
};
/***
Will use item
***/
FUNC VOID NPC_UseItem (var int slfInstance, var int itm)
{
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
//00698810 .text Debug data ?UseItem@oCNpc@@QAEHPAVoCItem@@@Z
const int oCNPC__UseItem = 6916112;
//CALL_PtrParam (MEM_InstToPtr (itm));
CALL_IntParam (itm);
CALL__thiscall (MEM_InstToPtr (slf), oCNPC__UseItem);
};
/***
If NPC has in hand ItLsTorchBurning - it will 'put it back to inventory', otherwise it will 'lit' ItLsTorch and put ItLsTorchBurning in hand
***/
FUNC VOID NPC_TorchSwitchOnOff (var int slfInstance)
{
var int ptr;
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
//Get pointer to ZS_LEFTHAND
ptr = NPC_GetSlotItem (slf, "ZS_LEFTHAND");
//Is there anything already in hand?
if (ptr) {
var C_Item itm;
itm = _^ (ptr);
//Is it ItLsTorchBurning ?
if (Hlp_GetInstanceID (itm) == Hlp_GetInstanceID (ItLsTorchBurning))
{
//Use ItLsTorchBurning - will put ItLsTorch back to inventory
NPC_UseItem (slf, ptr);
//Remove ItLsTorchBurning
NPC_RemoveInvItem (slf, ptr);
};
} else
{
//Fill item with pointer to any ItLsTorch in inventory
if (NPC_Get_Inventory_Item (slf, ItLsTorch))
{
//Equip it - puts ItLsTorchBurning in hand
NPC_UseItem (slf, _@ (item));
//Remove ItLsTorch
NPC_RemoveInvItem (slf, _@ (item));
};
};
};
-
Hmmm, aebo, tnx for your post! This can be a nice atmospheric improvement - 2 more functions can give couple of ZS_ functions new flavor
Code:
FUNC VOID NPC_TorchSwitchOn (var int slfInstance)
{
var int ptr;
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
//Get pointer to ZS_LEFTHAND
ptr = NPC_GetSlotItem (slf, "ZS_LEFTHAND");
//Is hand empty?
if (!ptr) {
//Fill item with pointer to some ItLsTorch in inventory
if (NPC_Get_Inventory_Item (slf, ItLsTorch))
{
//Equip it - puts ItLsTorchBurning in hand
NPC_UseItem (slf, _@ (item));
//Remove ItLsTorch
NPC_RemoveInvItem (slf, _@ (item));
};
};
};
FUNC VOID NPC_TorchSwitchOff (var int slfInstance)
{
var int ptr;
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
//Get pointer to ZS_LEFTHAND
ptr = NPC_GetSlotItem (slf, "ZS_LEFTHAND");
//Is there anything in hand?
if (ptr) {
var C_Item itm;
itm = _^ (ptr);
//Is it ItLsTorchBurning ?
if (Hlp_GetInstanceID (itm) == Hlp_GetInstanceID (ItLsTorchBurning))
{
//Use ItLsTorchBurning - will put ItLsTorch back to inventory
NPC_UseItem (slf, ptr);
//Remove ItLsTorchBurning
NPC_RemoveInvItem (slf, ptr);
};
};
};
ZS_Guard, when walking from one waypoint to another:
Code:
FUNC VOID ZS_Guard ()
{
...
//Night time ?
if (Wld_IsTime (21, 30, 05, 30))
{
//Is target WP far enough - use torch
if (NPC_GetDistToWP (self, self.WP) > 500)
{
NPC_TorchSwitchOn (self);
};
} else
{
NPC_TorchSwitchOff (self);
};
};
FUNC INT ZS_Guard_Loop ()
{
//If guard is on its waypoint - remove torch
if (NPC_GetDistToWP (self, self.WP) < 500)
{
NPC_TorchSwitchOff (self);
};
...
AI_Wait (self, 1);
return LOOP_CONTINUE;
};
FUNC VOID ZS_Guard_End ()
{
...
NPC_TorchSwitchOff (self);
};
ZS_Guide when guiding player somewhere:
Code:
FUNC VOID ZS_GuidePC ()
{
...
};
FUNC INT ZS_GuidePC_Loop ()
{
//If guiding around - use torch in night time, remove during day time
if (Wld_IsTime (21, 30, 05, 30))
{
NPC_TorchSwitchOn (self);
} else
{
NPC_TorchSwitchOff (self);
};
};
FUNC VOID ZS_GuidePC_End ()
{
...
NPC_TorchSwitchOff (self);
};
B_SelectWeapon - remove torch before drawing a weapon:
Code:
FUNC VOID B_SelectWeapon (var C_NPC slf, var C_NPC oth)
{
//Remove torch
NPC_TorchSwitchOff (self);
...
and probably others as well.
-
Again thanks for sharing Fawkes!
-
I like this atmospheric improvement to the ZS. Just a remark: Maybe you could make sure that NPCs do have a torch.
Zitat von F a w k e s
Code:
FUNC VOID NPC_TorchSwitchOn (var int slfInstance)
{
var int ptr;
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
//Get pointer to ZS_LEFTHAND
ptr = NPC_GetSlotItem (slf, "ZS_LEFTHAND");
//Is hand empty?
if (!ptr) {
if (!Npc_IsPlayer(slf)) && (!Npc_HasItems(ItLsTorch)) {
CreateInvItem(slf, ItLsTorch);
};
//Fill item with pointer to some ItLsTorch in inventory
if (NPC_Get_Inventory_Item (slf, ItLsTorch))
{
//Equip it - puts ItLsTorchBurning in hand
NPC_UseItem (slf, _@ (item));
//Remove ItLsTorch
NPC_RemoveInvItem (slf, _@ (item));
};
};
};
-
G1 remove torch when drawing weapon
Zitat von mud-freak
Maybe you could make sure that NPCs do have a torch.
Thank you ! I thought it would maybe be better to have only NPC's using torch if they have it already in inventory - this way you can have a simple control over who is walking around with torch (guard patrolling Old Camp's outer ring) and who not (guard patrolling inside Old Camp's Castle).
Seems like decision of having NPC removing torch only when B_SelectWeapon is called, is not perfect. I tried instead to hook EV_DrawWeapon - and think I like this one much more - anytime NPC or hero draws weapon, while holding a torch - torch will move to inventory.
In case anyone would find this useful: (Gothic 1 address only)
Code:
//006A8500 .text Debug data ?EV_DrawWeapon@oCNpc@@QAEHPAVoCMsgWeapon@@@Z
//006A8B80 .text Debug data ?EV_DrawWeapon1@oCNpc@@QAEHPAVoCMsgWeapon@@@Z
//006A8E20 .text Debug data ?EV_DrawWeapon2@oCNpc@@QAEHPAVoCMsgWeapon@@@Z
const int oCNpc__EV_DrawWeapon = 6980864;
const int oCNpc__EV_DrawWeapon1 = 6982528;
const int oCNpc__EV_DrawWeapon2 = 6983200;
FUNC VOID _HOOK_NPC_DRAWWEAPON ()
{
var oCNPC npc;
npc = _^ (ECX);
if (Hlp_IsValidNPC (npc))
{
NPC_TorchSwitchOff (npc);
};
};
Hook it with:
Code:
HookEngine (oCNpc__EV_DrawWeapon, 6, "_HOOK_NPC_DRAWWEAPON");
HookEngine (oCNpc__EV_DrawWeapon1, 5, "_HOOK_NPC_DRAWWEAPON");
HookEngine (oCNpc__EV_DrawWeapon2, 6, "_HOOK_NPC_DRAWWEAPON");
Geändert von F a w k e s (16.01.2019 um 01:08 Uhr)
-
Zitat von F a w k e s
Thank you ! I thought it would maybe be better to have only NPC's using torch if they have it already in inventory - this way you can have a simple control over who is walking around with torch (guard patrolling Old Camp's outer ring) and who not (guard patrolling inside Old Camp's Castle).
Seems like decision of having NPC removing torch only when B_SelectWeapon is called, is not perfect. I tried instead to hook EV_DrawWeapon - and think I like this one much more - anytime NPC or hero draws weapon, while holding a torch - torch will move to inventory.
In case anyone would find this useful: (Gothic 1 address only)
Code:
//006A8500 .text Debug data ?EV_DrawWeapon@oCNpc@@QAEHPAVoCMsgWeapon@@@Z
const int oCNpc__EV_DrawWeapon = 6980864;
FUNC VOID _HOOK_NPC_DRAWWEAPON ()
{
var oCNPC npc;
npc = _^ (ECX);
if (Hlp_IsValidNPC (npc))
{
NPC_TorchSwitchOff (npc);
};
};
Hook it with:
Code:
HookEngine (oCNpc__EV_DrawWeapon, 6, "_HOOK_NPC_DRAWWEAPON");
In G2, there seem to be multiple addresses that drawing a weapon may occur at. Copying some of our code
Code:
HookEngineF (7654416, 6, Hook_EV_DrawWeapon); //Hook EV_DrawWeapon located at 0x74CC10
HookEngineF (7656160, 5, Hook_EV_DrawWeapon); //Hook EV_DrawWeapon1 located at 0x74D2E0
HookEngineF (7656832, 6, Hook_EV_DrawWeapon); //Hook EV_DrawWeapon2 located at 0x74D580
LeGo also already comes with two of these addresses:
Code:
const int oCNpc__EV_DrawWeapon = 7654416; //0x74CC10 Hook: Shields
const int oCNpc__EV_DrawWeapon1 = 7656160; //0x74D2E0 Hook: Shields
These may be useful when people want to use your code in G2. I don't know whether G1 might also have additional functions you would want to hook?
-
Zitat von Milky-Way
In G2, there seem to be multiple addresses that drawing a weapon may occur at... I don't know whether G1 might also have additional functions you would want to hook?
Thanks for pointing that out !! G1 list of addresses updated.
-
Okay, soweit funktioniert es nun ganz gut. Jetzt brauche ich aber nochmal ein wenig Hilfe.
Ich möchte herausfinden ob die Fackel "manuel" aus dem Inventar angeklickt wurde. Ich habe es schon über die On_state der Fackel probiert, aber leider funktionier diese nicht. Brauche also einen hook, der mir ein "Klick" auf die Fackel aus dem Inventar zurückgibt.
Das Wappen -Eine fantastische Spielwelt erwartet dich- -bis zu 100 Stunden Spielzeit-
-
Wenn man eine Fackel trägt, eine weitere im Inventar hat und diese benutzt, dann wird die Fackel wieder eingesteckt. Deswegen laufen viele (die es wissen) das ganze Spiel nur mit zwei Fackeln herum. Das "Feature" könnte die Umsetzung vereinfachen.
"Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
-
Zitat von NicoDE
Wenn man eine Fackel trägt, eine weitere im Inventar hat und diese benutzt, dann wird die Fackel wieder eingesteckt. Deswegen laufen viele (die es wissen) das ganze Spiel nur mit zwei Fackeln herum. Das "Feature" könnte die Umsetzung vereinfachen.
Genau richtig. Das widerum möchte ich interbinden. Bei dem Feature mit dem Hotkey für die Fackel wird eine Fackel aus dem Inventar entfernt. Nun möchte ich, dass dieses auch funktioniert wenn man auf das Item in dem Inventar klickt. Dafür benötige ich aber einen Hook, der mir das anklicken anzeigt.
Das Wappen -Eine fantastische Spielwelt erwartet dich- -bis zu 100 Stunden Spielzeit-
-
Hi aebo,
Maybe you can try to use something like this - in code below I am checking global variable flg_UseItem_Script - if this is TRUE - then it means function was called from script:
Code:
//Global variable determining whether function was called via script, or via use of inventory
var int flg_UseItem_Script;
//00698810 .text Debug data ?UseItem@oCNpc@@QAEHPAVoCItem@@@Z
const int oCNPC__UseItem_G1 = 6916112;
//0x0073BC10 public: int __thiscall oCNpc::UseItem(class oCItem *)
const int oCNPC__UseItem_G2 = 7584784;
FUNC VOID _HOOK_NPC_USEITEM ()
{
var oCNPC slf;
slf = _^ (ECX);
var oCItem itm;
itm = _^ (MEM_ReadInt (ESP + 4));
//Was this function invoked with script ?
if (flg_UseItem_Script == TRUE)
{
//Reset value
flg_UseItem_Script = FALSE;
} else
{
//Here you know that player used item via inventory
...
};
};
NPC_UseItem - add 1 more line to set value of global variable flg_UseItem_Script to TRUE:
Code:
FUNC VOID NPC_UseItem (var int slfInstance, var int itmInstance)
{
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
flg_UseItem_Script = TRUE;
CALL_PtrParam (MEM_InstToPtr (itmInstance));
CALL__thiscall (MEM_InstToPtr (slf), MEMINT_SwitchG1G2 (oCNPC__UseItem_G1, oCNPC__UseItem_G2));
};
Hook it with:
Code:
HookEngine (MEMINT_SwitchG1G2 (oCNPC__UseItem_G1, oCNPC__UseItem_G2), 7, "_HOOK_NPC_USEITEM");
-
Zitat von F a w k e s
Hi aebo,
Maybe you can try to use something like this - in code below I am checking global variable flg_UseItem_Script - if this is TRUE - then it means function was called from script:
Code:
//Global variable determining whether function was called via script, or via use of inventory
var int flg_UseItem_Script;
//00698810 .text Debug data ?UseItem@oCNpc@@QAEHPAVoCItem@@@Z
const int oCNPC__UseItem_G1 = 6916112;
//0x0073BC10 public: int __thiscall oCNpc::UseItem(class oCItem *)
const int oCNPC__UseItem_G2 = 7584784;
FUNC VOID _HOOK_NPC_USEITEM ()
{
var oCNPC slf;
slf = _^ (ECX);
var oCItem itm;
itm = _^ (MEM_ReadInt (ESP + 4));
//Was this function invoked with script ?
if (flg_UseItem_Script == TRUE)
{
//Reset value
flg_UseItem_Script = FALSE;
} else
{
//Here you know that player used item via inventory
...
};
};
NPC_UseItem - add 1 more line to set value of global variable flg_UseItem_Script to TRUE:
Code:
FUNC VOID NPC_UseItem (var int slfInstance, var int itmInstance)
{
var C_NPC slf;
slf = Hlp_GetNPC (slfInstance);
flg_UseItem_Script = TRUE;
CALL_PtrParam (MEM_InstToPtr (itmInstance));
CALL__thiscall (MEM_InstToPtr (slf), MEMINT_SwitchG1G2 (oCNPC__UseItem_G1, oCNPC__UseItem_G2));
};
Hook it with:
Code:
HookEngine (MEMINT_SwitchG1G2 (oCNPC__UseItem_G1, oCNPC__UseItem_G2), 7, "_HOOK_NPC_USEITEM");
Yeah, now it works. Thanks a lot
Das Wappen -Eine fantastische Spielwelt erwartet dich- -bis zu 100 Stunden Spielzeit-
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|