[Saylinks] Implement Auto Saylink Injection (#1525)

* Implement auto saylink injection

* Cover Lua say since it takes a different code path
This commit is contained in:
Chris Miles 2021-09-12 22:08:30 -05:00 committed by GitHub
parent 94c1a50cc8
commit 6b93130c13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 112 additions and 30 deletions

View File

@ -598,6 +598,8 @@ RULE_INT(Chat, IntervalDurationMS, 60000, "Interval length in milliseconds")
RULE_INT(Chat, KarmaUpdateIntervalMS, 1200000, "Karma update interval in milliseconds")
RULE_INT(Chat, KarmaGlobalChatLimit, 72, "Amount of karma you need to be able to talk in ooc/auction/chat below the level limit")
RULE_INT(Chat, GlobalChatLevelLimit, 8, "Level limit you need to of reached to talk in ooc/auction/chat if your karma is too low")
RULE_BOOL(Chat, AutoInjectSaylinksToSay, true, "Automatically injects saylinks into dialogue that has [brackets in them]")
RULE_BOOL(Chat, AutoInjectSaylinksToClientMessage, true, "Automatically injects saylinks into dialogue that has [brackets in them]")
RULE_CATEGORY_END()
RULE_CATEGORY(Merchant)

View File

@ -1,5 +1,5 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
@ -11,7 +11,7 @@
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@ -339,4 +339,48 @@ std::string EQ::SayLinkEngine::GenerateQuestSaylink(std::string saylink_text, bo
linker.SetProxyText(link_name.c_str());
return linker.GenerateLink();
}
}
std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
{
std::string new_message = message;
int link_index = 0;
std::vector<std::string> links = {};
// loop through brackets until none exist
while (new_message.find('[') != std::string::npos && new_message.find(']') != std::string::npos) {
std::string bracket_message = get_between(new_message, "[", "]");
// already a saylink
// todo: improve this later
if (!bracket_message.empty() && bracket_message.length() > 50) {
links.emplace_back(bracket_message);
}
else {
links.emplace_back(EQ::SayLinkEngine::GenerateQuestSaylink(bracket_message, false, bracket_message));
}
// replace with anchor
find_replace(
new_message,
fmt::format("[{}]", bracket_message),
fmt::format("<link:{}>", link_index)
);
link_index++;
}
// pop links onto anchors
link_index = 0;
for (auto &link: links) {
find_replace(
new_message,
fmt::format("<link:{}>", link_index),
fmt::format("[{}]", link)
);
link_index++;
}
return new_message;
}

View File

@ -1,17 +1,17 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@ -105,6 +105,7 @@ namespace EQ
void Reset();
static std::string InjectSaylinksIfNotExist(const char *message);
private:
void generate_body();
void generate_text();

View File

@ -1593,7 +1593,7 @@ XS(XS__addldonpoints) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: quest::addldonpoints(uint32 theme_id, int points)");
uint32 theme_id = (uint32) SvUV(ST(0));
int points = (int) SvIV(ST(1));
quest_manager.addldonpoints(theme_id, points);
@ -6483,7 +6483,7 @@ XS(XS__gethexcolorcode) {
sv_setpv(TARG, hex_color_code.c_str());
XSprePUSH;
PUSHTARG;
XSRETURN(1);
XSRETURN(1);
}
XS(XS__getaaexpmodifierbycharid);
@ -6491,7 +6491,7 @@ XS(XS__getaaexpmodifierbycharid) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: quest::getaaexpmodifierbycharid(uint32 character_id, uint32 zone_id)");
dXSTARG;
double aa_modifier;
uint32 character_id = (uint32) SvUV(ST(0));
@ -6507,7 +6507,7 @@ XS(XS__getexpmodifierbycharid) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: quest::getexpmodifierbycharid(uint32 character_id, uint32 zone_id)");
dXSTARG;
double exp_modifier;
uint32 character_id = (uint32) SvUV(ST(0));
@ -6870,7 +6870,7 @@ XS(XS__getspellstat) {
uint8 slot = 0;
if (items == 3)
slot = (uint8) SvUV(ST(2));
stat_value = quest_manager.getspellstat(spell_id, stat_identifier, slot);
XSprePUSH;

View File

@ -4185,8 +4185,10 @@ bool Entity::CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z,
return false;
}
void EntityList::QuestJournalledSayClose(Mob *sender, float dist, const char *mobname, const char *message,
Journal::Options &opts)
void EntityList::QuestJournalledSayClose(
Mob *sender, float dist, const char *mobname, const char *message,
Journal::Options &opts
)
{
SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
@ -4199,7 +4201,15 @@ void EntityList::QuestJournalledSayClose(Mob *sender, float dist, const char *mo
buf.WriteInt32(0); // location, client doesn't seem to do anything with this
buf.WriteInt32(0);
buf.WriteInt32(0);
buf.WriteString(message);
// auto inject saylinks (say)
if (RuleB(Chat, AutoInjectSaylinksToSay)) {
std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(message);
buf.WriteString(new_message);
}
else {
buf.WriteString(message);
}
auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);

View File

@ -755,7 +755,15 @@ double Lua_Mob::GetSize() {
void Lua_Mob::Message(int type, const char *message) {
Lua_Safe_Call_Void();
self->Message(type, message);
// auto inject saylinks
if (RuleB(Chat, AutoInjectSaylinksToClientMessage)) {
std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(message);
self->Message(type, new_message.c_str());
}
else {
self->Message(type, message);
}
}
void Lua_Mob::MessageString(int type, int string_id, uint32 distance) {
@ -2747,7 +2755,7 @@ luabind::scope lua_register_mob() {
.def("GetNimbusEffect2", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect2)
.def("GetNimbusEffect3", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect3)
.def("IsTargetable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTargetable)
.def("HasShieldEquiped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasShieldEquiped)
.def("HasShieldEquiped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasShieldEquiped)
.def("HasTwoHandBluntEquiped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHandBluntEquiped)
.def("HasTwoHanderEquipped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHanderEquipped)
.def("GetHerosForgeModel", (int32(Lua_Mob::*)(uint8))&Lua_Mob::GetHerosForgeModel)

View File

@ -2923,10 +2923,19 @@ void Mob::Say(const char *format, ...)
talker = this;
}
entity_list.MessageCloseString(
talker, false, 200, 10,
GENERIC_SAY, GetCleanName(), buf
);
if (RuleB(Chat, AutoInjectSaylinksToSay)) {
std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(buf);
entity_list.MessageCloseString(
talker, false, 200, 10,
GENERIC_SAY, GetCleanName(), new_message.c_str()
);
}
else {
entity_list.MessageCloseString(
talker, false, 200, 10,
GENERIC_SAY, GetCleanName(), buf
);
}
}
//

View File

@ -989,7 +989,7 @@ XS(XS_Mob_BuffCount) {
VALIDATE_THIS_IS_MOB;
RETVAL = THIS->BuffCount();
XSprePUSH;
PUSHu((UV) RETVAL);
PUSHu((UV) RETVAL);
}
XSRETURN(1);
}
@ -2620,7 +2620,15 @@ XS(XS_Mob_Message) {
uint32 type = (uint32) SvUV(ST(1));
char *message = (char *) SvPV_nolen(ST(2));
VALIDATE_THIS_IS_MOB;
THIS->Message(type, message);
// auto inject saylinks
if (RuleB(Chat, AutoInjectSaylinksToClientMessage)) {
std::string new_message = EQ::SayLinkEngine::InjectSaylinksIfNotExist(message);
THIS->Message(type, new_message.c_str());
}
else {
THIS->Message(type, message);
}
}
XSRETURN_EMPTY;
}
@ -6016,7 +6024,7 @@ XS(XS_Mob_GetClassName) {
XSprePUSH;
PUSHTARG;
}
XSRETURN(1);
XSRETURN(1);
}
XS(XS_Mob_GetRaceName);
@ -6039,7 +6047,7 @@ XS(XS_Mob_GetRaceName) {
XS(XS_Mob_DeleteBucket);
XS(XS_Mob_DeleteBucket) {
dXSARGS;
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::DeleteBucket(THIS, std::string bucket_name)"); // @categories Script Utility
{
@ -6053,7 +6061,7 @@ XS(XS_Mob_DeleteBucket) {
XS(XS_Mob_GetBucket);
XS(XS_Mob_GetBucket) {
dXSARGS;
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::GetBucket(THIS, std::string bucket_name)"); // @categories Script Utility
{
@ -6072,7 +6080,7 @@ XS(XS_Mob_GetBucket) {
XS(XS_Mob_GetBucketExpires);
XS(XS_Mob_GetBucketExpires) {
dXSARGS;
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::GetBucketExpires(THIS, std::string bucket_name)"); // @categories Script Utility
{
@ -6091,7 +6099,7 @@ XS(XS_Mob_GetBucketExpires) {
XS(XS_Mob_GetBucketKey);
XS(XS_Mob_GetBucketKey) {
dXSARGS;
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: Mob::GetBucketKey(THIS)"); // @categories Script Utility
{
@ -6109,7 +6117,7 @@ XS(XS_Mob_GetBucketKey) {
XS(XS_Mob_GetBucketRemaining);
XS(XS_Mob_GetBucketRemaining) {
dXSARGS;
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::GetBucketRemaining(THIS, std::string bucket_name)"); // @categories Script Utility
{
@ -6128,7 +6136,7 @@ XS(XS_Mob_GetBucketRemaining) {
XS(XS_Mob_SetBucket);
XS(XS_Mob_SetBucket) {
dXSARGS;
dXSARGS;
if (items < 3 || items > 4)
Perl_croak(aTHX_ "Usage: Mob::SetBucket(THIS, std::string bucket_name, std::string bucket_value, [std::string expiration])"); // @categories Script Utility
{
@ -6146,7 +6154,7 @@ XS(XS_Mob_SetBucket) {
}
XS(XS_Mob_IsHorse);
XS(XS_Mob_IsHorse) {
XS(XS_Mob_IsHorse) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: Mob::IsHorse(THIS)"); // @categories Script Utility