View previous topic :: View next topic |
Author |
Message |
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Fri Jun 15, 2007 12:14 Post subject: |
|
|
I'd better do UseFeat/UseSkill. |
|
Back to top |
|
|
acaos
Joined: 08 May 2007 Posts: 153
|
Posted: Fri Jun 15, 2007 15:29 Post subject: |
|
|
You rock! Looking forward to it.
Could you get CastSpell as well? Would be great to have a hook that would occur before the spell is actually expended (as it is in the Bioware spell hook).
Thanks again!
Acaos |
|
Back to top |
|
|
acaos
Joined: 08 May 2007 Posts: 153
|
Posted: Mon Jun 18, 2007 15:08 Post subject: |
|
|
Again, this plugin is really amazing.
I have a small contribution, adding EVENT_CAST_SPELL, GetEventItemRadial(), GetEventSpellId(), and GetEventAttackFeatId(), and adding the ability to bypass attack, spell, and pickpocket events.
Acaos
Code: |
--- readme.txt.orig 2007-06-21 14:14:56.000000000 -0500
+++ readme.txt 2007-06-21 14:51:12.000000000 -0500
@@ -1,18 +1,24 @@
-Modified NWNX2 library (2.7 beta2) & NWNX Events plugin (version 1.1.5)
+Modified NWNX2 library (2.7 beta2) & NWNX Events plugin (version 1.1.5-acaos)
Provides hooks for the following events:
-* PickPocket
+* PickPocket (this action can be blocked from script)
- oCreature
- oTarget
-* Attack
+* Attack (this action can be blocked from script)
- oCreature
- oTarget
-* UseItem
+ - nFeatId
+* UseItem (this action can be blocked from script)
- oCreature
- oTarget
- oItem
- vPosition
- (this action can be blocked from script)
+ - nRadial
+* CastSpell (this action can be blocked from script)
+ - oCreature
+ - oTarget
+ - vPosition
+ - nSpellId
Provides functions for conditional and action scripts:
int GetCurrentNodeType();
@@ -40,6 +46,15 @@
-----------------
CHANGELOG:
+1.1.5-acaos (21.06.2007)
+- Renamed GetActionItem to GetEventItem to match other names
+- Added ability to bypass EVENT_PICKPOCKET and EVENT_ATTACK
+- Added EVENT_CAST_SPELL
+- New functions for attack feat, cast spell, and item radial:
+ int GetEventItemRadial()
+ int GetEventSpellId()
+ int GetEventAttackFeatId()
+
1.1.5 (14.04.2007)
- New functions for conversations:
string GetCurrentNodeText(int nLangID, int nGender);
@@ -65,4 +80,4 @@
int GetCurrentNodeType();
int GetCurrentNodeID();
int GetCurrentAbsoluteNodeID();
-- Released the sources
\ No newline at end of file
+- Released the sources
--- nwnx_events.nss.orig 2007-06-18 07:57:21.000000000 -0500
+++ nwnx_events.nss 2007-06-21 14:51:27.000000000 -0500
@@ -2,6 +2,7 @@
const int EVENT_PICKPOCKET = 2;
const int EVENT_ATTACK = 3;
const int EVENT_USE_ITEM = 4;
+const int EVENT_CAST_SPELL = 5;
const int NODE_TYPE_STARTING_NODE = 0;
const int NODE_TYPE_ENTRY_NODE = 1;
@@ -19,8 +20,11 @@
const int LANGUAGE_JAPANESE = 131;
int GetEventType();
-object GetActionTarget();
-object GetActionItem();
+object GetEventTarget();
+object GetEventItem();
+int GetEventItemRadial();
+int GetEventAttackFeatId();
+int GetEventSpellId();
vector GetEventPosition();
void BypassEvent();
@@ -49,6 +53,24 @@
return GetLocalObject(GetModule(), "NWNX!EVENTS!ITEM");
}
+int GetEventItemRadial()
+{
+ SetLocalString(GetModule(), "NWNX!EVENTS!GET_EVENT_SUBID", " ");
+ return StringToInt(GetLocalString(GetModule(), "NWNX!EVENTS!GET_EVENT_SUBID"));
+}
+
+int GetEventAttackFeatId()
+{
+ SetLocalString(GetModule(), "NWNX!EVENTS!GET_EVENT_SUBID", " ");
+ return StringToInt(GetLocalString(GetModule(), "NWNX!EVENTS!GET_EVENT_SUBID"));
+}
+
+int GetEventSpellId()
+{
+ SetLocalString(GetModule(), "NWNX!EVENTS!GET_EVENT_SUBID", " ");
+ return StringToInt(GetLocalString(GetModule(), "NWNX!EVENTS!GET_EVENT_SUBID"));
+}
+
vector GetEventPosition()
{
SetLocalString(GetModule(), "NWNX!EVENTS!GET_EVENT_POSITION", " ");
@@ -130,4 +152,4 @@
{
if(nGender!=1) nGender = 0;
SetLocalString(GetModule(), "NWNX!EVENTS!SET_NODE_TEXT", IntToString(nLangID*2 + nGender)+"¬"+sText);
-}
\ No newline at end of file
+}
--- events/HookFunc.cpp.orig 2007-04-14 12:13:46.000000000 -0500
+++ events/HookFunc.cpp 2007-06-21 14:46:12.000000000 -0500
@@ -39,6 +39,7 @@
dword oPC = 0;
dword oTarget_b = OBJECT_INVALID;
dword oItem_b = OBJECT_INVALID;
+int nSubID_b = 0;
int bBypass_b;
dword buffer;
@@ -55,6 +56,7 @@
unsigned char d_ret_code_pp[0x20];
unsigned char d_ret_code_at[0x20];
unsigned char d_ret_code_ui[0x20];
+unsigned char d_ret_code_us[0x20];
unsigned char d_ret_code_cn[0x20];
unsigned char d_ret_code_sn[0x20];
unsigned char d_ret_code_cs[0x20];
@@ -92,10 +94,15 @@
asm ("mov %eax, oTarget_b");
events.oTarget = oTarget_b;
//asm ("sub $4, %edi");
- events.FireEvent(*(dword *)oPC, EVENT_PICKPOCKET);
+ bBypass_b = events.FireEvent(*(dword *)oPC, EVENT_PICKPOCKET);
}
asm ("popa");
asm ("leave");
+ if(bBypass_b)
+ {
+ asm("mov $1, %eax");
+ asm("ret");
+ }
asm ("mov $d_ret_code_pp, %eax");
asm ("jmp %eax");
}
@@ -115,10 +122,20 @@
asm ("mov %eax, oTarget_b");
events.oTarget = oTarget_b;
//asm ("sub $4, %edi");
- events.FireEvent(*(dword *)oPC, EVENT_ATTACK);
+
+ asm ("mov 0x1C(%ebp), %eax");
+ asm ("mov %eax, nSubID_b");
+ events.nSubID = nSubID_b;
+
+ bBypass_b = events.FireEvent(*(dword *)oPC, EVENT_ATTACK);
}
asm ("popa");
asm ("leave");
+ if(bBypass_b)
+ {
+ asm("mov $1, %eax");
+ asm("ret");
+ }
asm ("mov $d_ret_code_at, %eax");
asm ("jmp %eax");
}
@@ -152,7 +169,12 @@
asm ("mov %eax, oItem_b");
events.oItem = oItem_b;
- events.Log(2, "UseItem: oPC=%08lX, oTarget=%08lX, oItem=%08lX, vTarget=%f/%f/%f\n", *(dword *)oPC, events.oTarget, events.oItem, pvTarget->x, pvTarget->y, pvTarget->z);
+ //Get nSubID
+ asm ("mov 0x10(%ebp), %eax");
+ asm ("mov %eax, nSubID_b");
+ events.nSubID = nSubID_b;
+
+ events.Log(4, "UseItem: oPC=%08lX, oTarget=%08lX, oItem=%08lX, vTarget=%08lX (%f/%f/%f), nRadial=%d\n", *(dword *)oPC, events.oTarget, events.oItem, pvTarget, pvTarget->x, pvTarget->y, pvTarget->z, nSubID_b);
bBypass_b = events.FireEvent(*(dword *)oPC, EVENT_USE_ITEM);
}
asm ("popa");
@@ -166,6 +188,49 @@
asm ("jmp %eax");
}
+void CastSpellHookProc()
+{
+ asm ("pusha");
+ if (!scriptRun)
+ {
+ //Get oPC
+ asm ("mov 0x8(%ebp), %eax");
+ asm ("add $4, %eax");
+ asm ("mov %eax, oPC");
+
+ //Get oTarget
+ asm ("mov 0x2c(%ebp), %eax");
+ asm ("mov %eax, oTarget_b");
+ events.oTarget = oTarget_b;
+
+ //Get vTarget
+ asm ("mov %ebp, %eax");
+ asm ("add $0x20, %eax");
+ asm ("mov %eax, buffer");
+ CNWSVector *pvTarget = (CNWSVector *) buffer;
+ events.vPosition.x = pvTarget->x;
+ events.vPosition.y = pvTarget->y;
+ events.vPosition.z = pvTarget->z;
+
+ //Get nSubID
+ asm ("mov 0xc(%ebp), %eax");
+ asm ("mov %eax, nSubID_b");
+ events.nSubID = nSubID_b;
+
+ events.Log(4, "CastSpell: oPC=%08lX, oTarget=%08lX, vTarget=%08lX (%f/%f/%f), nSpellId=%d\n", *(dword *)oPC, oTarget_b, pvTarget, pvTarget->x, pvTarget->y, pvTarget->z, nSubID_b);
+ bBypass_b = events.FireEvent(*(dword *)oPC, EVENT_CAST_SPELL);
+ }
+ asm ("popa");
+ asm ("leave");
+ if(bBypass_b)
+ {
+ asm("mov $1, %eax");
+ asm("ret");
+ }
+ asm ("mov $d_ret_code_us, %eax");
+ asm ("jmp %eax");
+}
+
void ConversationNodeSelectHookProc()
{
asm ("pusha");
@@ -482,6 +547,37 @@
return 0;
}
+unsigned long
+FindHookCastSpell ()
+{
+ unsigned long start_addr = 0x08048000, end_addr = 0x08300000;
+ char *ptr = (char *) start_addr;
+
+ while (ptr < (char *) end_addr)
+ {
+ if ((ptr[0] == (char) 0x55) &&
+ (ptr[1] == (char) 0x89) &&
+ (ptr[2] == (char) 0xe5) &&
+ (ptr[3] == (char) 0x57) &&
+ (ptr[4] == (char) 0x56) &&
+ (ptr[5] == (char) 0x53) &&
+ (ptr[6] == (char) 0x81) &&
+ (ptr[7] == (char) 0xec) &&
+ (ptr[8] == (char) 0x1c) &&
+ (ptr[9] == (char) 0x01) &&
+ (ptr[0xA] == (char) 0x00) &&
+ (ptr[0xB] == (char) 0x00) &&
+ (ptr[0xC] == (char) 0x8a) &&
+ (ptr[0xD] == (char) 0x45) &&
+ (ptr[0xE] == (char) 0x3c)
+ )
+ return (unsigned long) ptr;
+ else
+ ptr++;
+ }
+ return 0;
+}
+
/*
.text:08238B50 55 push ebp
.text:08238B51 89 E5 mov ebp, esp
@@ -686,6 +782,7 @@
dword org_PickPocket = FindHookPickPocket();
dword org_Attack = FindHookAttack();
dword org_UseItem = FindHookUseItem();
+ dword org_CastSpell = FindHookCastSpell();
dword org_ConvSelect = FindHookConversationNodeSelect();
dword org_ConvShow = FindHookShowEntryNode();
dword org_ConditionalScript = FindHookConditionalScript();
@@ -708,6 +805,10 @@
{
d_redirect (org_UseItem, (unsigned long)UseItemHookProc, d_ret_code_ui, 12);
}
+ if (org_CastSpell)
+ {
+ d_redirect (org_CastSpell, (unsigned long)CastSpellHookProc, d_ret_code_us, 12);
+ }
if (org_ConvSelect)
{
d_redirect (org_ConvSelect, (unsigned long)ConversationNodeSelectHookProc, d_ret_code_cn, 12);
@@ -746,6 +847,11 @@
else
events.Log(0, "X Could not find UseItem function or hook failed: %x\n", org_UseItem);
+ if (org_CastSpell)
+ events.Log(0, "! CastSpell hooked at %x.\n", org_CastSpell);
+ else
+ events.Log(0, "X Could not find CastSpell function or hook failed: %x\n", org_CastSpell);
+
if (org_ConvSelect)
events.Log(0, "! ConversationNodeSelect hooked at %x.\n", org_ConvSelect);
else
--- events/NWNXEvents.h.orig 2007-06-18 07:49:21.000000000 -0500
+++ events/NWNXEvents.h 2007-06-21 14:01:44.000000000 -0500
@@ -45,6 +45,7 @@
int nEventID;
dword oTarget;
dword oItem;
+ int nSubID;
CNWSDialogClass *pConversation;
int nSelectedNodeID;
int nSelectedAbsoluteNodeID;
@@ -61,5 +62,6 @@
#define EVENT_PICKPOCKET 2
#define EVENT_ATTACK 3
#define EVENT_USE_ITEM 4
+#define EVENT_CAST_SPELL 5
#endif
--- events/NWNXEvents.cpp.orig 2007-06-18 07:50:40.000000000 -0500
+++ events/NWNXEvents.cpp 2007-06-21 14:02:06.000000000 -0500
@@ -201,6 +201,11 @@
if (strlen(Parameters) > 24)
snprintf(Parameters, strlen(Parameters), "%f¬%f¬%f", vPosition.x, vPosition.y, vPosition.z);
}
+ else if (strncmp(Request, "GET_EVENT_SUBID", 18) == 0)
+ {
+ if (strlen(Parameters) > 1)
+ sprintf(Parameters, "%d", nSubID);
+ }
else if (strncmp(Request, "BYPASS", 6) == 0)
{
bBypass = atoi(Parameters);
|
|
|
Back to top |
|
|
acaos
Joined: 08 May 2007 Posts: 153
|
Posted: Fri Jun 22, 2007 0:19 Post subject: |
|
|
I just updated my diff above with hooks for cast spell and attack feat events.
Acaos |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Sat Jun 23, 2007 23:35 Post subject: |
|
|
Thanks! I'll include your modifications in the next version. |
|
Back to top |
|
|
ShaDoOoW
Joined: 20 Aug 2005 Posts: 584
|
Posted: Wed Jul 11, 2007 0:47 Post subject: |
|
|
Interesting, Im using latest win version and i found out, that if i get command Stay and Guard (or I use V,W,X) it fire attack event (with no valid value).
I don't mind it, but this hide function can help you .
EDIT: When I attacked in familiar to my person and then use V,W,X, OnAttack started with my familiar as Target. _________________ Community Patch / NWNX Patch / NWNX Files / NWNX Connect |
|
Back to top |
|
|
ShaDoOoW
Joined: 20 Aug 2005 Posts: 584
|
Posted: Wed Jul 11, 2007 22:59 Post subject: |
|
|
Next issue:
NWNX.ini
Code: | [EVENTS]
event_script= sh_onuserdefined
[CHAT]
chat_script= sh_onuserdefined
server_script= sh_onuserdefined |
However script sh_onuserdefined is not fired. I found out that it try to run sh_onuserdefine script. So maximal length of fired script is 15. (but valid script name can contain 16chars)
EDIT: It's issue both events and chat .... _________________ Community Patch / NWNX Patch / NWNX Files / NWNX Connect
Last edited by ShaDoOoW on Thu Jul 12, 2007 1:59; edited 1 time in total |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Thu Jul 12, 2007 1:36 Post subject: |
|
|
Ok, thanks, I'll try to fix it. |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Sat Feb 23, 2008 14:52 Post subject: |
|
|
NWNX Events 1.1.7 (Linux)
- New function for UseItem event:
Code: | int GetEventItemRadial(); |
Added bypass option to PickPocket event
Fixed a bug that could cause the server to crash
New event: EVENT_QUICKCHAT
New function:
Code: | int GetEventSubType(); |
http://data.virusman.ru/nwn/nwnx_events-1.1.7-linux.rar |
|
Back to top |
|
|
gabonacorp
Joined: 27 Dec 2007 Posts: 12
|
Posted: Sat Feb 23, 2008 19:22 Post subject: |
|
|
If you can make a UseHIPS() event - or something like that - that would be great, becouse we would like to control the time when the SD can use this feat. |
|
Back to top |
|
|
Timear
Joined: 23 Aug 2005 Posts: 31
|
Posted: Thu Mar 06, 2008 8:05 Post subject: |
|
|
Is it possible to get a "Companion/Familiar dismissed" event?
While for Henchmen this is achieved by a silent shout within the BioWare-AI, familiars and companions do not seem to receive this silent shout at all. |
|
Back to top |
|
|
Zunath
Joined: 06 Jul 2006 Posts: 183
|
Posted: Sun Mar 09, 2008 19:32 Post subject: |
|
|
Sorry to bug you about this, but is there any chance of getting a windows version of the events the linux version has?
Thanks. |
|
Back to top |
|
|
Timear
Joined: 23 Aug 2005 Posts: 31
|
Posted: Fri Mar 14, 2008 7:50 Post subject: |
|
|
Next one: http://nwvault.ign.com/View.php?view=Hakpaks.Detail&id=7424 adds elven, dwarven and alchemical fonts to the game.
With an OnExamined()-Event that is also able of being bypassed it should be possible to script a system to show up a translated Description only to those players whose characters are capable of reading the corresponding language.
Or in case of signs, books or letters in common speech to only those who are capable reading.
Possible sequence:
- catch event
- check if there's a special description stored in a local variable on the examined object
- check if the player is able to read this special description
- if not, exit the event-script and standard description will be shown
- if yes, set description of the to the special description, use ActionExamine() and restore the description afterwards. |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|