[Rules] Add Rule to Disable NPC Last Names. (#2227)

* [Rules] Add Rule to Disable NPC Last Names.
- Add NPC:DisableLastNames to disable NPC Last Names.
- Fix #npcedit lastname to allow you to use an empty string.

* Cleanup of classes in naming.

* Duplicate.

* Update classes.cpp
This commit is contained in:
Kinglykrab 2022-06-04 14:01:00 -04:00 committed by GitHub
parent 7160aa651e
commit 8f729fe948
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 135 additions and 177 deletions

View File

@ -380,12 +380,12 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Merchant";
case DISCORD_MERCHANT:
return "Discord Merchant";
case ADVENTURERECRUITER:
case ADVENTURE_RECRUITER:
return "Adventure Recruiter";
case ADVENTUREMERCHANT:
case ADVENTURE_MERCHANT:
return "Adventure Merchant";
case CORPSE_CLASS:
return "Corpse Class";
case LDON_TREASURE:
return "LDoN Treasure";
case TRIBUTE_MASTER:
return "Tribute Master";
case GUILD_TRIBUTE_MASTER:
@ -400,7 +400,7 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
return "Fellowship Master";
case ALT_CURRENCY_MERCHANT:
return "Alternate Currency Merchant";
case MERCERNARY_MASTER:
case MERCENARY_MASTER:
return "Mercenary Liaison";
default:
return "Unknown";

View File

@ -55,10 +55,9 @@
#define BANKER 40
#define MERCHANT 41
#define DISCORD_MERCHANT 59
#define ADVENTURERECRUITER 60
#define ADVENTUREMERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs
#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far..
#define ADVENTURE_RECRUITER 60
#define ADVENTURE_MERCHANT 61
#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs, seen on Danvi's Corpse in Akheva
#define TRIBUTE_MASTER 63
#define GUILD_TRIBUTE_MASTER 64 // not sure
#define GUILD_BANKER 66
@ -66,7 +65,7 @@
#define DARK_REIGN_MERCHANT 68
#define FELLOWSHIP_MASTER 69
#define ALT_CURRENCY_MERCHANT 70
#define MERCERNARY_MASTER 71
#define MERCENARY_MASTER 71
// player class values

View File

@ -511,6 +511,7 @@ RULE_BOOL(NPC, UseMeditateBasedManaRegen, false, "Based NPC ooc regen on Meditat
RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the NPC will heal on gate if enabled")
RULE_BOOL(NPC, AnimalsOpenDoors, true, "Determines or not whether animals open doors or not when they approach them")
RULE_INT(NPC, MaxRaceID, 732, "Maximum Race ID, RoF2 by default supports up to 732")
RULE_BOOL(NPC, DisableLastNames, false, "Enable to disable NPC Last Names")
RULE_CATEGORY_END()
RULE_CATEGORY(Aggro)

View File

@ -2584,7 +2584,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
}
bool allow_merchant_corpse = RuleB(Merchant, AllowCorpse);
bool is_merchant = (class_ == MERCHANT || class_ == ADVENTUREMERCHANT || MerchantType != 0);
bool is_merchant = (class_ == MERCHANT || class_ == ADVENTURE_MERCHANT || MerchantType != 0);
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||

View File

@ -1875,7 +1875,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
Adventure_Purchase_Struct* aps = (Adventure_Purchase_Struct*)app->pBuffer;
uint32 merchantid = 0;
Mob* tmp = entity_list.GetMob(aps->npcid);
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTUREMERCHANT) &&
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTURE_MERCHANT) &&
(tmp->GetClass() != DISCORD_MERCHANT) && (tmp->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (tmp->GetClass() != DARK_REIGN_MERCHANT)))
return;
@ -2056,7 +2056,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
uint32 merchantid = 0;
Mob* tmp = entity_list.GetMob(eid->entity_id);
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTUREMERCHANT) &&
if (tmp == 0 || !tmp->IsNPC() || ((tmp->GetClass() != ADVENTURE_MERCHANT) &&
(tmp->GetClass() != DISCORD_MERCHANT) && (tmp->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (tmp->GetClass() != DARK_REIGN_MERCHANT)))
return;
@ -2127,7 +2127,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app)
Adventure_Sell_Struct *ams_in = (Adventure_Sell_Struct*)app->pBuffer;
Mob* vendor = entity_list.GetMob(ams_in->npcid);
if (vendor == 0 || !vendor->IsNPC() || ((vendor->GetClass() != ADVENTUREMERCHANT) &&
if (vendor == 0 || !vendor->IsNPC() || ((vendor->GetClass() != ADVENTURE_MERCHANT) &&
(vendor->GetClass() != NORRATHS_KEEPERS_MERCHANT) && (vendor->GetClass() != DARK_REIGN_MERCHANT)))
{
Message(Chat::Red, "Vendor was not found.");
@ -2224,7 +2224,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app)
switch (vendor->GetClass())
{
case ADVENTUREMERCHANT:
case ADVENTURE_MERCHANT:
{
UpdateLDoNPoints(6, price);
break;
@ -9773,7 +9773,7 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app)
if (DistanceSquared(m_Position, tar->GetPosition()) > USE_NPC_RANGE2)
return;
if (tar->GetClass() != MERCERNARY_MASTER) {
if (tar->GetClass() != MERCENARY_MASTER) {
return;
}

View File

@ -10,7 +10,7 @@ void command_findclass(Client *c, const Seperator *sep)
if (sep->IsNumber(1)) {
int class_id = std::stoi(sep->arg[1]);
if (class_id >= WARRIOR && class_id <= MERCERNARY_MASTER) {
if (class_id >= WARRIOR && class_id <= MERCENARY_MASTER) {
std::string class_name = GetClassIDName(class_id);
c->Message(
Chat::White,
@ -41,7 +41,7 @@ void command_findclass(Client *c, const Seperator *sep)
} else {
auto search_criteria = str_tolower(sep->argplus[1]);
int found_count = 0;
for (uint16 class_id = WARRIOR; class_id <= MERCERNARY_MASTER; class_id++) {
for (uint16 class_id = WARRIOR; class_id <= MERCENARY_MASTER; class_id++) {
std::string class_name = GetClassIDName(class_id);
auto class_name_lower = str_tolower(class_name);
if (

View File

@ -204,24 +204,20 @@ void command_npcedit(Client *c, const Seperator *sep)
return;
} else if (!strcasecmp(sep->arg[1], "lastname")) {
std::string last_name = sep->argplus[2];
if (!last_name.empty()) {
c->Message(
Chat::Yellow,
fmt::format(
"{} now has the lastname '{}'.",
npc_id_string,
sep->argplus[2]
).c_str()
);
auto query = fmt::format(
"UPDATE npc_types SET lastname = '{}' WHERE id = {}",
sep->argplus[2],
npc_id
);
content_db.QueryDatabase(query);
} else {
c->Message(Chat::White, "Usage: #npcedit lastname [Last Name] - Sets an NPC's Last Name");
}
c->Message(
Chat::Yellow,
fmt::format(
"{} now has the lastname '{}'.",
npc_id_string,
last_name
).c_str()
);
auto query = fmt::format(
"UPDATE npc_types SET lastname = '{}' WHERE id = {}",
last_name,
npc_id
);
content_db.QueryDatabase(query);
return;
} else if (!strcasecmp(sep->arg[1], "level")) {
if (sep->IsNumber(2)) {

View File

@ -4446,17 +4446,16 @@ luabind::scope lua_register_classes() {
luabind::value("BANKER", BANKER),
luabind::value("MERCHANT", MERCHANT),
luabind::value("DISCORD_MERCHANT", DISCORD_MERCHANT),
luabind::value("ADVENTURERECRUITER", ADVENTURERECRUITER),
luabind::value("ADVENTUREMERCHANT", ADVENTUREMERCHANT),
luabind::value("ADVENTURE_RECRUITER", ADVENTURE_RECRUITER),
luabind::value("ADVENTURE_MERCHANT", ADVENTURE_MERCHANT),
luabind::value("LDON_TREASURE", LDON_TREASURE),
luabind::value("CORPSE_CLASS", CORPSE_CLASS),
luabind::value("TRIBUTE_MASTER", TRIBUTE_MASTER),
luabind::value("GUILD_TRIBUTE_MASTER", GUILD_TRIBUTE_MASTER),
luabind::value("NORRATHS_KEEPERS_MERCHANT", NORRATHS_KEEPERS_MERCHANT),
luabind::value("DARK_REIGN_MERCHANT", DARK_REIGN_MERCHANT),
luabind::value("FELLOWSHIP_MASTER", FELLOWSHIP_MASTER),
luabind::value("ALT_CURRENCY_MERCHANT", ALT_CURRENCY_MERCHANT),
luabind::value("MERCERNARY_MASTER", MERCERNARY_MASTER)
luabind::value("MERCENARY_MASTER", MERCENARY_MASTER)
];
}

View File

@ -1074,77 +1074,99 @@ uint8 Mob::GetArchetype() const {
}
}
void Mob::SetSpawnLastNameByClass(NewSpawn_Struct* ns)
{
switch (ns->spawn.class_) {
case TRIBUTE_MASTER:
strcpy(ns->spawn.lastName, "Tribute Master");
break;
case GUILD_TRIBUTE_MASTER:
strcpy(ns->spawn.lastName, "Guild Tribute Master");
break;
case GUILD_BANKER:
strcpy(ns->spawn.lastName, "Guild Banker");
break;
case ADVENTURE_RECRUITER:
strcpy(ns->spawn.lastName, "Adventure Recruiter");
break;
case ADVENTURE_MERCHANT:
strcpy(ns->spawn.lastName, "Adventure Merchant");
break;
case BANKER:
strcpy(ns->spawn.lastName, "Banker");
break;
case WARRIORGM:
strcpy(ns->spawn.lastName, "Warrior Guildmaster");
break;
case CLERICGM:
strcpy(ns->spawn.lastName, "Cleric Guildmaster");
break;
case PALADINGM:
strcpy(ns->spawn.lastName, "Paladin Guildmaster");
break;
case RANGERGM:
strcpy(ns->spawn.lastName, "Ranger Guildmaster");
break;
case SHADOWKNIGHTGM:
strcpy(ns->spawn.lastName, "Shadow Knight Guildmaster");
break;
case DRUIDGM:
strcpy(ns->spawn.lastName, "Druid Guildmaster");
break;
case MONKGM:
strcpy(ns->spawn.lastName, "Monk Guildmaster");
break;
case BARDGM:
strcpy(ns->spawn.lastName, "Bard Guildmaster");
break;
case ROGUEGM:
strcpy(ns->spawn.lastName, "Rogue Guildmaster");
break;
case SHAMANGM:
strcpy(ns->spawn.lastName, "Shaman Guildmaster");
break;
case NECROMANCERGM:
strcpy(ns->spawn.lastName, "Necromancer Guildmaster");
break;
case WIZARDGM:
strcpy(ns->spawn.lastName, "Wizard Guildmaster");
break;
case MAGICIANGM:
strcpy(ns->spawn.lastName, "Magician Guildmaster");
break;
case ENCHANTERGM:
strcpy(ns->spawn.lastName, "Enchanter Guildmaster");
break;
case BEASTLORDGM:
strcpy(ns->spawn.lastName, "Beastlord Guildmaster");
break;
case BERSERKERGM:
strcpy(ns->spawn.lastName, "Berserker Guildmaster");
break;
case MERCENARY_MASTER:
strcpy(ns->spawn.lastName, "Mercenary Liaison");
break;
default:
strcpy(ns->spawn.lastName, ns->spawn.lastName);
break;
}
}
void Mob::CreateSpawnPacket(EQApplicationPacket *app, Mob *ForWho)
{
app->SetOpcode(OP_NewSpawn);
app->size = sizeof(NewSpawn_Struct);
app->size = sizeof(NewSpawn_Struct);
app->pBuffer = new uchar[app->size];
memset(app->pBuffer, 0, app->size);
NewSpawn_Struct *ns = (NewSpawn_Struct *) app->pBuffer;
auto ns = (NewSpawn_Struct *) app->pBuffer;
FillSpawnStruct(ns, ForWho);
if (RuleB(NPC, UseClassAsLastName) && strlen(ns->spawn.lastName) == 0) {
switch (ns->spawn.class_) {
case TRIBUTE_MASTER:
strcpy(ns->spawn.lastName, "Tribute Master");
break;
case ADVENTURERECRUITER:
strcpy(ns->spawn.lastName, "Adventure Recruiter");
break;
case BANKER:
strcpy(ns->spawn.lastName, "Banker");
break;
case ADVENTUREMERCHANT:
strcpy(ns->spawn.lastName, "Adventure Merchant");
break;
case WARRIORGM:
strcpy(ns->spawn.lastName, "GM Warrior");
break;
case PALADINGM:
strcpy(ns->spawn.lastName, "GM Paladin");
break;
case RANGERGM:
strcpy(ns->spawn.lastName, "GM Ranger");
break;
case SHADOWKNIGHTGM:
strcpy(ns->spawn.lastName, "GM Shadowknight");
break;
case DRUIDGM:
strcpy(ns->spawn.lastName, "GM Druid");
break;
case BARDGM:
strcpy(ns->spawn.lastName, "GM Bard");
break;
case ROGUEGM:
strcpy(ns->spawn.lastName, "GM Rogue");
break;
case SHAMANGM:
strcpy(ns->spawn.lastName, "GM Shaman");
break;
case NECROMANCERGM:
strcpy(ns->spawn.lastName, "GM Necromancer");
break;
case WIZARDGM:
strcpy(ns->spawn.lastName, "GM Wizard");
break;
case MAGICIANGM:
strcpy(ns->spawn.lastName, "GM Magician");
break;
case ENCHANTERGM:
strcpy(ns->spawn.lastName, "GM Enchanter");
break;
case BEASTLORDGM:
strcpy(ns->spawn.lastName, "GM Beastlord");
break;
case BERSERKERGM:
strcpy(ns->spawn.lastName, "GM Berserker");
break;
case MERCERNARY_MASTER:
strcpy(ns->spawn.lastName, "Mercenary Recruiter");
break;
default:
break;
}
if (
!RuleB(NPC, DisableLastNames) &&
RuleB(NPC, UseClassAsLastName) &&
!strlen(ns->spawn.lastName)
) {
SetSpawnLastNameByClass(ns);
}
}
@ -1158,80 +1180,20 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) {
memcpy(app->pBuffer, ns, sizeof(NewSpawn_Struct));
// Custom packet data
NewSpawn_Struct* ns2 = (NewSpawn_Struct*)app->pBuffer;
auto ns2 = (NewSpawn_Struct*) app->pBuffer;
strcpy(ns2->spawn.name, ns->spawn.name);
// Set default Last Names for certain Classes if not defined
if (RuleB(NPC, UseClassAsLastName) && strlen(ns->spawn.lastName) == 0)
{
switch (ns->spawn.class_)
{
case TRIBUTE_MASTER:
strcpy(ns2->spawn.lastName, "Tribute Master");
break;
case ADVENTURERECRUITER:
strcpy(ns2->spawn.lastName, "Adventure Recruiter");
break;
case BANKER:
strcpy(ns2->spawn.lastName, "Banker");
break;
case ADVENTUREMERCHANT:
strcpy(ns2->spawn.lastName, "Adventure Merchant");
break;
case WARRIORGM:
strcpy(ns2->spawn.lastName, "GM Warrior");
break;
case PALADINGM:
strcpy(ns2->spawn.lastName, "GM Paladin");
break;
case RANGERGM:
strcpy(ns2->spawn.lastName, "GM Ranger");
break;
case SHADOWKNIGHTGM:
strcpy(ns2->spawn.lastName, "GM Shadowknight");
break;
case DRUIDGM:
strcpy(ns2->spawn.lastName, "GM Druid");
break;
case BARDGM:
strcpy(ns2->spawn.lastName, "GM Bard");
break;
case ROGUEGM:
strcpy(ns2->spawn.lastName, "GM Rogue");
break;
case SHAMANGM:
strcpy(ns2->spawn.lastName, "GM Shaman");
break;
case NECROMANCERGM:
strcpy(ns2->spawn.lastName, "GM Necromancer");
break;
case WIZARDGM:
strcpy(ns2->spawn.lastName, "GM Wizard");
break;
case MAGICIANGM:
strcpy(ns2->spawn.lastName, "GM Magician");
break;
case ENCHANTERGM:
strcpy(ns2->spawn.lastName, "GM Enchanter");
break;
case BEASTLORDGM:
strcpy(ns2->spawn.lastName, "GM Beastlord");
break;
case BERSERKERGM:
strcpy(ns2->spawn.lastName, "GM Berserker");
break;
case MERCERNARY_MASTER:
strcpy(ns2->spawn.lastName, "Mercenary liaison");
break;
default:
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
break;
}
}
else
{
if (
!RuleB(NPC, DisableLastNames) &&
RuleB(NPC, UseClassAsLastName) &&
!strlen(ns->spawn.lastName)
) {
SetSpawnLastNameByClass(ns2);
} else {
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
}
memset(&app->pBuffer[sizeof(Spawn_Struct)-7], 0xFF, 7);
}

View File

@ -737,6 +737,7 @@ public:
void CreateHPPacket(EQApplicationPacket* app);
void SendHPUpdate(bool force_update_all = false);
virtual void ResetHPUpdateTimer() {}; // does nothing
static void SetSpawnLastNameByClass(NewSpawn_Struct* ns);
//Util
static uint32 RandomTimer(int min, int max);

View File

@ -265,7 +265,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
HasAISpellEffects = false;
innate_proc_spell_id = 0;
if (GetClass() == MERCERNARY_MASTER && RuleB(Mercs, AllowMercs)) {
if (GetClass() == MERCENARY_MASTER && RuleB(Mercs, AllowMercs)) {
LoadMercTypes();
LoadMercs();
}

View File

@ -2511,8 +2511,8 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
t->see_invis = n.see_invis != 0;
t->see_invis_undead = n.see_invis_undead != 0; // Set see_invis_undead flag
if (!n.lastname.empty()) {
strn0cpy(t->lastname, n.lastname.c_str(), 32);
if (!RuleB(NPC, DisableLastNames) && !n.lastname.empty()) {
strn0cpy(t->lastname, n.lastname.c_str(), sizeof(t->lastname));
}
t->qglobal = n.qglobal != 0; // qglobal

View File

@ -35,7 +35,7 @@ spawn2 mediumblob, npcs mediumblob, npc_loot mediumblob, gmspawntype mediumblob,
struct NPCType
{
char name[64];
char lastname[70];
char lastname[64];
int64 current_hp;
int64 max_hp;
float size;