mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-27 08:52:27 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d3ca636a70 | |||
| 01855d40df | |||
| 748602b04e | |||
| a97a9a0d1c | |||
| a78c754c0e | |||
| ef214f91e9 | |||
| 04a74df0b2 | |||
| c15bfe12eb | |||
| 5702f7bcd1 | |||
| 9a5bf53e11 | |||
| 69c6a7b89a | |||
| 2f0dbc5d15 | |||
| 93c79817cd | |||
| 3296287d70 | |||
| 774a7fa779 | |||
| 1ff4541a9f | |||
| 3448758c03 | |||
| ff4ccfa98f | |||
| d2c3c14ae0 | |||
| a470931fdd | |||
| 078db3460d | |||
| 0980a780d0 | |||
| 7f01bb509c | |||
| 4bb189cbf4 | |||
| b03e8ff0fb | |||
| 6179b7481e |
@@ -1,3 +1,45 @@
|
||||
## [22.4.5] - 03/03/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add additional Heroic Sta/Wis/Int bonuses for Bots. ([#3013](https://github.com/EQEmu/Server/pull/3013)) @Aeadoin 2023-03-01
|
||||
* Cleanup AI_IdleCastCheck Logic ([#3004](https://github.com/EQEmu/Server/pull/3004)) @Aeadoin 2023-02-26
|
||||
|
||||
### Code
|
||||
|
||||
* Delete unused zone/skills.h ([#3007](https://github.com/EQEmu/Server/pull/3007)) @Kinglykrab 2023-02-27
|
||||
* Remove DumpPacketProfile() from client.h ([#3000](https://github.com/EQEmu/Server/pull/3000)) @Kinglykrab 2023-02-26
|
||||
* Remove GetCombinedAC_TEST() from client.h ([#2999](https://github.com/EQEmu/Server/pull/2999)) @Kinglykrab 2023-02-26
|
||||
* Remove GetDamageMultiplier() from client.h ([#3001](https://github.com/EQEmu/Server/pull/3001)) @Kinglykrab 2023-02-26
|
||||
* Remove NumberOfAvailableTitles() from titles.h ([#3006](https://github.com/EQEmu/Server/pull/3006)) @Kinglykrab 2023-02-27
|
||||
* Remove ReturnItemPacket from client.h/inventory.cpp ([#3002](https://github.com/EQEmu/Server/pull/3002)) @Kinglykrab 2023-02-26
|
||||
* Remove class EGNode from mob.h ([#3003](https://github.com/EQEmu/Server/pull/3003)) @Kinglykrab 2023-02-26
|
||||
* Remove unused ClientFactory in client.h ([#2998](https://github.com/EQEmu/Server/pull/2998)) @Kinglykrab 2023-02-26
|
||||
* Remove unused iterator from LoadCharacterDisciplines ([#3012](https://github.com/EQEmu/Server/pull/3012)) @Aeadoin 2023-03-02
|
||||
|
||||
### Crash
|
||||
|
||||
* Fix crash in CheckTradeskillLoreConflict ([#3009](https://github.com/EQEmu/Server/pull/3009)) @Aeadoin 2023-02-28
|
||||
|
||||
### Fixes
|
||||
|
||||
* Account for bad data in Tradeskill Recipe Entries ([#2991](https://github.com/EQEmu/Server/pull/2991)) @Aeadoin 2023-02-25
|
||||
* Fix DoAnim quest method default speed ([#3016](https://github.com/EQEmu/Server/pull/3016)) @Kinglykrab 2023-03-01
|
||||
* Fix an issue where EVENT_TIMER timers would not be cleaned up after zone ([#3018](https://github.com/EQEmu/Server/pull/3018)) @noudess 2023-03-03
|
||||
* Fix for Discipline Loading from Database causing issues with slot_ids ([#3008](https://github.com/EQEmu/Server/pull/3008)) @Aeadoin 2023-02-28
|
||||
* Fix for Lore Components where component is returned. ([#3005](https://github.com/EQEmu/Server/pull/3005)) @Aeadoin 2023-02-27
|
||||
* Fix issue where quest saylink responses would occur before the NPC's response ([#3010](https://github.com/EQEmu/Server/pull/3010)) @Akkadius 2023-03-01
|
||||
* Fix log messages when players join channel ([#2992](https://github.com/EQEmu/Server/pull/2992)) @Valorith 2023-03-03
|
||||
* Fix npcfeature and playerfeature ([#3017](https://github.com/EQEmu/Server/pull/3017)) @Kinglykrab 2023-03-02
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GetDefaultRaceSize() to Perl/Lua ([#2993](https://github.com/EQEmu/Server/pull/2993)) @Kinglykrab 2023-02-27
|
||||
* Add HasSpecialAbilities() to Perl/Lua ([#2994](https://github.com/EQEmu/Server/pull/2994)) @Kinglykrab 2023-02-27
|
||||
* Add IsBerserk() to Perl/Lua ([#2997](https://github.com/EQEmu/Server/pull/2997)) @Kinglykrab 2023-03-01
|
||||
* Add IsFindable() and IsTrackable() to Perl/Lua ([#2996](https://github.com/EQEmu/Server/pull/2996)) @Kinglykrab 2023-03-01
|
||||
* Add IsUnderwaterOnly() to Perl/Lua ([#2995](https://github.com/EQEmu/Server/pull/2995)) @Kinglykrab 2023-03-01
|
||||
|
||||
## [22.4.4] - 02/24/2023
|
||||
|
||||
### Bots
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.4.4-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.4.5-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__
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "22.4.4",
|
||||
"version": "22.4.5",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
+5
-5
@@ -48,10 +48,10 @@ ChatChannel::ChatChannel(std::string inName, std::string inOwner, std::string in
|
||||
m_moderated = false;
|
||||
|
||||
LogDebug(
|
||||
"New ChatChannel created: Name: [{}], Owner: [{}], Password: [{}], MinStatus: [{}]",
|
||||
m_name.c_str(),
|
||||
m_owner.c_str(),
|
||||
m_password.c_str(),
|
||||
"New ChatChannel created: Name: [{}] Owner: [{}] Password: [{}] MinStatus: [{}]",
|
||||
m_name,
|
||||
m_owner,
|
||||
m_password,
|
||||
m_minimum_status
|
||||
);
|
||||
|
||||
@@ -667,7 +667,7 @@ ChatChannel *ChatChannelList::RemoveClientFromChannel(const std::string& in_chan
|
||||
}
|
||||
|
||||
LogDebug("Client [{}] removed from channel [{}]. Channel is owned by {}. Command directed: {}", c->GetName(), channel_name, required_channel->GetOwnerName(), command_directed);
|
||||
if (c->GetName() == required_channel->GetOwnerName() && command_directed) { // Check if the client that is leaving is the the channel owner
|
||||
if (c->GetName() == required_channel->GetOwnerName() && command_directed) { // Check if the client that is leaving is the channel owner
|
||||
LogDebug("Owner left the channel [{}], removing channel from database...", channel_name);
|
||||
database.DeleteChatChannel(channel_name); // Remove the channel from the database.
|
||||
LogDebug("Flagging [{}] channel as temporary...", channel_name);
|
||||
|
||||
+4
-1
@@ -793,7 +793,10 @@ void Clientlist::ProcessOPMailCommand(Client *c, std::string command_string, boo
|
||||
case CommandJoin:
|
||||
if (!command_directed) {
|
||||
//Append saved channels to params
|
||||
parameters = parameters + ", " + database.CurrentPlayerChannels(c->GetName());
|
||||
const auto saved_channels = database.CurrentPlayerChannels(c->GetName());
|
||||
if (!saved_channels.empty()) {
|
||||
parameters += fmt::format(", {}", Strings::Join(saved_channels, ", "));
|
||||
}
|
||||
parameters = RemoveDuplicateChannels(parameters);
|
||||
}
|
||||
c->JoinChannels(parameters, command_directed);
|
||||
|
||||
+10
-9
@@ -336,16 +336,17 @@ void UCSDatabase::DeleteChatChannel(const std::string& channel_name)
|
||||
LogInfo("Deleting channel [{}] from the database.", channel_name);
|
||||
}
|
||||
|
||||
std::string UCSDatabase::CurrentPlayerChannels(const std::string& player_name) {
|
||||
int current_player_channel_count = CurrentPlayerChannelCount(player_name);
|
||||
if (current_player_channel_count == 0) {
|
||||
return "";
|
||||
std::vector<std::string> UCSDatabase::CurrentPlayerChannels(const std::string& player_name) {
|
||||
auto rows = ChatchannelsRepository::GetWhere(*this, fmt::format("`owner` = '{}'", Strings::Escape(player_name)));
|
||||
if (rows.empty()) {
|
||||
return {};
|
||||
}
|
||||
const auto rquery = fmt::format("SELECT GROUP_CONCAT(`name` SEPARATOR ', ') FROM chatchannels WHERE `owner` = '{}'; ", Strings::Escape(player_name));
|
||||
auto results = QueryDatabase(rquery);
|
||||
auto row = results.begin();
|
||||
std::string channels = row[0];
|
||||
LogDebug("Player [{}] has the following permanent channels saved to the database: [{}].", player_name, channels);
|
||||
std::vector<std::string> channels = {};
|
||||
channels.reserve(rows.size());
|
||||
for (auto &e: rows) {
|
||||
channels.emplace_back(e.name);
|
||||
}
|
||||
LogDebug("Player [{}] has the following [{}] permanent channels saved to the database: [{}].", player_name, rows.size(), Strings::Join(channels, ", "));
|
||||
return channels;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public:
|
||||
void SaveChatChannel(const std::string& channel_name, const std::string& channel_owner, const std::string& channel_password, const uint16& min_status);
|
||||
void DeleteChatChannel(const std::string& channel_name);
|
||||
int CurrentPlayerChannelCount(const std::string& player_name);
|
||||
std::string CurrentPlayerChannels(const std::string& player_name);
|
||||
std::vector<std::string> CurrentPlayerChannels(const std::string& player_name);
|
||||
void GetAccountStatus(Client *c);
|
||||
void SetChannelPassword(const std::string& channel_name, const std::string& password);
|
||||
void SetChannelOwner(const std::string& channel_name, const std::string& owner);
|
||||
|
||||
@@ -255,7 +255,6 @@ SET(zone_headers
|
||||
quest_parser_collection.h
|
||||
raids.h
|
||||
raycast_mesh.h
|
||||
skills.h
|
||||
shared_task_zone_messaging.h
|
||||
spawn2.cpp
|
||||
spawn2.h
|
||||
|
||||
@@ -2470,6 +2470,7 @@ void Bot::AI_Process()
|
||||
}
|
||||
|
||||
// We also need a leash owner and follow mob (subset of primary AI criteria)
|
||||
bot_group->VerifyGroup();
|
||||
Client* leash_owner = (bot_group->GetLeader() && bot_group->GetLeader()->IsClient() ? bot_group->GetLeader()->CastToClient() : bot_owner);
|
||||
if (!leash_owner) {
|
||||
return;
|
||||
@@ -6133,8 +6134,11 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) {
|
||||
int64 Bot::CalcMaxMana() {
|
||||
switch(GetCasterClass()) {
|
||||
case 'I':
|
||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
|
||||
max_mana += (GetHeroicINT() * 10);
|
||||
case 'W': {
|
||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
|
||||
max_mana += (GetHeroicWIS() * 10);
|
||||
break;
|
||||
}
|
||||
case 'N': {
|
||||
@@ -7084,6 +7088,7 @@ int32 Bot::LevelRegen() {
|
||||
|
||||
int64 Bot::CalcHPRegen() {
|
||||
int32 regen = (LevelRegen() + itembonuses.HPRegen + spellbonuses.HPRegen);
|
||||
regen += GetHeroicSTA() / 20;
|
||||
regen += (aabonuses.HPRegen + GroupLeadershipAAHealthRegeneration());
|
||||
regen = ((regen * RuleI(Character, HPRegenMultiplier)) / 100);
|
||||
return regen;
|
||||
@@ -7155,6 +7160,7 @@ int64 Bot::CalcMaxHP() {
|
||||
int32 bot_hp = 0;
|
||||
uint32 nd = 10000;
|
||||
bot_hp += (GenerateBaseHitPoints() + itembonuses.HP);
|
||||
bot_hp += (GetHeroicSTA() * 10);
|
||||
nd += aabonuses.MaxHP;
|
||||
bot_hp = ((float)bot_hp * (float)nd / (float)10000);
|
||||
bot_hp += (spellbonuses.HP + aabonuses.HP);
|
||||
|
||||
+46
-27
@@ -1303,8 +1303,7 @@ bool Bot::AI_IdleCastCheck() {
|
||||
|
||||
if (HasGroup() && GetGroup()->GetLeader() && GetGroup()->GetLeader()->IsClient()) {
|
||||
test_against = GetGroup()->GetLeader()->CastToClient();
|
||||
}
|
||||
else if (GetOwner() && GetOwner()->IsClient()) {
|
||||
} else if (GetOwner() && GetOwner()->IsClient()) {
|
||||
test_against = GetOwner()->CastToClient();
|
||||
}
|
||||
|
||||
@@ -1317,17 +1316,12 @@ bool Bot::AI_IdleCastCheck() {
|
||||
// Healers WITHOUT pets will check if a heal is needed before buffing.
|
||||
case CLERIC:
|
||||
case PALADIN:
|
||||
case RANGER:
|
||||
case MONK:
|
||||
case ROGUE:
|
||||
case WARRIOR:
|
||||
case BERSERKER: {
|
||||
case RANGER: {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1337,13 +1331,46 @@ bool Bot::AI_IdleCastCheck() {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case MONK:
|
||||
case ROGUE:
|
||||
case WARRIOR:
|
||||
case BERSERKER: {
|
||||
if (!AICastSpell(this, 100, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Heal)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
// Pets class will first cast their pet, then buffs
|
||||
case DRUID:
|
||||
|
||||
case MAGICIAN:
|
||||
case SHADOWKNIGHT:
|
||||
case SHAMAN:
|
||||
case NECROMANCER:
|
||||
case ENCHANTER:
|
||||
case ENCHANTER: {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Cure)) {
|
||||
if (!AICastSpell(GetPet(), 100, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
if (!AICastSpell(GetPet(), 100, SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case DRUID:
|
||||
case SHAMAN:
|
||||
case BEASTLORD: {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
@@ -1365,16 +1392,12 @@ bool Bot::AI_IdleCastCheck() {
|
||||
}
|
||||
case WIZARD: { // This can eventually be move into the BEASTLORD case handler once pre-combat is fully implemented
|
||||
if (pre_combat) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
if (!AICastSpell(GetPet(), 100, SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_PreCombatBuff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) {
|
||||
}
|
||||
}
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_PreCombatBuff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1383,15 +1406,11 @@ bool Bot::AI_IdleCastCheck() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Cure)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Pet)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) {
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
if (!AICastSpell(GetPet(), 100, SpellType_Heal)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) {
|
||||
}
|
||||
}
|
||||
if (!AICastSpell(this, 100, SpellType_Buff)) {
|
||||
if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,11 +218,6 @@ struct ClientReward
|
||||
uint32 amount;
|
||||
};
|
||||
|
||||
class ClientFactory {
|
||||
public:
|
||||
Client *MakeClient(std::shared_ptr<EQStreamInterface> ieqs);
|
||||
};
|
||||
|
||||
class Client : public Mob
|
||||
{
|
||||
public:
|
||||
@@ -343,8 +338,6 @@ public:
|
||||
bool HasRecipeLearned(uint32 recipe_id);
|
||||
bool CanIncreaseTradeskill(EQ::skills::SkillType tradeskill);
|
||||
|
||||
EQApplicationPacket* ReturnItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type);
|
||||
|
||||
bool GetRevoked() const { return revoked; }
|
||||
void SetRevoked(bool rev) { revoked = rev; }
|
||||
inline uint32 GetIP() const { return ip; }
|
||||
@@ -697,7 +690,6 @@ public:
|
||||
void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity, bool quest = false);
|
||||
void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp);
|
||||
int32 GetRawItemAC();
|
||||
uint16 GetCombinedAC_TEST();
|
||||
|
||||
inline uint32 LSAccountID() const { return lsaccountid; }
|
||||
inline uint32 GetWID() const { return WID; }
|
||||
@@ -851,9 +843,6 @@ public:
|
||||
inline void SetBecomeNPC(bool flag) { npcflag = flag; }
|
||||
inline void SetBecomeNPCLevel(uint8 level) { npclevel = level; }
|
||||
EQStreamInterface* Connection() { return eqs; }
|
||||
#ifdef PACKET_PROFILER
|
||||
void DumpPacketProfile() { if(eqs) eqs->DumpPacketProfile(); }
|
||||
#endif
|
||||
uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id
|
||||
uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
virtual void UpdateEquipmentLight() { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); }
|
||||
@@ -1595,7 +1584,6 @@ public:
|
||||
void SetAccountFlag(std::string flag, std::string val);
|
||||
std::string GetAccountFlag(std::string flag);
|
||||
void SetGMStatus(int16 new_status);
|
||||
float GetDamageMultiplier(EQ::skills::SkillType how_long_has_this_been_missing);
|
||||
void Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto_consume);
|
||||
void PlayMP3(const char* fname);
|
||||
void ExpeditionSay(const char *str, int ExpID);
|
||||
|
||||
@@ -8737,12 +8737,12 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
if (!response.empty()) {
|
||||
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
|
||||
|
||||
if (!silentsaylink) {
|
||||
Message(Chat::LightGray, "You say, '%s'", response.c_str());
|
||||
}
|
||||
|
||||
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1063,12 +1063,12 @@ void Perl__playertexture(int texture_id)
|
||||
quest_manager.playertexture(texture_id);
|
||||
}
|
||||
|
||||
void Perl__playerfeature(char* feature, int value)
|
||||
void Perl__playerfeature(const char* feature, int value)
|
||||
{
|
||||
quest_manager.playerfeature(feature, value);
|
||||
}
|
||||
|
||||
void Perl__npcfeature(char* feature, int value)
|
||||
void Perl__npcfeature(const char* feature, int value)
|
||||
{
|
||||
quest_manager.npcfeature(feature, value);
|
||||
}
|
||||
|
||||
@@ -3376,31 +3376,6 @@ void Client::SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPac
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
EQApplicationPacket* Client::ReturnItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type)
|
||||
{
|
||||
if (!inst)
|
||||
return nullptr;
|
||||
|
||||
// Serialize item into |-delimited string
|
||||
std::string packet = inst->Serialize(slot_id);
|
||||
|
||||
EmuOpcode opcode = OP_Unknown;
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
BulkItemPacket_Struct* itempacket = nullptr;
|
||||
|
||||
// Construct packet
|
||||
opcode = OP_ItemPacket;
|
||||
outapp = new EQApplicationPacket(opcode, packet.length()+1);
|
||||
itempacket = (BulkItemPacket_Struct*)outapp->pBuffer;
|
||||
memcpy(itempacket->SerializedItem, packet.c_str(), packet.length());
|
||||
|
||||
#if EQDEBUG >= 9
|
||||
DumpPacket(outapp);
|
||||
#endif
|
||||
|
||||
return outapp;
|
||||
}
|
||||
|
||||
static int16 BandolierSlotToWeaponSlot(int BandolierSlot)
|
||||
{
|
||||
switch (BandolierSlot)
|
||||
|
||||
@@ -3049,7 +3049,6 @@ bool Lua_Client::IsAutoFireEnabled()
|
||||
{
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->AutoFireEnabled();
|
||||
|
||||
}
|
||||
|
||||
luabind::scope lua_register_client() {
|
||||
|
||||
@@ -2823,6 +2823,22 @@ Lua_HateList Lua_Mob::GetHateListBots(uint32 distance) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Lua_Mob::IsFindable() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsFindable();
|
||||
}
|
||||
|
||||
|
||||
bool Lua_Mob::IsTrackable() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsTrackable();
|
||||
}
|
||||
|
||||
float Lua_Mob::GetDefaultRaceSize() {
|
||||
Lua_Safe_Call_Real();
|
||||
return self->GetDefaultRaceSize();
|
||||
}
|
||||
|
||||
luabind::scope lua_register_mob() {
|
||||
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -3022,6 +3038,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("GetDEX", &Lua_Mob::GetDEX)
|
||||
.def("GetDR", &Lua_Mob::GetDR)
|
||||
.def("GetDamageAmount", (uint32(Lua_Mob::*)(Lua_Mob))&Lua_Mob::GetDamageAmount)
|
||||
.def("GetDefaultRaceSize", &Lua_Mob::GetDefaultRaceSize)
|
||||
.def("GetDeity", &Lua_Mob::GetDeity)
|
||||
.def("GetDisplayAC", &Lua_Mob::GetDisplayAC)
|
||||
.def("GetDrakkinDetails", &Lua_Mob::GetDrakkinDetails)
|
||||
@@ -3164,6 +3181,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("IsEngaged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEngaged)
|
||||
.def("IsEnraged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEnraged)
|
||||
.def("IsFeared", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFeared)
|
||||
.def("IsFindable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFindable)
|
||||
.def("IsHorse", &Lua_Mob::IsHorse)
|
||||
.def("IsImmuneToSpell", (bool(Lua_Mob::*)(int,Lua_Mob))&Lua_Mob::IsImmuneToSpell)
|
||||
.def("IsInvisible", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsInvisible)
|
||||
@@ -3179,6 +3197,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("IsStunned", (bool(Lua_Mob::*)(void))&Lua_Mob::IsStunned)
|
||||
.def("IsTargetable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTargetable)
|
||||
.def("IsTargeted", &Lua_Mob::IsTargeted)
|
||||
.def("IsTrackable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTrackable)
|
||||
.def("IsWarriorClass", &Lua_Mob::IsWarriorClass)
|
||||
.def("Kill", (void(Lua_Mob::*)(void))&Lua_Mob::Kill)
|
||||
.def("Mesmerize", (void(Lua_Mob::*)(void))&Lua_Mob::Mesmerize)
|
||||
|
||||
@@ -513,6 +513,9 @@ public:
|
||||
void CopyHateList(Lua_Mob to);
|
||||
bool IsAttackAllowed(Lua_Mob target);
|
||||
bool IsAttackAllowed(Lua_Mob target, bool is_spell_attack);
|
||||
bool IsFindable();
|
||||
bool IsTrackable();
|
||||
float GetDefaultRaceSize();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -767,6 +767,16 @@ void Lua_NPC::ScaleNPC(uint8 npc_level, bool override_special_abilities)
|
||||
self->ScaleNPC(npc_level, true, override_special_abilities);
|
||||
}
|
||||
|
||||
bool Lua_NPC::IsUnderwaterOnly() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsUnderwaterOnly();
|
||||
}
|
||||
|
||||
bool Lua_NPC::HasSpecialAbilities() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasSpecialAbilities();
|
||||
}
|
||||
|
||||
luabind::scope lua_register_npc() {
|
||||
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -860,6 +870,7 @@ luabind::scope lua_register_npc() {
|
||||
.def("IsRaidTarget", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRaidTarget)
|
||||
.def("IsRareSpawn", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRareSpawn)
|
||||
.def("IsTaunting", (bool(Lua_NPC::*)(void))&Lua_NPC::IsTaunting)
|
||||
.def("IsUnderwaterOnly", (bool(Lua_NPC::*)(void))&Lua_NPC::IsUnderwaterOnly)
|
||||
.def("MerchantCloseShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantCloseShop)
|
||||
.def("MerchantOpenShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantOpenShop)
|
||||
.def("ModifyNPCStat", (void(Lua_NPC::*)(std::string,std::string))&Lua_NPC::ModifyNPCStat)
|
||||
|
||||
@@ -174,6 +174,8 @@ public:
|
||||
void SetLDoNTrapDetected(bool is_detected);
|
||||
void ScaleNPC(uint8 npc_level);
|
||||
void ScaleNPC(uint8 npc_level, bool override_special_abilities);
|
||||
bool IsUnderwaterOnly();
|
||||
bool HasSpecialAbilities();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+3
-1
@@ -518,7 +518,9 @@ Mob::Mob(
|
||||
}
|
||||
|
||||
Mob::~Mob()
|
||||
{
|
||||
{
|
||||
quest_manager.stopalltimers(this);
|
||||
|
||||
mMovementManager->RemoveMob(this);
|
||||
|
||||
AI_Stop();
|
||||
|
||||
@@ -42,7 +42,6 @@ char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||
|
||||
#define MAX_SPECIAL_ATTACK_PARAMS 8
|
||||
|
||||
class EGNode;
|
||||
class Client;
|
||||
class EQApplicationPacket;
|
||||
class Group;
|
||||
|
||||
@@ -2786,6 +2786,26 @@ Bot* Perl_Mob_GetHateRandomBot(Mob* self) // @categories Hate and Aggro
|
||||
return self->GetHateRandomBot();
|
||||
}
|
||||
|
||||
bool Perl_Mob_IsFindable(Mob* self) // @categories Script Utility
|
||||
{
|
||||
return self->IsFindable();
|
||||
}
|
||||
|
||||
bool Perl_Mob_IsTrackable(Mob* self) // @categories Script Utility
|
||||
{
|
||||
return self->IsTrackable();
|
||||
}
|
||||
|
||||
bool Perl_Mob_IsBerserk(Mob* self) // @categories Script Utility
|
||||
{
|
||||
return self->IsBerserk();
|
||||
}
|
||||
|
||||
float Perl_Mob_GetDefaultRaceSize(Mob* self) // @categories Script Utility
|
||||
{
|
||||
return self->GetDefaultRaceSize();
|
||||
}
|
||||
|
||||
void perl_register_mob()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -2970,6 +2990,7 @@ void perl_register_mob()
|
||||
package.add("GetClassName", &Perl_Mob_GetClassName);
|
||||
package.add("GetCleanName", &Perl_Mob_GetCleanName);
|
||||
package.add("GetCorruption", &Perl_Mob_GetCorruption);
|
||||
package.add("GetDefaultRaceSize", &Perl_Mob_GetDefaultRaceSize);
|
||||
package.add("GetDEX", &Perl_Mob_GetDEX);
|
||||
package.add("GetDR", &Perl_Mob_GetDR);
|
||||
package.add("GetDamageAmount", &Perl_Mob_GetDamageAmount);
|
||||
@@ -3112,6 +3133,7 @@ void perl_register_mob()
|
||||
package.add("IsAttackAllowed", (bool(*)(Mob*, Mob*, bool))&Perl_Mob_IsAttackAllowed);
|
||||
package.add("IsBeacon", &Perl_Mob_IsBeacon);
|
||||
package.add("IsBeneficialAllowed", &Perl_Mob_IsBeneficialAllowed);
|
||||
package.add("IsBerserk", &Perl_Mob_IsBerserk);
|
||||
package.add("IsBlind", &Perl_Mob_IsBlind);
|
||||
package.add("IsBot", &Perl_Mob_IsBot);
|
||||
package.add("IsCasting", &Perl_Mob_IsCasting);
|
||||
@@ -3122,6 +3144,7 @@ void perl_register_mob()
|
||||
package.add("IsEngaged", &Perl_Mob_IsEngaged);
|
||||
package.add("IsEnraged", &Perl_Mob_IsEnraged);
|
||||
package.add("IsFeared", &Perl_Mob_IsFeared);
|
||||
package.add("IsFindable", &Perl_Mob_IsFindable);
|
||||
package.add("IsHorse", &Perl_Mob_IsHorse);
|
||||
package.add("IsImmuneToSpell", &Perl_Mob_IsImmuneToSpell);
|
||||
package.add("IsInvisible", (bool(*)(Mob*))&Perl_Mob_IsInvisible);
|
||||
@@ -3142,6 +3165,7 @@ void perl_register_mob()
|
||||
package.add("IsStunned", &Perl_Mob_IsStunned);
|
||||
package.add("IsTargetable", &Perl_Mob_IsTargetable);
|
||||
package.add("IsTargeted", &Perl_Mob_IsTargeted);
|
||||
package.add("IsTrackable", &Perl_Mob_IsTrackable);
|
||||
package.add("IsTrap", &Perl_Mob_IsTrap);
|
||||
package.add("IsWarriorClass", &Perl_Mob_IsWarriorClass);
|
||||
package.add("Kill", &Perl_Mob_Kill);
|
||||
|
||||
@@ -765,6 +765,16 @@ void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level, bool override_special_abiliti
|
||||
return self->ScaleNPC(npc_level, override_special_abilities);
|
||||
}
|
||||
|
||||
bool Perl_NPC_IsUnderwaterOnly(NPC* self) // @categories Script Utility
|
||||
{
|
||||
return self->IsUnderwaterOnly();
|
||||
}
|
||||
|
||||
bool Perl_NPC_HasSpecialAbilities(NPC* self) // @categories Script Utility
|
||||
{
|
||||
return self->HasSpecialAbilities();
|
||||
}
|
||||
|
||||
void perl_register_npc()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -852,6 +862,7 @@ void perl_register_npc()
|
||||
package.add("GetSwarmTarget", &Perl_NPC_GetSwarmTarget);
|
||||
package.add("GetWaypointMax", &Perl_NPC_GetWaypointMax);
|
||||
package.add("HasAISpellEffect", &Perl_NPC_HasAISpellEffect);
|
||||
package.add("HasSpecialAbilities", &Perl_NPC_HasSpecialAbilities);
|
||||
package.add("HasItem", &Perl_NPC_HasItem);
|
||||
package.add("IsAnimal", &Perl_NPC_IsAnimal);
|
||||
package.add("IsGuarding", &Perl_NPC_IsGuarding);
|
||||
@@ -862,6 +873,7 @@ void perl_register_npc()
|
||||
package.add("IsRaidTarget", &Perl_NPC_IsRaidTarget);
|
||||
package.add("IsRareSpawn", &Perl_NPC_IsRareSpawn);
|
||||
package.add("IsTaunting", &Perl_NPC_IsTaunting);
|
||||
package.add("IsUnderwaterOnly", (bool(*)(NPC*))&Perl_NPC_IsUnderwaterOnly);
|
||||
package.add("MerchantCloseShop", &Perl_NPC_MerchantCloseShop);
|
||||
package.add("MerchantOpenShop", &Perl_NPC_MerchantOpenShop);
|
||||
package.add("ModifyNPCStat", &Perl_NPC_ModifyNPCStat);
|
||||
|
||||
+3
-3
@@ -88,7 +88,7 @@ void QuestManager::Process() {
|
||||
end = QTimerList.end();
|
||||
while (cur != end) {
|
||||
if (cur->Timer_.Enabled() && cur->Timer_.Check()) {
|
||||
if (cur->mob && entity_list.IsMobInZone(cur->mob)) {
|
||||
if (cur->mob) {
|
||||
if (cur->mob->IsNPC()) {
|
||||
if (parse->HasQuestSub(cur->mob->GetNPCTypeID(), EVENT_TIMER)) {
|
||||
parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0);
|
||||
@@ -2130,7 +2130,7 @@ void QuestManager::playertexture(int newtexture)
|
||||
initiator->SendIllusionPacket(initiator->GetRace(), 0xFF, newtexture);
|
||||
}
|
||||
|
||||
void QuestManager::playerfeature(char *feature, int setting)
|
||||
void QuestManager::playerfeature(const char* feature, int setting)
|
||||
{
|
||||
QuestManagerCurrentQuestVars();
|
||||
uint16 Race = initiator->GetRace();
|
||||
@@ -2187,7 +2187,7 @@ void QuestManager::playerfeature(char *feature, int setting)
|
||||
DrakkinHeritage, DrakkinTattoo, DrakkinDetails, Size);
|
||||
}
|
||||
|
||||
void QuestManager::npcfeature(char *feature, int setting)
|
||||
void QuestManager::npcfeature(const char* feature, int setting)
|
||||
{
|
||||
QuestManagerCurrentQuestVars();
|
||||
uint16 Race = owner->GetRace();
|
||||
|
||||
+3
-3
@@ -140,7 +140,7 @@ public:
|
||||
void movepc(int zone_id, float x, float y, float z, float heading);
|
||||
void gmmove(float x, float y, float z);
|
||||
void movegrp(int zoneid, float x, float y, float z);
|
||||
void doanim(int animation_id, int animation_speed = 1, bool ackreq = true, eqFilterType filter = FilterNone);
|
||||
void doanim(int animation_id, int animation_speed = 0, bool ackreq = true, eqFilterType filter = FilterNone);
|
||||
void addskill(int skill_id, int value);
|
||||
void setlanguage(int skill_id, int value);
|
||||
void setskill(int skill_id, int value);
|
||||
@@ -208,8 +208,8 @@ public:
|
||||
void playergender(int gender_id);
|
||||
void playersize(int newsize);
|
||||
void playertexture(int newtexture);
|
||||
void playerfeature(char *feature, int setting);
|
||||
void npcfeature(char *feature, int setting);
|
||||
void playerfeature(const char* feature, int setting);
|
||||
void npcfeature(const char* feature, int setting);
|
||||
void popup(const char *title, const char *text, uint32 popupid, uint32 buttons, uint32 Duration);
|
||||
void taskselector(const std::vector<int>& tasks, bool ignore_cooldown = false);
|
||||
void tasksetselector(int tasksettid, bool ignore_cooldown = false);
|
||||
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef SKILLS_H
|
||||
#define SKILLS_H
|
||||
|
||||
#define HIGHEST_SKILL_UNUSED 74
|
||||
|
||||
|
||||
// Correct Skill Numbers as of 4-14-2002
|
||||
#define _1H_BLUNT_UNUSED 0
|
||||
#define _1H_SLASHING_UNUSED 1
|
||||
#define _2H_BLUNT_UNUSED 2
|
||||
#define _2H_SLASHING_UNUSED 3
|
||||
#define ABJURE_UNUSED 4
|
||||
#define ALTERATION_UNUSED 5
|
||||
#define APPLY_POISON_UNUSED 6
|
||||
#define ARCHERY_UNUSED 7
|
||||
#define BACKSTAB_UNUSED 8
|
||||
#define BIND_WOUND_UNUSED 9
|
||||
#define BASH_UNUSED 10
|
||||
#define BLOCKSKILL_UNUSED 11
|
||||
#define BRASS_INSTRUMENTS_UNUSED 12
|
||||
#define CHANNELING_UNUSED 13
|
||||
#define CONJURATION_UNUSED 14
|
||||
#define DEFENSE_UNUSED 15
|
||||
#define DISARM_UNUSED 16
|
||||
#define DISARM_TRAPS_UNUSED 17
|
||||
#define DIVINATION_UNUSED 18
|
||||
#define DODGE_UNUSED 19
|
||||
#define DOUBLE_ATTACK_UNUSED 20
|
||||
#define DRAGON_PUNCH_UNUSED 21
|
||||
#define DUAL_WIELD_UNUSED 22
|
||||
#define EAGLE_STRIKE_UNUSED 23
|
||||
#define EVOCATION_UNUSED 24
|
||||
#define FEIGN_DEATH_UNUSED 25
|
||||
#define FLYING_KICK_UNUSED 26
|
||||
#define FORAGE_UNUSED 27
|
||||
#define HAND_TO_HAND_UNUSED 28
|
||||
#define HIDE_UNUSED 29
|
||||
#define KICK_UNUSED 30
|
||||
#define MEDITATE_UNUSED 31
|
||||
#define MEND_UNUSED 32
|
||||
#define OFFENSE_UNUSED 33
|
||||
#define PARRY_UNUSED 34
|
||||
#define PICK_LOCK_UNUSED 35
|
||||
#define PIERCING_UNUSED 36
|
||||
#define RIPOSTE_UNUSED 37
|
||||
#define ROUND_KICK_UNUSED 38
|
||||
#define SAFE_FALL_UNUSED 39
|
||||
#define SENSE_HEADING_UNUSED 40
|
||||
#define SINGING_UNUSED 41
|
||||
#define SNEAK_UNUSED 42
|
||||
#define SPECIALIZE_ABJURE_UNUSED 43
|
||||
#define SPECIALIZE_ALTERATION_UNUSED 44
|
||||
#define SPECIALIZE_CONJURATION_UNUSED 45
|
||||
#define SPECIALIZE_DIVINATION_UNUSED 46
|
||||
#define SPECIALIZE_EVOCATION_UNUSED 47
|
||||
#define PICK_POCKETS_UNUSED 48
|
||||
#define STRINGED_INSTRUMENTS_UNUSED 49
|
||||
#define SWIMMING_UNUSED 50
|
||||
#define THROWING_UNUSED 51
|
||||
#define TIGER_CLAW_UNUSED 52
|
||||
#define TRACKING_UNUSED 53
|
||||
#define WIND_INSTRUMENTS_UNUSED 54
|
||||
#define FISHING_UNUSED 55
|
||||
#define MAKE_POISON_UNUSED 56
|
||||
#define TINKERING_UNUSED 57
|
||||
#define RESEARCH_UNUSED 58
|
||||
#define ALCHEMY_UNUSED 59
|
||||
#define BAKING_UNUSED 60
|
||||
#define TAILORING_UNUSED 61
|
||||
#define SENSE_TRAPS_UNUSED 62
|
||||
#define BLACKSMITHING_UNUSED 63
|
||||
#define FLETCHING_UNUSED 64
|
||||
#define BREWING_UNUSED 65
|
||||
#define ALCOHOL_TOLERANCE_UNUSED 66
|
||||
#define BEGGING_UNUSED 67
|
||||
#define JEWELRY_MAKING_UNUSED 68
|
||||
#define POTTERY_UNUSED 69
|
||||
#define PERCUSSION_INSTRUMENTS_UNUSED 70
|
||||
#define INTIMIDATION_UNUSED 71
|
||||
#define BERSERKING_UNUSED 72
|
||||
#define TAUNT_UNUSED 73
|
||||
#define FRENZY_UNUSED 74
|
||||
|
||||
#endif
|
||||
@@ -93,18 +93,6 @@ EQApplicationPacket *TitleManager::MakeTitlesPacket(Client *client)
|
||||
return(outapp);
|
||||
}
|
||||
|
||||
int TitleManager::NumberOfAvailableTitles(Client *client)
|
||||
{
|
||||
int count = 0;
|
||||
for (const auto& title : titles) {
|
||||
if (IsClientEligibleForTitle(client, title)) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
std::string TitleManager::GetPrefix(int title_id)
|
||||
{
|
||||
if (!title_id) {
|
||||
|
||||
@@ -51,7 +51,6 @@ public:
|
||||
EQApplicationPacket *MakeTitlesPacket(Client *client);
|
||||
std::string GetPrefix(int title_id);
|
||||
std::string GetSuffix(int title_id);
|
||||
int NumberOfAvailableTitles(Client *client);
|
||||
bool IsClientEligibleForTitle(Client *client, TitleEntry title);
|
||||
bool IsNewAATitleAvailable(int aa_points, int class_id);
|
||||
bool IsNewTradeSkillTitleAvailable(int skill_id, int skill_value);
|
||||
|
||||
+50
-19
@@ -1865,32 +1865,63 @@ bool ZoneDatabase::DisableRecipe(uint32 recipe_id)
|
||||
|
||||
bool Client::CheckTradeskillLoreConflict(int32 recipe_id)
|
||||
{
|
||||
const auto& recipe_entries = TradeskillRecipeEntriesRepository::GetWhere(
|
||||
content_db,
|
||||
fmt::format(
|
||||
"recipe_id = {} ORDER BY id ASC",
|
||||
recipe_id
|
||||
)
|
||||
auto recipe_entries = TradeskillRecipeEntriesRepository::GetWhere(
|
||||
content_db,
|
||||
fmt::format(
|
||||
"recipe_id = {} ORDER BY componentcount DESC",
|
||||
recipe_id
|
||||
)
|
||||
);
|
||||
if (recipe_entries.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& e : recipe_entries) {
|
||||
auto item_inst = database.GetItem(e.item_id);
|
||||
if (item_inst) {
|
||||
if (item_inst->LoreGroup == 0 || e.componentcount > 0 || e.iscontainer) {
|
||||
continue;
|
||||
// validate which items from the recipe we will call CheckLoreConflict on
|
||||
for (const auto &tre : recipe_entries) {
|
||||
if (tre.item_id) {
|
||||
auto tre_inst = database.GetItem(tre.item_id);
|
||||
|
||||
// To compare items we iterate against each item in the recipe that have a loregroup.
|
||||
for (auto &tre_update_item : recipe_entries) {
|
||||
bool fi_is_valid = tre_update_item.item_id && tre_inst && tre_inst->LoreGroup != 0;
|
||||
|
||||
if (fi_is_valid) {
|
||||
auto tre_update_item_inst = database.GetItem(tre_update_item.item_id);
|
||||
bool ei_is_valid = tre_update_item_inst && tre_update_item_inst->LoreGroup != 0;
|
||||
|
||||
if (ei_is_valid) {
|
||||
bool unique_lore_group_match = tre_inst->LoreGroup > 0 && tre_inst->LoreGroup == tre_update_item_inst->LoreGroup;
|
||||
bool component_count_is_valid = tre_update_item.componentcount == 0 && tre.componentcount > 0;
|
||||
|
||||
// If the recipe item is a component, and matches a unique lore group (> 0) or the item_id matches another entry in the recipe
|
||||
// zero out the item_id, this will prevent us from doing a lore check inadvertently where
|
||||
// the item is a component, and returned on success, fail, salvage.
|
||||
// or uses an item that is part of a unique loregroup that returns an item of the same unique loregroup
|
||||
if (ei_is_valid && (tre_update_item.item_id == tre.item_id || unique_lore_group_match) && component_count_is_valid) {
|
||||
tre_update_item.item_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CheckLoreConflict(item_inst)) {
|
||||
EQ::SayLinkEngine linker;
|
||||
linker.SetLinkType(EQ::saylink::SayLinkItemData);
|
||||
linker.SetItemData(item_inst);
|
||||
auto item_link = linker.GenerateLink();
|
||||
MessageString(Chat::Red, TRADESKILL_COMBINE_LORE, item_link.c_str());
|
||||
return true;
|
||||
|
||||
if (tre_inst) {
|
||||
if (tre_inst->LoreGroup == 0 || tre.componentcount > 0 || tre.iscontainer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CheckLoreConflict(tre_inst)) {
|
||||
EQ::SayLinkEngine linker;
|
||||
linker.SetLinkType(EQ::saylink::SayLinkItemData);
|
||||
linker.SetItemData(tre_inst);
|
||||
auto item_link = linker.GenerateLink();
|
||||
MessageString(Chat::Red, TRADESKILL_COMBINE_LORE, item_link.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-13
@@ -13,6 +13,7 @@
|
||||
#include "zonedb.h"
|
||||
#include "aura.h"
|
||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||
#include "../common/repositories/character_disciplines_repository.h"
|
||||
#include "../common/repositories/npc_types_repository.h"
|
||||
|
||||
#include <ctime>
|
||||
@@ -814,22 +815,25 @@ bool ZoneDatabase::LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_
|
||||
}
|
||||
|
||||
bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){
|
||||
std::string query = StringFormat(
|
||||
"SELECT "
|
||||
"disc_id "
|
||||
"FROM "
|
||||
"`character_disciplines`"
|
||||
"WHERE `id` = %u ORDER BY `slot_id`", character_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
int i = 0;
|
||||
|
||||
auto character_disciplines = CharacterDisciplinesRepository::GetWhere(
|
||||
database, fmt::format(
|
||||
"`id` = {} ORDER BY `slot_id`",
|
||||
character_id
|
||||
)
|
||||
);
|
||||
|
||||
if (character_disciplines.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize Disciplines */
|
||||
memset(pp->disciplines.values, 0, (sizeof(pp->disciplines.values[0]) * MAX_PP_DISCIPLINES));
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
if (i < MAX_PP_DISCIPLINES)
|
||||
pp->disciplines.values[i] = atoi(row[0]);
|
||||
++i;
|
||||
}
|
||||
for (auto& row : character_disciplines) {
|
||||
if (row.slot_id < MAX_PP_DISCIPLINES && IsValidSpell(row.disc_id)) {
|
||||
pp->disciplines.values[row.slot_id] = row.disc_id;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user