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?