Compare commits

..

2 Commits

Author SHA1 Message Date
Trust 2434bab697 Updated for bypass all rule 2024-02-25 16:00:44 -05:00
Trust 7a5a755033 [Bug Fix] Cleanup NPC Mana Tap Logic
Mana Tap rule logic was invalid - Cleaned up and simplified, either we care about npc mana or we dont.
2024-02-25 15:20:58 -05:00
58 changed files with 356 additions and 1003 deletions
-112
View File
@@ -1,115 +1,3 @@
## [22.47.0] 3/5/2024
### Crash Fix
* Added a guild_mgr check ([#4163](https://github.com/EQEmu/Server/pull/4163)) @neckkola 2024-03-06
* Goto Command could crash using Developer Tools ([#4158](https://github.com/EQEmu/Server/pull/4158)) @neckkola 2024-03-04
* Groundspawn Memory Corruption ([#4157](https://github.com/EQEmu/Server/pull/4157)) @neckkola 2024-03-04
* Update to location of qGlobals initialization ([#4144](https://github.com/EQEmu/Server/pull/4144)) @neckkola 2024-03-02
### Feature
* Adds rules to control level requirements for Double Backstab, Assassinate, and Double Bowshot (#4159) ([#29](https://github.com/EQEmu/Server/pull/29)) @catapultam-habeo 2024-03-04
* Adjust String-based Rules Length ([#4138](https://github.com/EQEmu/Server/pull/4138)) @Kinglykrab 2024-03-06
* Exempt a zone from IP-limit checks. ([#4137](https://github.com/EQEmu/Server/pull/4137)) @catapultam-habeo 2024-03-02
### Fixes
* Add id to the guild_bank table ([#4155](https://github.com/EQEmu/Server/pull/4155)) @neckkola 2024-03-05
* Fix Bots/Bot Pets ending up on XTargets ([#4132](https://github.com/EQEmu/Server/pull/4132)) @Kinglykrab 2024-03-02
* Fix Character EXP Modifiers default ([#4161](https://github.com/EQEmu/Server/pull/4161)) @Kinglykrab 2024-03-06
* Fix Spawns Not Parsing Quest on Zone Bootup ([#4149](https://github.com/EQEmu/Server/pull/4149)) @Kinglykrab 2024-03-05
* Fix typo when updating spawn events in spawn condition manager ([#4160](https://github.com/EQEmu/Server/pull/4160)) @joligario 2024-03-05
* GetBotNameByID Temporary Reference Warning ([#4145](https://github.com/EQEmu/Server/pull/4145)) @Kinglykrab 2024-03-02
* Prevent NPE when creating DZ using ad-hoc version IDs ([#4141](https://github.com/EQEmu/Server/pull/4141)) @catapultam-habeo 2024-03-05
* Update FreeGuildID Routine ([#4143](https://github.com/EQEmu/Server/pull/4143)) @neckkola 2024-03-02
### Quest API
* Add Bot Special Attacks for Immune Aggro/Damage ([#4108](https://github.com/EQEmu/Server/pull/4108)) @Kinglykrab 2024-03-02
* Add GetHeroicStrikethrough() to Perl/Lua ([#4150](https://github.com/EQEmu/Server/pull/4150)) @Kinglykrab 2024-03-03
* Add IsAlwaysAggro() to Perl/Lua ([#4152](https://github.com/EQEmu/Server/pull/4152)) @Kinglykrab 2024-03-04
* Add IsBoat()/IsControllableBoat() to Perl/Lua ([#4151](https://github.com/EQEmu/Server/pull/4151)) @Kinglykrab 2024-03-03
* Add IsDestructibleObject() to Perl/Lua ([#4153](https://github.com/EQEmu/Server/pull/4153)) @Kinglykrab 2024-03-03
### Zone
* Zone Routing Improvements ([#4142](https://github.com/EQEmu/Server/pull/4142)) @Akkadius 2024-03-02
### Zoning
* Zone routing adjustment ([#4162](https://github.com/EQEmu/Server/pull/4162)) @Akkadius 2024-03-06
## [22.46.1] 3/2/2024
### Fixes
* Change `UnburyCorpse` to use repository methods ([#4147](https://github.com/EQEmu/Server/pull/4147)) @joligario 2024-03-03
## [22.46.0] 3/2/2024
### Commands
* Add #fish Command ([#4136](https://github.com/EQEmu/Server/pull/4136)) @Kinglykrab 2024-03-01
### Crash Fix
* Raid::UpdateGroupAAs ([#4139](https://github.com/EQEmu/Server/pull/4139)) @neckkola 2024-03-02
* Update to location of qGlobals initialization ([#4144](https://github.com/EQEmu/Server/pull/4144)) @neckkola 2024-03-02
### Feature
* Exempt a zone from IP-limit checks. ([#4137](https://github.com/EQEmu/Server/pull/4137)) @catapultam-habeo 2024-03-02
### Fixes
* Cleanup NPC Mana Tap Logic ([#4134](https://github.com/EQEmu/Server/pull/4134)) @noudess 2024-03-02
* Fix Bots/Bot Pets ending up on XTargets ([#4132](https://github.com/EQEmu/Server/pull/4132)) @Kinglykrab 2024-03-02
* Fix issue with NPC Secondary Textures ([#4129](https://github.com/EQEmu/Server/pull/4129)) @Kinglykrab 2024-03-01
* GetBotNameByID Temporary Reference Warning ([#4145](https://github.com/EQEmu/Server/pull/4145)) @Kinglykrab 2024-03-02
* Update FreeGuildID Routine ([#4143](https://github.com/EQEmu/Server/pull/4143)) @neckkola 2024-03-02
* Use std::clamp for Mob::ChangeSize ([#4140](https://github.com/EQEmu/Server/pull/4140)) @joligario 2024-03-02
### Quest API
* Add Bot Special Attacks for Immune Aggro/Damage ([#4108](https://github.com/EQEmu/Server/pull/4108)) @Kinglykrab 2024-03-02
### Zone
* Zone Routing Improvements ([#4142](https://github.com/EQEmu/Server/pull/4142)) @Akkadius 2024-03-02
## [22.45.1] 2/29/2024
### Character Creation
* Improved Random Name Generator ([#4081](https://github.com/EQEmu/Server/pull/4081)) @catapultam-habeo 2024-02-27
### Code
* Fix Server Rules Documentation Generation ([#4125](https://github.com/EQEmu/Server/pull/4125)) @Kinglykrab 2024-02-26
* Remove unnecessary stoptimer logs ([#4128](https://github.com/EQEmu/Server/pull/4128)) @Kinglykrab 2024-02-28
### Commands
* Add `#forage` command ([#4133](https://github.com/EQEmu/Server/pull/4133)) @joligario 2024-02-29
### Crash
* Fix crash issue during database dump ([#4127](https://github.com/EQEmu/Server/pull/4127)) @Akkadius 2024-02-29
### Crash Fix
* D20 crash if mitigation average resulted in 0 ([#4131](https://github.com/EQEmu/Server/pull/4131)) @nytmyr 2024-02-29
### Fixes
* Fix forage returning first result from table ([#4130](https://github.com/EQEmu/Server/pull/4130)) @nytmyr 2024-02-29
* Who /all displays incorrect guild name ([#4123](https://github.com/EQEmu/Server/pull/4123)) @neckkola 2024-02-25
### Quest API
* Add Pet Owner Methods to Perl/Lua ([#4115](https://github.com/EQEmu/Server/pull/4115)) @Kinglykrab 2024-02-25
## [22.45.0] 2/24/2024
### Beacon
+42 -83
View File
@@ -178,13 +178,12 @@ void WorldContentService::ReloadContentFlags()
LogInfo(
"Loaded content flag [{}] [{}]",
f.flag_name,
(f.enabled ? "enabled" : "disabled")
(f.enabled ? "Enabled" : "Disabled")
);
}
SetContentFlags(set_content_flags);
LoadZones();
LoadStaticGlobalZoneInstances();
SetContentZones(ZoneRepository::All(*m_content_database));
}
Database *WorldContentService::GetDatabase() const
@@ -236,6 +235,19 @@ void WorldContentService::SetContentFlag(const std::string &content_flag_name, b
ReloadContentFlags();
}
// SetZones sets the zones for the world content service
// this is used for zone routing middleware
// we pull the zone list from the zone repository and feed from the zone store for now
// we're holding a copy in the content service - but we're talking 250kb of data in memory to handle routing of zoning
WorldContentService *WorldContentService::SetContentZones(const std::vector<BaseZoneRepository::Zone>& zones)
{
m_zones = zones;
LogInfo("Loaded [{}] zones", m_zones.size());
return this;
}
// HandleZoneRoutingMiddleware is meant to handle content and context aware zone routing
//
// example # 1
@@ -248,57 +260,16 @@ void WorldContentService::SetContentFlag(const std::string &content_flag_name, b
// scripts handle all the same way, you don't have to think about instances, the middleware will handle the magic
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
// we decide to route the client to the correct version of the zone based on the current server side expansion
// example # 2
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
{
auto r = FindZone(zc->zoneID, zc->instanceID);
if (r.zone_id == 0) {
// if we're already in an instance, we don't want to route the player to another instance
if (zc->instanceID > 0) {
return;
}
zc->instanceID = r.instance.id;
}
// LoadStaticGlobalZoneInstances loads all static global zone instances
// these are zones that are never set to expire and are global
// these are used commonly in v1/v2/v3 versions of the same zone for expansion routing
WorldContentService * WorldContentService::LoadStaticGlobalZoneInstances()
{
m_zone_instances = InstanceListRepository::GetWhere(*GetDatabase(), fmt::format("never_expires = 1 AND is_global = 1"));
LogInfo("Loaded [{}] zone_instances", m_zone_instances.size());
return this;
}
// LoadZones sets the zones for the world content service
// this is used for zone routing middleware
// we pull the zone list from the zone repository and feed from the zone store for now
// we're holding a copy in the content service - but we're talking 250kb of data in memory to handle routing of zoning
WorldContentService * WorldContentService::LoadZones()
{
m_zones = ZoneRepository::All(*GetContentDatabase());
LogInfo("Loaded [{}] zones", m_zones.size());
return this;
}
// FindZone is critical to the zone routing middleware and any logic that needs to route players to the correct zone
// era contextual routing, multiple version of zones, etc
WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
{
// if there's an active dynamic instance, we don't need to route
if (instance_id > 0) {
auto inst = InstanceListRepository::FindOne(*GetDatabase(), instance_id);
if (inst.id != 0 && !inst.is_global && !inst.never_expires) {
return WorldContentService::FindZoneResult{
.zone_id = 0,
};
}
}
for (auto &z: m_zones) {
if (z.zoneidnumber == zone_id) {
if (z.zoneidnumber == zc->zoneID) {
auto f = ContentFlags{
.min_expansion = z.min_expansion,
.max_expansion = z.max_expansion,
@@ -315,45 +286,33 @@ WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id
z.long_name
);
// first pass, explicit match on public static global zone instances
for (auto &i: m_zone_instances) {
if (i.zone == zone_id && i.version == z.version) {
LogInfo(
"Routed player to instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
i.id,
z.short_name,
z.zoneidnumber,
z.version,
z.long_name,
i.notes
);
return WorldContentService::FindZoneResult{
.zone_id = static_cast<uint32>(z.zoneidnumber),
.instance = i,
.zone = z
};
}
}
LogInfo(
"Routed player to non-instance zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
z.short_name,
z.zoneidnumber,
z.version,
z.long_name,
z.note
auto instances = InstanceListRepository::GetWhere(
*GetDatabase(),
fmt::format(
"zone = {} AND version = {} AND never_expires = 1 AND is_global = 1",
z.zoneidnumber,
z.version
)
);
return WorldContentService::FindZoneResult{
.zone_id = static_cast<uint32>(z.zoneidnumber),
.instance = InstanceListRepository::NewEntity(),
.zone = z
};
if (!instances.empty()) {
auto instance = instances.front();
zc->instanceID = instance.id;
LogInfo(
"Routed player to instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
instance.id,
z.short_name,
z.zoneidnumber,
z.version,
z.long_name,
instance.notes
);
break;
}
}
}
}
return WorldContentService::FindZoneResult{.zone_id = 0};
}
+1 -12
View File
@@ -5,7 +5,6 @@
#include <vector>
#include "../repositories/content_flags_repository.h"
#include "../repositories/zone_repository.h"
#include "../repositories/instance_list_repository.h"
class Database;
@@ -170,14 +169,7 @@ public:
void SetContentFlag(const std::string &content_flag_name, bool enabled);
void HandleZoneRoutingMiddleware(ZoneChange_Struct *zc);
struct FindZoneResult {
uint32 zone_id = 0;
InstanceListRepository::InstanceList instance;
ZoneRepository::Zone zone;
};
FindZoneResult FindZone(uint32 zone_id, uint32 instance_id);
WorldContentService * SetContentZones(const std::vector<ZoneRepository::Zone>& zones);
private:
int current_expansion{};
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
@@ -188,9 +180,6 @@ private:
// holds a record of the zone table from the database
std::vector<ZoneRepository::Zone> m_zones = {};
WorldContentService *LoadStaticGlobalZoneInstances();
std::vector<InstanceListRepository::InstanceList> m_zone_instances;
WorldContentService * LoadZones();
};
extern WorldContentService content_service;
+1 -6
View File
@@ -575,12 +575,7 @@ void DatabaseDumpService::RemoveSqlBackup()
{
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
if (File::Exists(file)) {
try {
std::filesystem::remove(file);
}
catch (std::exception &e) {
LogError("std::filesystem::remove err [{}]", e.what());
}
std::filesystem::remove(file);
}
RemoveCredentialsFile();
@@ -5410,29 +5410,6 @@ ADD COLUMN `augment_five` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_fou
ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9265,
.description = "2024_03_03_add_id_to_guild_bank.sql",
.check = "SHOW COLUMNS FROM `guild_bank` LIKE 'id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `guild_bank`
ADD COLUMN `id` INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
)",
},
ManifestEntry{
.version = 9266,
.description = "2024_03_02_rule_values_rule_value_length.sql",
.check = "SHOW COLUMNS FROM `rule_values` LIKE 'rule_value'",
.condition = "contains",
.match = "varchar(30)",
.sql = R"(
ALTER TABLE `rule_values`
MODIFY COLUMN `rule_value` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `rule_name`;
)"
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
-2
View File
@@ -698,8 +698,6 @@ const std::map<uint32, std::string>& EQ::constants::GetSpecialAbilityMap()
{ IMMUNE_OPEN, "Immune to Open" },
{ IMMUNE_ASSASSINATE, "Immune to Assassinate" },
{ IMMUNE_HEADSHOT, "Immune to Headshot" },
{ IMMUNE_AGGRO_BOT, "Immune to Bot Aggro" },
{ IMMUNE_DAMAGE_BOT, "Immune to Bot Damage" },
};
return special_ability_map;
+1 -3
View File
@@ -656,9 +656,7 @@ enum {
IMMUNE_OPEN = 53,
IMMUNE_ASSASSINATE = 54,
IMMUNE_HEADSHOT = 55,
IMMUNE_AGGRO_BOT = 56,
IMMUNE_DAMAGE_BOT = 57,
MAX_SPECIAL_ATTACK = 58
MAX_SPECIAL_ATTACK = 56
};
-2
View File
@@ -141,7 +141,6 @@ namespace Logs {
Zoning,
EqTime,
Corpses,
XTargets,
MaxCategoryID /* Don't Remove this */
};
@@ -242,7 +241,6 @@ namespace Logs {
"Zoning",
"EqTime",
"Corpses",
"XTargets"
};
}
-10
View File
@@ -834,16 +834,6 @@
OutF(LogSys, Logs::Detail, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogXTargets(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::XTargets))\
OutF(LogSys, Logs::General, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogXTargetsDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::XTargets))\
OutF(LogSys, Logs::Detail, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.IsLogEnabled(debug_level, log_category))\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
+34 -7
View File
@@ -342,14 +342,41 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id)
return true;
}
uint32 BaseGuildManager::_GetFreeGuildID()
{
GuildsRepository::DeleteWhere(*m_db, "`name` = ''");
GuildsRepository::Guilds out;
out.id = 0;
out.leader = 0;
out.minstatus = 0;
out.tribute = 0;
out.name = "";
out.motd = "";
out.motd_setter = "";
out.url = "";
out.channel = "";
auto last_insert_id = GuildsRepository::InsertOne(*m_db, out);
if (last_insert_id.id > 0) {
LogGuilds("Located a free guild ID [{}] in the database", last_insert_id.id);
return last_insert_id.id;
}
LogGuilds("Unable to find a free guild ID in the database");
return GUILD_NONE;
}
uint32 BaseGuildManager::CreateGuild(std::string name, uint32 leader_char_id)
{
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
if (guild_id == GUILD_NONE) {
return (GUILD_NONE);
}
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
if (guild_id == GUILD_NONE) {
return (GUILD_NONE);
}
//RefreshGuild(guild_id);
//SendGuildRefresh(guild_id, true, false, false, false);
//SendCharRefresh(GUILD_NONE, guild_id, leader_char_id);
return guild_id;
return guild_id;
}
bool BaseGuildManager::DeleteGuild(uint32 guild_id)
@@ -512,8 +539,8 @@ bool BaseGuildManager::SetPublicNote(uint32 charid, std::string public_note)
uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
{
auto new_id = GuildsRepository::GetMaxId(*m_db) + 1;
if (!new_id) {
auto new_id = _GetFreeGuildID();
if (new_id == GUILD_NONE) {
return GUILD_NONE;
}
+1
View File
@@ -208,6 +208,7 @@ class BaseGuildManager
bool _StoreGuildDB(uint32 guild_id);
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
uint32 _GetFreeGuildID();
GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in);
};
#endif /*GUILD_BASE_H_*/
@@ -213,23 +213,23 @@ public:
const glm::vec4& position
)
{
auto corpse = FindOne(db, corpse_id);
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{}` SET `is_buried` = 0, `zone_id` = {}, `instance_id` = {}, `x` = {:.2f}, `y` = {:.2f}, `z` = {:.2f}, `heading` = {:.2f}, `time_of_death` = {}, `was_at_graveyard` = 0 WHERE `{}` = {}",
TableName(),
zone_id,
instance_id,
position.x,
position.y,
position.z,
position.w,
std::time(nullptr),
PrimaryKey(),
corpse_id
)
);
if (corpse.id == 0) {
return 0;
}
corpse.is_buried = 0;
corpse.zone_id = zone_id;
corpse.instance_id = instance_id;
corpse.x = position.x;
corpse.y = position.y;
corpse.z = position.z;
corpse.heading = position.w;
corpse.time_of_death = time(nullptr);
corpse.was_at_graveyard = 0;
return UpdateOne(db, corpse);
return results.Success() ? results.RowsAffected() : 0;
}
};
@@ -74,11 +74,9 @@ public:
};
}
const auto& m = l.front();
return EXPModifier{
.aa_modifier = m.aa_modifier,
.exp_modifier = m.exp_modifier
.aa_modifier = l[0].aa_modifier,
.exp_modifier = l[0].exp_modifier
};
}
+5 -35
View File
@@ -34,8 +34,8 @@ const char *RuleManager::s_categoryNames[_CatCount + 1] = {
"InvalidCategory"
};
const RuleManager::RuleInfo RuleManager::s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount + 1] = {
/* this is done in three steps, so we can reliably get to them by index*/
const RuleManager::RuleInfo RuleManager::s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + 1] = {
/* this is done in three steps so we can reliably get to them by index*/
#define RULE_INT(category_name, rule_name, default_value, notes) \
{ #category_name ":" #rule_name, Category__##category_name, IntRule, Int__##rule_name, notes },
#include "ruletypes.h"
@@ -45,9 +45,6 @@ const RuleManager::RuleInfo RuleManager::s_RuleInfo[IntRuleCount + RealRuleCount
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
{ #category_name ":" #rule_name, Category__##category_name, BoolRule, Bool__##rule_name, notes },
#include "ruletypes.h"
#define RULE_STRING(category_name, rule_name, default_value, notes) \
{ #category_name ":" #rule_name, Category__##category_name, StringRule, String__##rule_name, notes },
#include "ruletypes.h"
{ "Invalid Rule", _CatCount, IntRule }
};
@@ -117,9 +114,6 @@ bool RuleManager::GetRule(const std::string &rule_name, std::string &rule_value)
case BoolRule:
rule_value = m_RuleBoolValues[index] ? "true" : "false";
break;
case StringRule:
rule_value = m_RuleStringValues[index];
break;
}
return true;
@@ -158,10 +152,6 @@ bool RuleManager::SetRule(const std::string &rule_name, const std::string &rule_
m_RuleBoolValues[index] = static_cast<uint32>(Strings::ToBool(rule_value));
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
break;
case StringRule:
m_RuleStringValues[index] = rule_value;
LogRules("Set rule [{}] to value [{}]", rule_name, rule_value);
break;
}
if (db_save) {
@@ -225,13 +215,11 @@ std::string RuleManager::_GetRuleName(RuleType type, uint16 index) {
return s_RuleInfo[index + IntRuleCount].name;
case BoolRule:
return s_RuleInfo[index + IntRuleCount + RealRuleCount].name;
case StringRule:
return s_RuleInfo[index + IntRuleCount + RealRuleCount + StringRuleCount].name;
default:
break;
}
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount].name;
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount].name;
}
//assumes index is valid!
@@ -243,13 +231,11 @@ const std::string &RuleManager::_GetRuleNotes(RuleType type, uint16 index) {
return s_RuleInfo[index + IntRuleCount].notes;
case BoolRule:
return s_RuleInfo[index + IntRuleCount + RealRuleCount].notes;
case StringRule:
return s_RuleInfo[index + IntRuleCount + RealRuleCount + StringRuleCount].notes;
default:
break;
}
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount].notes;
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount].notes;
}
bool RuleManager::LoadRules(Database *db, const std::string &rule_set_name, bool reload) {
@@ -357,10 +343,6 @@ void RuleManager::SaveRules(Database *db, const std::string &rule_set_name) {
for (i = 0; i < BoolRuleCount; i++) {
_SaveRule(db, BoolRule, i);
}
for (i = 0; i < StringRuleCount; i++) {
_SaveRule(db, StringRule, i);
}
}
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
@@ -385,9 +367,6 @@ void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
case BoolRule:
rule_value = m_RuleBoolValues[index] ? "true" : "false";
break;
case StringRule:
rule_value = m_RuleStringValues[index];
break;
}
const auto& rule_notes = _GetRuleNotes(type, index);
@@ -467,10 +446,6 @@ bool RuleManager::UpdateInjectedRules(Database *db, const std::string &rule_set_
rule_data[r.name].first = fmt::format("{}", m_RuleBoolValues[r.rule_index] ? "true" : "false");
rule_data[r.name].second = &r.notes;
break;
case StringRule:
rule_data[r.name].first = m_RuleStringValues[r.rule_index];
rule_data[r.name].second = &r.notes;
break;
default:
break;
}
@@ -577,7 +552,7 @@ bool RuleManager::RestoreRuleNotes(Database *db)
}
}
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount];
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount];
}(e.rule_name);
if (Strings::Contains(rule.name, e.rule_name)) {
@@ -642,8 +617,3 @@ bool RuleManager::GetBoolRule(RuleManager::BoolType t) const
{
return m_RuleBoolValues[t] == 1;
}
std::string RuleManager::GetStringRule(RuleManager::StringType t) const
{
return m_RuleStringValues[t];
}
+25 -45
View File
@@ -23,7 +23,6 @@
* - RuleI(category, rule) -> fetch an integer rule's value
* - RuleR(category, rule) -> fetch a real (float) rule's value
* - RuleB(category, rule) -> fetch a boolean/flag rule's value
* - RuleS(category, rule) -> fetch a string rule's value
*
*/
@@ -36,8 +35,6 @@
RuleManager::Instance()->GetRealRule( RuleManager::Real__##rule_name )
#define RuleB(category_name, rule_name) \
RuleManager::Instance()->GetBoolRule( RuleManager::Bool__##rule_name )
#define RuleS(category_name, rule_name) \
RuleManager::Instance()->GetStringRule( RuleManager::String__##rule_name )
#include <vector>
@@ -84,17 +81,6 @@ public:
static const int BoolRuleCount = static_cast<int>(_BoolRuleCount);
typedef enum {
#define RULE_STRING(category_name, rule_name, default_value, notes) \
String__##rule_name,
#include "ruletypes.h"
_StringRuleCount
} StringType;
static const int StringRuleCount = static_cast<int>(_StringRuleCount);
typedef enum {
#define RULE_CATEGORY(category_name) \
Category__##category_name,
@@ -113,49 +99,45 @@ public:
static const IntType InvalidInt = _IntRuleCount;
static const RealType InvalidReal = _RealRuleCount;
static const BoolType InvalidBool = _BoolRuleCount;
static const StringType InvalidString = _StringRuleCount;
static const CategoryType InvalidCategory = _CatCount;
static const uint32 RulesCount = IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount;
static const uint32 RulesCount = IntRuleCount + RealRuleCount + BoolRuleCount;
//fetch routines, you should generally use the Rule* macros instead of this
int GetIntRule(IntType t) const;
float GetRealRule(RealType t) const;
bool GetBoolRule(BoolType t) const;
std::string GetStringRule(StringType t) const;
//management routines
static std::string GetRuleName(IntType t) { return s_RuleInfo[static_cast<int>(t)].name; }
static std::string GetRuleName(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].name; }
static std::string GetRuleName(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].name; }
static std::string GetRuleName(StringType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount + StringRuleCount].name; }
static const std::string& GetRuleNotes(IntType t) { return s_RuleInfo[static_cast<int>(t)].notes; }
static const std::string& GetRuleNotes(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].notes; }
static const std::string& GetRuleNotes(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].notes; }
static const std::string& GetRuleNotes(StringType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount + StringRuleCount].notes; }
static const std::string &GetRuleNotes(IntType t) { return s_RuleInfo[static_cast<int>(t)].notes; }
static const std::string &GetRuleNotes(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].notes; }
static const std::string &GetRuleNotes(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].notes; }
static uint32 CountRules() { return RulesCount; }
static CategoryType FindCategory(const std::string& category_name);
bool ListRules(const std::string& category_name, std::vector<std::string>& l);
bool ListCategories(std::vector<std::string>& l);
bool GetRule(const std::string& rule_name, std::string& rule_value);
static CategoryType FindCategory(const std::string &category_name);
bool ListRules(const std::string &category_name, std::vector <std::string> &l);
bool ListCategories(std::vector <std::string> &l);
bool GetRule(const std::string &rule_name, std::string &rule_value);
bool SetRule(
const std::string& rule_name,
const std::string& rule_value,
Database* db = nullptr,
const std::string &rule_name,
const std::string &rule_value,
Database *db = nullptr,
bool db_save = false,
bool reload = false
);
int GetActiveRulesetID() const { return m_activeRuleset; }
std::string GetActiveRuleset() const { return m_activeName; }
static bool ListRulesets(Database* db, std::map<int, std::string>& l);
static bool ListRulesets(Database *db, std::map<int, std::string> &l);
void ResetRules(bool reload = false);
bool LoadRules(Database* db, const std::string& rule_set_name, bool reload = false);
void SaveRules(Database* db, const std::string& rule_set_name);
bool UpdateInjectedRules(Database* db, const std::string& rule_set_name, bool quiet_update = false);
bool UpdateOrphanedRules(Database* db, bool quiet_update = false);
bool RestoreRuleNotes(Database* db);
bool LoadRules(Database *db, const std::string &rule_set_name, bool reload = false);
void SaveRules(Database *db, const std::string &rule_set_name);
bool UpdateInjectedRules(Database *db, const std::string &rule_set_name, bool quiet_update = false);
bool UpdateOrphanedRules(Database *db, bool quiet_update = false);
bool RestoreRuleNotes(Database *db);
private:
RuleManager();
@@ -165,23 +147,21 @@ private:
int m_activeRuleset;
std::string m_activeName;
int m_RuleIntValues[IntRuleCount];
float m_RuleRealValues[RealRuleCount];
uint32 m_RuleBoolValues[BoolRuleCount];
std::string m_RuleStringValues[StringRuleCount];
int m_RuleIntValues[IntRuleCount];
float m_RuleRealValues[RealRuleCount];
uint32 m_RuleBoolValues[BoolRuleCount];
typedef enum {
IntRule,
RealRule,
BoolRule,
StringRule
BoolRule
} RuleType;
static bool _FindRule(const std::string& rule_name, RuleType& type_into, uint16& index_into);
static bool _FindRule(const std::string &rule_name, RuleType &type_into, uint16 &index_into);
static std::string _GetRuleName(RuleType type, uint16 index);
static const std::string& _GetRuleNotes(RuleType type, uint16 index);
static int _FindOrCreateRuleset(Database* db, const std::string& rule_set_name);
void _SaveRule(Database* db, RuleType type, uint16 index);
static const std::string &_GetRuleNotes(RuleType type, uint16 index);
static int _FindOrCreateRuleset(Database *db, const std::string &rule_set_name);
void _SaveRule(Database *db, RuleType type, uint16 index);
static const char* s_categoryNames[];
typedef struct {
+3 -12
View File
@@ -28,9 +28,6 @@
#ifndef RULE_BOOL
#define RULE_BOOL(cat, rule, default_value, notes)
#endif
#ifndef RULE_STRING
#define RULE_STRING(cat, rule, default_value, notes)
#endif
#ifndef RULE_CATEGORY_END
#define RULE_CATEGORY_END()
#endif
@@ -51,10 +48,10 @@ RULE_BOOL(Character, DeathKeepLevel, false, "Players can not drop below 0% exper
RULE_BOOL(Character, UseDeathExpLossMult, false, "Setting to control whether DeathExpLossMultiplier or the code default is used: (Level x Level / 18.0) x 12000")
RULE_BOOL(Character, UseOldRaceRezEffects, false, "Older clients had ID 757 for races with high starting STR, but it doesn't seem used anymore")
RULE_INT(Character, CorpseDecayTime, 604800000, "Time after which the corpse decays (milliseconds) DEFAULT: 604800000 (7 Days)")
RULE_INT(Character, EmptyCorpseDecayTime, 10800000, "Time after which an empty corpse decays (milliseconds) DEFAULT: 10800000 (3 Hours)")
RULE_INT( Character, EmptyCorpseDecayTime, 10800000, "Time after which an empty corpse decays (milliseconds) DEFAULT: 10800000 (3 Hours)")
RULE_INT(Character, CorpseResTime, 10800000, "Time after which the corpse can no longer be resurrected (milliseconds) DEFAULT: 10800000 (3 Hours)")
RULE_INT(Character, DuelCorpseResTime, 600000, "Time before cant res corpse after a duel (milliseconds) DEFAULT: 600000 (10 Minutes)")
RULE_INT(Character, CorpseOwnerOnlineTime, 30000, "How often corpse will check if its owner is online DEFAULT: 30000 (30 Seconds)")
RULE_INT( Character, DuelCorpseResTime, 600000, "Time before cant res corpse after a duel (milliseconds) DEFAULT: 600000 (10 Minutes)")
RULE_INT( Character, CorpseOwnerOnlineTime, 30000, "How often corpse will check if its owner is online DEFAULT: 30000 (30 Seconds)")
RULE_BOOL(Character, LeaveCorpses, true, "Setting whether you leave a corpse behind")
RULE_BOOL(Character, LeaveNakedCorpses, false, "Setting whether you leave a corpse without items")
RULE_INT(Character, MaxDraggedCorpses, 2, "Maximum number of corpses you can drag at once")
@@ -327,8 +324,6 @@ RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest err
RULE_INT(World, BootHour, 0, "Sets the in-game hour world will set when it first boots. 0-24 are valid options, where 0 disables this rule")
RULE_BOOL(World, UseItemLinksForKeyRing, false, "Uses item links for Key Ring Listing instead of item name")
RULE_BOOL(World, UseOldShadowKnightClassExport, true, "Disable to have Shadowknight show as Shadow Knight (live-like)")
RULE_STRING(World, IPExemptionZones, "", "Comma-delimited list of zones to exclude from IP-limit checks. Empty string to disable.")
RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to have this be used instead of variables table 'motd' value")
RULE_CATEGORY_END()
RULE_CATEGORY(Zone)
@@ -527,7 +522,6 @@ RULE_REAL(Combat, BaseProcChance, 0.035, "Base chance for procs")
RULE_REAL(Combat, ProcDexDivideBy, 11000, "Divisor for the probability of a proc increased by dexterity")
RULE_INT(Combat, MinRangedAttackDist, 25, "Minimum Distance to use Ranged Attacks")
RULE_BOOL(Combat, ArcheryBonusRequiresStationary, true, "does the 2x archery bonus chance require a stationary npc")
RULE_INT(Combat, ArcheryBonusLevelRequirement, 51, "Level requirement when the 2x archery bonus will be enabled. The default is 51.")
RULE_REAL(Combat, ArcheryNPCMultiplier, 1.0, "Value is multiplied by the regular dmg to get the archery dmg")
RULE_BOOL(Combat, AssistNoTargetSelf, true, "When assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like)")
RULE_INT(Combat, MaxRampageTargets, 3, "Maximum number of people hit with rampage")
@@ -576,12 +570,10 @@ RULE_BOOL(Combat, NPCsUseFrontalStunImmunityClasses, false, "Enable or disable N
RULE_INT(Combat, FrontalStunImmunityRaces, 512, "Bitmask for Races than have frontal stun immunity, Ogre (512) only by default.")
RULE_BOOL(Combat, NPCsUseFrontalStunImmunityRaces, true, "Enable or disable NPCs using frontal stun immunity Races from Combat:FrontalStunImmunityRaces, true by default.")
RULE_BOOL(Combat, AssassinateOnlyHumanoids, true, "Enable or disable Assassinate only being allowed on Humanoids, true by default.")
RULE_INT(Combat, AssassinateLevelRequirement, 60, "Level requirement to enable assassinate attempts on backstabs. The default is 60.")
RULE_BOOL(Combat, HeadshotOnlyHumanoids, true, "Enable or disable Headshot only being allowed on Humanoids, true by default.")
RULE_BOOL(Combat, EnableWarriorShielding, true, "Enable or disable Warrior Shielding Ability (/shield), true by default.")
RULE_BOOL(Combat, BackstabIgnoresElemental, false, "Enable or disable Elemental weapon damage affecting backstab damage, false by default.")
RULE_BOOL(Combat, BackstabIgnoresBane, false, "Enable or disable Bane weapon damage affecting backstab damage, false by default.")
RULE_INT(Combat, DoubleBackstabLevelRequirement, 55, "Level requirement to enable double backstab attempts. The default is 55.")
RULE_BOOL(Combat, SummonMeleeRange, true, "Enable or disable summoning of a player when already in melee range of the summoner.")
RULE_BOOL(Combat, WaterMatchRequiredForAutoFireLoS, true, "Enable/Disable the requirement of both the attacker/victim being both in or out of water for AutoFire LoS to pass.")
RULE_INT(Combat, ExtraAllowedKickClassesBitmask, 0, "Bitmask for allowing extra classes beyond Warrior, Ranger, Beastlord, and Berserker to kick, No Extra Classes (0) by default")
@@ -959,5 +951,4 @@ RULE_CATEGORY_END()
#undef RULE_INT
#undef RULE_REAL
#undef RULE_BOOL
#undef RULE_STRING
#undef RULE_CATEGORY_END
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.47.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.45.0-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9266
#define CURRENT_BINARY_DATABASE_VERSION 9264
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9043
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.47.0",
"version": "22.45.0",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+70 -72
View File
@@ -52,7 +52,6 @@
#include "../common/repositories/player_event_logs_repository.h"
#include "../common/repositories/inventory_repository.h"
#include "../common/events/player_event_logs.h"
#include "../common/content/world_content_service.h"
#include <iostream>
#include <iomanip>
@@ -600,63 +599,79 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app)
}
bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
char newName[17] = {0};
bool unique = false;
while (!unique) {
std::string cons = "bcdfghjklmnpqrstvwxyz";
std::string vows = "aeou";
std::string allVows = "aeiou";
std::vector<std::string> endPhon = {"a", "e", "i", "o", "u", "os", "as", "us", "is", "y", "an", "en", "in", "on", "un"};
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> lenDist(5, 10);
std::uniform_int_distribution<int> firstCharDist(0, 1);
std::uniform_int_distribution<int> consDist(0, cons.size() - 1);
std::uniform_int_distribution<int> vowDist(0, vows.size() - 1);
std::uniform_int_distribution<int> allVowDist(0, allVows.size() - 1);
std::uniform_int_distribution<int> endPhonDist(0, endPhon.size() - 1);
int len = 0;
memset(newName, 0, sizeof(newName));
if (firstCharDist(gen) == 0) {
newName[len++] = vows[vowDist(gen)];
newName[len++] = cons[consDist(gen)];
} else {
newName[len++] = cons[consDist(gen)];
newName[len++] = allVows[allVowDist(gen)];
}
newName[0] = toupper(newName[0]);
while (len < lenDist(gen) - 1) {
if (len % 2 == 0) {
newName[len++] = cons[consDist(gen)];
} else {
newName[len++] = allVows[allVowDist(gen)];
// creates up to a 10 char name
char vowels[18]="aeiouyaeiouaeioe";
char cons[48]="bcdfghjklmnpqrstvwxzybcdgklmnprstvwbcdgkpstrkd";
char rndname[17]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
char paircons[33]="ngrkndstshthphsktrdrbrgrfrclcr";
int rndnum=emu_random.Int(0, 75),n=1;
bool dlc=false;
bool vwl=false;
bool dbl=false;
if (rndnum>63)
{ // rndnum is 0 - 75 where 64-75 is cons pair, 17-63 is cons, 0-16 is vowel
rndnum=(rndnum-61)*2; // name can't start with "ng" "nd" or "rk"
rndname[0]=paircons[rndnum];
rndname[1]=paircons[rndnum+1];
n=2;
}
else if (rndnum>16)
{
rndnum-=17;
rndname[0]=cons[rndnum];
}
else
{
rndname[0]=vowels[rndnum];
vwl=true;
}
int namlen=emu_random.Int(5, 10);
for (int i=n;i<namlen;i++)
{
dlc=false;
if (vwl) //last char was a vowel
{ // so pick a cons or cons pair
rndnum=emu_random.Int(0, 62);
if (rndnum>46)
{ // pick a cons pair
if (i>namlen-3) // last 2 chars in name?
{ // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng"
rndnum=emu_random.Int(0, 7)*2;
}
else
{ // pick any from the set
rndnum=(rndnum-47)*2;
}
rndname[i]=paircons[rndnum];
rndname[i+1]=paircons[rndnum+1];
dlc=true; // flag keeps second letter from being doubled below
i+=1;
}
else
{ // select a single cons
rndname[i]=cons[rndnum];
}
}
std::string end = endPhon[endPhonDist(gen)];
for (char c : end) {
if (len < 10) newName[len++] = c;
else
{ // select a vowel
rndname[i]=vowels[emu_random.Int(0, 16)];
}
if (database.CheckNameFilter(newName)) {
std::string query = StringFormat("SELECT `name` FROM `character_data` WHERE `name` = '%s'", newName);
auto res = database.QueryDatabase(query);
if (res.Success() && res.RowCount() == 0) {
unique = true;
vwl=!vwl;
if (!dbl && !dlc)
{ // one chance at double letters in name
if (!emu_random.Int(0, i+9)) // chances decrease towards end of name
{
rndname[i+1]=rndname[i];
dbl=true;
i+=1;
}
}
}
rndname[0]=toupper(rndname[0]);
NameGeneration_Struct* ngs = (NameGeneration_Struct*)app->pBuffer;
memset(ngs->name, 0, 64);
strcpy(ngs->name, newName);
memset(ngs->name,0,64);
strcpy(ngs->name,rndname);
QueuePacket(app);
return true;
@@ -772,18 +787,6 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
return true;
}
auto r = content_service.FindZone(zone_id, instance_id);
if (r.zone_id && r.instance.id != instance_id) {
LogInfo(
"Zone [{}] has been remapped to instance_id [{}] from instance_id [{}] for client [{}]",
r.zone.short_name,
r.instance.id,
instance_id,
char_name
);
instance_id = r.instance.id;
}
// Make sure this account owns this character
if (temporary_account_id != account_id) {
LogInfo("Account [{}] does not own the character named [{}] from account [{}]", account_id, char_name, temporary_account_id);
@@ -900,19 +903,14 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
}
auto outapp = new EQApplicationPacket(OP_MOTD);
std::string motd = RuleS(World, MOTD);
if (!motd.empty()) {
outapp->size = motd.length() + 1;
std::string motd_message;
if (database.GetVariable("MOTD", motd_message)) {
outapp->size = motd_message.length() + 1;
outapp->pBuffer = new uchar[outapp->size];
memset(outapp->pBuffer, 0, outapp->size);
strcpy((char*) outapp->pBuffer, motd.c_str());
} else if (database.GetVariable("MOTD", motd)) {
outapp->size = motd.length() + 1;
outapp->pBuffer = new uchar[outapp->size];
memset(outapp->pBuffer, 0, outapp->size);
strcpy((char*) outapp->pBuffer, motd.c_str());
strcpy((char*)outapp->pBuffer, motd_message.c_str());
} else { // Null Message of the Day. :)
outapp->size = 1;
outapp->size = 1;
outapp->pBuffer = new uchar[outapp->size];
outapp->pBuffer[0] = 0;
}
-9
View File
@@ -96,15 +96,6 @@ void ClientList::GetCLEIP(uint32 in_ip) {
while (iterator.MoreElements()) {
cle = iterator.GetData();
const auto zones = Strings::Split(RuleS(World, IPExemptionZones), ",");
for (const auto &z : zones) {
if (Strings::ToUnsignedInt(z) == cle->zone()) {
iterator.Advance();
continue;
}
}
if (
cle->GetIP() == in_ip &&
(
-1
View File
@@ -142,7 +142,6 @@ std::vector<Reload> reload_types = {
Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"},
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
Reload{.command = "content_flags", .opcode = ServerOP_ReloadContentFlags, .desc = "Content Flags"},
Reload{.command = "data_buckets_cache", .opcode = ServerOP_ReloadDataBucketsCache, .desc = "Data Buckets Cache"},
Reload{.command = "doors", .opcode = ServerOP_ReloadDoors, .desc = "Doors"},
Reload{.command = "dztemplates", .opcode = ServerOP_ReloadDzTemplates, .desc = "Dynamic Zone Templates"},
-5
View File
@@ -188,11 +188,6 @@ int main(int argc, char **argv)
RegisterConsoleFunctions(console);
}
content_service.SetDatabase(&database)
->SetContentDatabase(&content_db)
->SetExpansionContext()
->ReloadContentFlags();
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
server_connection = std::make_unique<EQ::Net::ServertalkServer>();
+1 -11
View File
@@ -230,23 +230,13 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) {
case ServerOP_GuildChannel:
case ServerOP_GuildURL:
case ServerOP_GuildMemberRemove:
case ServerOP_GuildMemberAdd:
case ServerOP_GuildSendGuildList:
case ServerOP_GuildMembersList:
{
zoneserver_list.SendPacketToBootedZones(pack);
break;
}
case ServerOP_GuildMemberAdd:
{
auto in = (ServerOP_GuildMessage_Struct *)pack->pBuffer;
auto guild = GetGuildByGuildID(in->guild_id);
if (!guild) {
BaseGuildManager::RefreshGuild(in->guild_id);
}
zoneserver_list.SendPacketToBootedZones(pack);
break;
}
default:
LogGuilds("Unknown packet {:#04x} received from zone??", pack->opcode);
break;
+1 -1
View File
@@ -1100,7 +1100,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
}
auto smotd = (ServerMotd_Struct*) pack->pBuffer;
RuleManager::Instance()->SetRule("MOTD", smotd->motd, &database, true, true);
database.SetVariable("MOTD", smotd->motd);
zoneserver_list.SendPacket(pack);
break;
}
+7 -17
View File
@@ -621,38 +621,28 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
// NPC *npc1, *npc2;
int reverse;
if (!zone->CanDoCombat()) {
if(!zone->CanDoCombat())
return false;
}
// some special cases
if (!target) {
if(!target)
return false;
}
if (this == target) { // you can attack yourself
if(this == target) // you can attack yourself
return true;
}
if (target->GetSpecialAbility(NO_HARM_FROM_CLIENT)) {
if(target->GetSpecialAbility(NO_HARM_FROM_CLIENT)){
return false;
}
if (IsBot() && target->GetSpecialAbility(IMMUNE_DAMAGE_BOT)) {
if (target->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT) && IsClient())
return false;
}
if (IsClient() && target->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT)) {
if (target->GetSpecialAbility(IMMUNE_DAMAGE_NPC) && IsNPC())
return false;
}
if (IsNPC() && target->GetSpecialAbility(IMMUNE_DAMAGE_NPC)) {
if (target->IsHorse())
return false;
}
if (target->IsHorse()) {
return false;
}
// can't damage own pet (applies to everthing)
Mob *target_owner = target->GetOwner();
+17 -32
View File
@@ -1005,7 +1005,7 @@ double Mob::RollD20(int offense, int mitigation)
auto atk_roll = zone->random.Roll0(offense + 5);
auto def_roll = zone->random.Roll0(mitigation + 5);
int avg = std::max(1, (offense + mitigation + 10) / 2);
int avg = (offense + mitigation + 10) / 2;
int index = std::max(0, (atk_roll - def_roll) + (avg / 2));
index = EQ::Clamp((index * 20) / avg, 0, 19);
@@ -3091,37 +3091,26 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
TryTriggerOnCastRequirement();
}
if (IsClient() && !IsAIControlled()) {
if (IsClient() && !IsAIControlled())
return;
}
if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) {
if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO))
return;
}
if (other->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) {
if (GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC())
return;
}
if (other->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) {
if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient())
return;
}
if (other->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC)) {
if (IsValidSpell(spell_id) && IsNoDetrimentalSpellAggroSpell(spell_id))
return;
}
if (IsValidSpell(spell_id) && IsNoDetrimentalSpellAggroSpell(spell_id)) {
if (other == myowner)
return;
}
if (other == myowner) {
if (other->GetSpecialAbility(IMMUNE_AGGRO_ON))
return;
}
if (other->GetSpecialAbility(IMMUNE_AGGRO_ON)) {
return;
}
if (GetSpecialAbility(NPC_TUNNELVISION)) {
int tv_mod = GetSpecialAbilityParam(NPC_TUNNELVISION, 0);
@@ -3205,9 +3194,8 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
// owner must get on list, but he's not actually gained any hate yet
if (
!owner->GetSpecialAbility(IMMUNE_AGGRO) &&
!(owner->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
!(owner->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
!(owner->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC))
!(GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && owner->IsClient()) &&
!(GetSpecialAbility(IMMUNE_AGGRO_NPC) && owner->IsNPC())
) {
if (owner->IsClient() && !CheckAggro(owner)) {
owner->CastToClient()->AddAutoXTarget(this);
@@ -3221,9 +3209,8 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
if (
!mypet->IsFamiliar() &&
!mypet->GetSpecialAbility(IMMUNE_AGGRO) &&
!(IsBot() && mypet->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
!(IsClient() && mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
!(IsNPC() && mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC))
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && IsClient()) &&
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && IsNPC())
) {
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
}
@@ -3232,9 +3219,8 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
if (
myowner->IsAIControlled() &&
!myowner->GetSpecialAbility(IMMUNE_AGGRO) &&
!(myowner->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
!(myowner->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
!(myowner->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC))
!(GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && myowner->IsClient()) &&
!(GetSpecialAbility(IMMUNE_AGGRO_NPC) && myowner->IsNPC())
) {
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
}
@@ -4074,9 +4060,8 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
!pet->GetSpecialAbility(IMMUNE_AGGRO) &&
!pet->IsEngaged() &&
attacker &&
!(attacker->IsBot() && pet->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
!(attacker->IsClient() && pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
!(attacker->IsNPC() && pet->GetSpecialAbility(IMMUNE_AGGRO_NPC)) &&
!(pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) &&
!(pet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) &&
attacker != this &&
!attacker->IsCorpse() &&
!pet->IsGHeld() &&
@@ -6209,7 +6194,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
if (headshot > 0) {
hit.damage_done = headshot;
}
else if (GetClass() == Class::Ranger && GetLevel() >= RuleI(Combat, ArcheryBonusLevelRequirement)) { // no double dmg on headshot
else if (GetClass() == Class::Ranger && GetLevel() > 50) { // no double dmg on headshot
if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) {
hit.damage_done *= 2;
MessageString(Chat::MeleeCrit, BOW_DOUBLE_DAMAGE);
+1 -1
View File
@@ -2367,7 +2367,7 @@ const uint8 BotDatabase::GetBotLevelByID(const uint32 bot_id)
return e.bot_id ? e.level : 0;
}
const std::string BotDatabase::GetBotNameByID(const uint32 bot_id)
const std::string& BotDatabase::GetBotNameByID(const uint32 bot_id)
{
const auto& e = BotDataRepository::FindOne(database, bot_id);
+1 -1
View File
@@ -164,7 +164,7 @@ public:
const uint8 GetBotGenderByID(const uint32 bot_id);
std::vector<uint32> GetBotIDsByCharacterID(const uint32 character_id, uint8 class_id = Class::None);
const uint8 GetBotLevelByID(const uint32 bot_id);
const std::string GetBotNameByID(const uint32 bot_id);
const std::string& GetBotNameByID(const uint32 bot_id);
const uint16 GetBotRaceByID(const uint32 bot_id);
class fail {
+11 -42
View File
@@ -284,7 +284,6 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
PendingSacrifice = false;
controlling_boat_id = 0;
controlled_mob_id = 0;
qGlobals = nullptr;
if (!RuleB(Character, PerCharacterQglobalMaxLevel) && !RuleB(Character, PerCharacterBucketMaxLevel)) {
SetClientMaxLevel(0);
@@ -312,6 +311,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
aa_los_them_mob = nullptr;
los_status = false;
los_status_facing = false;
qGlobals = nullptr;
HideCorpseMode = HideCorpseNone;
PendingGuildInvitation = false;
@@ -6285,17 +6285,7 @@ void Client::SendZonePoints()
zp->zpe[i].z = data->target_z;
zp->zpe[i].heading = data->target_heading;
zp->zpe[i].zoneid = data->target_zone_id;
// if the target zone is the same as the current zone, use the instance of the current zone
// if we don't use the same instance_id that the client was sent, the client will forcefully
// issue a zone change request when they should be simply moving to a different point in the same zone
// because the client will think the zone point target is different from the current instance
auto target_instance = data->target_zone_instance;
if (data->target_zone_id == zone->GetZoneID() && data->target_zone_instance == 0) {
target_instance = zone->GetInstanceID();
}
zp->zpe[i].zoneinstance = target_instance;
zp->zpe[i].zoneinstance = data->target_zone_instance;
i++;
}
iterator.Advance();
@@ -6775,36 +6765,23 @@ void Client::UpdateClientXTarget(Client *c)
// IT IS NOT SAFE TO CALL THIS IF IT'S NOT INITIAL AGGRO
void Client::AddAutoXTarget(Mob *m, bool send)
{
if (m->IsBot() || (m->IsPet() && m->IsPetOwnerBot())) {
return;
}
m_activeautohatermgr->increment_count(m);
if (!XTargettingAvailable() || !XTargetAutoAddHaters || IsXTarget(m)) {
if (!XTargettingAvailable() || !XTargetAutoAddHaters || IsXTarget(m))
return;
}
for (int i = 0; i < GetMaxXTargets(); ++i) {
if (XTargets[i].Type == Auto && XTargets[i].ID == 0) {
for(int i = 0; i < GetMaxXTargets(); ++i)
{
if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0))
{
XTargets[i].ID = m->GetID();
if (send) { // if we don't send we're bulk sending updates later on
if (send) // if we don't send we're bulk sending updates later on
SendXTargetPacket(i, m);
} else {
else
XTargets[i].dirty = true;
}
break;
}
}
LogXTargets(
"Adding [{}] to [{}] ({}) XTargets",
m->GetCleanName(),
GetCleanName(),
GetID()
);
}
void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots)
@@ -6813,23 +6790,15 @@ void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots)
// now we may need to clean up our CurrentTargetNPC entries
for (int i = 0; i < GetMaxXTargets(); ++i) {
if (XTargets[i].Type == CurrentTargetNPC && XTargets[i].ID == m->GetID()) {
XTargets[i].Type = Auto;
XTargets[i].ID = 0;
XTargets[i].Type = Auto;
XTargets[i].ID = 0;
XTargets[i].dirty = true;
}
}
auto r = GetRaid();
if (r) {
r->UpdateRaidXTargets();
}
LogXTargets(
"Removing [{}] from [{}] ({}) XTargets",
m->GetCleanName(),
GetCleanName(),
GetID()
);
}
void Client::UpdateXTargetType(XTargetType Type, Mob *m, const char *Name)
+1 -1
View File
@@ -1090,7 +1090,7 @@ public:
void SetPEQZoneFlag(uint32 zone_id);
bool CanFish();
void GoFish(bool guarantee = false, bool use_bait = true);
void GoFish();
void ForageItem(bool guarantee = false);
//Calculate vendor price modifier based on CHA: (reverse==selling)
float CalcPriceMod(Mob* other = 0, bool reverse = false);
-4
View File
@@ -131,10 +131,8 @@ int command_init(void)
command_add("feature", "Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) ||
command_add("size", "Change your targets size (alias of #feature size)", AccountStatus::QuestTroupe, command_feature) ||
command_add("find", "Search command used to find various things", AccountStatus::Guide, command_find) ||
command_add("fish", "Fish for an item", AccountStatus::QuestTroupe, command_fish) ||
command_add("fixmob", "[race|gender|texture|helm|face|hair|haircolor|beard|beardcolor|heritage|tattoo|detail] [next|prev] - Manipulate appearance of your target", AccountStatus::QuestTroupe, command_fixmob) ||
command_add("flagedit", "Edit zone flags on your target. Use #flagedit help for more info.", AccountStatus::GMAdmin, command_flagedit) ||
command_add("forage", "Forage an item", AccountStatus::QuestTroupe, command_forage) ||
command_add("gearup", "Developer tool to quickly equip yourself or your target", AccountStatus::GMMgmt, command_gearup) ||
command_add("giveitem", "[itemid] [charges] - Summon an item onto your target's cursor. Charges are optional.", AccountStatus::GMMgmt, command_giveitem) ||
command_add("givemoney", "[Platinum] [Gold] [Silver] [Copper] - Gives specified amount of money to you or your player target", AccountStatus::GMMgmt, command_givemoney) ||
@@ -824,10 +822,8 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/faction.cpp"
#include "gm_commands/feature.cpp"
#include "gm_commands/find.cpp"
#include "gm_commands/fish.cpp"
#include "gm_commands/fixmob.cpp"
#include "gm_commands/flagedit.cpp"
#include "gm_commands/forage.cpp"
#include "gm_commands/gearup.cpp"
#include "gm_commands/giveitem.cpp"
#include "gm_commands/givemoney.cpp"
-2
View File
@@ -83,10 +83,8 @@ void command_faction(Client *c, const Seperator *sep);
void command_faction_association(Client *c, const Seperator *sep);
void command_feature(Client *c, const Seperator *sep);
void command_find(Client *c, const Seperator *sep);
void command_fish(Client* c, const Seperator* sep);
void command_fixmob(Client *c, const Seperator *sep);
void command_flagedit(Client *c, const Seperator *sep);
void command_forage(Client* c, const Seperator* sep);
void command_gearup(Client *c, const Seperator *sep);
void command_giveitem(Client *c, const Seperator *sep);
void command_givemoney(Client *c, const Seperator *sep);
-9
View File
@@ -73,15 +73,6 @@ Doors::Doors(const DoorsRepository::Doors &door) :
m_door_param = door.door_param;
m_size = door.size;
m_invert_state = door.invert_state;
// if the target zone is the same as the current zone, use the instance of the current zone
// if we don't use the same instance_id that the client was sent, the client will forcefully
// issue a zone change request when they should be simply moving to a different point in the same zone
// because the client will think the zone point target is different from the current instance
if (door.dest_zone == zone->GetShortName() && m_destination_instance_id == 0) {
m_destination_instance_id = zone->GetInstanceID();
}
m_destination_instance_id = door.dest_instance;
m_is_ldon_door = door.is_ldon_door;
m_dz_switch_id = door.dz_switch_id;
+4 -6
View File
@@ -4379,9 +4379,8 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
if (
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
!(other->IsBot() && n->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
!(other->IsClient() && n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
!(other->IsNPC() && n->GetSpecialAbility(IMMUNE_AGGRO_NPC))
!(n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) &&
!(n->GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC())
) {
n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
}
@@ -4406,9 +4405,8 @@ void EntityList::AddTempPetsToHateListOnOwnerDamage(Mob *owner, Mob* attacker, i
attacker != n &&
!n->IsEngaged() &&
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
!(attacker->IsBot() && n->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
!(attacker->IsClient() && n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
!(attacker->IsNPC() && n->GetSpecialAbility(IMMUNE_AGGRO_NPC)) &&
!(n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) &&
!(n->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) &&
!attacker->IsTrap() &&
!attacker->IsCorpse()
) {
+5 -7
View File
@@ -89,7 +89,7 @@ uint32 ZoneDatabase::LoadForage(uint32 zone_id, uint8 skill_level)
}
forage_items[count] = e.Itemid;
forage_chances[count] = e.chance + current_chance;
forage_chances[count] = e.chance;
current_chance = forage_chances[count];
@@ -257,7 +257,7 @@ bool Client::CanFish() {
return true;
}
void Client::GoFish(bool guarantee, bool use_bait)
void Client::GoFish()
{
//TODO: generate a message if we're already fishing
@@ -306,7 +306,7 @@ void Client::GoFish(bool guarantee, bool use_bait)
fishing_skill = 100+((fishing_skill-100)/2);
}
if (guarantee || zone->random.Int(0,175) < fishing_skill) {
if (zone->random.Int(0,175) < fishing_skill) {
uint32 food_id = 0;
//25% chance to fish an item.
@@ -343,10 +343,8 @@ void Client::GoFish(bool guarantee, bool use_bait)
}
}
if (use_bait) {
//consume bait, should we always consume bait on success?
DeleteItemInInventory(bslot, 1, true); //do we need client update?
}
//consume bait, should we always consume bait on success?
DeleteItemInInventory(bslot, 1, true); //do we need client update?
if(food_id == 0) {
int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1);
-6
View File
@@ -1,6 +0,0 @@
#include "../client.h"
void command_fish(Client *c, const Seperator *sep)
{
c->GoFish(true, false);
}
-6
View File
@@ -1,6 +0,0 @@
#include "../client.h"
void command_forage(Client *c, const Seperator *sep)
{
c->ForageItem(true);
}
+1 -2
View File
@@ -3,7 +3,6 @@
void command_goto(Client *c, const Seperator *sep)
{
std::string arg1 = sep->arg[1];
std::string arg4 = sep->arg[4];
bool goto_via_target_no_args = sep->arg[1][0] == '\0' && c->GetTarget();
bool goto_via_player_name = !sep->IsNumber(1) && !arg1.empty();
@@ -53,7 +52,7 @@ void command_goto(Client *c, const Seperator *sep)
Strings::ToFloat(sep->arg[1]),
Strings::ToFloat(sep->arg[2]),
Strings::ToFloat(sep->arg[3]),
(!arg4.empty() ? Strings::ToFloat(sep->arg[4]) : c->GetHeading())
(sep->arg[4] ? Strings::ToFloat(sep->arg[4]) : c->GetHeading())
);
}
else {
+1 -18
View File
@@ -5653,10 +5653,6 @@ bool get_ruleb(int rule) {
return RuleManager::Instance()->GetBoolRule((RuleManager::BoolType)rule);
}
std::string get_rules(int rule) {
return RuleManager::Instance()->GetStringRule((RuleManager::StringType)rule);
}
luabind::scope lua_register_general() {
return luabind::namespace_("eq")
[(
@@ -7248,13 +7244,7 @@ luabind::scope lua_register_rules_const() {
#define RULE_BOOL(cat, rule, default_value, notes) \
luabind::value(#rule, RuleManager::Bool__##rule),
#include "../common/ruletypes.h"
luabind::value("_BoolRuleCount", RuleManager::_BoolRuleCount),
#undef RULE_BOOL
#define RULE_STRING(cat, rule, default_value, notes) \
luabind::value(#rule, RuleManager::String__##rule),
#include "../common/ruletypes.h"
luabind::value("_StringRuleCount", RuleManager::_StringRuleCount)
#undef RULE_STRING
luabind::value("_BoolRuleCount", RuleManager::_BoolRuleCount)
)];
}
@@ -7279,13 +7269,6 @@ luabind::scope lua_register_ruleb() {
];
}
luabind::scope lua_register_rules() {
return luabind::namespace_("RuleS")
[
luabind::def("Get", &get_rules)
];
}
luabind::scope lua_register_journal_speakmode() {
return luabind::class_<Journal_SpeakMode>("SpeakMode")
.enum_("constants")
+1 -38
View File
@@ -3267,36 +3267,6 @@ bool Lua_Mob::IsPetOwnerNPC()
return self->IsPetOwnerNPC();
}
bool Lua_Mob::IsDestructibleObject()
{
Lua_Safe_Call_Bool();
return self->IsDestructibleObject();
}
bool Lua_Mob::IsBoat()
{
Lua_Safe_Call_Bool();
return self->IsBoat();
}
bool Lua_Mob::IsControllableBoat()
{
Lua_Safe_Call_Bool();
return self->IsControllableBoat();
}
int Lua_Mob::GetHeroicStrikethrough()
{
Lua_Safe_Call_Int();
return self->GetHeroicStrikethrough();
}
bool Lua_Mob::IsAlwaysAggro()
{
Lua_Safe_Call_Bool();
return self->AlwaysAggro();
}
luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>())
@@ -3576,7 +3546,6 @@ luabind::scope lua_register_mob() {
.def("GetHateTopNPC", (Lua_NPC(Lua_Mob::*)(void))&Lua_Mob::GetHateTopNPC)
.def("GetHeading", &Lua_Mob::GetHeading)
.def("GetHelmTexture", &Lua_Mob::GetHelmTexture)
.def("GetHeroicStrikethrough", &Lua_Mob::GetHeroicStrikethrough)
.def("GetHerosForgeModel", (int32(Lua_Mob::*)(uint8))&Lua_Mob::GetHerosForgeModel)
.def("GetINT", &Lua_Mob::GetINT)
.def("GetInvisibleLevel", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetInvisibleLevel)
@@ -3673,7 +3642,6 @@ luabind::scope lua_register_mob() {
.def("InterruptSpell", (void(Lua_Mob::*)(int))&Lua_Mob::InterruptSpell)
.def("InterruptSpell", (void(Lua_Mob::*)(void))&Lua_Mob::InterruptSpell)
.def("IsAIControlled", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAIControlled)
.def("IsAlwaysAggro", &Lua_Mob::IsAlwaysAggro)
.def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad)
.def("IsAnimation", &Lua_Mob::IsAnimation)
.def("IsAttackAllowed", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsAttackAllowed)
@@ -3681,11 +3649,8 @@ luabind::scope lua_register_mob() {
.def("IsBeneficialAllowed", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsBeneficialAllowed)
.def("IsBerserk", &Lua_Mob::IsBerserk)
.def("IsBlind", (bool(Lua_Mob::*)(void))&Lua_Mob::IsBlind)
.def("IsBoat", &Lua_Mob::IsBoat)
.def("IsCasting", &Lua_Mob::IsCasting)
.def("IsCharmed", &Lua_Mob::IsCharmed)
.def("IsControllableBoat", &Lua_Mob::IsControllableBoat)
.def("IsDestructibleObject", &Lua_Mob::IsDestructibleObject)
.def("IsEliteMaterialItem", (uint32(Lua_Mob::*)(uint8))&Lua_Mob::IsEliteMaterialItem)
.def("IsEngaged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEngaged)
.def("IsEnraged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEnraged)
@@ -3901,9 +3866,7 @@ luabind::scope lua_register_special_abilities() {
luabind::value("modify_avoid_damage", static_cast<int>(MODIFY_AVOID_DAMAGE)),
luabind::value("immune_open", static_cast<int>(IMMUNE_OPEN)),
luabind::value("immune_assassinate", static_cast<int>(IMMUNE_ASSASSINATE)),
luabind::value("immune_headshot", static_cast<int>(IMMUNE_HEADSHOT)),
luabind::value("immune_aggro_bot", static_cast<int>(IMMUNE_AGGRO_BOT)),
luabind::value("immune_damage_bot", static_cast<int>(IMMUNE_DAMAGE_BOT))
luabind::value("immune_headshot", static_cast<int>(IMMUNE_HEADSHOT))
)];
}
-5
View File
@@ -577,11 +577,6 @@ public:
bool IsPetOwnerBot();
bool IsPetOwnerClient();
bool IsPetOwnerNPC();
bool IsDestructibleObject();
bool IsBoat();
bool IsControllableBoat();
int GetHeroicStrikethrough();
bool IsAlwaysAggro();
};
#endif
+1
View File
@@ -403,6 +403,7 @@ int main(int argc, char **argv)
content_service.SetDatabase(&database)
->SetContentDatabase(&content_db)
->SetContentZones(zone_store.GetZones())
->SetExpansionContext()
->ReloadContentFlags();
+45 -128
View File
@@ -1220,7 +1220,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
UpdateActiveLight();
ns->spawn.light = m_Light.Type[EQ::lightsource::LightActive];
ns->spawn.showhelm = helmtexture != std::numeric_limits<uint8>::max() ? 1 : 0;
if (IsNPC() && race == ERUDITE)
ns->spawn.showhelm = 1;
else
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
ns->spawn.NPC = IsClient() ? 0 : 1;
@@ -1269,8 +1272,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName));
for (i = 0; i < EQ::textures::materialCount; i++) {
if (IsPlayerRace(race) || i > EQ::textures::armorFeet) {
//for (i = 0; i < _MaterialCount; i++)
for (i = 0; i < 9; i++) {
// Only Player Races Wear Armor
if (IsPlayerRace(race) || i > 6) {
ns->spawn.equipment.Slot[i].Material = GetEquipmentMaterial(i);
ns->spawn.equipment.Slot[i].EliteModel = IsEliteMaterialItem(i);
ns->spawn.equipment.Slot[i].HerosForgeModel = GetHerosForgeModel(i);
@@ -1278,42 +1283,13 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
}
}
for (i = 0; i < EQ::textures::weaponPrimary; i++) {
if (texture == std::numeric_limits<uint8>::max()) {
continue;
if (texture > 0) {
for (i = 0; i < 9; i++) {
if (i == EQ::textures::weaponPrimary || i == EQ::textures::weaponSecondary || texture == 255) {
continue;
}
ns->spawn.equipment.Slot[i].Material = texture;
}
if (i == EQ::textures::armorHead && helmtexture != texture) {
ns->spawn.equipment.Slot[i].Material = helmtexture;
continue;
}
if (i == EQ::textures::armorArms && armtexture != 0) {
ns->spawn.equipment.Slot[i].Material = armtexture;
continue;
}
if (i == EQ::textures::armorWrist && bracertexture != 0) {
ns->spawn.equipment.Slot[i].Material = bracertexture;
continue;
}
if (i == EQ::textures::armorHands && handtexture != 0) {
ns->spawn.equipment.Slot[i].Material = handtexture;
continue;
}
if (i == EQ::textures::armorLegs && legtexture != 0) {
ns->spawn.equipment.Slot[i].Material = legtexture;
continue;
}
if (i == EQ::textures::armorFeet && feettexture != 0) {
ns->spawn.equipment.Slot[i].Material = feettexture;
continue;
}
ns->spawn.equipment.Slot[i].Material = texture;
}
memset(ns->spawn.set_to_0xFF, 0xFF, sizeof(ns->spawn.set_to_0xFF));
@@ -4384,15 +4360,17 @@ void Mob::SendWearChangeAndLighting(int8 last_texture) {
void Mob::ChangeSize(float in_size = 0, bool unrestricted)
{
size = std::clamp(in_size, 1.0f, 255.0f);
if (!unrestricted) {
if (IsClient() || petid != 0) {
size = std::clamp(in_size, 3.0f, 15.0f);
EQ::Clamp(in_size, 3.0f, 15.0f);
}
}
SendAppearancePacket(AppearanceType::Size, static_cast<uint32>(size));
EQ::Clamp(in_size, 1.0f, 255.0f);
size = in_size;
SendAppearancePacket(AppearanceType::Size, static_cast<uint32>(in_size));
}
Mob* Mob::GetOwnerOrSelf()
@@ -5204,47 +5182,32 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime)
}
void Mob::ExecWeaponProc(const EQ::ItemInstance* inst, uint16 spell_id, Mob* on, int level_override)
{
void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, int level_override) {
// Changed proc targets to look up based on the spells goodEffect flag.
// This should work for the majority of weapons.
if (!on) {
return;
}
if (!IsValidSpell(spell_id) || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) {
if(!IsValidSpell(spell_id) || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) {
//This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging.
return;
}
if (IsBot() && on->GetSpecialAbility(IMMUNE_DAMAGE_BOT)) {
if (on->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT) && IsClient())
return;
}
if (IsClient() && on->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT)) {
if (on->GetSpecialAbility(IMMUNE_DAMAGE_NPC) && IsNPC())
return;
}
if (IsNPC() && on->GetSpecialAbility(IMMUNE_DAMAGE_NPC)) {
if (IsNoCast())
return;
}
if (IsNoCast()) {
return;
}
if (!IsValidSpell(spell_id)) { // Check for a valid spell otherwise it will crash through the function
if (IsClient()) {
Message(
Chat::White,
fmt::format(
"Invalid spell ID for proc {}.",
spell_id
).c_str()
);
if(!IsValidSpell(spell_id)) { // Check for a valid spell otherwise it will crash through the function
if(IsClient()){
Message(0, "Invalid spell proc %u", spell_id);
LogSpells("Player [{}] Weapon Procced invalid spell [{}]", GetName(), spell_id);
}
return;
}
@@ -5258,7 +5221,7 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance* inst, uint16 spell_id, Mob* on,
return;
}
if (inst && IsClient()) {
if(inst && IsClient()) {
//const cast is dirty but it would require redoing a ton of interfaces at this point
//It should be safe as we don't have any truly const EQ::ItemInstance floating around anywhere.
//So we'll live with it for now
@@ -5278,76 +5241,30 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance* inst, uint16 spell_id, Mob* on,
}
}
bool twin_proc = false;
int32 twin_proc_chance = 0;
bool twinproc = false;
int32 twinproc_chance = 0;
if (IsClient() || IsBot()) {
twin_proc_chance = GetFocusEffect(focusTwincast, spell_id);
twinproc_chance = GetFocusEffect(focusTwincast, spell_id);
}
if (twin_proc_chance && zone->random.Roll(twin_proc_chance)) {
twin_proc = true;
if (twinproc_chance && zone->random.Roll(twinproc_chance)) {
twinproc = true;
}
if (
IsBeneficialSpell(spell_id) &&
(
!IsNPC() ||
(
IsNPC() &&
CastToNPC()->GetInnateProcSpellID() != spell_id
)
) &&
spells[spell_id].target_type != ST_TargetsTarget
) { // NPC innate procs don't take this path ever
SpellFinished(
spell_id,
this,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[spell_id].resist_difficulty,
true,
level_override
);
if (twin_proc) {
SpellFinished(
spell_id,
this,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[spell_id].resist_difficulty,
true,
level_override
);
}
} else if (!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients
SpellFinished(
spell_id,
on,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[spell_id].resist_difficulty,
true,
level_override
);
if (twin_proc && (!(on->IsClient() && on->CastToClient()->dead))) {
SpellFinished(
spell_id,
on,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[spell_id].resist_difficulty,
true,
level_override
);
if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id)) && spells[spell_id].target_type != ST_TargetsTarget) { // NPC innate procs don't take this path ever
SpellFinished(spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty, true, level_override);
if (twinproc) {
SpellFinished(spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty, true, level_override);
}
}
else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients
SpellFinished(spell_id, on, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty, true, level_override);
if (twinproc && (!(on->IsClient() && on->CastToClient()->dead))) {
SpellFinished(spell_id, on, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty, true, level_override);
}
}
return;
}
uint32 Mob::GetZoneID() const {
-2
View File
@@ -3798,8 +3798,6 @@ void NPC::DescribeSpecialAbilities(Client* c)
IMMUNE_OPEN,
IMMUNE_ASSASSINATE,
IMMUNE_HEADSHOT,
IMMUNE_AGGRO_BOT,
IMMUNE_DAMAGE_BOT
};
// These abilities have parameters that need to be parsed out individually
-30
View File
@@ -3395,31 +3395,6 @@ bool Perl_Mob_IsPetOwnerNPC(Mob* self)
return self->IsPetOwnerNPC();
}
bool Perl_Mob_IsDestructibleObject(Mob* self)
{
return self->IsDestructibleObject();
}
bool Perl_Mob_IsBoat(Mob* self)
{
return self->IsBoat();
}
bool Perl_Mob_IsControllableBoat(Mob* self)
{
return self->IsControllableBoat();
}
int Perl_Mob_GetHeroicStrikethrough(Mob* self)
{
return self->GetHeroicStrikethrough();
}
bool Perl_Mob_IsAlwaysAggro(Mob* self)
{
return self->AlwaysAggro();
}
void perl_register_mob()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3685,7 +3660,6 @@ void perl_register_mob()
package.add("GetHateTopNPC", &Perl_Mob_GetHateTopNPC);
package.add("GetHeading", &Perl_Mob_GetHeading);
package.add("GetHelmTexture", &Perl_Mob_GetHelmTexture);
package.add("GetHeroicStrikethrough", &Perl_Mob_GetHeroicStrikethrough);
package.add("GetHerosForgeModel", &Perl_Mob_GetHerosForgeModel);
package.add("GetID", &Perl_Mob_GetID);
package.add("GetINT", &Perl_Mob_GetINT);
@@ -3785,7 +3759,6 @@ void perl_register_mob()
package.add("InterruptSpell", (void(*)(Mob*))&Perl_Mob_InterruptSpell);
package.add("InterruptSpell", (void(*)(Mob*, uint16))&Perl_Mob_InterruptSpell);
package.add("IsAIControlled", &Perl_Mob_IsAIControlled);
package.add("IsAlwaysAggro", &Perl_Mob_IsAlwaysAggro);
package.add("IsAmnesiad", &Perl_Mob_IsAmnesiad);
package.add("IsAnimation", &Perl_Mob_IsAnimation);
package.add("IsAttackAllowed", (bool(*)(Mob*, Mob*))&Perl_Mob_IsAttackAllowed);
@@ -3795,14 +3768,11 @@ void perl_register_mob()
package.add("IsBeneficialAllowed", &Perl_Mob_IsBeneficialAllowed);
package.add("IsBerserk", &Perl_Mob_IsBerserk);
package.add("IsBlind", &Perl_Mob_IsBlind);
package.add("IsBoat", &Perl_Mob_IsBoat);
package.add("IsBot", &Perl_Mob_IsBot);
package.add("IsCasting", &Perl_Mob_IsCasting);
package.add("IsCharmed", &Perl_Mob_IsCharmed);
package.add("IsClient", &Perl_Mob_IsClient);
package.add("IsControllableBoat", &Perl_Mob_IsControllableBoat);
package.add("IsCorpse", &Perl_Mob_IsCorpse);
package.add("IsDestructibleObject", &Perl_Mob_IsDestructibleObject);
package.add("IsDoor", &Perl_Mob_IsDoor);
package.add("IsEliteMaterialItem", &Perl_Mob_IsEliteMaterialItem);
package.add("IsEncounter", &Perl_Mob_IsEncounter);
+9 -9
View File
@@ -805,7 +805,7 @@ int QuestParserCollection::EventBotGlobal(
QuestInterface* QuestParserCollection::GetQIByNPCQuest(uint32 npc_id, std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -871,7 +871,7 @@ QuestInterface* QuestParserCollection::GetQIByNPCQuest(uint32 npc_id, std::strin
QuestInterface* QuestParserCollection::GetQIByPlayerQuest(std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -922,7 +922,7 @@ QuestInterface* QuestParserCollection::GetQIByPlayerQuest(std::string& filename)
QuestInterface* QuestParserCollection::GetQIByGlobalNPCQuest(std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -947,7 +947,7 @@ QuestInterface* QuestParserCollection::GetQIByGlobalNPCQuest(std::string& filena
QuestInterface* QuestParserCollection::GetQIByGlobalPlayerQuest(std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -971,7 +971,7 @@ QuestInterface* QuestParserCollection::GetQIByGlobalPlayerQuest(std::string& fil
QuestInterface* QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -1023,7 +1023,7 @@ QuestInterface* QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s
QuestInterface* QuestParserCollection::GetQIByItemQuest(std::string item_script, std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -1075,7 +1075,7 @@ QuestInterface* QuestParserCollection::GetQIByItemQuest(std::string item_script,
QuestInterface* QuestParserCollection::GetQIByEncounterQuest(std::string encounter_name, std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -1125,7 +1125,7 @@ QuestInterface* QuestParserCollection::GetQIByEncounterQuest(std::string encount
QuestInterface* QuestParserCollection::GetQIByBotQuest(std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
@@ -1176,7 +1176,7 @@ QuestInterface* QuestParserCollection::GetQIByBotQuest(std::string& filename)
QuestInterface* QuestParserCollection::GetQIByGlobalBotQuest(std::string& filename)
{
if (!zone) {
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
+4
View File
@@ -752,7 +752,11 @@ void QuestManager::stoptimer(const std::string& timer_name)
);
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
LogInfo("Current [{}] Timer [{}]", e->name, timer_name);
if (e->mob && e->mob == owner && e->name == timer_name) {
LogInfo("Matched [{}] Timer [{}]", e->name, timer_name);
if (has_stop_event) {
if (owner->IsClient()) {
parse->EventPlayer(EVENT_TIMER_STOP, owner->CastToClient(), timer_name, 0);
+6 -2
View File
@@ -40,6 +40,8 @@ extern WorldServer worldserver;
Raid::Raid(uint32 raidID)
: GroupIDConsumer(raidID)
{
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
memset(group_aa, 0, sizeof(GroupLeadershipAA_Struct) * MAX_RAID_GROUPS);
for (auto& gm : group_mentor) {
gm.mentor_percent = 0;
gm.mentoree = nullptr;
@@ -63,6 +65,8 @@ Raid::Raid(uint32 raidID)
Raid::Raid(Client* nLeader)
: GroupIDConsumer()
{
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
memset(group_aa, 0, sizeof(GroupLeadershipAA_Struct) * MAX_RAID_GROUPS);
for (auto& gm : group_mentor) {
gm.mentor_percent = 0;
gm.mentoree = nullptr;
@@ -447,13 +451,13 @@ void Raid::SaveRaidLeaderAA()
void Raid::UpdateGroupAAs(uint32 gid)
{
if (gid > MAX_RAID_GROUPS || gid == RAID_GROUPLESS || gid < 0) {
if (gid > MAX_RAID_GROUPS) {
return;
}
Client *gl = GetGroupLeader(gid);
if (gl && gl->IsClient()) {
if (gl) {
gl->GetGroupAAs(&group_aa[gid]);
} else {
memset(&group_aa[gid], 0, sizeof(GroupLeadershipAA_Struct));
+2 -2
View File
@@ -292,8 +292,8 @@ protected:
bool disbandCheck;
bool forceDisband;
std::string motd;
RaidLeadershipAA_Struct raid_aa{};
GroupLeadershipAA_Struct group_aa[MAX_RAID_GROUPS]{};
RaidLeadershipAA_Struct raid_aa;
GroupLeadershipAA_Struct group_aa[MAX_RAID_GROUPS];
GroupMentor group_mentor[MAX_RAID_GROUPS];
+1 -1
View File
@@ -807,7 +807,7 @@ void SpawnConditionManager::UpdateSpawnEvent(SpawnEvent &event)
e.next_month = event.next.month;
e.next_year = event.next.year;
e.enabled = event.enabled ? 1 : 0;
e.strict = event.strict ? 1 : 0;
e.next_minute = event.strict;
SpawnEventsRepository::UpdateOne(database, e);
}
+2 -2
View File
@@ -707,7 +707,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
CastToClient()->Message(Chat::White,"Your fierce attack is executed with such grace, your target did not see it coming!");
RogueBackstab(other,false,ReuseTime);
if (level >= RuleI(Combat, DoubleBackstabLevelRequirement)) {
if (level > 54) {
// TODO: 55-59 doesn't appear to match just checking double attack, 60+ does though
if(IsClient() && CastToClient()->CheckDoubleAttack())
{
@@ -2402,7 +2402,7 @@ int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse)
if (
defender &&
!defender->IsClient() &&
GetLevel() >= RuleI(Combat, AssassinateLevelRequirement) &&
GetLevel() >= 60 &&
(skillInUse == EQ::skills::SkillBackstab || skillInUse == EQ::skills::SkillThrowing) &&
(defender->GetBodyType() == BT_Humanoid || !RuleB(Combat, AssassinateOnlyHumanoids)) &&
!defender->GetSpecialAbility(IMMUNE_ASSASSINATE)
+2 -5
View File
@@ -221,12 +221,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
BuffFadeByEffect(SE_NegateIfCombat);
}
// check to see if target is a caster mob before performing a mana tap
if(GetTarget() && IsManaTapSpell(spell_id)) {
// If melee, block if ManaTapsOnAnyClass rule is false
// if caster, block if ManaTapsRequireNPCMana and no mana
bool melee_block = !RuleB(Spells, ManaTapsOnAnyClass);
bool caster_block = (GetTarget()->GetCasterClass() != 'N' && RuleB(Spells, ManaTapsRequireNPCMana) && GetTarget()->GetMana() == 0);
if (melee_block || caster_block) {
if (!RuleB(Spells, ManaTapsOnAnyClass) && GetTarget()->GetCasterClass() != 'N' && RuleB(Spells, ManaTapsRequireNPCMana) && GetTarget()->GetMana() == 0) {
InterruptSpell(TARGET_NO_MANA, 0x121, spell_id);
return false;
}
+2 -2
View File
@@ -2290,8 +2290,8 @@ void ClientTaskState::CreateTaskDynamicZone(Client* client, int task_id, Dynamic
}
// dz should be named the version-based zone name (used in choose zone window and dz window on live)
auto zone_info = zone_store.GetZoneWithFallback(dz_request.GetZoneID(), dz_request.GetZoneVersion());
dz_request.SetName(zone_info && !zone_info->long_name.empty() ? zone_info->long_name : task->title);
auto zone_info = zone_store.GetZone(dz_request.GetZoneID(), dz_request.GetZoneVersion());
dz_request.SetName(zone_info->long_name.empty() ? task->title : zone_info->long_name);
dz_request.SetMinPlayers(task->min_players);
dz_request.SetMaxPlayers(task->max_players);
+14 -16
View File
@@ -3696,31 +3696,29 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
break;
}
case ServerOP_GuildTributeUpdateDonations: {
auto in = (GuildTributeUpdate *) pack->pBuffer;
auto outapp = new EQApplicationPacket(OP_GuildOptInOut, sizeof(GuildTributeOptInOutReply_Struct));
auto data = (GuildTributeOptInOutReply_Struct *) outapp->pBuffer;
case ServerOP_GuildTributeUpdateDonations:
{
GuildTributeUpdate* in = (GuildTributeUpdate*)pack->pBuffer;
data->guild_id = in->guild_id;
data->no_donations = in->member_favor;
data->tribute_toggle = in->member_enabled ? true : false;
data->tribute_trophy_toggle = 0; // not yet implemented
data->time = in->member_time;
data->command = 1;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildOptInOut, sizeof(GuildTributeOptInOutReply_Struct));
GuildTributeOptInOutReply_Struct* data = (GuildTributeOptInOutReply_Struct*)outapp->pBuffer;
data->guild_id = in->guild_id;
strn0cpy(data->player_name, in->player_name, sizeof(data->player_name));
data->no_donations = in->member_favor;
data->tribute_toggle = in->member_enabled ? true : false;
data->tribute_trophy_toggle = 0; //not yet implemented
data->time = in->member_time;
data->command = 1;
entity_list.QueueClientsGuild(outapp, in->guild_id);
safe_delete(outapp);
//my new items
outapp = new EQApplicationPacket(OP_GuildTributeToggleReply, sizeof(GuildTributeSendActive_Struct));
auto out = (GuildTributeSendActive_Struct *) outapp->pBuffer;
GuildTributeSendActive_Struct *out = (GuildTributeSendActive_Struct *) outapp->pBuffer;
auto guild = guild_mgr.GetGuildByGuildID(in->guild_id);
if (!guild) {
safe_delete(outapp)
return;
}
out->not_used = in->guild_id;
out->guild_favor = guild->tribute.favor;
out->tribute_enabled = guild->tribute.enabled;
+3 -70
View File
@@ -355,7 +355,9 @@ bool Zone::IsSpecialBindLocation(const glm::vec4& location)
//this also just loads into entity_list, not really into zone
bool Zone::LoadGroundSpawns() {
GroundSpawns g{};
GroundSpawns g;
memset(&g, 0, sizeof(g));
content_db.LoadGroundSpawns(zoneid, GetInstanceVersion(), &g);
@@ -3165,11 +3167,6 @@ void Zone::ClearEXPModifier(Client* c)
exp_modifiers.erase(c->CharacterID());
}
void Zone::ClearEXPModifierByCharacterID(const uint32 character_id)
{
exp_modifiers.erase(character_id);
}
float Zone::GetAAEXPModifier(Client* c)
{
const auto& l = exp_modifiers.find(c->CharacterID());
@@ -3182,18 +3179,6 @@ float Zone::GetAAEXPModifier(Client* c)
return v.aa_modifier;
}
float Zone::GetAAEXPModifierByCharacterID(const uint32 character_id)
{
const auto& l = exp_modifiers.find(character_id);
if (l == exp_modifiers.end()) {
return 1.0f;
}
const auto& v = l->second;
return v.aa_modifier;
}
float Zone::GetEXPModifier(Client* c)
{
const auto& l = exp_modifiers.find(c->CharacterID());
@@ -3206,18 +3191,6 @@ float Zone::GetEXPModifier(Client* c)
return v.exp_modifier;
}
float Zone::GetEXPModifierByCharacterID(const uint32 character_id)
{
const auto& l = exp_modifiers.find(character_id);
if (l == exp_modifiers.end()) {
return 1.0f;
}
const auto& v = l->second;
return v.exp_modifier;
}
void Zone::SetAAEXPModifier(Client* c, float aa_modifier)
{
auto l = exp_modifiers.find(c->CharacterID());
@@ -3238,26 +3211,6 @@ void Zone::SetAAEXPModifier(Client* c, float aa_modifier)
);
}
void Zone::SetAAEXPModifierByCharacterID(const uint32 character_id, float aa_modifier)
{
auto l = exp_modifiers.find(character_id);
if (l == exp_modifiers.end()) {
return;
}
auto& m = l->second;
m.aa_modifier = aa_modifier;
CharacterExpModifiersRepository::SetEXPModifier(
database,
character_id,
GetZoneID(),
GetInstanceVersion(),
m
);
}
void Zone::SetEXPModifier(Client* c, float exp_modifier)
{
auto l = exp_modifiers.find(c->CharacterID());
@@ -3278,26 +3231,6 @@ void Zone::SetEXPModifier(Client* c, float exp_modifier)
);
}
void Zone::SetEXPModifierByCharacterID(const uint32 character_id, float exp_modifier)
{
auto l = exp_modifiers.find(character_id);
if (l == exp_modifiers.end()) {
return;
}
auto& m = l->second;
m.exp_modifier = exp_modifier;
CharacterExpModifiersRepository::SetEXPModifier(
database,
character_id,
GetZoneID(),
GetInstanceVersion(),
m
);
}
bool Zone::IsIdleWhenEmpty() const
{
return m_idle_when_empty;
-5
View File
@@ -269,15 +269,10 @@ public:
void SendReloadMessage(std::string reload_type);
void ClearEXPModifier(Client* c);
void ClearEXPModifierByCharacterID(const uint32 character_id);
float GetAAEXPModifier(Client* c);
float GetAAEXPModifierByCharacterID(const uint32 character_id);
float GetEXPModifier(Client* c);
float GetEXPModifierByCharacterID(const uint32 character_id);
void SetAAEXPModifier(Client* c, float aa_modifier);
void SetAAEXPModifierByCharacterID(const uint32 character_id, float aa_modifier);
void SetEXPModifier(Client* c, float exp_modifier);
void SetEXPModifierByCharacterID(const uint32 character_id, float exp_modifier);
void AddAggroMob() { aggroedmobs++; }
void AddAuth(ServerZoneIncomingClient_Struct *szic);
+2 -2
View File
@@ -4270,7 +4270,7 @@ void ZoneDatabase::SetAAEXPModifierByCharID(
instance_version,
EXPModifier{
.aa_modifier = aa_modifier,
.exp_modifier = zone->GetEXPModifierByCharacterID(character_id)
.exp_modifier = -1.0f
}
);
}
@@ -4288,7 +4288,7 @@ void ZoneDatabase::SetEXPModifierByCharID(
zone_id,
instance_version,
EXPModifier{
.aa_modifier = zone->GetAAEXPModifierByCharacterID(character_id),
.aa_modifier = -1.0f,
.exp_modifier = exp_modifier
}
);
+7 -56
View File
@@ -405,23 +405,11 @@ void Client::SendZoneCancel(ZoneChange_Struct *zc) {
zc->success
);
strn0cpy(zc2->char_name, zc->char_name, 64);
strcpy(zc2->char_name, zc->char_name);
zc2->zoneID = zone->GetZoneID();
zc2->success = 1;
zc2->instanceID = zone->GetInstanceID();
// this fixes an issue where when we do a zone cancel what often ends up happening is we are sending
// the client the wrong coordinates to zone back to. Often times it is the x,y,z of the destination zone
// because we saved the destination x,y,z on the client profile before we rejected the zone request.
// we're using rewind location because it should be where the client relatively was before we rejected the zone request.
// it also prevents the client from getting caught up in a zone loop because if we sent them exactly back to where they
// originated the request we could end up in a situation where the client is caught in a zone loop.
m_Position.x = m_RewindLocation.x;
m_Position.y = m_RewindLocation.y;
m_Position.z = m_RewindLocation.z;
zc2->x = m_Position.x;
zc2->y = m_Position.y;
zc2->z = m_Position.z;
outapp->priority = 6;
FastQueuePacket(&outapp);
LogZoning(
"(zc2) Client [{}] char_name [{}] zoning to [{}] ({}) cancelled instance_id [{}] x [{}] y [{}] z [{}] zone_reason [{}] success [{}]",
@@ -437,9 +425,6 @@ void Client::SendZoneCancel(ZoneChange_Struct *zc) {
zc2->success
);
outapp->priority = 6;
FastQueuePacket(&outapp);
//reset to unsolicited.
zone_mode = ZoneUnsolicited;
// reset since we're not zoning anymore
@@ -755,34 +740,10 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
pZoneName = strcpy(new char[zd->long_name.length() + 1], zd->long_name.c_str());
}
// If we are zoning to the same zone, we need to use the current instance ID if it is not specified.
if (zoneID == zone->GetZoneID() && instance_id == 0) {
instance_id = zone->GetInstanceID();
}
auto r = content_service.FindZone(zoneID, instance_id);
if (r.zone_id) {
zoneID = r.zone_id;
instance_id = r.instance.id;
LogZoning(
"Client caught HandleZoneRoutingMiddleware [{}] zone_id [{}] instance_id [{}] x [{}] y [{}] z [{}] heading [{}] ignorerestrictions [{}] zone_mode [{}]",
GetCleanName(),
zoneID,
instance_id,
x,
y,
z,
heading,
ignorerestrictions,
static_cast<int>(zm)
);
}
LogInfo(
"Client [{}] zone_id [{}] instance_id [{}] x [{}] y [{}] z [{}] heading [{}] ignorerestrictions [{}] zone_mode [{}]",
"Client [{}] zone_id [{}] x [{}] y [{}] z [{}] heading [{}] ignorerestrictions [{}] zone_mode [{}]",
GetCleanName(),
zoneID,
instance_id,
x,
y,
z,
@@ -906,8 +867,9 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
outapp->priority = 6;
FastQueuePacket(&outapp);
}
else if (zm == ZoneSolicited || zm == ZoneToSafeCoords) {
auto outapp = new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct));
else if(zm == ZoneSolicited || zm == ZoneToSafeCoords) {
auto outapp =
new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct));
RequestClientZoneChange_Struct* gmg = (RequestClientZoneChange_Struct*) outapp->pBuffer;
gmg->zone_id = zoneID;
@@ -918,17 +880,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
gmg->instance_id = instance_id;
gmg->type = 0x01; //an observed value, not sure of meaning
LogZoning(
"Player [{}] has requested zoning to zone_id [{}] instance_id [{}] x [{}] y [{}] z [{}] heading [{}]",
GetCleanName(),
zoneID,
instance_id,
x,
y,
z,
heading
);
outapp->priority = 6;
FastQueuePacket(&outapp);
}