logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Hooking Player Attitude Changes for pvp
Goto page Previous  1, 2, 3
 
Post new topic   Reply to topic    nwnx.org Forum Index -> Windows development
View previous topic :: View next topic  
Author Message
MaxRock



Joined: 24 Jan 2008
Posts: 196

PostPosted: Fri Jul 30, 2010 0:20    Post subject: Reply with quote

No, no, you haven't wasted anybody's time. It'll work!

SetPCDislike and SetPCLike are script functions.

Yes, there will have to be an override variable... let's see.

Use the include from nwnx_funcs. The include folder and nwn_internals folder should be universally usable, not just for nwnx_funcs.

So, in project properties add it to the include path (just the "include" folder) and add #include "types.h" - and probably "nwn_internals.h" - to stdafx.cpp.

Then drag the .cpp files you want to use in the "Source Files" section of the project.
This should give you all the strucs and functionality for the internal nwn calls, like creating a CExoString.

To get the override variable you can actually set a local on the creature(s)
and then in SetLikesme you can get them with:
Code:

CNWSObject *oTarget = (CNWSObject*)(*NWN_AppManager)->app_server->srv_internal->GetCreatureByGameObjectID(objid);
CExoString VarName("OverrideVarname");

int bOverride1 = ((CNWSObject*)cre)->obj_vartable.GetInt(VarName);
int bOverride2 = oTarget->obj_vartable.GetInt(VarName);


This will get you the local from both creatures. You probably only need to get it from one of them.
Back to top
View user's profile Send private message Send e-mail MSN Messenger
Baaleos



Joined: 02 Sep 2007
Posts: 830

PostPosted: Fri Jul 30, 2010 0:26    Post subject: Reply with quote

cool, I was hoking around nwn funcs trying to 'rip' the parts I need from it. Lol

In regards to the method you suggested, it might be best if I just do a simple comparison between a var on the originator, and a var on the target. Which would prevent the need of any complicated nwnscript functions


I am making my module so that Vampires are marked with a variable called
"IS_VAMP"
and the Humans, well.... they wont have this.

so a simple comparison of their Vampire status, will allow us to tell if they are faction enemies, and if so, disallow friendlyness.
eg - if(IS_VAMP1 != IS_VAMP2)
{
Bypass
}

In regards to the bOverride, just getting it once from the originator would probably be sufficient, because it could be set from nwnscript, to identify that the whole operation should continue without interference.
Back to top
View user's profile Send private message
Baaleos



Joined: 02 Sep 2007
Posts: 830

PostPosted: Fri Jul 30, 2010 1:13    Post subject: Reply with quote

Finally got it building.

Code:

void CNWNXEvents::FireEvent(const int pObj, int nEvID, const char * czName )
{
   nEventID = nEvID;

   if( LOG == 1 )
      Log( "o %s (%d): OBJECT_SELF: %08lx.\n", czName, nEventID, pObj );

   //RunScript(eventScript, pObj);
    CExoString ScriptName(eventScript);
   RunScript_Hook((*NWN_VirtualMachine), NULL, &ScriptName, pObj, 1);
   oTarget = OBJECT_INVALID;
   nEventID = 0;

   //fflush(m_fFile);
}


I have changed it now, to see if it works with CExoString ScriptName("events_script"); instead, just on the off chance that the ExoString didnt like arrays of char's

I tried to edit the original fire event script, to use the new RunScript_Hook, but this has actually broken the other functions, such as the SteathHook etc
Causes a crash in 'unknown' when the toggle is fired.
Back to top
View user's profile Send private message
Baaleos



Joined: 02 Sep 2007
Posts: 830

PostPosted: Fri Jul 30, 2010 1:29    Post subject: duh... I hadnt Reply with quote

I had forgot to Do the actual hooking for the ExecuteScript.

Question.
Now that ExecuteScript is now hooked, and it is hooked onto a __fastcall method, will this allow future __fastcall methods to function using it?


Also, will the fastcall method get executed in the dll, if I tell the dll to use the old method?

I mean, I assume since it is hooked, that the new method, should take over from the old method.
Back to top
View user's profile Send private message
Baaleos



Joined: 02 Sep 2007
Posts: 830

PostPosted: Fri Jul 30, 2010 1:32    Post subject: Reply with quote

thats a new one..
error in offset d0458

I will try changing it to use the new RunScript then.



K, Got it working now, hooked on SetLikesMe etc

One question, about what we have done,
By putting a hook on RunScript, have we at all compromized the performance of the server?

I mean, from my own understanding, by putting a hook there, it means everytime someone or something in the server, tries to run a script, or a heartbeat, its going to be going through nwnx now.


Since we have done it, I noticed that some triggers etc are sluggish. Eg - Can walk halfway into them, before they fire.
Back to top
View user's profile Send private message
Baaleos



Joined: 02 Sep 2007
Posts: 830

PostPosted: Fri Jul 30, 2010 2:51    Post subject: k Guys Reply with quote

I managed to get it working, thanks to the wonderful help I received here. More a less a step by step walkthrough guide to be honest.



Code:

void __fastcall SetLikesMeHookProc(CNWSCreature* cre, void* pVoid, unsigned long objid, int a, int b) {
  // __log(3, "cre: %08X\nobjid: %08X\na: %d\nb: %d\n", cre, objid, a, b);
   
   

   CNWSObject *oTarget = (CNWSObject*)(*NWN_AppManager)->app_server->srv_internal->GetCreatureByGameObjectID(objid);
   

   events.oTarget = (DWORD)cre;
   events.FireEvent(objid, 17,"SetLikesMe");

   //CExoString VarName("PVP_TOGGLE_ALLOW");
   //int bOverride1 = ((CNWSObject*)cre)->obj_vartable.GetInt(VarName);

   if(events.nBypass == 1)
   {
      events.nBypass = 0;
      return;
   }

    SetLikesMeNextHook(cre, NULL, objid, a, b);
}


Works like a charm, it does, as you say, still show the annoying message about 'blah now dislikes you' etc - but I can live with that for now.

Question.
How do I get the object id from a creature type object?
Can I simply cast it as a generic object?
Back to top
View user's profile Send private message
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Fri Jul 30, 2010 4:24    Post subject: Reply with quote

For the purposes of getting the oid, yeah, a straight cast should work.

BTW, I just realized it might be easier to hook the network message handler instead, and just abort if you get a request from a player to change their attitude towards someone else.
_________________
Win32 SVN builds: http://www.mercuric.net/nwn/nwnx/

<Fluffy-Kooshy> NWNx plugin is to this as nuclear warheads are to getting rid of fire ants.

<ThriWork> whenever I hear nwn extender, I think what does NWN need a penis extender for?
Back to top
View user's profile Send private message Visit poster's website
MaxRock



Joined: 24 Jan 2008
Posts: 196

PostPosted: Fri Jul 30, 2010 4:28    Post subject: Re: k Guys Reply with quote

Baaleos wrote:

Question.
How do I get the object id from a creature type object?
Can I simply cast it as a generic object?


Sorry, had to run some errands.

Yes, you can cast a creature to a generic object (nwn calls it CGameObject)

CGenericObject obj = (CGenericObject*)Creature;
obj.obj_id;

or

creature->obj.obj_generic.obj_id;

will work too. (a simple cast can potentially save some typing though.)

If you look in the class/struct files you'll see that all of the game object (creatures, items, placeables) share CNWSObject and CGenericObject is the first 20? bytes of CNWSObject. So you can pretty much cast between them if necessary.
CNWSItem is a little tricky because it uses its first 10 bytes for item appearence and then starts CNWSObject, but you can still get an item's object id with: item->obj.obj_generic.obj_id
Back to top
View user's profile Send private message Send e-mail MSN Messenger
MaxRock



Joined: 24 Jan 2008
Posts: 196

PostPosted: Fri Jul 30, 2010 5:16    Post subject: Reply with quote

I might be wrong about this but isn't the "fastcall trick" an all or nothing kinda thing?
Meaning you have to "recreate" the whole function if you just want to make a change in a single line?

On a more related note, I think if you hook and override CNWSMessage__SendServerToPlayerPVP_Attitude_Change as well you could get rid of the messages "soandso dislikes ..." and maybe even the button change.
Back to top
View user's profile Send private message Send e-mail MSN Messenger
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Fri Jul 30, 2010 5:52    Post subject: Reply with quote

It's all or nothing in that it doesn't really let you change the functionality of only one part of a function, but it's perfectly suited for a hook where you're either going to run the original function or bypass it entirely.
_________________
Win32 SVN builds: http://www.mercuric.net/nwn/nwnx/

<Fluffy-Kooshy> NWNx plugin is to this as nuclear warheads are to getting rid of fire ants.

<ThriWork> whenever I hear nwn extender, I think what does NWN need a penis extender for?
Back to top
View user's profile Send private message Visit poster's website
Baaleos



Joined: 02 Sep 2007
Posts: 830

PostPosted: Fri Jul 30, 2010 14:08    Post subject: Hi Guys Reply with quote

I tried to post last night/ rather this morning...GMT time an all, to say I got it all working, however, for some reason, when its after 1am here or whatever, NWNX Forums refuse me entry to the forum. Attempting to log in, just causes the login form to refresh. Odd... So naturally I was annoyed that I couldnt post to say thanks and that it was working.


So, anyway, Yeah, I will give the new suggestion a try, to hook the ServerToPlayer message, and override it completely.

Question, Because this method does not use a CNWSCreature class, is it possible to get the CNWSCreature, or OBJ_ID from the function, relating to who it originated from?

Or do you suggest hooking both the LikesMe function, as well as this Server Message?

Neva mind, I see that it actually has 2 unsigned long arguments for that function, no doubt both of these relate to player/creature ids?
Back to top
View user's profile Send private message
MaxRock



Joined: 24 Jan 2008
Posts: 196

PostPosted: Fri Jul 30, 2010 16:19    Post subject: Reply with quote

CNWSMessage__HandlePlayerToServerPVPListOperations(CNWSMessage *msg, CNWSPlayer *pl, char a3);

a3 is used for the switch/case statement (type?) and I think you'd want case 3.

The id of the creature the player dislikes is extracted from NWSMessage with CNWSMessage::ReadObjectIDServer(). (That creature becomes the this pointer in CNWSCreature::SetPVPPlayerLikesMe(...))

I don't think ReadObjectIDServer is in the CNWSMessage class but once you get that you can get both creatures likes this:
Code:

CNWSCreature *Creature1 = ((*NWN_AppManager)->app_server->srv_internal)->GetCreatureByGameObjectID((pl->GetGameObject())->obj_id);

CNWSCreature *Creature2 = ((*NWN_AppManager)->app_server->srv_internal)->GetCreatureByGameObjectID(msg->ReadObjectIDServer());



Compare variables and quit or continue the function.

Still on my first cup of coffee, so no guarantees Wink
Back to top
View user's profile Send private message Send e-mail MSN Messenger
MaxRock



Joined: 24 Jan 2008
Posts: 196

PostPosted: Fri Jul 30, 2010 17:41    Post subject: Reply with quote

I've updated the nwn classes (include and nwn_internals folders).
Added CNWSMessage::ReadOBJECTIDServer and CVirtualMachine::Runscript.
The latter lets you run scripts whenever you want
Code:

(*NWN_VirtualMachine)->Runscript(&ScriptName, obj_id);

without having to explicityly hook it again.
Back to top
View user's profile Send private message Send e-mail MSN Messenger
Zebranky



Joined: 04 Jun 2006
Posts: 415

PostPosted: Fri Jul 30, 2010 21:24    Post subject: Reply with quote

Reading messages, on the other hand, is an all or nothing operation, to my understanding. Skywing manages quite a bit of it in his NWN2 client extension, though -- he's the one to talk to about that.
_________________
Win32 SVN builds: http://www.mercuric.net/nwn/nwnx/

<Fluffy-Kooshy> NWNx plugin is to this as nuclear warheads are to getting rid of fire ants.

<ThriWork> whenever I hear nwn extender, I think what does NWN need a penis extender for?
Back to top
View user's profile Send private message Visit poster's website
Skywing



Joined: 03 Jan 2008
Posts: 321

PostPosted: Sat Aug 07, 2010 5:12    Post subject: Reply with quote

For NWN2, we have:

Code:

bool
ClientExtensions::SendPVP_SetPVP_Attitude(
   __in bool Friendly,
   __in NWN::OBJECTID ObjectId
   )
/*++

Routine Description:

   This function sends a PVP.SetPVP_Attitude message to the server, asking the
   server to change our friendly/hostile state towards another player.

   This message is always looped through in standalone mode.

Arguments:

   Friendly - Supplies a Boolean value indicating whether the player requested
              to become friendly (true) or hostile (false) towards the object.

   ObjectId - Supplies the PC control object id of the player to change PVP
              attitudes towards.

Return Value:

   On success, true, else false.  Raises an std::exception on catastrophic
   failure.

Environment:

   User mode, associated with server.

--*/
{
   NWN::ProtocolMessage    Message(
      NWN::ProtocolMessage::CLS::PlayerToServer,
      NWN::ProtocolMessage::CMD::PVP,
      NWN::ProtocolMessage::PVP::SetPVP_Attitude);
   NWN::ExoBuildBuffer   * Builder = Message.GetBuilder( );

   Builder->WriteBOOL( Friendly );
   Builder->WriteOBJECTID( ObjectId );

   return SendProtocolMessageLoopthrough( Message );
}


Where PVP::SetPVP_Attitude is minor function 0x03.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> Windows development All times are GMT + 2 Hours
Goto page Previous  1, 2, 3
Page 3 of 3

 
Jump to:  
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