Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Reply
 
Thread Tools Display Modes
  #1  
Old 09-24-2008, 04:08 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default New Event - EVENT_AGGRO_SAY

While working on some custom quests we found that there isn't currently a way to have an NPC respond to say messages while in combat with them. In most cases, this should be unnecessary, but in order to open up another option, I created this new event. The EVENT_AGGRO_SAY is just like EVENT_SAY, accept it only works while in combat. To use it, it should be just like writing an EVENT_SAY, accept you start with "sub EVENT_AGGRO_SAY" instead.

An example use of this might be a script where you attack an NPC in a city, but then say "sorry" and it whipes it's hate list. So, if you aren't still attacking it, it will just stop attacking and leave you alone as long as you aren't already KoS to it. Though, I can think of a few more uses for it.


In client.cpp after this:
Code:
		if (target != 0 && target->IsNPC() && !target->CastToNPC()->IsEngaged()) {
#ifdef EMBPERL
			if(((PerlembParser *)parse)->HasQuestSub(target->GetNPCTypeID(),"EVENT_SAY")){
#endif
				if (DistNoRootNoZ(*target) <= 200) {
					if(target->CastToNPC()->IsMoving() && !target->CastToNPC()->IsOnHatelist(target))
						target->CastToNPC()->PauseWandering(RuleI(NPC, SayPauseTimeInSec));
					parse->Event(EVENT_SAY, target->GetNPCTypeID(), message, target->CastToNPC(), this);
				#ifdef IPC
					if(target->CastToNPC()->IsInteractive()) {
						target->CastToNPC()->InteractiveChat(chan_num,language,message,targetname,this);
					}
				#endif
					//parse->Event(EVENT_SAY, target->GetNPCTypeID(), message, target->CastToNPC(), this);
				}
#ifdef EMBPERL
			}
#endif
		}
		break;
Add this:
Code:
		if (target != 0 && target->IsNPC() && target->CastToNPC()->IsEngaged()) {
#ifdef EMBPERL
			if(((PerlembParser *)parse)->HasQuestSub(target->GetNPCTypeID(),"EVENT_AGGRO_SAY")){
#endif
				if (DistNoRootNoZ(*target) <= 200) {
					parse->Event(EVENT_AGGRO_SAY, target->GetNPCTypeID(), message, target->CastToNPC(), this);
				#ifdef IPC
					if(target->CastToNPC()->IsInteractive()) {
						target->CastToNPC()->InteractiveChat(chan_num,language,message,targetname,this);
					}
				#endif
				}
#ifdef EMBPERL
			}
#endif
		}
		break;

In embparser.cpp after this:
Code:
	"EVENT_ZONE",
	"EVENT_LEVEL_UP",
	"EVENT_KILLED_MERIT",
	"EVENT_CAST_ON"
Add a comma after the end of the "EVENT_CAST_ON" as shown below and then add the line after it:
Code:
	"EVENT_CAST_ON",
	"EVENT_AGGRO_SAY"
And, after this:
Code:
	//do any event-specific stuff...
	switch (event) {
		case EVENT_SAY: {
			npcmob->FaceTarget(mob);
			ExportVar(packagename.c_str(), "data", npcid);
			ExportVar(packagename.c_str(), "text", data);
			break;
		}
Add this:
Code:
		case EVENT_AGGRO_SAY: {
			ExportVar(packagename.c_str(), "data", npcid);
			ExportVar(packagename.c_str(), "text", data);
			break;
		}
In event_codes.h after this:
Code:
	EVENT_CAST_ON,		//pc casted a spell on npc
Add this:
Code:
	EVENT_AGGRO_SAY,		//NPC responds to /say text while in combat mode

In parser.cpp after this:
Code:
	switch (event) {
		case EVENT_SAY: {
			MakeVars(data, npcid);
			npcmob->FaceTarget(mob);
			SendCommands("event_say", qstID, npcmob, mob);
			break;
		}
Add this:
Code:
		case EVENT_AGGRO_SAY: {
			MakeVars(data, npcid);
			SendCommands("event_aggro_say", qstID, npcmob, mob);
			break;
		}
And this is the only part I am not very sure about:


In entity.cpp change this:
Code:
	   if (tmp)
		parse->Event(EVENT_SAY, sender->GetTarget()->GetNPCTypeID(), tmp, sender->GetTarget(), sender);
To this:
Code:
	   if (tmp) {
		parse->Event(EVENT_SAY, sender->GetTarget()->GetNPCTypeID(), tmp, sender->GetTarget(), sender);
		parse->Event(EVENT_AGGRO_SAY, sender->GetTarget()->GetNPCTypeID(), tmp, sender->GetTarget(), sender);
	   }

Or maybe it is suppsed to be:

In entity.cpp change this:
Code:
		parse->Event(EVENT_SAY, sender->GetTarget()->GetNPCTypeID(), tmp, sender->GetTarget(), sender);
To this:
Code:
		parse->Event((EVENT_SAY && EVENT_AGGRO_SAY), sender->GetTarget()->GetNPCTypeID(), tmp, sender->GetTarget(), sender);

I have tested this on my server and so far it doesn't seem to work just yet, so I must be missing something or have something set wrong. I am guessing it may be the last part where it parses the event. I will move this post to the Code Submissions section once it is working and tested. If anyone else has any suggestions to improve it, I would love to hear them. I am still unsure which of the last 2 code changes need to be used, but I think it will be the first one of the 2.

Also, I was considering making an EVENT_LISTEN which would be for NPCs to listen for ANY /say messages within range even if they aren't currently the target of the player. I do think it would be useful, but the code for it may be a bit over my skill level. One example I heard a rumor of on live was that there was an NPC in the Plane of Growth that would attack anyone who said "uber lewts" or something like that if they were in range of the NPC for it to hear the say message. Maybe using a within range check instead of a target check for when messages are seen?
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 10-11-2008 at 02:38 PM..
Reply With Quote
  #2  
Old 09-24-2008, 05:04 AM
joligario's Avatar
joligario
Developer
 
Join Date: Mar 2003
Posts: 1,498
Default

I think you deserve to die to a city NPC if you attack it and you aren't KOS. We all have learned that lesson before!
Reply With Quote
  #3  
Old 09-24-2008, 05:46 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

LOL, ya I agree :P I was just using it as an example. The main reason I want to get this working is because there is an event on my server where players are supposed to sing along with an NPC while they are fighting it or they get consequences. With the current EVENT_SAY, mobs won't respond to messages if they are engaged. This new sub event is mostly for custom servers to add more options
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #4  
Old 09-24-2008, 08:38 AM
janusd
Sarnak
 
Join Date: Jan 2008
Posts: 47
Default

Trevius, PLEASE figure out an EVENT_LISTEN. I can think of at least four quests that require you to say a phrase in a specific spot to trigger an event (plate house in Kael anyone?) while there's no NPC targeted (IE an invisible man with a name of _ listens for it?). At the moment we're having to kinda hack together some slightly ugly code to achieve the same effect, and in some cases we're not able to 100% Live on that. With an Event_Listen, the code for the one that's written could be made a lot simpler and the others that are yet to be coded could be coded.
Reply With Quote
  #5  
Old 09-25-2008, 12:08 AM
AndMetal
Developer
 
Join Date: Mar 2007
Location: Ohio
Posts: 648
Default

The way Live handles quest dialogue is, or at least was, different from the Emu. On Live, NPCs respond to dialogue within say distance. So, if multiple NPCs in the same area respond to the same phrase, they will all speak at once (I can't remember where it was, maybe Neriak or something, that I saw this firsthand and made that discovery). So, on Live, when you hail an NPC, it doesn't respond to the Hail, portion, it responds to "Hail, NPC_001".

I believe the Emu handles quests the way it does for 2 main reasons: server resources and simplicity/directness.

1st, if you have every NPC run through all of the quest stuff, even if you pick out mobs within a certain radius of you, then execute, it's a lot more expensive than just running it through your specific target. This is because, even if you don't have really anything being done, all of the variables available to the quest have to be exported (unless there's a check to see if an NPC doesn't have a quest file?). Just imagine if you had a custom death emote on a bunch of mobs in a zone, and a group AEs them, then tries to talk to one while killing them. All of that processing at once would make the processor blow a gasket.

2nd, if you know what specific mob you want to handle the quest, you don't have to worry about multiple mobs being around each other making everything confusing.

I think if we can find a cost effective way to handle 1, the benefits should outweigh the negatives of 2.
__________________
GM-Impossible of 'A work in progress'
A non-legit PEQ DB server
How to create your own non-legit server

My Contributions to the Wiki
Reply With Quote
  #6  
Old 09-25-2008, 12:21 AM
joligario's Avatar
joligario
Developer
 
Join Date: Mar 2003
Posts: 1,498
Default

I don't think all NPCs were like that. Maybe that changed throughout the years to be targeted-based. You had to actually target them for it to work with trigger phrases. Inlcuding the hails. I remember trying hailing with the NPC name typed in and got no response. Maybe so it would be less resource intensive, specific NPCs were set up to respond to ranged speech?
Reply With Quote
  #7  
Old 09-25-2008, 12:27 AM
ChaosSlayer
Demi-God
 
Join Date: May 2007
Posts: 1,032
Default

this could have been npc specific, but on LIVE I remeber 2 distinct examples:

in Qeynos bank saying any class name or guild name will have bankers (while NOT targeted) automaticly speak up with full guild info for class mentioned

In Plane of Sky there was a Lunatic doing emotes near, or sayign anythign else other than talking to him him would cuase him to attack
Reply With Quote
  #8  
Old 09-25-2008, 08:37 AM
janusd
Sarnak
 
Join Date: Jan 2008
Posts: 47
Default

Yeah. Sirran the Lunatic. He would go insane if you did anything other than hail him and hand him the key piece. Many times I can think of a raid wiping because someone spoke up in /say. There are also cases where invisible NPCs respond to spoken phrases without a target.

I don't think ALL NPCs would respond to just phrases uttered, but there were some that would respond when they weren't targeted.
Reply With Quote
  #9  
Old 10-11-2008, 07:26 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

I am still wanting to get this code working, but I am not sure what is still missing for it to work. This is my first attempt at making a new sub event, so most likely, I am just missing something minor, but not sure.

If I can get this working, I think I know how to get EVENT_LISTEN working as well. I will start on that as soon as I figure out what is wrong with this one.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #10  
Old 10-20-2008, 02:16 PM
Derision
Developer
 
Join Date: Feb 2004
Location: UK
Posts: 1,540
Default

I just tested and comitted this, pretty much as you had it in the first post.

Example use:

Code:
sub EVENT_AGGRO_SAY {
        quest::say("I am fighting!");
        if($text=~/Stop/i){
                $npc->WipeHateList();
                quest::say("OK, I'll stop!");
                $npc->FaceTarget($client);
        }
}
Reply With Quote
  #11  
Old 10-21-2008, 05:31 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

LOL, what was I missing? Maybe I needed to do a make clean and a make to get it to accept the change? I normally only do a make when I do changes and it always seems to work fine.

Thanks for getting that added BTW! <3 new features
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 02:36 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3