mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[NPC] Support for multiple emotes per type, emote variables (#3801)
* [forage rule feature] add a rule to disabled using common_food_ids from the list in forage.cpp. currently set to enabled. * NPC database emotes now supports basic variables. More than one variable can be used at a time. * Format manifest * Formatting * Formatting * Formatting --------- Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
parent
6396a6fbef
commit
25872203ff
@ -5133,6 +5133,16 @@ CHANGE COLUMN `slot` `inventory_slot` mediumint(9) NOT NULL DEFAULT -1 AFTER `st
|
||||
|
||||
ALTER TABLE `starting_items`
|
||||
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9248,
|
||||
.description = "2023_12_22_drop_npc_emotes_index.sql",
|
||||
.check = "show index from npc_emotes where key_name = 'emoteid'",
|
||||
.condition = "not_empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
||||
)"
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseNpcEmotesRepository {
|
||||
public:
|
||||
struct NpcEmotes {
|
||||
@ -120,8 +121,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
npc_emotes_id
|
||||
)
|
||||
);
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9247
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9248
|
||||
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041
|
||||
|
||||
|
||||
@ -1820,7 +1820,7 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill
|
||||
|
||||
auto emote_id = killerMob->GetEmoteID();
|
||||
if (emote_id) {
|
||||
killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid);
|
||||
killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid, this);
|
||||
}
|
||||
|
||||
killerMob->TrySpellOnKill(killed_level, spell);
|
||||
@ -2710,7 +2710,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
if (IsNPC()) {
|
||||
auto emote_id = GetEmoteID();
|
||||
if (emote_id) {
|
||||
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid);
|
||||
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid, killer_mob);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2721,7 +2721,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
|
||||
auto emote_id = oos->GetEmoteID();
|
||||
if (emote_id) {
|
||||
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id);
|
||||
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id, this);
|
||||
}
|
||||
if (killer_mob) {
|
||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||
@ -2799,7 +2799,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
ApplyIllusionToCorpse(illusion_spell_id, corpse);
|
||||
|
||||
if (killer != 0 && emoteid != 0)
|
||||
corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid);
|
||||
corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid, killer);
|
||||
if (killer != 0 && killer->IsClient()) {
|
||||
corpse->AllowPlayerLoot(killer, 0);
|
||||
if (killer->IsGrouped()) {
|
||||
|
||||
@ -6172,7 +6172,7 @@ void Client::CheckEmoteHail(NPC* n, const char* message)
|
||||
|
||||
const auto emote_id = n->GetEmoteID();
|
||||
if (emote_id) {
|
||||
n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id);
|
||||
n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,10 +7,7 @@ void FindEmote(Client *c, const Seperator *sep)
|
||||
if (sep->IsNumber(2)) {
|
||||
auto emote_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
|
||||
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
auto &e = iterator.GetData();
|
||||
for (auto& e : zone->npc_emote_list) {
|
||||
if (emote_id == e->emoteid) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@ -40,7 +37,6 @@ void FindEmote(Client *c, const Seperator *sep)
|
||||
break;
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if (found_count == 50) {
|
||||
@ -70,10 +66,7 @@ void FindEmote(Client *c, const Seperator *sep)
|
||||
|
||||
const std::string& search_criteria = sep->argplus[2];
|
||||
|
||||
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
auto &e = iterator.GetData();
|
||||
for (auto& e : zone->npc_emote_list) {
|
||||
|
||||
const std::string& current_text = Strings::ToLower(e->text);
|
||||
|
||||
@ -106,7 +99,6 @@ void FindEmote(Client *c, const Seperator *sep)
|
||||
break;
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if (found_count == 50) {
|
||||
|
||||
@ -12,10 +12,7 @@ void ShowEmotes(Client *c, const Seperator *sep)
|
||||
uint32 emote_count = 0;
|
||||
const uint32 emote_id = t->GetEmoteID();
|
||||
|
||||
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
const auto& e = iterator.GetData();
|
||||
for (auto& e : zone->npc_emote_list) {
|
||||
if (emote_id == e->emoteid) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@ -41,7 +38,6 @@ void ShowEmotes(Client *c, const Seperator *sep)
|
||||
emote_count++;
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
c->Message(
|
||||
|
||||
@ -1800,7 +1800,7 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help)
|
||||
|
||||
auto emote_id = GetEmoteID();
|
||||
if (emote_id) {
|
||||
CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emoteid);
|
||||
CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emoteid, attacker);
|
||||
}
|
||||
|
||||
std::string mob_name = GetCleanName();
|
||||
|
||||
78
zone/npc.cpp
78
zone/npc.cpp
@ -3046,42 +3046,72 @@ void NPC::SendPayload(int payload_id, std::string payload_value)
|
||||
}
|
||||
|
||||
NPC_Emote_Struct* NPC::GetNPCEmote(uint32 emoteid, uint8 event_) {
|
||||
LinkedListIterator<NPC_Emote_Struct*> iterator(zone->NPCEmoteList);
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements())
|
||||
{
|
||||
NPC_Emote_Struct* nes = iterator.GetData();
|
||||
std::vector<NPC_Emote_Struct *> emotes;
|
||||
for (auto &e: zone->npc_emote_list) {
|
||||
NPC_Emote_Struct *nes = e;
|
||||
if (emoteid == nes->emoteid && event_ == nes->event_) {
|
||||
return nes;
|
||||
emotes.push_back(e);
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
if (emotes.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
else if (emotes.size() == 1) {
|
||||
return emotes[0];
|
||||
}
|
||||
|
||||
int index = zone->random.Roll0(emotes.size());
|
||||
|
||||
return emotes[index];
|
||||
}
|
||||
|
||||
void NPC::DoNPCEmote(uint8 event_, uint32 emoteid)
|
||||
void NPC::DoNPCEmote(uint8 event_, uint32 emoteid, Mob* target)
|
||||
{
|
||||
if (emoteid == 0)
|
||||
{
|
||||
if (emoteid == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NPC_Emote_Struct* nes = GetNPCEmote(emoteid,event_);
|
||||
if(nes == nullptr)
|
||||
{
|
||||
NPC_Emote_Struct *nes = GetNPCEmote(emoteid, event_);
|
||||
if (nes == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(emoteid == nes->emoteid)
|
||||
{
|
||||
if(nes->type == 1)
|
||||
Emote("%s",nes->text);
|
||||
else if(nes->type == 2)
|
||||
Shout("%s",nes->text);
|
||||
else if(nes->type == 3)
|
||||
entity_list.MessageCloseString(this, true, 200, 10, GENERIC_STRING, nes->text);
|
||||
else
|
||||
Say("%s",nes->text);
|
||||
std::string processed = nes->text;
|
||||
Strings::FindReplace(processed, "$mname", GetCleanName());
|
||||
Strings::FindReplace(processed, "$mracep", GetRacePlural() = GetClass());
|
||||
Strings::FindReplace(processed, "$mrace", GetPlayerRaceName(GetRace()));
|
||||
Strings::FindReplace(processed, "$mclass", GetClassIDName(GetClass()));
|
||||
if (target) {
|
||||
Strings::FindReplace(processed, "$name", target->GetCleanName());
|
||||
Strings::FindReplace(processed, "$racep", GetRacePlural() = target->GetClass());
|
||||
Strings::FindReplace(processed, "$race", GetPlayerRaceName(target->GetRace()));
|
||||
Strings::FindReplace(processed, "$class", GetClassIDName(target->GetClass()));
|
||||
}
|
||||
else {
|
||||
Strings::FindReplace(processed, "$name", "foe");
|
||||
Strings::FindReplace(processed, "$race", "race");
|
||||
Strings::FindReplace(processed, "$racep", "races");
|
||||
Strings::FindReplace(processed, "$class", "class");
|
||||
}
|
||||
|
||||
if (emoteid == nes->emoteid) {
|
||||
if (event_ == EQ::constants::EmoteEventTypes::Hailed && target) {
|
||||
DoQuestPause(target);
|
||||
}
|
||||
|
||||
if (nes->type == 1) {
|
||||
Emote("%s", processed.c_str());
|
||||
}
|
||||
else if (nes->type == 2) {
|
||||
Shout("%s", processed.c_str());
|
||||
}
|
||||
else if (nes->type == 3) {
|
||||
entity_list.MessageCloseString(this, true, 200, 10, GENERIC_STRING, processed.c_str());
|
||||
}
|
||||
else {
|
||||
Say("%s", processed.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -476,7 +476,7 @@ public:
|
||||
const uint32 GetAltCurrencyType() const { return NPCTypedata->alt_currency_type; }
|
||||
|
||||
NPC_Emote_Struct* GetNPCEmote(uint32 emoteid, uint8 event_);
|
||||
void DoNPCEmote(uint8 event_, uint32 emoteid);
|
||||
void DoNPCEmote(uint8 event_, uint32 emoteid, Mob* target = nullptr);
|
||||
bool CanTalk();
|
||||
void DoQuestPause(Mob *other);
|
||||
|
||||
|
||||
@ -2015,7 +2015,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
{
|
||||
if (zone && zone->IsLoaded()) {
|
||||
zone->SendReloadMessage("NPC Emotes");
|
||||
zone->LoadNPCEmotes(&zone->NPCEmoteList);
|
||||
zone->LoadNPCEmotes(&zone->npc_emote_list);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1056,7 +1056,7 @@ Zone::~Zone() {
|
||||
safe_delete_array(short_name);
|
||||
safe_delete_array(long_name);
|
||||
safe_delete(Weather_Timer);
|
||||
NPCEmoteList.Clear();
|
||||
npc_emote_list.clear();
|
||||
zone_point_list.Clear();
|
||||
entity_list.Clear();
|
||||
ClearBlockedSpells();
|
||||
@ -1152,7 +1152,7 @@ bool Zone::Init(bool is_static) {
|
||||
LoadLDoNTrapEntries();
|
||||
LoadVeteranRewards();
|
||||
LoadAlternateCurrencies();
|
||||
LoadNPCEmotes(&NPCEmoteList);
|
||||
LoadNPCEmotes(&npc_emote_list);
|
||||
|
||||
LoadAlternateAdvancement();
|
||||
|
||||
@ -1233,8 +1233,8 @@ void Zone::ReloadStaticData() {
|
||||
|
||||
LoadVeteranRewards();
|
||||
LoadAlternateCurrencies();
|
||||
NPCEmoteList.Clear();
|
||||
LoadNPCEmotes(&NPCEmoteList);
|
||||
npc_emote_list.clear();
|
||||
LoadNPCEmotes(&npc_emote_list);
|
||||
|
||||
//load the zone config file.
|
||||
if (!LoadZoneCFG(GetShortName(), GetInstanceVersion())) { // try loading the zone name...
|
||||
@ -2548,10 +2548,10 @@ void Zone::DoAdventureActions()
|
||||
|
||||
}
|
||||
|
||||
void Zone::LoadNPCEmotes(LinkedList<NPC_Emote_Struct*>* NPCEmoteList)
|
||||
void Zone::LoadNPCEmotes(std::vector<NPC_Emote_Struct*>* NPCEmoteList)
|
||||
{
|
||||
|
||||
NPCEmoteList->Clear();
|
||||
NPCEmoteList->clear();
|
||||
const std::string query = "SELECT emoteid, event_, type, text FROM npc_emotes";
|
||||
auto results = content_db.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
@ -2565,7 +2565,7 @@ void Zone::LoadNPCEmotes(LinkedList<NPC_Emote_Struct*>* NPCEmoteList)
|
||||
nes->event_ = Strings::ToInt(row[1]);
|
||||
nes->type = Strings::ToInt(row[2]);
|
||||
strn0cpy(nes->text, row[3], sizeof(nes->text));
|
||||
NPCEmoteList->Insert(nes);
|
||||
NPCEmoteList->push_back(nes);
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] npc emotes", Strings::Commify(results.RowCount()));
|
||||
|
||||
@ -185,7 +185,7 @@ public:
|
||||
DynamicZone *GetDynamicZone();
|
||||
|
||||
IPathfinder *pathing;
|
||||
LinkedList<NPC_Emote_Struct *> NPCEmoteList;
|
||||
std::vector<NPC_Emote_Struct *> npc_emote_list;
|
||||
LinkedList<Spawn2 *> spawn2_list;
|
||||
LinkedList<ZonePoint *> zone_point_list;
|
||||
std::vector<ZonePointsRepository::ZonePoints> virtual_zone_point_list;
|
||||
@ -282,7 +282,7 @@ public:
|
||||
void LoadMercSpells();
|
||||
void LoadMercTemplates();
|
||||
void LoadNewMerchantData(uint32 merchantid);
|
||||
void LoadNPCEmotes(LinkedList<NPC_Emote_Struct *> *NPCEmoteList);
|
||||
void LoadNPCEmotes(std::vector<NPC_Emote_Struct *> *NPCEmoteList);
|
||||
void LoadTempMerchantData();
|
||||
void LoadTickItems();
|
||||
void LoadVeteranRewards();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user