mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-17 10:48:21 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c45d3b09e | |||
| 59e4adb117 | |||
| d5a06bfe2e | |||
| 0f0676824c | |||
| caa647dc6b | |||
| 76b9ce0ac1 | |||
| d01d091b47 | |||
| 47ddcb54f1 | |||
| dda0e410ff | |||
| eae05167f8 | |||
| 16f21893a3 | |||
| 4ca724956b | |||
| 217a80ee76 | |||
| 8b166bf5b9 | |||
| 4c614661e7 | |||
| 9392f86333 | |||
| 0d888268a8 |
@@ -1,3 +1,45 @@
|
|||||||
|
## [22.52.0] 6/1/2024
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Cleanup Bucket Comparison Code ([#4374](https://github.com/EQEmu/Server/pull/4374)) @Kinglykrab 2024-06-02
|
||||||
|
* Cleanup Bug Category Code ([#4367](https://github.com/EQEmu/Server/pull/4367)) @Kinglykrab 2024-06-01
|
||||||
|
* Cleanup Deity Code ([#4363](https://github.com/EQEmu/Server/pull/4363)) @Kinglykrab 2024-06-01
|
||||||
|
* Cleanup Special Ability Code ([#4365](https://github.com/EQEmu/Server/pull/4365)) @Kinglykrab 2024-06-01
|
||||||
|
* Remove unused code in common/eq_constants.h ([#4364](https://github.com/EQEmu/Server/pull/4364)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### Combat
|
||||||
|
|
||||||
|
* Adjustments to Crippling Blows/Slay Undead and Confirmed Critical Code ([#4354](https://github.com/EQEmu/Server/pull/4354)) @fryguy503 2024-05-27
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Add protection to ensure adventure points award are only attempted on players ([#4371](https://github.com/EQEmu/Server/pull/4371)) @joligario 2024-05-31
|
||||||
|
* Adjust Kick/RoundKick Damage Lower levels ([#4355](https://github.com/EQEmu/Server/pull/4355)) @fryguy503 2024-05-28
|
||||||
|
* Bazaar Search not working correctly for Iksar, Vashir, Drakkin and Froglok races ([#4379](https://github.com/EQEmu/Server/pull/4379)) @neckkola 2024-06-02
|
||||||
|
* Fix Unescaped String in Client::GotoPlayer ([#4373](https://github.com/EQEmu/Server/pull/4373)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### NPC Spells
|
||||||
|
|
||||||
|
* Fixed an issue where the repository spell adj value was overriding the spell difficulty default value ([#4370](https://github.com/EQEmu/Server/pull/4370)) @regneq 2024-06-01
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add Item Link Methods to Perl/Lua ([#4359](https://github.com/EQEmu/Server/pull/4359)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### Quests
|
||||||
|
|
||||||
|
* Fix Lua encounter double register ([#4369](https://github.com/EQEmu/Server/pull/4369)) @Akkadius 2024-05-31
|
||||||
|
* Fix issue with Lua encounters loading in certain circumstances ([#4378](https://github.com/EQEmu/Server/pull/4378)) @Akkadius 2024-06-01
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Add Skill Base Damage Rules ([#4360](https://github.com/EQEmu/Server/pull/4360)) @Kinglykrab 2024-06-01
|
||||||
|
|
||||||
|
### Skills
|
||||||
|
|
||||||
|
* Fix caps out of bounds issue ([#4377](https://github.com/EQEmu/Server/pull/4377)) @Akkadius 2024-06-01
|
||||||
|
|
||||||
## [22.51.1] 5/27/2024
|
## [22.51.1] 5/27/2024
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "../../common/repositories/skill_caps_repository.h"
|
#include "../../common/repositories/skill_caps_repository.h"
|
||||||
#include "../../common/file.h"
|
#include "../../common/file.h"
|
||||||
#include "../../common/events/player_event_logs.h"
|
#include "../../common/events/player_event_logs.h"
|
||||||
|
#include "../../common/skill_caps.h"
|
||||||
|
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
WorldContentService content_service;
|
WorldContentService content_service;
|
||||||
@@ -213,17 +214,16 @@ void ExportSkillCaps(SharedDatabase* db)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8 skill_cap_max_level = (
|
|
||||||
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
|
||||||
RuleI(Character, SkillCapMaxLevel) :
|
|
||||||
RuleI(Character, MaxLevel)
|
|
||||||
);
|
|
||||||
|
|
||||||
for (uint8 class_id = Class::Warrior; class_id <= Class::Berserker; class_id++) {
|
for (uint8 class_id = Class::Warrior; class_id <= Class::Berserker; class_id++) {
|
||||||
for (uint8 skill_id = EQ::skills::Skill1HBlunt; skill_id <= EQ::skills::Skill2HPiercing; skill_id++) {
|
for (uint8 skill_id = EQ::skills::Skill1HBlunt; skill_id <= EQ::skills::Skill2HPiercing; skill_id++) {
|
||||||
if (SkillUsable(db, skill_id, class_id)) {
|
if (SkillUsable(db, skill_id, class_id)) {
|
||||||
uint32 previous_cap = 0;
|
uint32 previous_cap = 0;
|
||||||
for (uint8 level = 1; level <= skill_cap_max_level; level++) {
|
|
||||||
|
for (
|
||||||
|
uint8 level = 1;
|
||||||
|
level <= SkillCaps::GetSkillCapMaxLevel(class_id, static_cast<EQ::skills::SkillType>(skill_id));
|
||||||
|
level++
|
||||||
|
) {
|
||||||
uint32 cap = GetSkill(db, skill_id, class_id, level);
|
uint32 cap = GetSkill(db, skill_id, class_id, level);
|
||||||
if (cap < previous_cap) {
|
if (cap < previous_cap) {
|
||||||
cap = previous_cap;
|
cap = previous_cap;
|
||||||
|
|||||||
+1
-1
@@ -314,7 +314,7 @@ Bazaar::GetSearchResults(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.should_check = search.race != 0xFFFFFFFF,
|
.should_check = search.race != 0xFFFFFFFF,
|
||||||
.condition = static_cast<bool>(item->Races & GetPlayerRaceBit(search.race))
|
.condition = static_cast<bool>(item->Races & GetPlayerRaceBit(GetRaceIDFromPlayerRaceValue(search.race)))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.should_check = search.augment != 0,
|
.should_check = search.augment != 0,
|
||||||
|
|||||||
+6
-70
@@ -19,81 +19,17 @@
|
|||||||
|
|
||||||
#include "deity.h"
|
#include "deity.h"
|
||||||
|
|
||||||
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
|
uint32 Deity::GetBitmask(uint32 deity_id)
|
||||||
{
|
{
|
||||||
switch (deity_type) {
|
return IsValid(deity_id) ? deity_bitmasks[deity_id] : Deity::Bitmask::All;
|
||||||
case DeityBertoxxulous:
|
|
||||||
return bit_DeityBertoxxulous;
|
|
||||||
case DeityBrellSirilis:
|
|
||||||
return bit_DeityBrellSirilis;
|
|
||||||
case DeityCazicThule:
|
|
||||||
return bit_DeityCazicThule;
|
|
||||||
case DeityErollisiMarr:
|
|
||||||
return bit_DeityErollisiMarr;
|
|
||||||
case DeityBristlebane:
|
|
||||||
return bit_DeityBristlebane;
|
|
||||||
case DeityInnoruuk:
|
|
||||||
return bit_DeityInnoruuk;
|
|
||||||
case DeityKarana:
|
|
||||||
return bit_DeityKarana;
|
|
||||||
case DeityMithanielMarr:
|
|
||||||
return bit_DeityMithanielMarr;
|
|
||||||
case DeityPrexus:
|
|
||||||
return bit_DeityPrexus;
|
|
||||||
case DeityQuellious:
|
|
||||||
return bit_DeityQuellious;
|
|
||||||
case DeityRallosZek:
|
|
||||||
return bit_DeityRallosZek;
|
|
||||||
case DeityRodcetNife:
|
|
||||||
return bit_DeityRodcetNife;
|
|
||||||
case DeitySolusekRo:
|
|
||||||
return bit_DeitySolusekRo;
|
|
||||||
case DeityTheTribunal:
|
|
||||||
return bit_DeityTheTribunal;
|
|
||||||
case DeityTunare:
|
|
||||||
return bit_DeityTunare;
|
|
||||||
case DeityVeeshan:
|
|
||||||
return bit_DeityVeeshan;
|
|
||||||
case DeityAgnostic_LB:
|
|
||||||
case DeityAgnostic:
|
|
||||||
return bit_DeityAgnostic;
|
|
||||||
default:
|
|
||||||
return bit_DeityAll;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<EQ::deity::DeityType, std::string>& EQ::deity::GetDeityMap()
|
std::string Deity::GetName(uint32 deity_id)
|
||||||
{
|
{
|
||||||
static const std::map<EQ::deity::DeityType, std::string> deity_map = {
|
return IsValid(deity_id) ? deity_names[deity_id] : "UNKNOWN DEITY";
|
||||||
{ DeityAgnostic, "Agnostic" },
|
|
||||||
{ DeityAgnostic_LB, "Agnostic" },
|
|
||||||
{ DeityBertoxxulous, "Bertoxxulous" },
|
|
||||||
{ DeityBrellSirilis, "Brell Serilis" },
|
|
||||||
{ DeityBristlebane, "Bristlebane" },
|
|
||||||
{ DeityCazicThule, "Cazic-Thule" },
|
|
||||||
{ DeityErollisiMarr, "Erollisi Marr" },
|
|
||||||
{ DeityInnoruuk, "Innoruuk" },
|
|
||||||
{ DeityKarana, "Karana" },
|
|
||||||
{ DeityMithanielMarr, "Mithaniel Marr" },
|
|
||||||
{ DeityPrexus, "Prexus" },
|
|
||||||
{ DeityQuellious, "Quellious" },
|
|
||||||
{ DeityRallosZek, "Rallos Zek" },
|
|
||||||
{ DeityRodcetNife, "Rodcet Nife" },
|
|
||||||
{ DeitySolusekRo, "Solusek Ro" },
|
|
||||||
{ DeityTheTribunal, "The Tribunal" },
|
|
||||||
{ DeityTunare, "Tunare" },
|
|
||||||
{ DeityVeeshan, "Veeshan" }
|
|
||||||
};
|
|
||||||
|
|
||||||
return deity_map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EQ::deity::GetDeityName(DeityType deity_type)
|
bool Deity::IsValid(uint32 deity_id)
|
||||||
{
|
{
|
||||||
|
return deity_names.find(deity_id) != deity_names.end();
|
||||||
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) {
|
|
||||||
return EQ::deity::GetDeityMap().find(deity_type)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
}
|
||||||
|
|||||||
+85
-52
@@ -23,62 +23,95 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace Deity {
|
||||||
|
constexpr uint32 Unknown = 0;
|
||||||
|
constexpr uint32 Agnostic1 = 140;
|
||||||
|
constexpr uint32 Bertoxxulous = 201;
|
||||||
|
constexpr uint32 BrellSirilis = 202;
|
||||||
|
constexpr uint32 CazicThule = 203;
|
||||||
|
constexpr uint32 ErollisiMarr = 204;
|
||||||
|
constexpr uint32 Bristlebane = 205;
|
||||||
|
constexpr uint32 Innoruuk = 206;
|
||||||
|
constexpr uint32 Karana = 207;
|
||||||
|
constexpr uint32 MithanielMarr = 208;
|
||||||
|
constexpr uint32 Prexus = 209;
|
||||||
|
constexpr uint32 Quellious = 210;
|
||||||
|
constexpr uint32 RallosZek = 211;
|
||||||
|
constexpr uint32 RodcetNife = 212;
|
||||||
|
constexpr uint32 SolusekRo = 213;
|
||||||
|
constexpr uint32 TheTribunal = 214;
|
||||||
|
constexpr uint32 Tunare = 215;
|
||||||
|
constexpr uint32 Veeshan = 216;
|
||||||
|
constexpr uint32 Agnostic2 = 396;
|
||||||
|
|
||||||
namespace EQ
|
namespace Bitmask {
|
||||||
{
|
constexpr uint32 Agnostic = 1;
|
||||||
namespace deity {
|
constexpr uint32 Bertoxxulous = 2;
|
||||||
enum DeityType {
|
constexpr uint32 BrellSirilis = 4;
|
||||||
DeityUnknown = 0,
|
constexpr uint32 CazicThule = 8;
|
||||||
DeityAgnostic_LB = 140,
|
constexpr uint32 ErollisiMarr = 16;
|
||||||
DeityBertoxxulous = 201,
|
constexpr uint32 Bristlebane = 32;
|
||||||
DeityBrellSirilis,
|
constexpr uint32 Innoruuk = 64;
|
||||||
DeityCazicThule,
|
constexpr uint32 Karana = 128;
|
||||||
DeityErollisiMarr,
|
constexpr uint32 MithanielMarr = 256;
|
||||||
DeityBristlebane,
|
constexpr uint32 Prexus = 512;
|
||||||
DeityInnoruuk,
|
constexpr uint32 Quellious = 1024;
|
||||||
DeityKarana,
|
constexpr uint32 RallosZek = 2048;
|
||||||
DeityMithanielMarr,
|
constexpr uint32 RodcetNife = 4096;
|
||||||
DeityPrexus,
|
constexpr uint32 SolusekRo = 8192;
|
||||||
DeityQuellious,
|
constexpr uint32 TheTribunal = 16384;
|
||||||
DeityRallosZek,
|
constexpr uint32 Tunare = 32768;
|
||||||
DeityRodcetNife,
|
constexpr uint32 Veeshan = 65536;
|
||||||
DeitySolusekRo,
|
constexpr uint32 All = std::numeric_limits<uint32>::max();
|
||||||
DeityTheTribunal,
|
}
|
||||||
DeityTunare,
|
|
||||||
DeityVeeshan,
|
|
||||||
DeityAgnostic = 396
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DeityTypeBit : uint32 {
|
uint32 GetBitmask(uint32 deity_id);
|
||||||
bit_DeityAgnostic = 0x00000001,
|
std::string GetName(uint32 deity_id);
|
||||||
bit_DeityBertoxxulous = 0x00000002,
|
bool IsValid(uint32 deity_id);
|
||||||
bit_DeityBrellSirilis = 0x00000004,
|
}
|
||||||
bit_DeityCazicThule = 0x00000008,
|
|
||||||
bit_DeityErollisiMarr = 0x00000010,
|
|
||||||
bit_DeityBristlebane = 0x00000020,
|
|
||||||
bit_DeityInnoruuk = 0x00000040,
|
|
||||||
bit_DeityKarana = 0x00000080,
|
|
||||||
bit_DeityMithanielMarr = 0x00000100,
|
|
||||||
bit_DeityPrexus = 0x00000200,
|
|
||||||
bit_DeityQuellious = 0x00000400,
|
|
||||||
bit_DeityRallosZek = 0x00000800,
|
|
||||||
bit_DeityRodcetNife = 0x00001000,
|
|
||||||
bit_DeitySolusekRo = 0x00002000,
|
|
||||||
bit_DeityTheTribunal = 0x00004000,
|
|
||||||
bit_DeityTunare = 0x00008000,
|
|
||||||
bit_DeityVeeshan = 0x00010000,
|
|
||||||
bit_DeityAll = UINT32_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr int format_as(DeityType type) { return static_cast<int>(type); }
|
static std::map<uint32, std::string> deity_names = {
|
||||||
|
{ Deity::Agnostic1, "Agnostic" },
|
||||||
|
{ Deity::Agnostic2, "Agnostic" },
|
||||||
|
{ Deity::Bertoxxulous, "Bertoxxulous" },
|
||||||
|
{ Deity::BrellSirilis, "Brell Serilis" },
|
||||||
|
{ Deity::Bristlebane, "Bristlebane" },
|
||||||
|
{ Deity::CazicThule, "Cazic-Thule" },
|
||||||
|
{ Deity::ErollisiMarr, "Erollisi Marr" },
|
||||||
|
{ Deity::Innoruuk, "Innoruuk" },
|
||||||
|
{ Deity::Karana, "Karana" },
|
||||||
|
{ Deity::MithanielMarr, "Mithaniel Marr" },
|
||||||
|
{ Deity::Prexus, "Prexus" },
|
||||||
|
{ Deity::Quellious, "Quellious" },
|
||||||
|
{ Deity::RallosZek, "Rallos Zek" },
|
||||||
|
{ Deity::RodcetNife, "Rodcet Nife" },
|
||||||
|
{ Deity::SolusekRo, "Solusek Ro" },
|
||||||
|
{ Deity::TheTribunal, "The Tribunal" },
|
||||||
|
{ Deity::Tunare, "Tunare" },
|
||||||
|
{ Deity::Veeshan, "Veeshan" }
|
||||||
|
};
|
||||||
|
|
||||||
extern DeityTypeBit GetDeityBitmask(DeityType deity_type);
|
static std::map<uint32, uint32> deity_bitmasks = {
|
||||||
extern std::string GetDeityName(DeityType deity_type);
|
{ Deity::Agnostic1, Deity::Bitmask::Agnostic },
|
||||||
extern const std::map<DeityType, std::string>& GetDeityMap();
|
{ Deity::Agnostic2, Deity::Bitmask::Agnostic },
|
||||||
|
{ Deity::Bertoxxulous, Deity::Bitmask::Bertoxxulous },
|
||||||
} /*deity*/
|
{ Deity::BrellSirilis, Deity::Bitmask::BrellSirilis },
|
||||||
|
{ Deity::CazicThule, Deity::Bitmask::CazicThule },
|
||||||
} /*EQEmu*/
|
{ Deity::ErollisiMarr, Deity::Bitmask::ErollisiMarr },
|
||||||
|
{ Deity::Bristlebane, Deity::Bitmask::Bristlebane },
|
||||||
|
{ Deity::Innoruuk, Deity::Bitmask::Innoruuk },
|
||||||
|
{ Deity::Karana, Deity::Bitmask::Karana },
|
||||||
|
{ Deity::MithanielMarr, Deity::Bitmask::MithanielMarr },
|
||||||
|
{ Deity::Prexus, Deity::Bitmask::Prexus },
|
||||||
|
{ Deity::Quellious, Deity::Bitmask::Quellious },
|
||||||
|
{ Deity::RallosZek, Deity::Bitmask::RallosZek },
|
||||||
|
{ Deity::RodcetNife, Deity::Bitmask::RodcetNife },
|
||||||
|
{ Deity::SolusekRo, Deity::Bitmask::SolusekRo },
|
||||||
|
{ Deity::TheTribunal, Deity::Bitmask::TheTribunal },
|
||||||
|
{ Deity::Tunare, Deity::Bitmask::Tunare },
|
||||||
|
{ Deity::Veeshan, Deity::Bitmask::Veeshan }
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* COMMON_DEITY_H */
|
#endif /* COMMON_DEITY_H */
|
||||||
|
|||||||
+29
-127
@@ -59,68 +59,25 @@ int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
|
|||||||
return local_array[inv_type];
|
return local_array[inv_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* EQ::bug::CategoryIDToCategoryName(CategoryID category_id) {
|
uint32 Bug::GetID(const std::string& category_name)
|
||||||
switch (category_id) {
|
{
|
||||||
case catVideo:
|
for (const auto& e : bug_category_names) {
|
||||||
return "Video";
|
if (e.second == category_name) {
|
||||||
case catAudio:
|
return e.first;
|
||||||
return "Audio";
|
}
|
||||||
case catPathing:
|
|
||||||
return "Pathing";
|
|
||||||
case catQuest:
|
|
||||||
return "Quest";
|
|
||||||
case catTradeskills:
|
|
||||||
return "Tradeskills";
|
|
||||||
case catSpellStacking:
|
|
||||||
return "Spell stacking";
|
|
||||||
case catDoorsPortals:
|
|
||||||
return "Doors/Portals";
|
|
||||||
case catItems:
|
|
||||||
return "Items";
|
|
||||||
case catNPC:
|
|
||||||
return "NPC";
|
|
||||||
case catDialogs:
|
|
||||||
return "Dialogs";
|
|
||||||
case catLoNTCG:
|
|
||||||
return "LoN - TCG";
|
|
||||||
case catMercenaries:
|
|
||||||
return "Mercenaries";
|
|
||||||
case catOther:
|
|
||||||
default:
|
|
||||||
return "Other";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Bug::Category::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQ::bug::CategoryID EQ::bug::CategoryNameToCategoryID(const char* category_name) {
|
std::string Bug::GetName(uint32 category_id)
|
||||||
if (!category_name)
|
{
|
||||||
return catOther;
|
return IsValid(category_id) ? bug_category_names[category_id] : "UNKNOWN BUG CATEGORY";
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(category_name, "Video"))
|
bool Bug::IsValid(uint32 category_id)
|
||||||
return catVideo;
|
{
|
||||||
if (!strcmp(category_name, "Audio"))
|
return bug_category_names.find(category_id) != bug_category_names.end();
|
||||||
return catAudio;
|
|
||||||
if (!strcmp(category_name, "Pathing"))
|
|
||||||
return catPathing;
|
|
||||||
if (!strcmp(category_name, "Quest"))
|
|
||||||
return catQuest;
|
|
||||||
if (!strcmp(category_name, "Tradeskills"))
|
|
||||||
return catTradeskills;
|
|
||||||
if (!strcmp(category_name, "Spell stacking"))
|
|
||||||
return catSpellStacking;
|
|
||||||
if (!strcmp(category_name, "Doors/Portals"))
|
|
||||||
return catDoorsPortals;
|
|
||||||
if (!strcmp(category_name, "Items"))
|
|
||||||
return catItems;
|
|
||||||
if (!strcmp(category_name, "NPC"))
|
|
||||||
return catNPC;
|
|
||||||
if (!strcmp(category_name, "Dialogs"))
|
|
||||||
return catDialogs;
|
|
||||||
if (!strcmp(category_name, "LoN - TCG"))
|
|
||||||
return catLoNTCG;
|
|
||||||
if (!strcmp(category_name, "Mercenaries"))
|
|
||||||
return catMercenaries;
|
|
||||||
|
|
||||||
return catOther;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *EQ::constants::GetStanceName(StanceType stance_type) {
|
const char *EQ::constants::GetStanceName(StanceType stance_type) {
|
||||||
@@ -640,79 +597,14 @@ std::string EQ::constants::GetAppearanceTypeName(uint32 appearance_type)
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint32, std::string>& EQ::constants::GetSpecialAbilityMap()
|
std::string SpecialAbility::GetName(int ability_id)
|
||||||
{
|
{
|
||||||
static const std::map<uint32, std::string> special_ability_map = {
|
return IsValid(ability_id) ? special_ability_names[ability_id] : "UNKNOWN SPECIAL ABILITY";
|
||||||
{ SPECATK_SUMMON, "Summon" },
|
|
||||||
{ SPECATK_ENRAGE, "Enrage" },
|
|
||||||
{ SPECATK_RAMPAGE, "Rampage" },
|
|
||||||
{ SPECATK_AREA_RAMPAGE, "Area Rampage" },
|
|
||||||
{ SPECATK_FLURRY, "Flurry" },
|
|
||||||
{ SPECATK_TRIPLE, "Triple Attack" },
|
|
||||||
{ SPECATK_QUAD, "Quadruple Attack" },
|
|
||||||
{ SPECATK_INNATE_DW, "Dual Wield" },
|
|
||||||
{ SPECATK_BANE, "Bane Attack" },
|
|
||||||
{ SPECATK_MAGICAL, "Magical Attack" },
|
|
||||||
{ SPECATK_RANGED_ATK, "Ranged Attack" },
|
|
||||||
{ UNSLOWABLE, "Immune to Slow" },
|
|
||||||
{ UNMEZABLE, "Immune to Mesmerize" },
|
|
||||||
{ UNCHARMABLE, "Immune to Charm" },
|
|
||||||
{ UNSTUNABLE, "Immune to Stun" },
|
|
||||||
{ UNSNAREABLE, "Immune to Snare" },
|
|
||||||
{ UNFEARABLE, "Immune to Fear" },
|
|
||||||
{ UNDISPELLABLE, "Immune to Dispell" },
|
|
||||||
{ IMMUNE_MELEE, "Immune to Melee" },
|
|
||||||
{ IMMUNE_MAGIC, "Immune to Magic" },
|
|
||||||
{ IMMUNE_FLEEING, "Immune to Fleeing" },
|
|
||||||
{ IMMUNE_MELEE_EXCEPT_BANE, "Immune to Melee except Bane" },
|
|
||||||
{ IMMUNE_MELEE_NONMAGICAL, "Immune to Non-Magical Melee" },
|
|
||||||
{ IMMUNE_AGGRO, "Immune to Aggro" },
|
|
||||||
{ IMMUNE_AGGRO_ON, "Immune to Being Aggro" },
|
|
||||||
{ IMMUNE_CASTING_FROM_RANGE, "Immune to Ranged Spells" },
|
|
||||||
{ IMMUNE_FEIGN_DEATH, "Immune to Feign Death" },
|
|
||||||
{ IMMUNE_TAUNT, "Immune to Taunt" },
|
|
||||||
{ NPC_TUNNELVISION, "Tunnel Vision" },
|
|
||||||
{ NPC_NO_BUFFHEAL_FRIENDS, "Does Not Heal of Buff Allies" },
|
|
||||||
{ IMMUNE_PACIFY, "Immune to Pacify" },
|
|
||||||
{ LEASH, "Leashed" },
|
|
||||||
{ TETHER, "Tethered" },
|
|
||||||
{ DESTRUCTIBLE_OBJECT, "Destructible Object" },
|
|
||||||
{ NO_HARM_FROM_CLIENT, "Immune to Harm from Client" },
|
|
||||||
{ ALWAYS_FLEE, "Always Flees" },
|
|
||||||
{ FLEE_PERCENT, "Flee Percentage" },
|
|
||||||
{ ALLOW_BENEFICIAL, "Allows Beneficial Spells" },
|
|
||||||
{ DISABLE_MELEE, "Melee is Disabled" },
|
|
||||||
{ NPC_CHASE_DISTANCE, "Chase Distance" },
|
|
||||||
{ ALLOW_TO_TANK, "Allowed to Tank" },
|
|
||||||
{ IGNORE_ROOT_AGGRO_RULES, "Ignores Root Aggro" },
|
|
||||||
{ CASTING_RESIST_DIFF, "Casting Resist Difficulty" },
|
|
||||||
{ COUNTER_AVOID_DAMAGE, "Counter Damage Avoidance" },
|
|
||||||
{ PROX_AGGRO, "Proximity Aggro" },
|
|
||||||
{ IMMUNE_RANGED_ATTACKS, "Immune to Ranged Attacks" },
|
|
||||||
{ IMMUNE_DAMAGE_CLIENT, "Immune to Client Damage" },
|
|
||||||
{ IMMUNE_DAMAGE_NPC, "Immune to NPC Damage" },
|
|
||||||
{ IMMUNE_AGGRO_CLIENT, "Immune to Client Aggro" },
|
|
||||||
{ IMMUNE_AGGRO_NPC, "Immune to NPC Aggro" },
|
|
||||||
{ MODIFY_AVOID_DAMAGE, "Modify Damage Avoidance" },
|
|
||||||
{ IMMUNE_FADING_MEMORIES, "Immune to Memory Fades" },
|
|
||||||
{ 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EQ::constants::GetSpecialAbilityName(uint32 ability_id)
|
bool SpecialAbility::IsValid(int ability_id)
|
||||||
{
|
{
|
||||||
const auto& a = EQ::constants::GetSpecialAbilityMap().find(ability_id);
|
return special_ability_names.find(ability_id) != special_ability_names.end();
|
||||||
if (a != EQ::constants::GetSpecialAbilityMap().end()) {
|
|
||||||
return a->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint32, std::string>& EQ::constants::GetConsiderColorMap()
|
const std::map<uint32, std::string>& EQ::constants::GetConsiderColorMap()
|
||||||
@@ -736,3 +628,13 @@ std::string EQ::constants::GetConsiderColorName(uint32 consider_color)
|
|||||||
const auto& c = EQ::constants::GetConsiderColorMap().find(consider_color);
|
const auto& c = EQ::constants::GetConsiderColorMap().find(consider_color);
|
||||||
return c != EQ::constants::GetConsiderColorMap().end() ? c->second : std::string();
|
return c != EQ::constants::GetConsiderColorMap().end() ? c->second : std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ComparisonType::GetName(uint8 type)
|
||||||
|
{
|
||||||
|
return IsValid(type) ? comparison_types[type] : "UNKNOWN COMPARISON TYPE";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComparisonType::IsValid(uint8 type)
|
||||||
|
{
|
||||||
|
return comparison_types.find(type) != comparison_types.end();
|
||||||
|
}
|
||||||
|
|||||||
+200
-107
@@ -26,6 +26,35 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace ComparisonType {
|
||||||
|
constexpr uint8 Equal = 0;
|
||||||
|
constexpr uint8 NotEqual = 1;
|
||||||
|
constexpr uint8 GreaterOrEqual = 2;
|
||||||
|
constexpr uint8 LesserOrEqual = 3;
|
||||||
|
constexpr uint8 Greater = 4;
|
||||||
|
constexpr uint8 Lesser = 5;
|
||||||
|
constexpr uint8 Any = 6;
|
||||||
|
constexpr uint8 NotAny = 7;
|
||||||
|
constexpr uint8 Between = 8;
|
||||||
|
constexpr uint8 NotBetween = 9;
|
||||||
|
|
||||||
|
std::string GetName(uint8 type);
|
||||||
|
bool IsValid(uint8 type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<uint8, std::string> comparison_types = {
|
||||||
|
{ ComparisonType::Equal, "Equal" },
|
||||||
|
{ ComparisonType::NotEqual, "Not Equal" },
|
||||||
|
{ ComparisonType::GreaterOrEqual, "Greater or Equal" },
|
||||||
|
{ ComparisonType::LesserOrEqual, "Lesser or Equal" },
|
||||||
|
{ ComparisonType::Greater, "Greater" },
|
||||||
|
{ ComparisonType::Lesser, "Lesser" },
|
||||||
|
{ ComparisonType::Any, "Any" },
|
||||||
|
{ ComparisonType::NotAny, "Not Any" },
|
||||||
|
{ ComparisonType::Between, "Between" },
|
||||||
|
{ ComparisonType::NotBetween, "Not Between" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// local definitions are the result of using hybrid-client or server-only values and methods
|
// local definitions are the result of using hybrid-client or server-only values and methods
|
||||||
namespace EQ
|
namespace EQ
|
||||||
@@ -401,9 +430,6 @@ namespace EQ
|
|||||||
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
|
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
|
||||||
std::string GetAppearanceTypeName(uint32 animation_type);
|
std::string GetAppearanceTypeName(uint32 animation_type);
|
||||||
|
|
||||||
extern const std::map<uint32, std::string>& GetSpecialAbilityMap();
|
|
||||||
std::string GetSpecialAbilityName(uint32 ability_id);
|
|
||||||
|
|
||||||
extern const std::map<uint32, std::string>& GetConsiderColorMap();
|
extern const std::map<uint32, std::string>& GetConsiderColorMap();
|
||||||
std::string GetConsiderColorName(uint32 consider_color);
|
std::string GetConsiderColorName(uint32 consider_color);
|
||||||
|
|
||||||
@@ -464,37 +490,6 @@ namespace EQ
|
|||||||
|
|
||||||
} // namespace spells
|
} // namespace spells
|
||||||
|
|
||||||
namespace bug {
|
|
||||||
enum CategoryID : uint32 {
|
|
||||||
catOther = 0,
|
|
||||||
catVideo,
|
|
||||||
catAudio,
|
|
||||||
catPathing,
|
|
||||||
catQuest,
|
|
||||||
catTradeskills,
|
|
||||||
catSpellStacking,
|
|
||||||
catDoorsPortals,
|
|
||||||
catItems,
|
|
||||||
catNPC,
|
|
||||||
catDialogs,
|
|
||||||
catLoNTCG,
|
|
||||||
catMercenaries
|
|
||||||
};
|
|
||||||
|
|
||||||
enum OptionalInfoFlag : uint32 {
|
|
||||||
infoNoOptionalInfo = 0x0,
|
|
||||||
infoCanDuplicate = 0x1,
|
|
||||||
infoCrashBug = 0x2,
|
|
||||||
infoTargetInfo = 0x4,
|
|
||||||
infoCharacterFlags = 0x8,
|
|
||||||
infoUnknownValue = 0xFFFFFFF0
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* CategoryIDToCategoryName(CategoryID category_id);
|
|
||||||
CategoryID CategoryNameToCategoryID(const char* category_name);
|
|
||||||
|
|
||||||
} // namespace bug
|
|
||||||
|
|
||||||
enum WaypointStatus : int {
|
enum WaypointStatus : int {
|
||||||
RoamBoxPauseInProgress = -3,
|
RoamBoxPauseInProgress = -3,
|
||||||
QuestControlNoGrid = -2,
|
QuestControlNoGrid = -2,
|
||||||
@@ -588,19 +583,6 @@ enum ReloadWorld : uint8 {
|
|||||||
ForceRepop
|
ForceRepop
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BucketComparison : uint8 {
|
|
||||||
BucketEqualTo = 0,
|
|
||||||
BucketNotEqualTo,
|
|
||||||
BucketGreaterThanOrEqualTo,
|
|
||||||
BucketLesserThanOrEqualTo,
|
|
||||||
BucketGreaterThan,
|
|
||||||
BucketLesserThan,
|
|
||||||
BucketIsAny,
|
|
||||||
BucketIsNotAny,
|
|
||||||
BucketIsBetween,
|
|
||||||
BucketIsNotBetween
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class EntityFilterType {
|
enum class EntityFilterType {
|
||||||
All,
|
All,
|
||||||
Bots,
|
Bots,
|
||||||
@@ -614,67 +596,131 @@ enum class ApplySpellType {
|
|||||||
Raid
|
Raid
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
namespace SpecialAbility {
|
||||||
SPECATK_SUMMON = 1,
|
constexpr int Summon = 1;
|
||||||
SPECATK_ENRAGE = 2,
|
constexpr int Enrage = 2;
|
||||||
SPECATK_RAMPAGE = 3,
|
constexpr int Rampage = 3;
|
||||||
SPECATK_AREA_RAMPAGE = 4,
|
constexpr int AreaRampage = 4;
|
||||||
SPECATK_FLURRY = 5,
|
constexpr int Flurry = 5;
|
||||||
SPECATK_TRIPLE = 6,
|
constexpr int TripleAttack = 6;
|
||||||
SPECATK_QUAD = 7,
|
constexpr int QuadrupleAttack = 7;
|
||||||
SPECATK_INNATE_DW = 8,
|
constexpr int DualWield = 8;
|
||||||
SPECATK_BANE = 9,
|
constexpr int BaneAttack = 9;
|
||||||
SPECATK_MAGICAL = 10,
|
constexpr int MagicalAttack = 10;
|
||||||
SPECATK_RANGED_ATK = 11,
|
constexpr int RangedAttack = 11;
|
||||||
UNSLOWABLE = 12,
|
constexpr int SlowImmunity = 12;
|
||||||
UNMEZABLE = 13,
|
constexpr int MesmerizeImmunity = 13;
|
||||||
UNCHARMABLE = 14,
|
constexpr int CharmImmunity = 14;
|
||||||
UNSTUNABLE = 15,
|
constexpr int StunImmunity = 15;
|
||||||
UNSNAREABLE = 16,
|
constexpr int SnareImmunity = 16;
|
||||||
UNFEARABLE = 17,
|
constexpr int FearImmunity = 17;
|
||||||
UNDISPELLABLE = 18,
|
constexpr int DispellImmunity = 18;
|
||||||
IMMUNE_MELEE = 19,
|
constexpr int MeleeImmunity = 19;
|
||||||
IMMUNE_MAGIC = 20,
|
constexpr int MagicImmunity = 20;
|
||||||
IMMUNE_FLEEING = 21,
|
constexpr int FleeingImmunity = 21;
|
||||||
IMMUNE_MELEE_EXCEPT_BANE = 22,
|
constexpr int MeleeImmunityExceptBane = 22;
|
||||||
IMMUNE_MELEE_NONMAGICAL = 23,
|
constexpr int MeleeImmunityExceptMagical = 23;
|
||||||
IMMUNE_AGGRO = 24,
|
constexpr int AggroImmunity = 24;
|
||||||
IMMUNE_AGGRO_ON = 25,
|
constexpr int BeingAggroImmunity = 25;
|
||||||
IMMUNE_CASTING_FROM_RANGE = 26,
|
constexpr int CastingFromRangeImmunity = 26;
|
||||||
IMMUNE_FEIGN_DEATH = 27,
|
constexpr int FeignDeathImmunity = 27;
|
||||||
IMMUNE_TAUNT = 28,
|
constexpr int TauntImmunity = 28;
|
||||||
NPC_TUNNELVISION = 29,
|
constexpr int TunnelVision = 29;
|
||||||
NPC_NO_BUFFHEAL_FRIENDS = 30,
|
constexpr int NoBuffHealFriends = 30;
|
||||||
IMMUNE_PACIFY = 31,
|
constexpr int PacifyImmunity = 31;
|
||||||
LEASH = 32,
|
constexpr int Leash = 32;
|
||||||
TETHER = 33,
|
constexpr int Tether = 33;
|
||||||
DESTRUCTIBLE_OBJECT = 34,
|
constexpr int DestructibleObject = 34;
|
||||||
NO_HARM_FROM_CLIENT = 35,
|
constexpr int HarmFromClientImmunity = 35;
|
||||||
ALWAYS_FLEE = 36,
|
constexpr int AlwaysFlee = 36;
|
||||||
FLEE_PERCENT = 37,
|
constexpr int FleePercent = 37;
|
||||||
ALLOW_BENEFICIAL = 38,
|
constexpr int AllowBeneficial = 38;
|
||||||
DISABLE_MELEE = 39,
|
constexpr int DisableMelee = 39;
|
||||||
NPC_CHASE_DISTANCE = 40,
|
constexpr int NPCChaseDistance = 40;
|
||||||
ALLOW_TO_TANK = 41,
|
constexpr int AllowedToTank = 41;
|
||||||
IGNORE_ROOT_AGGRO_RULES = 42,
|
constexpr int IgnoreRootAggroRules = 42;
|
||||||
CASTING_RESIST_DIFF = 43,
|
constexpr int CastingResistDifficulty = 43;
|
||||||
COUNTER_AVOID_DAMAGE = 44, // Modify by percent NPC's opponents chance to riposte, block, parry or dodge individually, or for all skills
|
constexpr int CounterAvoidDamage = 44;
|
||||||
PROX_AGGRO = 45,
|
constexpr int ProximityAggro = 45;
|
||||||
IMMUNE_RANGED_ATTACKS = 46,
|
constexpr int RangedAttackImmunity = 46;
|
||||||
IMMUNE_DAMAGE_CLIENT = 47,
|
constexpr int ClientDamageImmunity = 47;
|
||||||
IMMUNE_DAMAGE_NPC = 48,
|
constexpr int NPCDamageImmunity = 48;
|
||||||
IMMUNE_AGGRO_CLIENT = 49,
|
constexpr int ClientAggroImmunity = 49;
|
||||||
IMMUNE_AGGRO_NPC = 50,
|
constexpr int NPCAggroImmunity = 50;
|
||||||
MODIFY_AVOID_DAMAGE = 51, // Modify by percent the NPCs chance to riposte, block, parry or dodge individually, or for all skills
|
constexpr int ModifyAvoidDamage = 51;
|
||||||
IMMUNE_FADING_MEMORIES = 52,
|
constexpr int MemoryFadeImmunity = 52;
|
||||||
IMMUNE_OPEN = 53,
|
constexpr int OpenImmunity = 53;
|
||||||
IMMUNE_ASSASSINATE = 54,
|
constexpr int AssassinateImmunity = 54;
|
||||||
IMMUNE_HEADSHOT = 55,
|
constexpr int HeadshotImmunity = 55;
|
||||||
IMMUNE_AGGRO_BOT = 56,
|
constexpr int BotAggroImmunity = 56;
|
||||||
IMMUNE_DAMAGE_BOT = 57,
|
constexpr int BotDamageImmunity = 57;
|
||||||
MAX_SPECIAL_ATTACK = 58
|
constexpr int Max = 58;
|
||||||
};
|
|
||||||
|
|
||||||
|
constexpr int MaxParameters = 9;
|
||||||
|
|
||||||
|
std::string GetName(int ability_id);
|
||||||
|
bool IsValid(int ability_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<int, std::string> special_ability_names = {
|
||||||
|
{ SpecialAbility::Summon, "Summon" },
|
||||||
|
{ SpecialAbility::Enrage, "Enrage" },
|
||||||
|
{ SpecialAbility::Rampage, "Rampage" },
|
||||||
|
{ SpecialAbility::AreaRampage, "Area Rampage" },
|
||||||
|
{ SpecialAbility::Flurry, "Flurry" },
|
||||||
|
{ SpecialAbility::TripleAttack, "Triple Attack" },
|
||||||
|
{ SpecialAbility::QuadrupleAttack, "Quadruple Attack" },
|
||||||
|
{ SpecialAbility::DualWield, "Dual Wield" },
|
||||||
|
{ SpecialAbility::BaneAttack, "Bane Attack" },
|
||||||
|
{ SpecialAbility::MagicalAttack, "Magical Attack" },
|
||||||
|
{ SpecialAbility::RangedAttack, "Ranged Attack" },
|
||||||
|
{ SpecialAbility::SlowImmunity, "Immune to Slow" },
|
||||||
|
{ SpecialAbility::MesmerizeImmunity, "Immune to Mesmerize" },
|
||||||
|
{ SpecialAbility::CharmImmunity, "Immune to Charm" },
|
||||||
|
{ SpecialAbility::StunImmunity, "Immune to Stun" },
|
||||||
|
{ SpecialAbility::SnareImmunity, "Immune to Snare" },
|
||||||
|
{ SpecialAbility::FearImmunity, "Immune to Fear" },
|
||||||
|
{ SpecialAbility::DispellImmunity, "Immune to Dispell" },
|
||||||
|
{ SpecialAbility::MeleeImmunity, "Immune to Melee" },
|
||||||
|
{ SpecialAbility::MagicImmunity, "Immune to Magic" },
|
||||||
|
{ SpecialAbility::FleeingImmunity, "Immune to Fleeing" },
|
||||||
|
{ SpecialAbility::MeleeImmunityExceptBane, "Immune to Melee except Bane" },
|
||||||
|
{ SpecialAbility::MeleeImmunityExceptMagical, "Immune to Non-Magical Melee" },
|
||||||
|
{ SpecialAbility::AggroImmunity, "Immune to Aggro" },
|
||||||
|
{ SpecialAbility::BeingAggroImmunity, "Immune to Being Aggro" },
|
||||||
|
{ SpecialAbility::CastingFromRangeImmunity, "Immune to Ranged Spells" },
|
||||||
|
{ SpecialAbility::FeignDeathImmunity, "Immune to Feign Death" },
|
||||||
|
{ SpecialAbility::TauntImmunity, "Immune to Taunt" },
|
||||||
|
{ SpecialAbility::TunnelVision, "Tunnel Vision" },
|
||||||
|
{ SpecialAbility::NoBuffHealFriends, "Does Not Heal or Buff Allies" },
|
||||||
|
{ SpecialAbility::PacifyImmunity, "Immune to Pacify" },
|
||||||
|
{ SpecialAbility::Leash, "Leashed" },
|
||||||
|
{ SpecialAbility::Tether, "Tethered" },
|
||||||
|
{ SpecialAbility::DestructibleObject, "Destructible Object" },
|
||||||
|
{ SpecialAbility::HarmFromClientImmunity, "Immune to Harm from Client" },
|
||||||
|
{ SpecialAbility::AlwaysFlee, "Always Flees" },
|
||||||
|
{ SpecialAbility::FleePercent, "Flee Percentage" },
|
||||||
|
{ SpecialAbility::AllowBeneficial, "Allows Beneficial Spells" },
|
||||||
|
{ SpecialAbility::DisableMelee, "Melee is Disabled" },
|
||||||
|
{ SpecialAbility::NPCChaseDistance, "Chase Distance" },
|
||||||
|
{ SpecialAbility::AllowedToTank, "Allowed to Tank" },
|
||||||
|
{ SpecialAbility::IgnoreRootAggroRules, "Ignores Root Aggro" },
|
||||||
|
{ SpecialAbility::CastingResistDifficulty, "Casting Resist Difficulty" },
|
||||||
|
{ SpecialAbility::CounterAvoidDamage, "Counter Damage Avoidance" },
|
||||||
|
{ SpecialAbility::ProximityAggro, "Proximity Aggro" },
|
||||||
|
{ SpecialAbility::RangedAttackImmunity, "Immune to Ranged Attacks" },
|
||||||
|
{ SpecialAbility::ClientDamageImmunity, "Immune to Client Damage" },
|
||||||
|
{ SpecialAbility::NPCDamageImmunity, "Immune to NPC Damage" },
|
||||||
|
{ SpecialAbility::ClientAggroImmunity, "Immune to Client Aggro" },
|
||||||
|
{ SpecialAbility::NPCAggroImmunity, "Immune to NPC Aggro" },
|
||||||
|
{ SpecialAbility::ModifyAvoidDamage, "Modify Damage Avoidance" },
|
||||||
|
{ SpecialAbility::MemoryFadeImmunity, "Immune to Memory Fades" },
|
||||||
|
{ SpecialAbility::OpenImmunity, "Immune to Open" },
|
||||||
|
{ SpecialAbility::AssassinateImmunity, "Immune to Assassinate" },
|
||||||
|
{ SpecialAbility::HeadshotImmunity, "Immune to Headshot" },
|
||||||
|
{ SpecialAbility::BotAggroImmunity, "Immune to Bot Aggro" },
|
||||||
|
{ SpecialAbility::BotDamageImmunity, "Immune to Bot Damage" },
|
||||||
|
};
|
||||||
|
|
||||||
namespace HeroicBonusBucket
|
namespace HeroicBonusBucket
|
||||||
{
|
{
|
||||||
@@ -700,4 +746,51 @@ namespace HeroicBonusBucket
|
|||||||
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
|
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Bug {
|
||||||
|
namespace Category {
|
||||||
|
constexpr uint32 Other = 0;
|
||||||
|
constexpr uint32 Video = 1;
|
||||||
|
constexpr uint32 Audio = 2;
|
||||||
|
constexpr uint32 Pathing = 3;
|
||||||
|
constexpr uint32 Quest = 4;
|
||||||
|
constexpr uint32 Tradeskills = 5;
|
||||||
|
constexpr uint32 SpellStacking = 6;
|
||||||
|
constexpr uint32 DoorsPortals = 7;
|
||||||
|
constexpr uint32 Items = 8;
|
||||||
|
constexpr uint32 NPC = 9;
|
||||||
|
constexpr uint32 Dialogs = 10;
|
||||||
|
constexpr uint32 LoNTCG = 11;
|
||||||
|
constexpr uint32 Mercenaries = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace InformationFlag {
|
||||||
|
constexpr uint32 None = 0;
|
||||||
|
constexpr uint32 Repeatable = 1;
|
||||||
|
constexpr uint32 Crash = 2;
|
||||||
|
constexpr uint32 TargetInfo = 4;
|
||||||
|
constexpr uint32 CharacterFlags = 8;
|
||||||
|
constexpr uint32 Unknown = 4294967280;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 GetID(const std::string& category_name);
|
||||||
|
std::string GetName(uint32 category_id);
|
||||||
|
bool IsValid(uint32 category_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<uint32, std::string> bug_category_names = {
|
||||||
|
{ Bug::Category::Other, "Other" },
|
||||||
|
{ Bug::Category::Video, "Video" },
|
||||||
|
{ Bug::Category::Audio, "Audio" },
|
||||||
|
{ Bug::Category::Pathing, "Pathing" },
|
||||||
|
{ Bug::Category::Quest, "Quest" },
|
||||||
|
{ Bug::Category::Tradeskills, "Tradeskills" },
|
||||||
|
{ Bug::Category::SpellStacking, "Spell Stacking" },
|
||||||
|
{ Bug::Category::DoorsPortals, "Doors and Portals" },
|
||||||
|
{ Bug::Category::Items, "Items" },
|
||||||
|
{ Bug::Category::NPC, "NPC" },
|
||||||
|
{ Bug::Category::Dialogs, "Dialogs" },
|
||||||
|
{ Bug::Category::LoNTCG, "LoN - TCG" },
|
||||||
|
{ Bug::Category::Mercenaries, "Mercenaries" }
|
||||||
|
};
|
||||||
|
|
||||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||||
|
|||||||
@@ -814,46 +814,6 @@ typedef enum {
|
|||||||
#define STAT_TIGER_CLAW 40
|
#define STAT_TIGER_CLAW 40
|
||||||
#define STAT_FRENZY 41
|
#define STAT_FRENZY 41
|
||||||
|
|
||||||
/*
|
|
||||||
** Recast timer types. Used as an off set to charProfileStruct timers.
|
|
||||||
**
|
|
||||||
** (Another orphaned enumeration...)
|
|
||||||
*/
|
|
||||||
enum RecastTimerTypes
|
|
||||||
{
|
|
||||||
RecTimer_0 = 0,
|
|
||||||
RecTimer_1,
|
|
||||||
RecTimer_WeaponHealClick, // 2
|
|
||||||
RecTimer_MuramiteBaneNukeClick, // 3
|
|
||||||
RecTimer_4,
|
|
||||||
RecTimer_DispellClick, // 5 (also click heal orbs?)
|
|
||||||
RecTimer_Epic, // 6
|
|
||||||
RecTimer_OoWBPClick, // 7
|
|
||||||
RecTimer_VishQuestClassItem, // 8
|
|
||||||
RecTimer_HealPotion, // 9
|
|
||||||
RecTimer_10,
|
|
||||||
RecTimer_11,
|
|
||||||
RecTimer_12,
|
|
||||||
RecTimer_13,
|
|
||||||
RecTimer_14,
|
|
||||||
RecTimer_15,
|
|
||||||
RecTimer_16,
|
|
||||||
RecTimer_17,
|
|
||||||
RecTimer_18,
|
|
||||||
RecTimer_ModRod, // 19
|
|
||||||
_RecTimerCount
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GroupUpdateAction
|
|
||||||
{
|
|
||||||
GUA_Joined = 0,
|
|
||||||
GUA_Left = 1,
|
|
||||||
GUA_LastLeft = 6,
|
|
||||||
GUA_FullGroupInfo = 7,
|
|
||||||
GUA_MakeLeader = 8,
|
|
||||||
GUA_Started = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8 DamageTypeSomething = 0x1C; //0x1c is something...
|
static const uint8 DamageTypeSomething = 0x1C; //0x1c is something...
|
||||||
static const uint8 DamageTypeFalling = 0xFC;
|
static const uint8 DamageTypeFalling = 0xFC;
|
||||||
static const uint8 DamageTypeSpell = 0xE7;
|
static const uint8 DamageTypeSpell = 0xE7;
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
SwapItemFailState &fail_state,
|
SwapItemFailState &fail_state,
|
||||||
uint16 race_id,
|
uint16 race_id,
|
||||||
uint8 class_id,
|
uint8 class_id,
|
||||||
uint16 deity_id,
|
uint32 deity_id,
|
||||||
uint8 level
|
uint8 level
|
||||||
) {
|
) {
|
||||||
fail_state = swapInvalid;
|
fail_state = swapInvalid;
|
||||||
@@ -354,7 +354,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
fail_state = swapRaceClass;
|
fail_state = swapRaceClass;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (deity_id && source_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & source_item->Deity)) {
|
if (deity_id && source_item->Deity && !(Deity::GetBitmask(deity_id) & source_item->Deity)) {
|
||||||
fail_state = swapDeity;
|
fail_state = swapDeity;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ bool EQ::InventoryProfile::SwapItem(
|
|||||||
fail_state = swapRaceClass;
|
fail_state = swapRaceClass;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (deity_id && destination_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & destination_item->Deity)) {
|
if (deity_id && destination_item->Deity && !(Deity::GetBitmask(deity_id) & destination_item->Deity)) {
|
||||||
fail_state = swapDeity;
|
fail_state = swapDeity;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ namespace EQ
|
|||||||
|
|
||||||
// Swap items in inventory
|
// Swap items in inventory
|
||||||
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
|
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
|
||||||
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
|
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint32 deity_id = Deity::Unknown, uint8 level = 0);
|
||||||
|
|
||||||
// Remove item from inventory
|
// Remove item from inventory
|
||||||
bool DeleteItem(int16 slot_id, int16 quantity = 0);
|
bool DeleteItem(int16 slot_id, int16 quantity = 0);
|
||||||
|
|||||||
@@ -2349,7 +2349,7 @@ namespace SoF
|
|||||||
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
||||||
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
||||||
|
|
||||||
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
|
emu->category_id = Bug::GetID(eq->category_name);
|
||||||
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
|
|||||||
@@ -806,7 +806,7 @@ namespace Titanium
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AppearanceType::GuildShow: {
|
case AppearanceType::GuildShow: {
|
||||||
FAIL_ENCODE();
|
FAIL_ENCODE();
|
||||||
@@ -2567,7 +2567,7 @@ namespace Titanium
|
|||||||
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
|
||||||
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
|
||||||
|
|
||||||
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
|
emu->category_id = Bug::GetID(eq->category_name);
|
||||||
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
|
||||||
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
|
|||||||
@@ -49,8 +49,10 @@ public:
|
|||||||
// these are the base definitions for command_subsettings and can be over-ridden by the database
|
// these are the base definitions for command_subsettings and can be over-ridden by the database
|
||||||
std::vector<CommandSubsettingsRepository::CommandSubsettings> static_records = {
|
std::vector<CommandSubsettingsRepository::CommandSubsettings> static_records = {
|
||||||
{.parent_command = "find", .sub_command = "aa", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaa"},
|
{.parent_command = "find", .sub_command = "aa", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaa"},
|
||||||
|
{.parent_command = "find", .sub_command = "bug_category", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findbugcategory"},
|
||||||
{.parent_command = "find", .sub_command = "character", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcharacter"},
|
{.parent_command = "find", .sub_command = "character", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcharacter"},
|
||||||
{.parent_command = "find", .sub_command = "class", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findclass"},
|
{.parent_command = "find", .sub_command = "class", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findclass"},
|
||||||
|
{.parent_command = "find", .sub_command = "comparison_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcomparisontype"},
|
||||||
{.parent_command = "find", .sub_command = "currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcurrency"},
|
{.parent_command = "find", .sub_command = "currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcurrency"},
|
||||||
{.parent_command = "find", .sub_command = "deity", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "finddeity"},
|
{.parent_command = "find", .sub_command = "deity", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "finddeity"},
|
||||||
{.parent_command = "find", .sub_command = "emote", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findemote"},
|
{.parent_command = "find", .sub_command = "emote", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findemote"},
|
||||||
@@ -61,6 +63,7 @@ public:
|
|||||||
{.parent_command = "find", .sub_command = "race", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrace"},
|
{.parent_command = "find", .sub_command = "race", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrace"},
|
||||||
{.parent_command = "find", .sub_command = "recipe", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrecipe"},
|
{.parent_command = "find", .sub_command = "recipe", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findrecipe"},
|
||||||
{.parent_command = "find", .sub_command = "skill", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findskill"},
|
{.parent_command = "find", .sub_command = "skill", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findskill"},
|
||||||
|
{.parent_command = "find", .sub_command = "special_ability", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fsa|findspecialability"},
|
||||||
{.parent_command = "find", .sub_command = "spell", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fs|findspell"},
|
{.parent_command = "find", .sub_command = "spell", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fs|findspell"},
|
||||||
{.parent_command = "find", .sub_command = "task", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findtask"},
|
{.parent_command = "find", .sub_command = "task", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findtask"},
|
||||||
{.parent_command = "find", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fz|findzone"},
|
{.parent_command = "find", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "fz|findzone"},
|
||||||
|
|||||||
@@ -615,6 +615,19 @@ RULE_INT(Combat, PCAccuracyAvoidanceMod2Scale, 100, "Scale Factor for PC Accurac
|
|||||||
RULE_BOOL(Combat, AllowRaidTargetBlind, false, "Toggle to allow raid targets to be blinded, default is false (Live-like)")
|
RULE_BOOL(Combat, AllowRaidTargetBlind, false, "Toggle to allow raid targets to be blinded, default is false (Live-like)")
|
||||||
RULE_BOOL(Combat, RogueBackstabHasteCorrection, false, "Toggle to enable correction for Haste impacting Backstab DPS too much. DEFAULT: false")
|
RULE_BOOL(Combat, RogueBackstabHasteCorrection, false, "Toggle to enable correction for Haste impacting Backstab DPS too much. DEFAULT: false")
|
||||||
RULE_BOOL(Combat, LegacyComputeDefense, false, "Trim AGI Scaling of defense mostly for lower levels to help compensate for the newer agi based defense system. Default: False")
|
RULE_BOOL(Combat, LegacyComputeDefense, false, "Trim AGI Scaling of defense mostly for lower levels to help compensate for the newer agi based defense system. Default: False")
|
||||||
|
RULE_REAL(Combat, SlayDamageAdjustment, 0.5, "Slay Damage Adjustment - Multiply final slay damage by this value. Default: 0.5")
|
||||||
|
RULE_INT(Combat, MaximumLevelStunsCripplingBlow, 55, "Maximum level that Crippling Blows will stun a npc. Default: 55")
|
||||||
|
RULE_INT(Combat, ArcheryBaseDamage, 0, "Archery base damage, default is 0")
|
||||||
|
RULE_INT(Combat, BackstabBaseDamage, 0, "Backstab base damage, default is 0")
|
||||||
|
RULE_INT(Combat, BashBaseDamage, 2, "Bash base damage, default is 2")
|
||||||
|
RULE_INT(Combat, DragonPunchBaseDamage, 12, "Dragon Punch base damage, default is 12")
|
||||||
|
RULE_INT(Combat, EagleStrikeBaseDamage, 7, "Eagle Strike base damage, default is 7")
|
||||||
|
RULE_INT(Combat, FlyingKickBaseDamage, 25, "Flying Kick base damage, default is 25")
|
||||||
|
RULE_INT(Combat, FrenzyBaseDamage, 10, "Frenzy base damage, default is 10")
|
||||||
|
RULE_INT(Combat, KickBaseDamage, 3, "Kick base damage, default is 3")
|
||||||
|
RULE_INT(Combat, RoundKickBaseDamage, 5, "Round Kick base damage, default is 5")
|
||||||
|
RULE_INT(Combat, ThrowingBaseDamage, 0, "Throwing base damage, default is 0")
|
||||||
|
RULE_INT(Combat, TigerClawBaseDamage, 4, "Tiger Claw base damage, default is 4")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(NPC)
|
RULE_CATEGORY(NPC)
|
||||||
|
|||||||
+48
-14
@@ -1,6 +1,15 @@
|
|||||||
#include "skill_caps.h"
|
#include "skill_caps.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
// cache the skill cap max level in the database
|
||||||
|
std::map<uint8_t, int32_t> skill_max_level = {};
|
||||||
|
|
||||||
|
uint8 skill_cap_max_level = (
|
||||||
|
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
||||||
|
RuleI(Character, SkillCapMaxLevel) :
|
||||||
|
RuleI(Character, MaxLevel)
|
||||||
|
);
|
||||||
|
|
||||||
SkillCaps *SkillCaps::SetContentDatabase(Database *db)
|
SkillCaps *SkillCaps::SetContentDatabase(Database *db)
|
||||||
{
|
{
|
||||||
m_content_database = db;
|
m_content_database = db;
|
||||||
@@ -8,15 +17,30 @@ SkillCaps *SkillCaps::SetContentDatabase(Database *db)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t SkillCaps::GetSkillCapMaxLevel(uint8 class_id, EQ::skills::SkillType skill_id)
|
||||||
|
{
|
||||||
|
// pull the max value defined in the database if it exists
|
||||||
|
auto it = skill_max_level.find((class_id * 1000000) + skill_id);
|
||||||
|
if (it != skill_max_level.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return skill_cap_max_level;
|
||||||
|
}
|
||||||
|
|
||||||
SkillCapsRepository::SkillCaps SkillCaps::GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
SkillCapsRepository::SkillCaps SkillCaps::GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
||||||
{
|
{
|
||||||
if (!IsPlayerClass(class_id)) {
|
if (!IsPlayerClass(class_id) || static_cast<uint32>(skill_id) > EQ::skills::HIGHEST_SKILL + 1) {
|
||||||
return SkillCapsRepository::NewEntity();
|
return SkillCapsRepository::NewEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
const uint8 max_level = GetSkillCapMaxLevel(class_id, skill_id);
|
||||||
|
if (level > max_level) {
|
||||||
|
level = max_level;
|
||||||
|
}
|
||||||
|
|
||||||
auto pos = m_skill_caps.find(key);
|
const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
||||||
|
auto pos = m_skill_caps.find(key);
|
||||||
if (pos != m_skill_caps.end()) {
|
if (pos != m_skill_caps.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
@@ -30,19 +54,12 @@ uint8 SkillCaps::GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_
|
|||||||
!IsPlayerClass(class_id) ||
|
!IsPlayerClass(class_id) ||
|
||||||
class_id > Class::PLAYER_CLASS_COUNT ||
|
class_id > Class::PLAYER_CLASS_COUNT ||
|
||||||
static_cast<uint32>(skill_id) > (EQ::skills::HIGHEST_SKILL + 1)
|
static_cast<uint32>(skill_id) > (EQ::skills::HIGHEST_SKILL + 1)
|
||||||
) {
|
) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8 skill_cap_max_level = (
|
|
||||||
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
|
||||||
RuleI(Character, SkillCapMaxLevel) :
|
|
||||||
RuleI(Character, MaxLevel)
|
|
||||||
);
|
|
||||||
|
|
||||||
const uint8 max_level = level > skill_cap_max_level ? level : skill_cap_max_level;
|
const uint8 max_level = level > skill_cap_max_level ? level : skill_cap_max_level;
|
||||||
const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
const uint64_t key = (class_id * 1000000) + (level * 1000) + static_cast<uint32>(skill_id);
|
||||||
|
|
||||||
for (uint8 current_level = 1; current_level <= max_level; current_level++) {
|
for (uint8 current_level = 1; current_level <= max_level; current_level++) {
|
||||||
auto pos = m_skill_caps.find(key);
|
auto pos = m_skill_caps.find(key);
|
||||||
if (pos != m_skill_caps.end()) {
|
if (pos != m_skill_caps.end()) {
|
||||||
@@ -55,21 +72,38 @@ uint8 SkillCaps::GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_
|
|||||||
|
|
||||||
void SkillCaps::LoadSkillCaps()
|
void SkillCaps::LoadSkillCaps()
|
||||||
{
|
{
|
||||||
const auto& l = SkillCapsRepository::All(*m_content_database);
|
const auto &l = SkillCapsRepository::All(*m_content_database);
|
||||||
|
|
||||||
m_skill_caps.clear();
|
m_skill_caps.clear();
|
||||||
|
|
||||||
for (const auto& e: l) {
|
for (const auto &e: l) {
|
||||||
if (
|
if (
|
||||||
e.level < 1 ||
|
e.level < 1 ||
|
||||||
!IsPlayerClass(e.class_id) ||
|
!IsPlayerClass(e.class_id) ||
|
||||||
static_cast<EQ::skills::SkillType>(e.skill_id) >= EQ::skills::SkillCount
|
static_cast<EQ::skills::SkillType>(e.skill_id) >= EQ::skills::SkillCount
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t key = (e.class_id * 1000000) + (e.level * 1000) + e.skill_id;
|
const uint64_t key = (e.class_id * 1000000) + (e.level * 1000) + e.skill_id;
|
||||||
m_skill_caps[key] = e;
|
m_skill_caps[key] = e;
|
||||||
|
|
||||||
|
const int max_level_key = (e.class_id * 1000000) + e.skill_id;
|
||||||
|
auto it = skill_max_level.find(max_level_key);
|
||||||
|
if (it != skill_max_level.end()) {
|
||||||
|
// Key found, update the value if the new level is higher
|
||||||
|
if (e.level > it->second) {
|
||||||
|
it->second = e.level;
|
||||||
|
}
|
||||||
|
// we never want to exceed the defined rule skill cap max level
|
||||||
|
if (it->second > skill_cap_max_level) {
|
||||||
|
it->second = skill_cap_max_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Key not found, insert the new key-value pair
|
||||||
|
skill_max_level[max_level_key] = e.level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public:
|
|||||||
uint8 GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
uint8 GetSkillTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
||||||
void LoadSkillCaps();
|
void LoadSkillCaps();
|
||||||
void ReloadSkillCaps();
|
void ReloadSkillCaps();
|
||||||
|
static int32_t GetSkillCapMaxLevel(uint8 class_id, EQ::skills::SkillType skill_id);
|
||||||
|
|
||||||
SkillCaps *SetContentDatabase(Database *db);
|
SkillCaps *SetContentDatabase(Database *db);
|
||||||
private:
|
private:
|
||||||
|
|||||||
+24
-18
@@ -127,24 +127,30 @@ bool EQ::skills::IsCastingSkill(SkillType skill)
|
|||||||
int32 EQ::skills::GetBaseDamage(SkillType skill)
|
int32 EQ::skills::GetBaseDamage(SkillType skill)
|
||||||
{
|
{
|
||||||
switch (skill) {
|
switch (skill) {
|
||||||
case SkillBash:
|
case SkillArchery:
|
||||||
return 2;
|
return RuleI(Combat, ArcheryBaseDamage);
|
||||||
case SkillDragonPunch:
|
case SkillBackstab:
|
||||||
return 12;
|
return RuleI(Combat, BackstabBaseDamage);
|
||||||
case SkillEagleStrike:
|
case SkillBash:
|
||||||
return 7;
|
return RuleI(Combat, BashBaseDamage);
|
||||||
case SkillFlyingKick:
|
case SkillDragonPunch:
|
||||||
return 25;
|
return RuleI(Combat, DragonPunchBaseDamage);
|
||||||
case SkillKick:
|
case SkillEagleStrike:
|
||||||
return 3;
|
return RuleI(Combat, EagleStrikeBaseDamage);
|
||||||
case SkillRoundKick:
|
case SkillFlyingKick:
|
||||||
return 5;
|
return RuleI(Combat, FlyingKickBaseDamage);
|
||||||
case SkillTigerClaw:
|
case SkillFrenzy:
|
||||||
return 4;
|
return RuleI(Combat, FrenzyBaseDamage);
|
||||||
case SkillFrenzy:
|
case SkillKick:
|
||||||
return 10;
|
return RuleI(Combat, KickBaseDamage);
|
||||||
default:
|
case SkillRoundKick:
|
||||||
return 0;
|
return RuleI(Combat, RoundKickBaseDamage);
|
||||||
|
case SkillThrowing:
|
||||||
|
return RuleI(Combat, ThrowingBaseDamage);
|
||||||
|
case SkillTigerClaw:
|
||||||
|
return RuleI(Combat, TigerClawBaseDamage);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// Build variables
|
// Build variables
|
||||||
// these get injected during the build pipeline
|
// these get injected during the build pipeline
|
||||||
#define CURRENT_VERSION "22.51.1-dev" // always append -dev to the current version for custom-builds
|
#define CURRENT_VERSION "22.52.0-dev" // always append -dev to the current version for custom-builds
|
||||||
#define LOGIN_VERSION "0.8.0"
|
#define LOGIN_VERSION "0.8.0"
|
||||||
#define COMPILE_DATE __DATE__
|
#define COMPILE_DATE __DATE__
|
||||||
#define COMPILE_TIME __TIME__
|
#define COMPILE_TIME __TIME__
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eqemu-server",
|
"name": "eqemu-server",
|
||||||
"version": "22.51.1",
|
"version": "22.52.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EQEmu/Server.git"
|
"url": "https://github.com/EQEmu/Server.git"
|
||||||
|
|||||||
+24
-35
@@ -282,88 +282,77 @@ void Adventure::IncrementAssassinationCount()
|
|||||||
void Adventure::Finished(AdventureWinStatus ws)
|
void Adventure::Finished(AdventureWinStatus ws)
|
||||||
{
|
{
|
||||||
auto iter = players.begin();
|
auto iter = players.begin();
|
||||||
while(iter != players.end())
|
while (iter != players.end()) {
|
||||||
{
|
|
||||||
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
|
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
|
||||||
if(current)
|
auto character_id = database.GetCharacterID(*iter);
|
||||||
{
|
|
||||||
if(current->Online() == CLE_Status::InZone)
|
if (character_id == 0) {
|
||||||
{
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current) {
|
||||||
|
if (current->Online() == CLE_Status::InZone) {
|
||||||
//We can send our packets only.
|
//We can send our packets only.
|
||||||
auto pack =
|
auto pack = new ServerPacket(ServerOP_AdventureFinish, sizeof(ServerAdventureFinish_Struct));
|
||||||
new ServerPacket(ServerOP_AdventureFinish, sizeof(ServerAdventureFinish_Struct));
|
|
||||||
ServerAdventureFinish_Struct *af = (ServerAdventureFinish_Struct*)pack->pBuffer;
|
ServerAdventureFinish_Struct *af = (ServerAdventureFinish_Struct*)pack->pBuffer;
|
||||||
strcpy(af->player, (*iter).c_str());
|
strcpy(af->player, (*iter).c_str());
|
||||||
af->theme = GetTemplate()->theme;
|
af->theme = GetTemplate()->theme;
|
||||||
if(ws == AWS_Win)
|
if (ws == AWS_Win) {
|
||||||
{
|
|
||||||
af->win = true;
|
af->win = true;
|
||||||
af->points = GetTemplate()->win_points;
|
af->points = GetTemplate()->win_points;
|
||||||
}
|
}
|
||||||
else if(ws == AWS_SecondPlace)
|
else if (ws == AWS_SecondPlace) {
|
||||||
{
|
|
||||||
af->win = true;
|
af->win = true;
|
||||||
af->points = GetTemplate()->lose_points;
|
af->points = GetTemplate()->lose_points;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
af->win = false;
|
af->win = false;
|
||||||
af->points = 0;
|
af->points = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
|
zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
|
||||||
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
|
database.UpdateAdventureStatsEntry(character_id, GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
|
||||||
delete pack;
|
delete pack;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
AdventureFinishEvent afe;
|
AdventureFinishEvent afe;
|
||||||
afe.name = (*iter);
|
afe.name = (*iter);
|
||||||
if(ws == AWS_Win)
|
if (ws == AWS_Win) {
|
||||||
{
|
|
||||||
afe.theme = GetTemplate()->theme;
|
afe.theme = GetTemplate()->theme;
|
||||||
afe.points = GetTemplate()->win_points;
|
afe.points = GetTemplate()->win_points;
|
||||||
afe.win = true;
|
afe.win = true;
|
||||||
}
|
}
|
||||||
else if(ws == AWS_SecondPlace)
|
else if (ws == AWS_SecondPlace) {
|
||||||
{
|
|
||||||
afe.theme = GetTemplate()->theme;
|
afe.theme = GetTemplate()->theme;
|
||||||
afe.points = GetTemplate()->lose_points;
|
afe.points = GetTemplate()->lose_points;
|
||||||
afe.win = true;
|
afe.win = true;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
afe.win = false;
|
afe.win = false;
|
||||||
afe.points = 0;
|
afe.points = 0;
|
||||||
}
|
}
|
||||||
adventure_manager.AddFinishedEvent(afe);
|
adventure_manager.AddFinishedEvent(afe);
|
||||||
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
|
database.UpdateAdventureStatsEntry(character_id, GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
AdventureFinishEvent afe;
|
AdventureFinishEvent afe;
|
||||||
afe.name = (*iter);
|
afe.name = (*iter);
|
||||||
if(ws == AWS_Win)
|
if (ws == AWS_Win) {
|
||||||
{
|
|
||||||
afe.theme = GetTemplate()->theme;
|
afe.theme = GetTemplate()->theme;
|
||||||
afe.points = GetTemplate()->win_points;
|
afe.points = GetTemplate()->win_points;
|
||||||
afe.win = true;
|
afe.win = true;
|
||||||
}
|
}
|
||||||
else if(ws == AWS_SecondPlace)
|
else if (ws == AWS_SecondPlace) {
|
||||||
{
|
|
||||||
afe.theme = GetTemplate()->theme;
|
afe.theme = GetTemplate()->theme;
|
||||||
afe.points = GetTemplate()->lose_points;
|
afe.points = GetTemplate()->lose_points;
|
||||||
afe.win = true;
|
afe.win = true;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
afe.win = false;
|
afe.win = false;
|
||||||
afe.points = 0;
|
afe.points = 0;
|
||||||
}
|
}
|
||||||
adventure_manager.AddFinishedEvent(afe);
|
adventure_manager.AddFinishedEvent(afe);
|
||||||
|
database.UpdateAdventureStatsEntry(character_id, GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
|
||||||
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
|
|
||||||
}
|
}
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -670,7 +670,7 @@ void WorldDatabase::SetTitaniumDefaultStartZone(PlayerProfile_Struct* in_pp, Cha
|
|||||||
{
|
{
|
||||||
case StartZoneIndex::Odus:
|
case StartZoneIndex::Odus:
|
||||||
{
|
{
|
||||||
if (in_cc->deity == EQ::deity::DeityCazicThule) // Cazic-Thule Erudites go to Paineel
|
if (in_cc->deity == Deity::CazicThule) // Cazic-Thule Erudites go to Paineel
|
||||||
{
|
{
|
||||||
in_pp->zone_id = Zones::PAINEEL; // paineel
|
in_pp->zone_id = Zones::PAINEEL; // paineel
|
||||||
in_pp->binds[0].zone_id = Zones::PAINEEL;
|
in_pp->binds[0].zone_id = Zones::PAINEEL;
|
||||||
|
|||||||
+3
-3
@@ -167,7 +167,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
|
|||||||
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) {
|
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) {
|
||||||
swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
|
swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
|
||||||
swarm_pet_npc->SetPetTargetLockID(targ->GetID());
|
swarm_pet_npc->SetPetTargetLockID(targ->GetID());
|
||||||
swarm_pet_npc->SetSpecialAbility(IMMUNE_AGGRO, 1);
|
swarm_pet_npc->SetSpecialAbility(SpecialAbility::AggroImmunity, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
||||||
@@ -272,7 +272,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
|||||||
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) {
|
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) {
|
||||||
swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
|
swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
|
||||||
swarm_pet_npc->SetPetTargetLockID(targ->GetID());
|
swarm_pet_npc->SetPetTargetLockID(targ->GetID());
|
||||||
swarm_pet_npc->SetSpecialAbility(IMMUNE_AGGRO, 1);
|
swarm_pet_npc->SetSpecialAbility(SpecialAbility::AggroImmunity, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
swarm_pet_npc->GetSwarmInfo()->target = 0;
|
||||||
@@ -401,7 +401,7 @@ void Mob::WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *tar, uint32 d
|
|||||||
made_npc->npc_spells_id = 7;
|
made_npc->npc_spells_id = 7;
|
||||||
break;
|
break;
|
||||||
case Class::Paladin:
|
case Class::Paladin:
|
||||||
//SPECATK_TRIPLE
|
//SpecialAbility::TripleAttack
|
||||||
strcpy(made_npc->special_abilities, "6,1");
|
strcpy(made_npc->special_abilities, "6,1");
|
||||||
made_npc->current_hp = made_npc->current_hp * 150 / 100;
|
made_npc->current_hp = made_npc->current_hp * 150 / 100;
|
||||||
made_npc->max_hp = made_npc->max_hp * 150 / 100;
|
made_npc->max_hp = made_npc->max_hp * 150 / 100;
|
||||||
|
|||||||
+12
-12
@@ -412,13 +412,13 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
(
|
(
|
||||||
!RuleB(Aggro, AggroPlayerPets) ||
|
!RuleB(Aggro, AggroPlayerPets) ||
|
||||||
pet_owner->CastToClient()->GetGM() ||
|
pet_owner->CastToClient()->GetGM() ||
|
||||||
mob->GetSpecialAbility(IMMUNE_AGGRO)
|
mob->GetSpecialAbility(SpecialAbility::AggroImmunity)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNPC() && mob->IsNPC() && mob->GetSpecialAbility(IMMUNE_AGGRO_NPC)) {
|
if (IsNPC() && mob->IsNPC() && mob->GetSpecialAbility(SpecialAbility::NPCAggroImmunity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,8 +452,8 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't aggro new clients if we are already engaged unless PROX_AGGRO is set
|
// Don't aggro new clients if we are already engaged unless SpecialAbility::ProximityAggro is set
|
||||||
if (IsEngaged() && (!GetSpecialAbility(PROX_AGGRO) || (GetSpecialAbility(PROX_AGGRO) && !CombatRange(mob)))) {
|
if (IsEngaged() && (!GetSpecialAbility(SpecialAbility::ProximityAggro) || (GetSpecialAbility(SpecialAbility::ProximityAggro) && !CombatRange(mob)))) {
|
||||||
LogAggro(
|
LogAggro(
|
||||||
"[{}] is in combat, and does not have prox_aggro, or does and is out of combat range with [{}]",
|
"[{}] is in combat, and does not have prox_aggro, or does and is out of combat range with [{}]",
|
||||||
GetName(),
|
GetName(),
|
||||||
@@ -634,19 +634,19 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->GetSpecialAbility(NO_HARM_FROM_CLIENT)) {
|
if (target->GetSpecialAbility(SpecialAbility::HarmFromClientImmunity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsBot() && target->GetSpecialAbility(IMMUNE_DAMAGE_BOT)) {
|
if (IsBot() && target->GetSpecialAbility(SpecialAbility::BotDamageImmunity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsClient() && target->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT)) {
|
if (IsClient() && target->GetSpecialAbility(SpecialAbility::ClientDamageImmunity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNPC() && target->GetSpecialAbility(IMMUNE_DAMAGE_NPC)) {
|
if (IsNPC() && target->GetSpecialAbility(SpecialAbility::NPCDamageImmunity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,13 +1053,13 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
|
|||||||
float _zDist = m_Position.z - other->GetZ();
|
float _zDist = m_Position.z - other->GetZ();
|
||||||
_zDist *= _zDist;
|
_zDist *= _zDist;
|
||||||
|
|
||||||
if (GetSpecialAbility(NPC_CHASE_DISTANCE)) {
|
if (GetSpecialAbility(SpecialAbility::NPCChaseDistance)) {
|
||||||
|
|
||||||
bool DoLoSCheck = true;
|
bool DoLoSCheck = true;
|
||||||
float max_dist = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 0));
|
float max_dist = static_cast<float>(GetSpecialAbilityParam(SpecialAbility::NPCChaseDistance, 0));
|
||||||
float min_distance = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 1));
|
float min_distance = static_cast<float>(GetSpecialAbilityParam(SpecialAbility::NPCChaseDistance, 1));
|
||||||
|
|
||||||
if (GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 2)) {
|
if (GetSpecialAbilityParam(SpecialAbility::NPCChaseDistance, 2)) {
|
||||||
DoLoSCheck = false; //Ignore line of sight check
|
DoLoSCheck = false; //Ignore line of sight check
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+236
-210
@@ -438,12 +438,12 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
|
|||||||
int counter_parry = 0;
|
int counter_parry = 0;
|
||||||
int counter_dodge = 0;
|
int counter_dodge = 0;
|
||||||
|
|
||||||
if (attacker->GetSpecialAbility(COUNTER_AVOID_DAMAGE)) {
|
if (attacker->GetSpecialAbility(SpecialAbility::CounterAvoidDamage)) {
|
||||||
counter_all = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 0);
|
counter_all = attacker->GetSpecialAbilityParam(SpecialAbility::CounterAvoidDamage, 0);
|
||||||
counter_riposte = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 1);
|
counter_riposte = attacker->GetSpecialAbilityParam(SpecialAbility::CounterAvoidDamage, 1);
|
||||||
counter_block = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 2);
|
counter_block = attacker->GetSpecialAbilityParam(SpecialAbility::CounterAvoidDamage, 2);
|
||||||
counter_parry = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 3);
|
counter_parry = attacker->GetSpecialAbilityParam(SpecialAbility::CounterAvoidDamage, 3);
|
||||||
counter_dodge = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 4);
|
counter_dodge = attacker->GetSpecialAbilityParam(SpecialAbility::CounterAvoidDamage, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
int modify_all = 0;
|
int modify_all = 0;
|
||||||
@@ -452,12 +452,12 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
|
|||||||
int modify_parry = 0;
|
int modify_parry = 0;
|
||||||
int modify_dodge = 0;
|
int modify_dodge = 0;
|
||||||
|
|
||||||
if (GetSpecialAbility(MODIFY_AVOID_DAMAGE)) {
|
if (GetSpecialAbility(SpecialAbility::ModifyAvoidDamage)) {
|
||||||
modify_all = GetSpecialAbilityParam(MODIFY_AVOID_DAMAGE, 0);
|
modify_all = GetSpecialAbilityParam(SpecialAbility::ModifyAvoidDamage, 0);
|
||||||
modify_riposte = GetSpecialAbilityParam(MODIFY_AVOID_DAMAGE, 1);
|
modify_riposte = GetSpecialAbilityParam(SpecialAbility::ModifyAvoidDamage, 1);
|
||||||
modify_block = GetSpecialAbilityParam(MODIFY_AVOID_DAMAGE, 2);
|
modify_block = GetSpecialAbilityParam(SpecialAbility::ModifyAvoidDamage, 2);
|
||||||
modify_parry = GetSpecialAbilityParam(MODIFY_AVOID_DAMAGE, 3);
|
modify_parry = GetSpecialAbilityParam(SpecialAbility::ModifyAvoidDamage, 3);
|
||||||
modify_dodge = GetSpecialAbilityParam(MODIFY_AVOID_DAMAGE, 4);
|
modify_dodge = GetSpecialAbilityParam(SpecialAbility::ModifyAvoidDamage, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Heroic Strikethrough Implementation per Dev Quotes (2018):
|
/* Heroic Strikethrough Implementation per Dev Quotes (2018):
|
||||||
@@ -1129,13 +1129,13 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item) {
|
|||||||
int64 banedmg = 0;
|
int64 banedmg = 0;
|
||||||
|
|
||||||
//can't hit invulnerable stuff with weapons.
|
//can't hit invulnerable stuff with weapons.
|
||||||
if (against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)) {
|
if (against->GetInvul() || against->GetSpecialAbility(SpecialAbility::MeleeImmunity)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check to see if our weapons or fists are magical.
|
//check to see if our weapons or fists are magical.
|
||||||
if (against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) {
|
if (against->GetSpecialAbility(SpecialAbility::MeleeImmunityExceptMagical)) {
|
||||||
if (GetSpecialAbility(SPECATK_MAGICAL)) {
|
if (GetSpecialAbility(SpecialAbility::MagicalAttack)) {
|
||||||
dmg = 1;
|
dmg = 1;
|
||||||
}
|
}
|
||||||
//On live this occurs for ALL NPC's >= 10
|
//On live this occurs for ALL NPC's >= 10
|
||||||
@@ -1178,7 +1178,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int eledmg = 0;
|
int eledmg = 0;
|
||||||
if (!against->GetSpecialAbility(IMMUNE_MAGIC)) {
|
if (!against->GetSpecialAbility(SpecialAbility::MagicImmunity)) {
|
||||||
if (weapon_item && weapon_item->ElemDmgAmt) {
|
if (weapon_item && weapon_item->ElemDmgAmt) {
|
||||||
//we don't check resist for npcs here
|
//we don't check resist for npcs here
|
||||||
eledmg = weapon_item->ElemDmgAmt;
|
eledmg = weapon_item->ElemDmgAmt;
|
||||||
@@ -1186,7 +1186,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) {
|
if (against->GetSpecialAbility(SpecialAbility::MeleeImmunityExceptBane)) {
|
||||||
if (weapon_item) {
|
if (weapon_item) {
|
||||||
if (weapon_item->BaneDmgBody == against->GetBodyType()) {
|
if (weapon_item->BaneDmgBody == against->GetBodyType()) {
|
||||||
banedmg += weapon_item->BaneDmgAmt;
|
banedmg += weapon_item->BaneDmgAmt;
|
||||||
@@ -1198,7 +1198,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!banedmg) {
|
if (!banedmg) {
|
||||||
if (!GetSpecialAbility(SPECATK_BANE))
|
if (!GetSpecialAbility(SpecialAbility::BaneAttack))
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1233,7 +1233,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
|
|||||||
int64 banedmg = 0;
|
int64 banedmg = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
if (!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE))
|
if (!against || against->GetInvul() || against->GetSpecialAbility(SpecialAbility::MeleeImmunity))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// check for items being illegally attained
|
// check for items being illegally attained
|
||||||
@@ -1261,7 +1261,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) {
|
if (against->GetSpecialAbility(SpecialAbility::MeleeImmunityExceptMagical)) {
|
||||||
if (weapon_item) {
|
if (weapon_item) {
|
||||||
// check to see if the weapon is magic
|
// check to see if the weapon is magic
|
||||||
bool MagicWeapon = weapon_item->GetItemMagical(true) || spellbonuses.MagicWeapon || itembonuses.MagicWeapon;
|
bool MagicWeapon = weapon_item->GetItemMagical(true) || spellbonuses.MagicWeapon || itembonuses.MagicWeapon;
|
||||||
@@ -1298,7 +1298,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
|
|||||||
RuleI(Combat, PetAttackMagicLevel)) { // pets wouldn't actually use this but...
|
RuleI(Combat, PetAttackMagicLevel)) { // pets wouldn't actually use this but...
|
||||||
dmg = 1; // it gives us an idea if we can hit
|
dmg = 1; // it gives us an idea if we can hit
|
||||||
}
|
}
|
||||||
else if (MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)) {
|
else if (MagicGloves || GetSpecialAbility(SpecialAbility::MagicalAttack)) {
|
||||||
dmg = 1;
|
dmg = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1328,7 +1328,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
int eledmg = 0;
|
int eledmg = 0;
|
||||||
if (!against->GetSpecialAbility(IMMUNE_MAGIC)) {
|
if (!against->GetSpecialAbility(SpecialAbility::MagicImmunity)) {
|
||||||
if (weapon_item && weapon_item->GetItem() && weapon_item->GetItemElementalFlag(true))
|
if (weapon_item && weapon_item->GetItem() && weapon_item->GetItemElementalFlag(true))
|
||||||
// the client actually has the way this is done, it does not appear to check req!
|
// the client actually has the way this is done, it does not appear to check req!
|
||||||
eledmg = against->ResistElementalWeaponDmg(weapon_item);
|
eledmg = against->ResistElementalWeaponDmg(weapon_item);
|
||||||
@@ -1338,9 +1338,9 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
|
|||||||
(weapon_item->GetItemBaneDamageBody(true) || weapon_item->GetItemBaneDamageRace(true)))
|
(weapon_item->GetItemBaneDamageBody(true) || weapon_item->GetItemBaneDamageRace(true)))
|
||||||
banedmg = against->CheckBaneDamage(weapon_item);
|
banedmg = against->CheckBaneDamage(weapon_item);
|
||||||
|
|
||||||
if (against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) {
|
if (against->GetSpecialAbility(SpecialAbility::MeleeImmunityExceptBane)) {
|
||||||
if (!banedmg) {
|
if (!banedmg) {
|
||||||
if (!GetSpecialAbility(SPECATK_BANE))
|
if (!GetSpecialAbility(SpecialAbility::BaneAttack))
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
@@ -3190,19 +3190,19 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) {
|
if (IsFamiliar() || GetSpecialAbility(SpecialAbility::AggroImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) {
|
if (other->IsBot() && GetSpecialAbility(SpecialAbility::BotAggroImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) {
|
if (other->IsClient() && GetSpecialAbility(SpecialAbility::ClientAggroImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC)) {
|
if (other->IsNPC() && GetSpecialAbility(SpecialAbility::NPCAggroImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3214,12 +3214,12 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->GetSpecialAbility(IMMUNE_AGGRO_ON)) {
|
if (other->GetSpecialAbility(SpecialAbility::BeingAggroImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(NPC_TUNNELVISION)) {
|
if (GetSpecialAbility(SpecialAbility::TunnelVision)) {
|
||||||
int tv_mod = GetSpecialAbilityParam(NPC_TUNNELVISION, 0);
|
int tv_mod = GetSpecialAbilityParam(SpecialAbility::TunnelVision, 0);
|
||||||
|
|
||||||
Mob *top = GetTarget();
|
Mob *top = GetTarget();
|
||||||
if (top && top != other) {
|
if (top && top != other) {
|
||||||
@@ -3299,10 +3299,10 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
// cb:2007-08-17
|
// cb:2007-08-17
|
||||||
// owner must get on list, but he's not actually gained any hate yet
|
// owner must get on list, but he's not actually gained any hate yet
|
||||||
if (
|
if (
|
||||||
!owner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!owner->GetSpecialAbility(SpecialAbility::AggroImmunity) &&
|
||||||
!(owner->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
!(owner->IsBot() && GetSpecialAbility(SpecialAbility::BotAggroImmunity)) &&
|
||||||
!(owner->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
!(owner->IsClient() && GetSpecialAbility(SpecialAbility::ClientAggroImmunity)) &&
|
||||||
!(owner->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
!(owner->IsNPC() && GetSpecialAbility(SpecialAbility::NPCAggroImmunity))
|
||||||
) {
|
) {
|
||||||
if (owner->IsClient() && !CheckAggro(owner)) {
|
if (owner->IsClient() && !CheckAggro(owner)) {
|
||||||
owner->CastToClient()->AddAutoXTarget(this);
|
owner->CastToClient()->AddAutoXTarget(this);
|
||||||
@@ -3315,10 +3315,10 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
if (mypet && !mypet->IsHeld() && !mypet->IsPetStop()) { // I have a pet, add other to it
|
if (mypet && !mypet->IsHeld() && !mypet->IsPetStop()) { // I have a pet, add other to it
|
||||||
if (
|
if (
|
||||||
!mypet->IsFamiliar() &&
|
!mypet->IsFamiliar() &&
|
||||||
!mypet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!mypet->GetSpecialAbility(SpecialAbility::AggroImmunity) &&
|
||||||
!(IsBot() && mypet->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
!(IsBot() && mypet->GetSpecialAbility(SpecialAbility::BotAggroImmunity)) &&
|
||||||
!(IsClient() && mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
!(IsClient() && mypet->GetSpecialAbility(SpecialAbility::ClientAggroImmunity)) &&
|
||||||
!(IsNPC() && mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
!(IsNPC() && mypet->GetSpecialAbility(SpecialAbility::NPCAggroImmunity))
|
||||||
) {
|
) {
|
||||||
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
@@ -3326,10 +3326,10 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
else if (myowner) { // I am a pet, add other to owner if it's NPC/LD
|
else if (myowner) { // I am a pet, add other to owner if it's NPC/LD
|
||||||
if (
|
if (
|
||||||
myowner->IsAIControlled() &&
|
myowner->IsAIControlled() &&
|
||||||
!myowner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!myowner->GetSpecialAbility(SpecialAbility::AggroImmunity) &&
|
||||||
!(myowner->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
!(myowner->IsBot() && GetSpecialAbility(SpecialAbility::BotAggroImmunity)) &&
|
||||||
!(myowner->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
!(myowner->IsClient() && GetSpecialAbility(SpecialAbility::ClientAggroImmunity)) &&
|
||||||
!(myowner->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
!(myowner->IsNPC() && GetSpecialAbility(SpecialAbility::NPCAggroImmunity))
|
||||||
) {
|
) {
|
||||||
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
@@ -4095,8 +4095,8 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this should actually happen MUCH sooner, need to investigate though -- good enough for now
|
// this should actually happen MUCH sooner, need to investigate though -- good enough for now
|
||||||
if ((skill_used == EQ::skills::SkillArchery || skill_used == EQ::skills::SkillThrowing) && GetSpecialAbility(IMMUNE_RANGED_ATTACKS)) {
|
if ((skill_used == EQ::skills::SkillArchery || skill_used == EQ::skills::SkillThrowing) && GetSpecialAbility(SpecialAbility::RangedAttackImmunity)) {
|
||||||
LogCombat("Avoiding [{}] damage due to IMMUNE_RANGED_ATTACKS", damage);
|
LogCombat("Avoiding [{}] damage due to SpecialAbility::RangedAttackImmunity", damage);
|
||||||
damage = DMG_INVULNERABLE;
|
damage = DMG_INVULNERABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4174,12 +4174,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
Mob* pet = GetPet();
|
Mob* pet = GetPet();
|
||||||
pet &&
|
pet &&
|
||||||
!pet->IsFamiliar() &&
|
!pet->IsFamiliar() &&
|
||||||
!pet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!pet->GetSpecialAbility(SpecialAbility::AggroImmunity) &&
|
||||||
!pet->IsEngaged() &&
|
!pet->IsEngaged() &&
|
||||||
attacker &&
|
attacker &&
|
||||||
!(attacker->IsBot() && pet->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
!(attacker->IsBot() && pet->GetSpecialAbility(SpecialAbility::BotAggroImmunity)) &&
|
||||||
!(attacker->IsClient() && pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
!(attacker->IsClient() && pet->GetSpecialAbility(SpecialAbility::ClientAggroImmunity)) &&
|
||||||
!(attacker->IsNPC() && pet->GetSpecialAbility(IMMUNE_AGGRO_NPC)) &&
|
!(attacker->IsNPC() && pet->GetSpecialAbility(SpecialAbility::NPCAggroImmunity)) &&
|
||||||
attacker != this &&
|
attacker != this &&
|
||||||
!attacker->IsCorpse() &&
|
!attacker->IsCorpse() &&
|
||||||
!pet->IsGHeld() &&
|
!pet->IsGHeld() &&
|
||||||
@@ -4463,7 +4463,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
can_stun = false;
|
can_stun = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(UNSTUNABLE)) {
|
if (GetSpecialAbility(SpecialAbility::StunImmunity)) {
|
||||||
can_stun = false;
|
can_stun = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5188,7 +5188,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!weapon && hand == EQ::invslot::slotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) {
|
if (!weapon && hand == EQ::invslot::slotRange && GetSpecialAbility(SpecialAbility::RangedAttack)) {
|
||||||
rangedattk = true;
|
rangedattk = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5388,6 +5388,101 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Mob::RollMeleeCritCheck(Mob *defender, EQ::skills::SkillType skill)
|
||||||
|
{
|
||||||
|
// We either require an innate crit chance or some SPA 169 to crit
|
||||||
|
bool innate_crit = false;
|
||||||
|
int crit_chance = GetCriticalChanceBonus(skill);
|
||||||
|
// Paladin check
|
||||||
|
if (defender->IsUndeadForSlay()) {
|
||||||
|
crit_chance = crit_chance + GetUndeadSlayRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetLevel() >= 12) {
|
||||||
|
if (
|
||||||
|
GetClass() == Class::Warrior ||
|
||||||
|
(GetClass() == Class::Ranger && skill == EQ::skills::SkillArchery) ||
|
||||||
|
(GetClass() == Class::Rogue && skill == EQ::skills::SkillThrowing) ||
|
||||||
|
GetClass() == Class::Berserker
|
||||||
|
) {
|
||||||
|
innate_crit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have a chance to crit!
|
||||||
|
if (innate_crit || crit_chance) {
|
||||||
|
int difficulty = 0;
|
||||||
|
|
||||||
|
if (skill == EQ::skills::SkillArchery) {
|
||||||
|
difficulty = RuleI(Combat, ArcheryCritDifficulty);
|
||||||
|
} else if (skill == EQ::skills::SkillThrowing) {
|
||||||
|
difficulty = RuleI(Combat, ThrowingCritDifficulty);
|
||||||
|
} else {
|
||||||
|
difficulty = RuleI(Combat, MeleeCritDifficulty);
|
||||||
|
}
|
||||||
|
|
||||||
|
int roll = zone->random.Int(1, difficulty);
|
||||||
|
|
||||||
|
int dex_bonus = GetDEX();
|
||||||
|
|
||||||
|
if (dex_bonus > 255) {
|
||||||
|
dex_bonus = 255 + ((dex_bonus - 255) / 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
dex_bonus += 45; // chances did not match live without a small boost
|
||||||
|
|
||||||
|
// so if we have an innate crit we have a better chance, except for ber throwing
|
||||||
|
if (!innate_crit || (GetClass() == Class::Berserker && skill == EQ::skills::SkillThrowing)) {
|
||||||
|
dex_bonus = dex_bonus * 3 / 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogCombat("Crit Chance: dex_bonus ({}) * crit_chance ({}) / 100", dex_bonus, crit_chance);
|
||||||
|
|
||||||
|
if (crit_chance) {
|
||||||
|
dex_bonus += dex_bonus * crit_chance / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we crited
|
||||||
|
LogCombat("Final Roll! Difficulty = [{}] -- Dex_Bonus = [{}] ", difficulty, dex_bonus);
|
||||||
|
return (roll < dex_bonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Mob::GetUndeadSlayRate()
|
||||||
|
{
|
||||||
|
return aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::DoUndeadSlay(DamageHitInfo &hit, int crit_mod)
|
||||||
|
{
|
||||||
|
|
||||||
|
int slay_damage_bonus = std::max(
|
||||||
|
{ aabonuses.SlayUndead[1], itembonuses.SlayUndead[1], spellbonuses.SlayUndead[1] });
|
||||||
|
|
||||||
|
LogCombatDetail("Slayundead bonus [{}]", slay_damage_bonus);
|
||||||
|
|
||||||
|
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
||||||
|
hit.damage_done = (hit.damage_done * slay_damage_bonus * crit_mod) / 100;
|
||||||
|
hit.damage_done = static_cast<int>(hit.damage_done * RuleR(Combat, SlayDamageAdjustment));
|
||||||
|
|
||||||
|
LogCombatDetail("Slayundead damage [{}]", hit.damage_done);
|
||||||
|
|
||||||
|
int slay_sex = GetGender() == Gender::Female ? FEMALE_SLAYUNDEAD : MALE_SLAYUNDEAD;
|
||||||
|
|
||||||
|
entity_list.FilteredMessageString(
|
||||||
|
this, /* Sender */
|
||||||
|
false, /* Skip Sender */
|
||||||
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
|
slay_sex, /* MessageFormat: %1's holy blade cleanses her target!(%2) */
|
||||||
|
GetCleanName(), /* Message1 */
|
||||||
|
itoa(hit.damage_done) /* Message2 */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// a lot of good info: http://giline.versus.jp/shiden/damage_e.htm, http://giline.versus.jp/shiden/su.htm
|
||||||
void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts)
|
void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts)
|
||||||
{
|
{
|
||||||
#ifdef LUA_EQEMU
|
#ifdef LUA_EQEMU
|
||||||
@@ -5414,185 +5509,116 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNPC() && !RuleB(Combat, NPCCanCrit))
|
if (IsNPC() && !RuleB(Combat, NPCCanCrit)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 1: Try Slay Undead
|
// Step 1: Check if we are critting
|
||||||
if (defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead ||
|
if (!RollMeleeCritCheck(defender, hit.skill)) {
|
||||||
defender->GetBodyType() == BT_Vampire) {
|
return;
|
||||||
int SlayRateBonus = aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] + itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] + spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD];
|
}
|
||||||
if (SlayRateBonus) {
|
|
||||||
float slayChance = static_cast<float>(SlayRateBonus) / 10000.0f;
|
|
||||||
if (zone->random.Roll(slayChance)) {
|
|
||||||
int SlayDmgBonus = std::max(
|
|
||||||
{aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD], itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD], spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] });
|
|
||||||
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
|
||||||
hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100;
|
|
||||||
|
|
||||||
/* Female */
|
int crit_mod = EQ::ClampLower((170 + GetCritDmgMod(hit.skill)), 100);
|
||||||
if (GetGender() == Gender::Female) {
|
|
||||||
entity_list.FilteredMessageCloseString(
|
// Step 2: Calculate damage
|
||||||
this, /* Sender */
|
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
||||||
false, /* Skip Sender */
|
int og_damage = hit.damage_done;
|
||||||
RuleI(Range, CriticalDamage),
|
hit.damage_done = hit.damage_done * crit_mod / 100;
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
LogCombatDetail("Crit info: [{}] scaled from: [{}] - IsUndeadForSlay: [{}]", hit.damage_done, og_damage, IsUndeadForSlay() ? "true" : "false");
|
||||||
FEMALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses her target!(%2) */
|
|
||||||
0,
|
// Try Slay Undead
|
||||||
GetCleanName(), /* Message1 */
|
if (defender->IsUndeadForSlay()) {
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
float chance = GetUndeadSlayRate() / 100.0f;
|
||||||
);
|
LogCombatDetail("Trying Undead slay: Chance: [{}]", chance);
|
||||||
}
|
|
||||||
/* Males and Neuter */
|
if(zone->random.Roll(chance)) {
|
||||||
else {
|
DoUndeadSlay(hit, crit_mod);
|
||||||
entity_list.FilteredMessageCloseString(
|
return;
|
||||||
this, /* Sender */
|
|
||||||
false, /* Skip Sender */
|
|
||||||
RuleI(Range, CriticalDamage),
|
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
|
||||||
MALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses his target!(%2) */
|
|
||||||
0,
|
|
||||||
GetCleanName(), /* Message1 */
|
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2: Try Melee Critical
|
// Step 3: Check deadly strike
|
||||||
// a lot of good info: http://giline.versus.jp/shiden/damage_e.htm, http://giline.versus.jp/shiden/su.htm
|
if (GetClass() == Class::Rogue && hit.skill == EQ::skills::SkillThrowing && BehindMob(defender, GetX(), GetY())) {
|
||||||
|
int chance = GetLevel() * 12;
|
||||||
|
if (zone->random.Int(1, 1000) < chance) {
|
||||||
|
// Check assassinate
|
||||||
|
int assassinate_damage = TryAssassinate(defender, hit.skill);
|
||||||
|
|
||||||
// We either require an innate crit chance or some SPA 169 to crit
|
if (assassinate_damage) {
|
||||||
bool innate_crit = false;
|
hit.damage_done = assassinate_damage;
|
||||||
int crit_chance = GetCriticalChanceBonus(hit.skill);
|
|
||||||
if ((GetClass() == Class::Warrior || GetClass() == Class::Berserker) && GetLevel() >= 12)
|
|
||||||
innate_crit = true;
|
|
||||||
else if (GetClass() == Class::Ranger && GetLevel() >= 12 && hit.skill == EQ::skills::SkillArchery)
|
|
||||||
innate_crit = true;
|
|
||||||
else if (GetClass() == Class::Rogue && GetLevel() >= 12 && hit.skill == EQ::skills::SkillThrowing)
|
|
||||||
innate_crit = true;
|
|
||||||
|
|
||||||
// we have a chance to crit!
|
|
||||||
if (innate_crit || crit_chance) {
|
|
||||||
int difficulty = 0;
|
|
||||||
if (hit.skill == EQ::skills::SkillArchery)
|
|
||||||
difficulty = RuleI(Combat, ArcheryCritDifficulty);
|
|
||||||
else if (hit.skill == EQ::skills::SkillThrowing)
|
|
||||||
difficulty = RuleI(Combat, ThrowingCritDifficulty);
|
|
||||||
else
|
|
||||||
difficulty = RuleI(Combat, MeleeCritDifficulty);
|
|
||||||
int roll = zone->random.Int(1, difficulty);
|
|
||||||
|
|
||||||
int dex_bonus = GetDEX();
|
|
||||||
if (dex_bonus > 255)
|
|
||||||
dex_bonus = 255 + ((dex_bonus - 255) / 5);
|
|
||||||
dex_bonus += 45; // chances did not match live without a small boost
|
|
||||||
|
|
||||||
// so if we have an innate crit we have a better chance, except for ber throwing
|
|
||||||
if (!innate_crit || (GetClass() == Class::Berserker && hit.skill == EQ::skills::SkillThrowing))
|
|
||||||
dex_bonus = dex_bonus * 3 / 5;
|
|
||||||
|
|
||||||
if (crit_chance)
|
|
||||||
dex_bonus += dex_bonus * crit_chance / 100;
|
|
||||||
|
|
||||||
// check if we crited
|
|
||||||
if (roll < dex_bonus) {
|
|
||||||
// step 1: check for finishing blow
|
|
||||||
if (TryFinishingBlow(defender, hit.damage_done))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// step 2: calculate damage
|
|
||||||
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
|
||||||
int og_damage = hit.damage_done;
|
|
||||||
int crit_mod = 170 + GetCritDmgMod(hit.skill);
|
|
||||||
if (crit_mod < 100) {
|
|
||||||
crit_mod = 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hit.damage_done = hit.damage_done * crit_mod / 100;
|
hit.damage_done = hit.damage_done * 200 / 100;
|
||||||
LogCombat("Crit success roll [{}] dex chance [{}] og dmg [{}] crit_mod [{}] new dmg [{}]", roll, dex_bonus, og_damage, crit_mod, hit.damage_done);
|
|
||||||
|
|
||||||
// step 3: check deadly strike
|
entity_list.FilteredMessageCloseString(
|
||||||
if (GetClass() == Class::Rogue && hit.skill == EQ::skills::SkillThrowing) {
|
|
||||||
if (BehindMob(defender, GetX(), GetY())) {
|
|
||||||
int chance = GetLevel() * 12;
|
|
||||||
if (zone->random.Int(1, 1000) < chance) {
|
|
||||||
// step 3a: check assassinate
|
|
||||||
int assdmg = TryAssassinate(defender, hit.skill); // I don't think this is right
|
|
||||||
if (assdmg) {
|
|
||||||
hit.damage_done = assdmg;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hit.damage_done = hit.damage_done * 200 / 100;
|
|
||||||
|
|
||||||
entity_list.FilteredMessageCloseString(
|
|
||||||
this, /* Sender */
|
|
||||||
false, /* Skip Sender */
|
|
||||||
RuleI(Range, CriticalDamage),
|
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
|
||||||
DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */
|
|
||||||
0,
|
|
||||||
GetCleanName(), /* Message1 */
|
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// step 4: check crips
|
|
||||||
// this SPA was reused on live ...
|
|
||||||
bool berserk = spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA;
|
|
||||||
if (!berserk) {
|
|
||||||
if (zone->random.Roll(GetCrippBlowChance())) {
|
|
||||||
berserk = true;
|
|
||||||
} // TODO: Holyforge is suppose to have an innate extra undead chance? 1/5 which matches the SPA crip though ...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsBerserk() || berserk) {
|
|
||||||
hit.damage_done += og_damage * 119 / 100;
|
|
||||||
LogCombat("Crip damage [{}]", hit.damage_done);
|
|
||||||
|
|
||||||
entity_list.FilteredMessageCloseString(
|
|
||||||
this, /* Sender */
|
this, /* Sender */
|
||||||
false, /* Skip Sender */
|
false, /* Skip Sender */
|
||||||
RuleI(Range, CriticalDamage),
|
RuleI(Range, CriticalDamage),
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */
|
DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */
|
||||||
0,
|
0,
|
||||||
GetCleanName(), /* Message1 */
|
GetCleanName(), /* Message1 */
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
itoa(hit.damage_done) /* Message2 */
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Crippling blows also have a chance to stun
|
// Step 4: check cripple
|
||||||
// Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a
|
bool berserk = spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA;
|
||||||
// staggers message.
|
|
||||||
if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(UNSTUNABLE)) {
|
|
||||||
defender->Emote("staggers.");
|
|
||||||
defender->Stun(RuleI(Combat, StunDuration));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normal Critical hit message */
|
if (!berserk && zone->random.Roll(GetCrippBlowChance())) {
|
||||||
entity_list.FilteredMessageCloseString(
|
berserk = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsBerserk() || berserk) {
|
||||||
|
hit.damage_done += og_damage * 119 / 100;
|
||||||
|
LogCombatDetail("Crippling damage [{}]", hit.damage_done);
|
||||||
|
|
||||||
|
entity_list.FilteredMessageCloseString(
|
||||||
this, /* Sender */
|
this, /* Sender */
|
||||||
false, /* Skip Sender */
|
false, /* Skip Sender */
|
||||||
RuleI(Range, CriticalDamage),
|
RuleI(Range, CriticalDamage),
|
||||||
Chat::MeleeCrit, /* Type: 301 */
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
FilterMeleeCrits, /* FilterType: 12 */
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
|
CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */
|
||||||
0,
|
0,
|
||||||
GetCleanName(), /* Message1 */
|
GetCleanName(), /* Message1 */
|
||||||
itoa(hit.damage_done + hit.min_damage) /* Message2 */
|
itoa(hit.damage_done) /* Message2 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// Crippling blows also have a chance to stun
|
||||||
|
// Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a
|
||||||
|
// staggers message.
|
||||||
|
if (defender->GetLevel() <= RuleI(Combat, MaximumLevelStunsCripplingBlow) && !defender->GetSpecialAbility(SpecialAbility::StunImmunity)) {
|
||||||
|
entity_list.MessageCloseString(
|
||||||
|
defender,
|
||||||
|
true,
|
||||||
|
RuleI(Range, Emote),
|
||||||
|
Chat::Emote,
|
||||||
|
STAGGERS,
|
||||||
|
GetName()
|
||||||
);
|
);
|
||||||
|
defender->Stun(RuleI(Combat, StunDuration));
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Normal Critical hit message */
|
||||||
|
entity_list.FilteredMessageCloseString(
|
||||||
|
this, /* Sender */
|
||||||
|
false, /* Skip Sender */
|
||||||
|
RuleI(Range, CriticalDamage),
|
||||||
|
Chat::MeleeCrit, /* Type: 301 */
|
||||||
|
FilterMeleeCrits, /* FilterType: 12 */
|
||||||
|
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
|
||||||
|
0,
|
||||||
|
GetCleanName(), /* Message1 */
|
||||||
|
itoa(hit.damage_done) /* Message2 */
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
||||||
@@ -6459,7 +6485,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
|||||||
// this appears where they do special attack dmg mods
|
// this appears where they do special attack dmg mods
|
||||||
int spec_mod = 0;
|
int spec_mod = 0;
|
||||||
if (IsSpecialAttack(eSpecialAttacks::Rampage)) {
|
if (IsSpecialAttack(eSpecialAttacks::Rampage)) {
|
||||||
int mod = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2);
|
int mod = GetSpecialAbilityParam(SpecialAbility::Rampage, 2);
|
||||||
if (mod > 0)
|
if (mod > 0)
|
||||||
spec_mod = mod;
|
spec_mod = mod;
|
||||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||||
@@ -6470,7 +6496,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsSpecialAttack(eSpecialAttacks::AERampage)) {
|
else if (IsSpecialAttack(eSpecialAttacks::AERampage)) {
|
||||||
int mod = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2);
|
int mod = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 2);
|
||||||
if (mod > 0)
|
if (mod > 0)
|
||||||
spec_mod = mod;
|
spec_mod = mod;
|
||||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||||
@@ -6773,8 +6799,8 @@ void NPC::SetAttackTimer()
|
|||||||
|
|
||||||
//special offhand stuff
|
//special offhand stuff
|
||||||
if (i == EQ::invslot::slotSecondary) {
|
if (i == EQ::invslot::slotSecondary) {
|
||||||
// SPECATK_QUAD is uncheesable
|
// SpecialAbility::QuadrupleAttack is uncheesable
|
||||||
if (!CanThisClassDualWield() || (HasTwoHanderEquipped() && !GetSpecialAbility(SPECATK_QUAD))) {
|
if (!CanThisClassDualWield() || (HasTwoHanderEquipped() && !GetSpecialAbility(SpecialAbility::QuadrupleAttack))) {
|
||||||
attack_dw_timer.Disable();
|
attack_dw_timer.Disable();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -6932,18 +6958,18 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, bool ram
|
|||||||
// thresholds, and if its truely random, then this should work
|
// thresholds, and if its truely random, then this should work
|
||||||
// out reasonably and will save us compute resources.
|
// out reasonably and will save us compute resources.
|
||||||
int32 RandRoll = zone->random.Int(0, 99);
|
int32 RandRoll = zone->random.Int(0, 99);
|
||||||
if ((CanThisClassDoubleAttack() || GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD))
|
if ((CanThisClassDoubleAttack() || GetSpecialAbility(SpecialAbility::TripleAttack) || GetSpecialAbility(SpecialAbility::QuadrupleAttack))
|
||||||
// check double attack, this is NOT the same rules that clients use...
|
// check double attack, this is NOT the same rules that clients use...
|
||||||
&&
|
&&
|
||||||
RandRoll < (GetLevel() + NPCDualAttackModifier)) {
|
RandRoll < (GetLevel() + NPCDualAttackModifier)) {
|
||||||
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
||||||
// lets see if we can do a triple attack with the main hand
|
// lets see if we can do a triple attack with the main hand
|
||||||
// pets are excluded from triple and quads...
|
// pets are excluded from triple and quads...
|
||||||
if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) && !IsPet() &&
|
if ((GetSpecialAbility(SpecialAbility::TripleAttack) || GetSpecialAbility(SpecialAbility::QuadrupleAttack)) && !IsPet() &&
|
||||||
RandRoll < (GetLevel() + NPCTripleAttackModifier)) {
|
RandRoll < (GetLevel() + NPCTripleAttackModifier)) {
|
||||||
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
||||||
// now lets check the quad attack
|
// now lets check the quad attack
|
||||||
if (GetSpecialAbility(SPECATK_QUAD) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) {
|
if (GetSpecialAbility(SpecialAbility::QuadrupleAttack) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) {
|
||||||
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6957,9 +6983,9 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, bool ramp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mobs will only dual wield w/ the flag or have a secondary weapon
|
// Mobs will only dual wield w/ the flag or have a secondary weapon
|
||||||
// For now, SPECATK_QUAD means innate DW when Combat:UseLiveCombatRounds is true
|
// For now, SpecialAbility::QuadrupleAttack means innate DW when Combat:UseLiveCombatRounds is true
|
||||||
if ((GetSpecialAbility(SPECATK_INNATE_DW) ||
|
if ((GetSpecialAbility(SpecialAbility::DualWield) ||
|
||||||
(RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) ||
|
(RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SpecialAbility::QuadrupleAttack))) ||
|
||||||
GetEquippedItemFromTextureSlot(EQ::textures::weaponSecondary) != 0) {
|
GetEquippedItemFromTextureSlot(EQ::textures::weaponSecondary) != 0) {
|
||||||
if (CheckDualWield()) {
|
if (CheckDualWield()) {
|
||||||
Attack(target, EQ::invslot::slotSecondary, false, false, false, opts);
|
Attack(target, EQ::invslot::slotSecondary, false, false, false, opts);
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ Beacon::Beacon(const glm::vec4 &in_pos, int lifetime) : Mob(
|
|||||||
Race::InvisibleMan, // in_race
|
Race::InvisibleMan, // in_race
|
||||||
Class::None, // in_class
|
Class::None, // in_class
|
||||||
BT_NoTarget, // in_bodytype
|
BT_NoTarget, // in_bodytype
|
||||||
0, // in_deity
|
Deity::Unknown, // in_deity
|
||||||
0, // in_level
|
0, // in_level
|
||||||
0, // in_npctype_id
|
0, // in_npctype_id
|
||||||
0.0f, // in_size
|
0.0f, // in_size
|
||||||
|
|||||||
+1
-1
@@ -2220,7 +2220,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
|||||||
{
|
{
|
||||||
// These don't generate the IMMUNE_ATKSPEED message and the icon shows up
|
// These don't generate the IMMUNE_ATKSPEED message and the icon shows up
|
||||||
// but have no effect on the mobs attack speed
|
// but have no effect on the mobs attack speed
|
||||||
if (GetSpecialAbility(UNSLOWABLE))
|
if (GetSpecialAbility(SpecialAbility::SlowImmunity))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow)
|
if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow)
|
||||||
|
|||||||
+5
-5
@@ -652,7 +652,7 @@ NPCType *Bot::FillNPCTypeStruct(
|
|||||||
n->race = botRace;
|
n->race = botRace;
|
||||||
n->class_ = botClass;
|
n->class_ = botClass;
|
||||||
n->bodytype = 1;
|
n->bodytype = 1;
|
||||||
n->deity = EQ::deity::DeityAgnostic;
|
n->deity = Deity::Agnostic1;
|
||||||
n->level = botLevel;
|
n->level = botLevel;
|
||||||
n->npc_spells_id = botSpellsID;
|
n->npc_spells_id = botSpellsID;
|
||||||
n->AC = ac;
|
n->AC = ac;
|
||||||
@@ -712,7 +712,7 @@ NPCType *Bot::CreateDefaultNPCTypeStructForBot(
|
|||||||
n->race = botRace;
|
n->race = botRace;
|
||||||
n->class_ = botClass;
|
n->class_ = botClass;
|
||||||
n->bodytype = 1;
|
n->bodytype = 1;
|
||||||
n->deity = EQ::deity::DeityAgnostic;
|
n->deity = Deity::Agnostic1;
|
||||||
n->level = botLevel;
|
n->level = botLevel;
|
||||||
n->AC = 12;
|
n->AC = 12;
|
||||||
n->ATK = 75;
|
n->ATK = 75;
|
||||||
@@ -2418,14 +2418,14 @@ bool Bot::TryPrimaryWeaponAttacks(Mob* tar, const EQ::ItemInstance* p_item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (GetAppearance() == eaDead) { return false; }
|
if (GetAppearance() == eaDead) { return false; }
|
||||||
if (GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) {
|
if (GetSpecialAbility(SpecialAbility::TripleAttack) && CheckBotDoubleAttack(true)) {
|
||||||
|
|
||||||
Attack(tar, EQ::invslot::slotPrimary, true);
|
Attack(tar, EQ::invslot::slotPrimary, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetAppearance() == eaDead) { return false; }
|
if (GetAppearance() == eaDead) { return false; }
|
||||||
// quad attack, does this belong here??
|
// quad attack, does this belong here??
|
||||||
if (GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) {
|
if (GetSpecialAbility(SpecialAbility::QuadrupleAttack) && CheckBotDoubleAttack(true)) {
|
||||||
Attack(tar, EQ::invslot::slotPrimary, true);
|
Attack(tar, EQ::invslot::slotPrimary, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5635,7 +5635,7 @@ int32 Bot::GenerateBaseManaPoints()
|
|||||||
|
|
||||||
void Bot::GenerateSpecialAttacks() {
|
void Bot::GenerateSpecialAttacks() {
|
||||||
if (((GetClass() == Class::Monk) || (GetClass() == Class::Warrior) || (GetClass() == Class::Ranger) || (GetClass() == Class::Berserker)) && (GetLevel() >= 60))
|
if (((GetClass() == Class::Monk) || (GetClass() == Class::Warrior) || (GetClass() == Class::Ranger) || (GetClass() == Class::Berserker)) && (GetLevel() >= 60))
|
||||||
SetSpecialAbility(SPECATK_TRIPLE, 1);
|
SetSpecialAbility(SpecialAbility::TripleAttack, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
|
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
|
||||||
|
|||||||
@@ -784,7 +784,7 @@ bool Bot::BotCastNuke(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
|||||||
stunChance = 50;
|
stunChance = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) {
|
if (!tar->GetSpecialAbility(SpecialAbility::StunImmunity) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) {
|
||||||
botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target);
|
botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-16
@@ -96,7 +96,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
|||||||
Race::Doug, // in_race
|
Race::Doug, // in_race
|
||||||
Class::None, // in_class
|
Class::None, // in_class
|
||||||
BT_Humanoid, // in_bodytype
|
BT_Humanoid, // in_bodytype
|
||||||
0, // in_deity
|
Deity::Unknown, // in_deity
|
||||||
0, // in_level
|
0, // in_level
|
||||||
0, // in_npctype_id
|
0, // in_npctype_id
|
||||||
0.0f, // in_size
|
0.0f, // in_size
|
||||||
@@ -2671,8 +2671,8 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who,
|
|||||||
|
|
||||||
if (against_who) {
|
if (against_who) {
|
||||||
if (
|
if (
|
||||||
against_who->GetSpecialAbility(IMMUNE_AGGRO) ||
|
against_who->GetSpecialAbility(SpecialAbility::AggroImmunity) ||
|
||||||
against_who->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) ||
|
against_who->GetSpecialAbility(SpecialAbility::ClientAggroImmunity) ||
|
||||||
against_who->IsClient() ||
|
against_who->IsClient() ||
|
||||||
GetLevelCon(against_who->GetLevel()) == ConsiderColor::Gray
|
GetLevelCon(against_who->GetLevel()) == ConsiderColor::Gray
|
||||||
) {
|
) {
|
||||||
@@ -5060,7 +5060,7 @@ void Client::HandleLDoNOpen(NPC *target)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->GetSpecialAbility(IMMUNE_OPEN))
|
if (target->GetSpecialAbility(SpecialAbility::OpenImmunity))
|
||||||
{
|
{
|
||||||
LogDebug("[{}] tried to open [{}] but it was immune", GetName(), target->GetName());
|
LogDebug("[{}] tried to open [{}] but it was immune", GetName(), target->GetName());
|
||||||
return;
|
return;
|
||||||
@@ -9170,29 +9170,32 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id)
|
|||||||
*
|
*
|
||||||
* @param player_name
|
* @param player_name
|
||||||
*/
|
*/
|
||||||
bool Client::GotoPlayer(std::string player_name)
|
bool Client::GotoPlayer(const std::string& player_name)
|
||||||
{
|
{
|
||||||
const auto& l = CharacterDataRepository::GetWhere(
|
const auto& l = CharacterDataRepository::GetWhere(
|
||||||
database,
|
database,
|
||||||
fmt::format("name = '{}' AND last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name)
|
fmt::format(
|
||||||
|
"name = '{}' AND last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1",
|
||||||
|
Strings::Escape(player_name)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (l.empty()) {
|
if (l.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& c = l[0];
|
const auto& e = l.front();
|
||||||
|
|
||||||
if (c.zone_instance > 0 && !database.CheckInstanceExists(c.zone_instance)) {
|
if (e.zone_instance > 0 && !database.CheckInstanceExists(e.zone_instance)) {
|
||||||
Message(Chat::Yellow, "Instance no longer exists...");
|
Message(Chat::Yellow, "Instance no longer exists...");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.zone_instance > 0) {
|
if (e.zone_instance > 0) {
|
||||||
database.AddClientToInstance(c.zone_instance, CharacterID());
|
database.AddClientToInstance(e.zone_instance, CharacterID());
|
||||||
}
|
}
|
||||||
|
|
||||||
MovePC(c.zone_id, c.zone_instance, c.x, c.y, c.z, c.heading);
|
MovePC(e.zone_id, e.zone_instance, e.x, e.y, e.z, e.heading);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -11783,11 +11786,11 @@ void Client::RegisterBug(BugReport_Struct* r) {
|
|||||||
b.target_id = r->target_id;
|
b.target_id = r->target_id;
|
||||||
b.target_name = r->target_name;
|
b.target_name = r->target_name;
|
||||||
b.optional_info_mask = r->optional_info_mask;
|
b.optional_info_mask = r->optional_info_mask;
|
||||||
b._can_duplicate = ((r->optional_info_mask & EQ::bug::infoCanDuplicate) != 0 ? 1 : 0);
|
b._can_duplicate = ((r->optional_info_mask & Bug::InformationFlag::Repeatable) != 0 ? 1 : 0);
|
||||||
b._crash_bug = ((r->optional_info_mask & EQ::bug::infoCrashBug) != 0 ? 1 : 0);
|
b._crash_bug = ((r->optional_info_mask & Bug::InformationFlag::Crash) != 0 ? 1 : 0);
|
||||||
b._target_info = ((r->optional_info_mask & EQ::bug::infoTargetInfo) != 0 ? 1 : 0);
|
b._target_info = ((r->optional_info_mask & Bug::InformationFlag::TargetInfo) != 0 ? 1 : 0);
|
||||||
b._character_flags = ((r->optional_info_mask & EQ::bug::infoCharacterFlags) != 0 ? 1 : 0);
|
b._character_flags = ((r->optional_info_mask & Bug::InformationFlag::CharacterFlags) != 0 ? 1 : 0);
|
||||||
b._unknown_value = ((r->optional_info_mask & EQ::bug::infoUnknownValue) != 0 ? 1 : 0);
|
b._unknown_value = ((r->optional_info_mask & Bug::InformationFlag::Unknown) != 0 ? 1 : 0);
|
||||||
b.bug_report = r->bug_report;
|
b.bug_report = r->bug_report;
|
||||||
b.system_info = r->system_info;
|
b.system_info = r->system_info;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -258,7 +258,7 @@ public:
|
|||||||
|
|
||||||
void SendChatLineBreak(uint16 color = Chat::White);
|
void SendChatLineBreak(uint16 color = Chat::White);
|
||||||
|
|
||||||
bool GotoPlayer(std::string player_name);
|
bool GotoPlayer(const std::string& player_name);
|
||||||
bool GotoPlayerGroup(const std::string& player_name);
|
bool GotoPlayerGroup(const std::string& player_name);
|
||||||
bool GotoPlayerRaid(const std::string& player_name);
|
bool GotoPlayerRaid(const std::string& player_name);
|
||||||
|
|
||||||
|
|||||||
@@ -5807,7 +5807,7 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app)
|
|||||||
RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e);
|
RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteItemInInventory(alc->from_slot, 1);
|
DeleteItemInInventory(alc->from_slot, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11536,8 +11536,8 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, mypet->GetCleanName());
|
entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, mypet->GetCleanName());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bool immune_aggro = GetSpecialAbility(IMMUNE_AGGRO);
|
bool has_aggro_immunity = GetSpecialAbility(SpecialAbility::AggroImmunity);
|
||||||
mypet->SetSpecialAbility(IMMUNE_AGGRO, 1);
|
mypet->SetSpecialAbility(SpecialAbility::AggroImmunity, 1);
|
||||||
mypet->WipeHateList();
|
mypet->WipeHateList();
|
||||||
mypet->SetPetOrder(SPO_FeignDeath);
|
mypet->SetPetOrder(SPO_FeignDeath);
|
||||||
mypet->SetRunAnimSpeed(0);
|
mypet->SetRunAnimSpeed(0);
|
||||||
@@ -11549,8 +11549,8 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
mypet->InterruptSpell();
|
mypet->InterruptSpell();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!immune_aggro) {
|
if (!has_aggro_immunity) {
|
||||||
mypet->SetSpecialAbility(IMMUNE_AGGRO, 0);
|
mypet->SetSpecialAbility(SpecialAbility::AggroImmunity, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -513,7 +513,7 @@ void Perl__sfollow()
|
|||||||
quest_manager.sfollow();
|
quest_manager.sfollow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__changedeity(int deity_id)
|
void Perl__changedeity(uint32 deity_id)
|
||||||
{
|
{
|
||||||
quest_manager.changedeity(deity_id);
|
quest_manager.changedeity(deity_id);
|
||||||
}
|
}
|
||||||
@@ -4940,6 +4940,11 @@ void Perl__set_proximity_range(float x_range, float y_range, float z_range, bool
|
|||||||
quest_manager.set_proximity_range(x_range, y_range, z_range, enable_say);
|
quest_manager.set_proximity_range(x_range, y_range, z_range, enable_say);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Perl__varlink(EQ::ItemInstance* inst)
|
||||||
|
{
|
||||||
|
return quest_manager.varlink(inst);
|
||||||
|
}
|
||||||
|
|
||||||
std::string Perl__varlink(uint32 item_id)
|
std::string Perl__varlink(uint32 item_id)
|
||||||
{
|
{
|
||||||
return quest_manager.varlink(item_id);
|
return quest_manager.varlink(item_id);
|
||||||
@@ -5845,9 +5850,9 @@ uint16 Perl__get_class_bitmask(uint8 class_id)
|
|||||||
return GetPlayerClassBit(class_id);
|
return GetPlayerClassBit(class_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Perl__get_deity_bitmask(uint16 deity_id)
|
uint32 Perl__get_deity_bitmask(uint32 deity_id)
|
||||||
{
|
{
|
||||||
return static_cast<uint32>(EQ::deity::GetDeityBitmask(static_cast<EQ::deity::DeityType>(deity_id)));
|
return Deity::GetBitmask(deity_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Perl__get_race_bitmask(uint16 race_id)
|
uint16 Perl__get_race_bitmask(uint16 race_id)
|
||||||
@@ -6856,6 +6861,7 @@ void perl_register_quest()
|
|||||||
package.add("updatetaskactivity", (void(*)(int, int, int))&Perl__updatetaskactivity);
|
package.add("updatetaskactivity", (void(*)(int, int, int))&Perl__updatetaskactivity);
|
||||||
package.add("updatetaskactivity", (void(*)(int, int, int, bool))&Perl__updatetaskactivity);
|
package.add("updatetaskactivity", (void(*)(int, int, int, bool))&Perl__updatetaskactivity);
|
||||||
package.add("UpdateZoneHeader", &Perl__UpdateZoneHeader);
|
package.add("UpdateZoneHeader", &Perl__UpdateZoneHeader);
|
||||||
|
package.add("varlink", (std::string(*)(EQ::ItemInstance*))&Perl__varlink);
|
||||||
package.add("varlink", (std::string(*)(uint32))&Perl__varlink);
|
package.add("varlink", (std::string(*)(uint32))&Perl__varlink);
|
||||||
package.add("varlink", (std::string(*)(uint32, int16))&Perl__varlink);
|
package.add("varlink", (std::string(*)(uint32, int16))&Perl__varlink);
|
||||||
package.add("varlink", (std::string(*)(uint32, int16, uint32))&Perl__varlink);
|
package.add("varlink", (std::string(*)(uint32, int16, uint32))&Perl__varlink);
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ Encounter::Encounter(const char *enc_name) : Mob(
|
|||||||
Race::InvisibleMan, // in_race
|
Race::InvisibleMan, // in_race
|
||||||
Class::None, // in_class
|
Class::None, // in_class
|
||||||
BT_NoTarget, // in_bodytype
|
BT_NoTarget, // in_bodytype
|
||||||
0, // in_deity
|
Deity::Unknown, // in_deity
|
||||||
0, // in_level
|
0, // in_level
|
||||||
0, // in_npcype_id
|
0, // in_npcype_id
|
||||||
0, // in_size
|
0, // in_size
|
||||||
|
|||||||
+11
-11
@@ -1544,7 +1544,7 @@ void EntityList::RemoveFromTargetsFadingMemories(Mob *spell_target, bool RemoveF
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mob->GetSpecialAbility(IMMUNE_FADING_MEMORIES)) {
|
if (mob->GetSpecialAbility(SpecialAbility::MemoryFadeImmunity)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3638,7 +3638,7 @@ void EntityList::ClearFeignAggro(Mob *targ)
|
|||||||
while (it != npc_list.end()) {
|
while (it != npc_list.end()) {
|
||||||
// add Feign Memory check because sometimes weird stuff happens
|
// add Feign Memory check because sometimes weird stuff happens
|
||||||
if (it->second->CheckAggro(targ) || (targ->IsClient() && it->second->IsOnFeignMemory(targ))) {
|
if (it->second->CheckAggro(targ) || (targ->IsClient() && it->second->IsOnFeignMemory(targ))) {
|
||||||
if (it->second->GetSpecialAbility(IMMUNE_FEIGN_DEATH)) {
|
if (it->second->GetSpecialAbility(SpecialAbility::FeignDeathImmunity)) {
|
||||||
++it;
|
++it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3667,7 +3667,7 @@ void EntityList::ClearFeignAggro(Mob *targ)
|
|||||||
|
|
||||||
it->second->RemoveFromHateList(targ);
|
it->second->RemoveFromHateList(targ);
|
||||||
|
|
||||||
if (it->second->GetSpecialAbility(SPECATK_RAMPAGE)) {
|
if (it->second->GetSpecialAbility(SpecialAbility::Rampage)) {
|
||||||
it->second->RemoveFromRampageList(targ, true);
|
it->second->RemoveFromRampageList(targ, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4384,10 +4384,10 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
|
|||||||
if (n && n->GetSwarmInfo()) {
|
if (n && n->GetSwarmInfo()) {
|
||||||
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
|
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
|
||||||
if (
|
if (
|
||||||
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!n->GetSpecialAbility(SpecialAbility::AggroImmunity) &&
|
||||||
!(other->IsBot() && n->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
!(other->IsBot() && n->GetSpecialAbility(SpecialAbility::BotAggroImmunity)) &&
|
||||||
!(other->IsClient() && n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
!(other->IsClient() && n->GetSpecialAbility(SpecialAbility::ClientAggroImmunity)) &&
|
||||||
!(other->IsNPC() && n->GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
!(other->IsNPC() && n->GetSpecialAbility(SpecialAbility::NPCAggroImmunity))
|
||||||
) {
|
) {
|
||||||
n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
@@ -4411,10 +4411,10 @@ void EntityList::AddTempPetsToHateListOnOwnerDamage(Mob *owner, Mob* attacker, i
|
|||||||
attacker &&
|
attacker &&
|
||||||
attacker != n &&
|
attacker != n &&
|
||||||
!n->IsEngaged() &&
|
!n->IsEngaged() &&
|
||||||
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!n->GetSpecialAbility(SpecialAbility::AggroImmunity) &&
|
||||||
!(attacker->IsBot() && n->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
!(attacker->IsBot() && n->GetSpecialAbility(SpecialAbility::BotAggroImmunity)) &&
|
||||||
!(attacker->IsClient() && n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
!(attacker->IsClient() && n->GetSpecialAbility(SpecialAbility::ClientAggroImmunity)) &&
|
||||||
!(attacker->IsNPC() && n->GetSpecialAbility(IMMUNE_AGGRO_NPC)) &&
|
!(attacker->IsNPC() && n->GetSpecialAbility(SpecialAbility::NPCAggroImmunity)) &&
|
||||||
!attacker->IsTrap() &&
|
!attacker->IsTrap() &&
|
||||||
!attacker->IsCorpse()
|
!attacker->IsCorpse()
|
||||||
) {
|
) {
|
||||||
|
|||||||
+6
-6
@@ -44,7 +44,7 @@ void Mob::CheckFlee()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//dont bother if we are immune to fleeing
|
//dont bother if we are immune to fleeing
|
||||||
if (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) {
|
if (GetSpecialAbility(SpecialAbility::FleeingImmunity) || spellbonuses.ImmuneToFlee) {
|
||||||
LogFlee("Mob [{}] is immune to fleeing via special ability or spell bonus", GetCleanName());
|
LogFlee("Mob [{}] is immune to fleeing via special ability or spell bonus", GetCleanName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ void Mob::CheckFlee()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int hp_ratio = GetIntHPRatio();
|
int hp_ratio = GetIntHPRatio();
|
||||||
int flee_ratio = GetSpecialAbility(FLEE_PERCENT); // if a special flee_percent exists
|
int flee_ratio = GetSpecialAbility(SpecialAbility::FleePercent); // if a special SpecialAbility::FleePercent exists
|
||||||
Mob *hate_top = GetHateTop();
|
Mob *hate_top = GetHateTop();
|
||||||
|
|
||||||
LogFlee("Mob [{}] hp_ratio [{}] flee_ratio [{}]", GetCleanName(), hp_ratio, flee_ratio);
|
LogFlee("Mob [{}] hp_ratio [{}] flee_ratio [{}]", GetCleanName(), hp_ratio, flee_ratio);
|
||||||
@@ -137,10 +137,10 @@ void Mob::CheckFlee()
|
|||||||
);
|
);
|
||||||
|
|
||||||
// If we got here we are allowed to roll on flee chance if there is not other hated NPC's in the area.
|
// If we got here we are allowed to roll on flee chance if there is not other hated NPC's in the area.
|
||||||
// ALWAYS_FLEE, skip roll
|
// SpecialAbility::AlwaysFlee, skip roll
|
||||||
// if FleeIfNotAlone is true, we skip alone check
|
// if FleeIfNotAlone is true, we skip alone check
|
||||||
// roll chance
|
// roll chance
|
||||||
if (GetSpecialAbility(ALWAYS_FLEE) ||
|
if (GetSpecialAbility(SpecialAbility::AlwaysFlee) ||
|
||||||
((RuleB(Combat, FleeIfNotAlone) || entity_list.GetHatedCount(hate_top, this, true) == 0) &&
|
((RuleB(Combat, FleeIfNotAlone) || entity_list.GetHatedCount(hate_top, this, true) == 0) &&
|
||||||
zone->random.Roll(flee_chance))) {
|
zone->random.Roll(flee_chance))) {
|
||||||
|
|
||||||
@@ -164,14 +164,14 @@ void Mob::ProcessFlee()
|
|||||||
|
|
||||||
//Stop fleeing if effect is applied after they start to run.
|
//Stop fleeing if effect is applied after they start to run.
|
||||||
//When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee.
|
//When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee.
|
||||||
if (flee_mode && (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) &&
|
if (flee_mode && (GetSpecialAbility(SpecialAbility::FleeingImmunity) || spellbonuses.ImmuneToFlee) &&
|
||||||
!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
|
!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
|
||||||
currently_fleeing = false;
|
currently_fleeing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hpratio = GetIntHPRatio();
|
int hpratio = GetIntHPRatio();
|
||||||
int fleeratio = GetSpecialAbility(FLEE_PERCENT); // if a special flee_percent exists
|
int fleeratio = GetSpecialAbility(SpecialAbility::FleePercent); // if a special SpecialAbility::FleePercent exists
|
||||||
Mob *hate_top = GetHateTop();
|
Mob *hate_top = GetHateTop();
|
||||||
|
|
||||||
// If no special flee_percent check for Gray or Other con rates
|
// If no special flee_percent check for Gray or Other con rates
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include "../client.h"
|
#include "../client.h"
|
||||||
#include "find/aa.cpp"
|
#include "find/aa.cpp"
|
||||||
|
#include "find/bug_category.cpp"
|
||||||
#include "find/character.cpp"
|
#include "find/character.cpp"
|
||||||
#include "find/class.cpp"
|
#include "find/class.cpp"
|
||||||
|
#include "find/comparison_type.cpp"
|
||||||
#include "find/currency.cpp"
|
#include "find/currency.cpp"
|
||||||
#include "find/deity.cpp"
|
#include "find/deity.cpp"
|
||||||
#include "find/emote.cpp"
|
#include "find/emote.cpp"
|
||||||
@@ -13,6 +15,7 @@
|
|||||||
#include "find/recipe.cpp"
|
#include "find/recipe.cpp"
|
||||||
#include "find/skill.cpp"
|
#include "find/skill.cpp"
|
||||||
#include "find/spell.cpp"
|
#include "find/spell.cpp"
|
||||||
|
#include "find/special_ability.cpp"
|
||||||
#include "find/task.cpp"
|
#include "find/task.cpp"
|
||||||
#include "find/zone.cpp"
|
#include "find/zone.cpp"
|
||||||
|
|
||||||
@@ -30,8 +33,10 @@ void command_find(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
std::vector<Cmd> commands = {
|
std::vector<Cmd> commands = {
|
||||||
Cmd{.cmd = "aa", .u = "aa [Search Criteria]", .fn = FindAA, .a = {"#findaa"}},
|
Cmd{.cmd = "aa", .u = "aa [Search Criteria]", .fn = FindAA, .a = {"#findaa"}},
|
||||||
|
Cmd{.cmd = "bug_category", .u = "bug_category [Search Criteria]", .fn = FindBugCategory, .a = {"#findbugcategory"}},
|
||||||
Cmd{.cmd = "character", .u = "character [Search Criteria]", .fn = FindCharacter, .a = {"#findcharacter"}},
|
Cmd{.cmd = "character", .u = "character [Search Criteria]", .fn = FindCharacter, .a = {"#findcharacter"}},
|
||||||
Cmd{.cmd = "class", .u = "class [Search Criteria]", .fn = FindClass, .a = {"#findclass"}},
|
Cmd{.cmd = "class", .u = "class [Search Criteria]", .fn = FindClass, .a = {"#findclass"}},
|
||||||
|
Cmd{.cmd = "comparison_type", .u = "comparison_type [Search Criteria]", .fn = FindComparisonType, .a = {"#findcomparisontype"}},
|
||||||
Cmd{.cmd = "currency", .u = "currency [Search Criteria]", .fn = FindCurrency, .a = {"#findcurrency"}},
|
Cmd{.cmd = "currency", .u = "currency [Search Criteria]", .fn = FindCurrency, .a = {"#findcurrency"}},
|
||||||
Cmd{.cmd = "deity", .u = "deity [Search Criteria]", .fn = FindDeity, .a = {"#finddeity"}},
|
Cmd{.cmd = "deity", .u = "deity [Search Criteria]", .fn = FindDeity, .a = {"#finddeity"}},
|
||||||
Cmd{.cmd = "emote", .u = "emote [Search Criteria]", .fn = FindEmote, .a = {"#findemote"}},
|
Cmd{.cmd = "emote", .u = "emote [Search Criteria]", .fn = FindEmote, .a = {"#findemote"}},
|
||||||
@@ -48,6 +53,7 @@ void command_find(Client *c, const Seperator *sep)
|
|||||||
Cmd{.cmd = "race", .u = "race [Search Criteria]", .fn = FindRace, .a = {"#findrace"}},
|
Cmd{.cmd = "race", .u = "race [Search Criteria]", .fn = FindRace, .a = {"#findrace"}},
|
||||||
Cmd{.cmd = "recipe", .u = "recipe [Search Criteria]", .fn = FindRecipe, .a = {"#findrecipe"}},
|
Cmd{.cmd = "recipe", .u = "recipe [Search Criteria]", .fn = FindRecipe, .a = {"#findrecipe"}},
|
||||||
Cmd{.cmd = "skill", .u = "skill [Search Criteria]", .fn = FindSkill, .a = {"#findskill"}},
|
Cmd{.cmd = "skill", .u = "skill [Search Criteria]", .fn = FindSkill, .a = {"#findskill"}},
|
||||||
|
Cmd{.cmd = "special_ability", .u = "special_ability [Search Criteria]", .fn = FindSpecialAbility, .a = {"#fsa", "#findspecialability"}},
|
||||||
Cmd{.cmd = "spell", .u = "spell [Search Criteria]", .fn = FindSpell, .a = {"#fs", "#findspell"}},
|
Cmd{.cmd = "spell", .u = "spell [Search Criteria]", .fn = FindSpell, .a = {"#fs", "#findspell"}},
|
||||||
Cmd{.cmd = "task", .u = "task [Search Criteria]", .fn = FindTask, .a = {"#findtask"}},
|
Cmd{.cmd = "task", .u = "task [Search Criteria]", .fn = FindTask, .a = {"#findtask"}},
|
||||||
Cmd{.cmd = "zone", .u = "zone [Search Criteria]", .fn = FindZone, .a = {"#fz", "#findzone"}},
|
Cmd{.cmd = "zone", .u = "zone [Search Criteria]", .fn = FindZone, .a = {"#fz", "#findzone"}},
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#include "../../client.h"
|
||||||
|
|
||||||
|
void FindBugCategory(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (sep->IsNumber(2)) {
|
||||||
|
const uint32 category_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||||
|
const std::string& category_name = Bug::GetName(category_id);
|
||||||
|
if (Strings::EqualFold(category_name, "UNKNOWN BUG CATEGORY")) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Bug Category ID {} does not exist.",
|
||||||
|
category_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Bug Category {} | {}",
|
||||||
|
category_id,
|
||||||
|
category_name
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
|
||||||
|
|
||||||
|
uint32 found_count = 0;
|
||||||
|
|
||||||
|
for (const auto& e : bug_category_names) {
|
||||||
|
const std::string& bug_category_name_lower = Strings::ToLower(e.second);
|
||||||
|
if (!Strings::Contains(bug_category_name_lower, search_criteria)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Bug Category {} | {}",
|
||||||
|
e.first,
|
||||||
|
e.second
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} Bug Categor{} found matching '{}'.",
|
||||||
|
found_count,
|
||||||
|
found_count != 1 ? "ies" : "y",
|
||||||
|
sep->argplus[2]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#include "../../client.h"
|
||||||
|
|
||||||
|
void FindComparisonType(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (sep->IsNumber(2)) {
|
||||||
|
const uint8 type = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[2]));
|
||||||
|
const std::string& type_name = ComparisonType::GetName(type);
|
||||||
|
if (Strings::EqualFold(type_name, "UNKNOWN COMPARISON TYPE")) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Comparison Type {} does not exist.",
|
||||||
|
type
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Comparison Type {} | {}",
|
||||||
|
type,
|
||||||
|
type_name
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
|
||||||
|
|
||||||
|
uint32 found_count = 0;
|
||||||
|
|
||||||
|
for (const auto& e : comparison_types) {
|
||||||
|
const std::string& type_name_lower = Strings::ToLower(e.second);
|
||||||
|
if (!Strings::Contains(type_name_lower, search_criteria)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Comparison Type {} | {}",
|
||||||
|
e.first,
|
||||||
|
e.second
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} Comparison Type{} found matching '{}'.",
|
||||||
|
found_count,
|
||||||
|
found_count != 1 ? "s" : "",
|
||||||
|
sep->argplus[2]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,46 +3,45 @@
|
|||||||
void FindDeity(Client *c, const Seperator *sep)
|
void FindDeity(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
if (sep->IsNumber(2)) {
|
if (sep->IsNumber(2)) {
|
||||||
const auto deity_id = static_cast<EQ::deity::DeityType>(Strings::ToInt(sep->arg[2]));
|
const uint32 deity_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||||
const auto& deity_name = EQ::deity::GetDeityName(deity_id);
|
const std::string& deity_name = Deity::GetName(deity_id);
|
||||||
if (!deity_name.empty()) {
|
if (Strings::EqualFold(deity_name, "UNKNOWN DEITY")) {
|
||||||
const auto deity_bit = EQ::deity::GetDeityBitmask(deity_id);
|
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Deity {} | {} ({})",
|
"Deity ID {} does not exist.",
|
||||||
deity_id,
|
deity_id
|
||||||
deity_name,
|
|
||||||
Strings::Commify(deity_bit)
|
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32 deity_bitmask = Deity::GetBitmask(deity_id);
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Deity ID {} was not found.",
|
"Deity {} | {} ({})",
|
||||||
deity_id
|
deity_id,
|
||||||
|
deity_name,
|
||||||
|
Strings::Commify(deity_bitmask)
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& search_criteria = Strings::ToLower(sep->argplus[2]);
|
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
|
||||||
|
|
||||||
auto found_count = 0;
|
uint32 found_count = 0;
|
||||||
|
|
||||||
for (const auto& d : EQ::deity::GetDeityMap()) {
|
for (const auto& d : deity_names) {
|
||||||
const auto& deity_name_lower = Strings::ToLower(d.second);
|
const std::string& deity_name_lower = Strings::ToLower(d.second);
|
||||||
if (!Strings::Contains(deity_name_lower, search_criteria)) {
|
if (!Strings::Contains(deity_name_lower, search_criteria)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto deity_bit = EQ::deity::GetDeityBitmask(d.first);
|
const uint32 deity_bitmask = Deity::GetBitmask(d.first);
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
@@ -50,7 +49,7 @@ void FindDeity(Client *c, const Seperator *sep)
|
|||||||
"Deity {} | {} ({})",
|
"Deity {} | {} ({})",
|
||||||
d.first,
|
d.first,
|
||||||
d.second,
|
d.second,
|
||||||
Strings::Commify(deity_bit)
|
Strings::Commify(deity_bitmask)
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#include "../../client.h"
|
||||||
|
|
||||||
|
void FindSpecialAbility(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (sep->IsNumber(2)) {
|
||||||
|
const int ability_id = Strings::ToInt(sep->arg[2]);
|
||||||
|
const std::string& ability_name = SpecialAbility::GetName(ability_id);
|
||||||
|
if (Strings::EqualFold(ability_name, "UNKNOWN SPECIAL ABILITY")) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Ability ID {} does not exist.",
|
||||||
|
ability_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Ability {} | {}",
|
||||||
|
ability_id,
|
||||||
|
ability_name
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
|
||||||
|
|
||||||
|
uint32 found_count = 0;
|
||||||
|
|
||||||
|
for (const auto& e : special_ability_names) {
|
||||||
|
const std::string& ability_name_lower = Strings::ToLower(e.second);
|
||||||
|
if (!Strings::Contains(ability_name_lower, search_criteria)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Ability {} | {}",
|
||||||
|
e.first,
|
||||||
|
e.second
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
found_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} Abilit{} found matching '{}'.",
|
||||||
|
found_count,
|
||||||
|
found_count != 1 ? "ies" : "y",
|
||||||
|
sep->argplus[2]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
+62
-43
@@ -2,63 +2,82 @@
|
|||||||
|
|
||||||
void command_goto(Client *c, const Seperator *sep)
|
void command_goto(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
std::string arg1 = sep->arg[1];
|
const uint16 arguments = sep->argnum;
|
||||||
std::string arg4 = sep->arg[4];
|
|
||||||
|
|
||||||
bool goto_via_target_no_args = sep->arg[1][0] == '\0' && c->GetTarget();
|
const bool goto_player = !sep->IsNumber(1) && sep->arg[1];
|
||||||
bool goto_via_player_name = !sep->IsNumber(1) && !arg1.empty();
|
const bool goto_position = sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3);
|
||||||
bool goto_via_x_y_z = sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3);
|
const bool goto_target = !arguments && c->GetTarget();
|
||||||
|
|
||||||
if (goto_via_target_no_args) {
|
if (!goto_player && !goto_position && !goto_target) {
|
||||||
c->MovePC(
|
c->Message(Chat::White, "Usage: #goto [x y z] [h]");
|
||||||
zone->GetZoneID(),
|
c->Message(Chat::White, "Usage: #goto [player_name]");
|
||||||
zone->GetInstanceID(),
|
c->Message(Chat::White, "Usage: #goto (Target required)");
|
||||||
c->GetTarget()->GetX(),
|
return;
|
||||||
c->GetTarget()->GetY(),
|
|
||||||
c->GetTarget()->GetZ(),
|
|
||||||
c->GetTarget()->GetHeading()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else if (goto_via_player_name) {
|
|
||||||
|
|
||||||
/**
|
if (goto_player) {
|
||||||
* Find them in zone first
|
const std::string& name = sep->arg[1];
|
||||||
*/
|
Client* t = entity_list.GetClientByName(name.c_str());
|
||||||
const char *player_name = sep->arg[1];
|
if (t) {
|
||||||
std::string player_name_string = sep->arg[1];
|
|
||||||
Client *client = entity_list.GetClientByName(player_name);
|
|
||||||
if (client) {
|
|
||||||
c->MovePC(
|
c->MovePC(
|
||||||
zone->GetZoneID(),
|
zone->GetZoneID(),
|
||||||
zone->GetInstanceID(),
|
zone->GetInstanceID(),
|
||||||
client->GetX(),
|
t->GetX(),
|
||||||
client->GetY(),
|
t->GetY(),
|
||||||
client->GetZ(),
|
t->GetZ(),
|
||||||
client->GetHeading()
|
t->GetHeading()
|
||||||
);
|
);
|
||||||
|
|
||||||
c->Message(Chat::Yellow, "Goto player '%s' same zone", player_name_string.c_str());
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Going to player {} in the same zone.",
|
||||||
|
name
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
} else if (c->GotoPlayer(name)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Going to player {} in a different zone.",
|
||||||
|
name
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Player {} could not be found.",
|
||||||
|
name
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (c->GotoPlayer(player_name_string)) {
|
} else if (goto_position) {
|
||||||
c->Message(Chat::Yellow, "Goto player '%s' different zone", player_name_string.c_str());
|
const glm::vec4& position = glm::vec4(
|
||||||
}
|
|
||||||
else {
|
|
||||||
c->Message(Chat::Yellow, "Player '%s' not found", player_name_string.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (goto_via_x_y_z) {
|
|
||||||
c->MovePC(
|
|
||||||
zone->GetZoneID(),
|
|
||||||
zone->GetInstanceID(),
|
|
||||||
Strings::ToFloat(sep->arg[1]),
|
Strings::ToFloat(sep->arg[1]),
|
||||||
Strings::ToFloat(sep->arg[2]),
|
Strings::ToFloat(sep->arg[2]),
|
||||||
Strings::ToFloat(sep->arg[3]),
|
Strings::ToFloat(sep->arg[3]),
|
||||||
(!arg4.empty() ? Strings::ToFloat(sep->arg[4]) : c->GetHeading())
|
sep->arg[4] && Strings::IsFloat(sep->arg[4]) ? Strings::ToFloat(sep->arg[1]) : c->GetHeading()
|
||||||
|
);
|
||||||
|
c->MovePC(
|
||||||
|
zone->GetZoneID(),
|
||||||
|
zone->GetInstanceID(),
|
||||||
|
position.x,
|
||||||
|
position.y,
|
||||||
|
position.z,
|
||||||
|
position.w
|
||||||
|
);
|
||||||
|
} else if (goto_target) {
|
||||||
|
Mob* t = c->GetTarget();
|
||||||
|
|
||||||
|
c->MovePC(
|
||||||
|
zone->GetZoneID(),
|
||||||
|
zone->GetInstanceID(),
|
||||||
|
t->GetX(),
|
||||||
|
t->GetY(),
|
||||||
|
t->GetZ(),
|
||||||
|
t->GetHeading()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
else {
|
|
||||||
c->Message(Chat::White, "Usage: #goto [x y z] [h]");
|
|
||||||
c->Message(Chat::White, "Usage: #goto [player_name]");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -496,7 +496,7 @@ Mob *HateList::GetMobWithMostHateOnList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!is_top_client_type) {
|
if (!is_top_client_type) {
|
||||||
if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)) {
|
if (top_hate->GetSpecialAbility(SpecialAbility::AllowedToTank)) {
|
||||||
is_top_client_type = true;
|
is_top_client_type = true;
|
||||||
top_client_type_in_range = top_hate;
|
top_client_type_in_range = top_hate;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -157,7 +157,7 @@ uint16 Lua_Client::GetClassBitmask() {
|
|||||||
|
|
||||||
uint32 Lua_Client::GetDeityBitmask() {
|
uint32 Lua_Client::GetDeityBitmask() {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return static_cast<uint32>(EQ::deity::GetDeityBitmask(static_cast<EQ::deity::DeityType>(GetDeity())));
|
return Deity::GetBitmask(GetDeity());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Lua_Client::GetRaceBitmask() {
|
uint16 Lua_Client::GetRaceBitmask() {
|
||||||
|
|||||||
@@ -3991,6 +3991,10 @@ void lua_do_anim(int animation_id, int animation_speed, bool ackreq, int filter)
|
|||||||
quest_manager.doanim(animation_id, animation_speed, ackreq, static_cast<eqFilterType>(filter));
|
quest_manager.doanim(animation_id, animation_speed, ackreq, static_cast<eqFilterType>(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string lua_item_link(Lua_ItemInst inst) {
|
||||||
|
return quest_manager.varlink(inst);
|
||||||
|
}
|
||||||
|
|
||||||
std::string lua_item_link(uint32 item_id) {
|
std::string lua_item_link(uint32 item_id) {
|
||||||
return quest_manager.varlink(item_id);
|
return quest_manager.varlink(item_id);
|
||||||
}
|
}
|
||||||
@@ -5480,8 +5484,8 @@ uint16 lua_get_class_bitmask(uint8 class_id) {
|
|||||||
return GetPlayerClassBit(class_id);
|
return GetPlayerClassBit(class_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 lua_get_deity_bitmask(uint16 deity_id) {
|
uint32 lua_get_deity_bitmask(uint32 deity_id) {
|
||||||
return static_cast<uint32>(EQ::deity::GetDeityBitmask(static_cast<EQ::deity::DeityType>(deity_id)));
|
return Deity::GetBitmask(deity_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 lua_get_race_bitmask(uint16 race_id) {
|
uint16 lua_get_race_bitmask(uint16 race_id) {
|
||||||
@@ -5922,6 +5926,7 @@ luabind::scope lua_register_general() {
|
|||||||
luabind::def("merchant_set_item", (void(*)(uint32,uint32))&lua_merchant_set_item),
|
luabind::def("merchant_set_item", (void(*)(uint32,uint32))&lua_merchant_set_item),
|
||||||
luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item),
|
luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item),
|
||||||
luabind::def("merchant_count_item", &lua_merchant_count_item),
|
luabind::def("merchant_count_item", &lua_merchant_count_item),
|
||||||
|
luabind::def("item_link", (std::string(*)(Lua_ItemInst))&lua_item_link),
|
||||||
luabind::def("item_link", (std::string(*)(uint32))&lua_item_link),
|
luabind::def("item_link", (std::string(*)(uint32))&lua_item_link),
|
||||||
luabind::def("item_link", (std::string(*)(uint32,int16))&lua_item_link),
|
luabind::def("item_link", (std::string(*)(uint32,int16))&lua_item_link),
|
||||||
luabind::def("item_link", (std::string(*)(uint32,int16,uint32))&lua_item_link),
|
luabind::def("item_link", (std::string(*)(uint32,int16,uint32))&lua_item_link),
|
||||||
|
|||||||
@@ -337,6 +337,17 @@ luabind::object Lua_ItemInst::GetAugmentIDs(lua_State* L)
|
|||||||
return lua_table;
|
return lua_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Lua_ItemInst::GetItemLink()
|
||||||
|
{
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
|
||||||
|
EQ::SayLinkEngine linker;
|
||||||
|
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
||||||
|
linker.SetItemInst(self);
|
||||||
|
|
||||||
|
return linker.GenerateLink();
|
||||||
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_iteminst() {
|
luabind::scope lua_register_iteminst() {
|
||||||
return luabind::class_<Lua_ItemInst>("ItemInst")
|
return luabind::class_<Lua_ItemInst>("ItemInst")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
@@ -363,6 +374,7 @@ luabind::scope lua_register_iteminst() {
|
|||||||
.def("GetItem", (Lua_Item(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItem)
|
.def("GetItem", (Lua_Item(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItem)
|
||||||
.def("GetItem", (Lua_ItemInst(Lua_ItemInst::*)(uint8))&Lua_ItemInst::GetItem)
|
.def("GetItem", (Lua_ItemInst(Lua_ItemInst::*)(uint8))&Lua_ItemInst::GetItem)
|
||||||
.def("GetItemID", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetItemID)
|
.def("GetItemID", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetItemID)
|
||||||
|
.def("GetItemLink", (std::string(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItemLink)
|
||||||
.def("GetItemScriptID", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItemScriptID)
|
.def("GetItemScriptID", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItemScriptID)
|
||||||
.def("GetKillsNeeded", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetKillsNeeded)
|
.def("GetKillsNeeded", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetKillsNeeded)
|
||||||
.def("GetMaxEvolveLvl", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetMaxEvolveLvl)
|
.def("GetMaxEvolveLvl", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetMaxEvolveLvl)
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ public:
|
|||||||
void ItemSay(const char* text);
|
void ItemSay(const char* text);
|
||||||
void ItemSay(const char* text, uint8 language_id);
|
void ItemSay(const char* text, uint8 language_id);
|
||||||
luabind::object GetAugmentIDs(lua_State* L);
|
luabind::object GetAugmentIDs(lua_State* L);
|
||||||
|
std::string GetItemLink();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool cloned_;
|
bool cloned_;
|
||||||
|
|||||||
+59
-60
@@ -3301,7 +3301,7 @@ bool Lua_Mob::IsAlwaysAggro()
|
|||||||
std::string Lua_Mob::GetDeityName()
|
std::string Lua_Mob::GetDeityName()
|
||||||
{
|
{
|
||||||
Lua_Safe_Call_String();
|
Lua_Safe_Call_String();
|
||||||
return EQ::deity::GetDeityName(static_cast<EQ::deity::DeityType>(self->GetDeity()));
|
return Deity::GetName(self->GetDeity());
|
||||||
}
|
}
|
||||||
|
|
||||||
luabind::object Lua_Mob::GetBuffs(lua_State* L)
|
luabind::object Lua_Mob::GetBuffs(lua_State* L)
|
||||||
@@ -3942,65 +3942,64 @@ luabind::scope lua_register_mob() {
|
|||||||
|
|
||||||
luabind::scope lua_register_special_abilities() {
|
luabind::scope lua_register_special_abilities() {
|
||||||
return luabind::class_<SpecialAbilities>("SpecialAbility")
|
return luabind::class_<SpecialAbilities>("SpecialAbility")
|
||||||
|
.enum_("constants")
|
||||||
.enum_("constants")
|
[(
|
||||||
[(
|
luabind::value("summon", SpecialAbility::Summon),
|
||||||
luabind::value("summon", static_cast<int>(SPECATK_SUMMON)),
|
luabind::value("enrage", SpecialAbility::Enrage),
|
||||||
luabind::value("enrage", static_cast<int>(SPECATK_ENRAGE)),
|
luabind::value("rampage", SpecialAbility::Rampage),
|
||||||
luabind::value("rampage", static_cast<int>(SPECATK_RAMPAGE)),
|
luabind::value("area_rampage", SpecialAbility::AreaRampage),
|
||||||
luabind::value("area_rampage", static_cast<int>(SPECATK_AREA_RAMPAGE)),
|
luabind::value("flurry", SpecialAbility::Flurry),
|
||||||
luabind::value("flurry", static_cast<int>(SPECATK_FLURRY)),
|
luabind::value("triple_attack", SpecialAbility::TripleAttack),
|
||||||
luabind::value("triple_attack", static_cast<int>(SPECATK_TRIPLE)),
|
luabind::value("quad_attack", SpecialAbility::QuadrupleAttack),
|
||||||
luabind::value("quad_attack", static_cast<int>(SPECATK_QUAD)),
|
luabind::value("innate_dual_wield", SpecialAbility::DualWield),
|
||||||
luabind::value("innate_dual_wield", static_cast<int>(SPECATK_INNATE_DW)),
|
luabind::value("bane_attack", SpecialAbility::BaneAttack),
|
||||||
luabind::value("bane_attack", static_cast<int>(SPECATK_BANE)),
|
luabind::value("magical_attack", SpecialAbility::MagicalAttack),
|
||||||
luabind::value("magical_attack", static_cast<int>(SPECATK_MAGICAL)),
|
luabind::value("ranged_attack", SpecialAbility::RangedAttack),
|
||||||
luabind::value("ranged_attack", static_cast<int>(SPECATK_RANGED_ATK)),
|
luabind::value("unslowable", SpecialAbility::SlowImmunity),
|
||||||
luabind::value("unslowable", static_cast<int>(UNSLOWABLE)),
|
luabind::value("unmezable", SpecialAbility::MesmerizeImmunity),
|
||||||
luabind::value("unmezable", static_cast<int>(UNMEZABLE)),
|
luabind::value("uncharmable", SpecialAbility::CharmImmunity),
|
||||||
luabind::value("uncharmable", static_cast<int>(UNCHARMABLE)),
|
luabind::value("unstunable", SpecialAbility::StunImmunity),
|
||||||
luabind::value("unstunable", static_cast<int>(UNSTUNABLE)),
|
luabind::value("unsnareable", SpecialAbility::SnareImmunity),
|
||||||
luabind::value("unsnareable", static_cast<int>(UNSNAREABLE)),
|
luabind::value("unfearable", SpecialAbility::FearImmunity),
|
||||||
luabind::value("unfearable", static_cast<int>(UNFEARABLE)),
|
luabind::value("undispellable", SpecialAbility::DispellImmunity),
|
||||||
luabind::value("undispellable", static_cast<int>(UNDISPELLABLE)),
|
luabind::value("immune_melee", SpecialAbility::MeleeImmunity),
|
||||||
luabind::value("immune_melee", static_cast<int>(IMMUNE_MELEE)),
|
luabind::value("immune_magic", SpecialAbility::MagicImmunity),
|
||||||
luabind::value("immune_magic", static_cast<int>(IMMUNE_MAGIC)),
|
luabind::value("immune_fleeing", SpecialAbility::FleeingImmunity),
|
||||||
luabind::value("immune_fleeing", static_cast<int>(IMMUNE_FLEEING)),
|
luabind::value("immune_melee_except_bane", SpecialAbility::MeleeImmunityExceptBane),
|
||||||
luabind::value("immune_melee_except_bane", static_cast<int>(IMMUNE_MELEE_EXCEPT_BANE)),
|
luabind::value("immune_melee_except_magical", SpecialAbility::MeleeImmunityExceptMagical),
|
||||||
luabind::value("immune_melee_except_magical", static_cast<int>(IMMUNE_MELEE_NONMAGICAL)),
|
luabind::value("immune_aggro", SpecialAbility::AggroImmunity),
|
||||||
luabind::value("immune_aggro", static_cast<int>(IMMUNE_AGGRO)),
|
luabind::value("immune_aggro_on", SpecialAbility::BeingAggroImmunity),
|
||||||
luabind::value("immune_aggro_on", static_cast<int>(IMMUNE_AGGRO_ON)),
|
luabind::value("immune_casting_from_range", SpecialAbility::CastingFromRangeImmunity),
|
||||||
luabind::value("immune_casting_from_range", static_cast<int>(IMMUNE_CASTING_FROM_RANGE)),
|
luabind::value("immune_feign_death", SpecialAbility::FeignDeathImmunity),
|
||||||
luabind::value("immune_feign_death", static_cast<int>(IMMUNE_FEIGN_DEATH)),
|
luabind::value("immune_taunt", SpecialAbility::TauntImmunity),
|
||||||
luabind::value("immune_taunt", static_cast<int>(IMMUNE_TAUNT)),
|
luabind::value("tunnelvision", SpecialAbility::TunnelVision),
|
||||||
luabind::value("tunnelvision", static_cast<int>(NPC_TUNNELVISION)),
|
luabind::value("dont_buff_friends", SpecialAbility::NoBuffHealFriends),
|
||||||
luabind::value("dont_buff_friends", static_cast<int>(NPC_NO_BUFFHEAL_FRIENDS)),
|
luabind::value("immune_pacify", SpecialAbility::PacifyImmunity),
|
||||||
luabind::value("immune_pacify", static_cast<int>(IMMUNE_PACIFY)),
|
luabind::value("leash", SpecialAbility::Leash),
|
||||||
luabind::value("leash", static_cast<int>(LEASH)),
|
luabind::value("tether", SpecialAbility::Tether),
|
||||||
luabind::value("tether", static_cast<int>(TETHER)),
|
luabind::value("destructible_object", SpecialAbility::DestructibleObject),
|
||||||
luabind::value("destructible_object", static_cast<int>(DESTRUCTIBLE_OBJECT)),
|
luabind::value("no_harm_from_client", SpecialAbility::HarmFromClientImmunity),
|
||||||
luabind::value("no_harm_from_client", static_cast<int>(NO_HARM_FROM_CLIENT)),
|
luabind::value("always_flee", SpecialAbility::AlwaysFlee),
|
||||||
luabind::value("always_flee", static_cast<int>(ALWAYS_FLEE)),
|
luabind::value("flee_percent", SpecialAbility::FleePercent),
|
||||||
luabind::value("flee_percent", static_cast<int>(FLEE_PERCENT)),
|
luabind::value("allow_beneficial", SpecialAbility::AllowBeneficial),
|
||||||
luabind::value("allow_beneficial", static_cast<int>(ALLOW_BENEFICIAL)),
|
luabind::value("disable_melee", SpecialAbility::DisableMelee),
|
||||||
luabind::value("disable_melee", static_cast<int>(DISABLE_MELEE)),
|
luabind::value("npc_chase_distance", SpecialAbility::NPCChaseDistance),
|
||||||
luabind::value("npc_chase_distance", static_cast<int>(NPC_CHASE_DISTANCE)),
|
luabind::value("allow_to_tank", SpecialAbility::AllowedToTank),
|
||||||
luabind::value("allow_to_tank", static_cast<int>(ALLOW_TO_TANK)),
|
luabind::value("ignore_root_aggro_rules", SpecialAbility::IgnoreRootAggroRules),
|
||||||
luabind::value("ignore_root_aggro_rules", static_cast<int>(IGNORE_ROOT_AGGRO_RULES)),
|
luabind::value("casting_resist_diff", SpecialAbility::CastingResistDifficulty),
|
||||||
luabind::value("casting_resist_diff", static_cast<int>(CASTING_RESIST_DIFF)),
|
luabind::value("counter_avoid_damage", SpecialAbility::CounterAvoidDamage),
|
||||||
luabind::value("counter_avoid_damage", static_cast<int>(COUNTER_AVOID_DAMAGE)),
|
luabind::value("immune_ranged_attacks", SpecialAbility::RangedAttackImmunity),
|
||||||
luabind::value("immune_ranged_attacks", static_cast<int>(IMMUNE_RANGED_ATTACKS)),
|
luabind::value("immune_damage_client", SpecialAbility::ClientDamageImmunity),
|
||||||
luabind::value("immune_damage_client", static_cast<int>(IMMUNE_DAMAGE_CLIENT)),
|
luabind::value("immune_damage_npc", SpecialAbility::NPCDamageImmunity),
|
||||||
luabind::value("immune_damage_npc", static_cast<int>(IMMUNE_DAMAGE_NPC)),
|
luabind::value("immune_aggro_client", SpecialAbility::ClientAggroImmunity),
|
||||||
luabind::value("immune_aggro_client", static_cast<int>(IMMUNE_AGGRO_CLIENT)),
|
luabind::value("immune_aggro_npc", SpecialAbility::NPCAggroImmunity),
|
||||||
luabind::value("immune_aggro_npc", static_cast<int>(IMMUNE_AGGRO_NPC)),
|
luabind::value("modify_avoid_damage", SpecialAbility::ModifyAvoidDamage),
|
||||||
luabind::value("modify_avoid_damage", static_cast<int>(MODIFY_AVOID_DAMAGE)),
|
luabind::value("immune_open", SpecialAbility::OpenImmunity),
|
||||||
luabind::value("immune_open", static_cast<int>(IMMUNE_OPEN)),
|
luabind::value("immune_assassinate", SpecialAbility::AssassinateImmunity),
|
||||||
luabind::value("immune_assassinate", static_cast<int>(IMMUNE_ASSASSINATE)),
|
luabind::value("immune_headshot", SpecialAbility::HeadshotImmunity),
|
||||||
luabind::value("immune_headshot", static_cast<int>(IMMUNE_HEADSHOT)),
|
luabind::value("immune_aggro_bot", SpecialAbility::BotAggroImmunity),
|
||||||
luabind::value("immune_aggro_bot", static_cast<int>(IMMUNE_AGGRO_BOT)),
|
luabind::value("immune_damage_bot", SpecialAbility::BotDamageImmunity)
|
||||||
luabind::value("immune_damage_bot", static_cast<int>(IMMUNE_DAMAGE_BOT))
|
)];
|
||||||
)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+3
-3
@@ -1191,13 +1191,13 @@ void Merc::AI_Process() {
|
|||||||
Attack(GetTarget(), EQ::invslot::slotPrimary, true);
|
Attack(GetTarget(), EQ::invslot::slotPrimary, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE)) {
|
if(GetOwner() && GetTarget() && GetSpecialAbility(SpecialAbility::TripleAttack)) {
|
||||||
tripleSuccess = true;
|
tripleSuccess = true;
|
||||||
Attack(GetTarget(), EQ::invslot::slotPrimary, true);
|
Attack(GetTarget(), EQ::invslot::slotPrimary, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//quad attack, does this belong here??
|
//quad attack, does this belong here??
|
||||||
if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_QUAD)) {
|
if(GetOwner() && GetTarget() && GetSpecialAbility(SpecialAbility::QuadrupleAttack)) {
|
||||||
Attack(GetTarget(), EQ::invslot::slotPrimary, true);
|
Attack(GetTarget(), EQ::invslot::slotPrimary, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1888,7 +1888,7 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) {
|
|||||||
|
|
||||||
selectedMercSpell = GetBestMercSpellForAENuke(this, tar);
|
selectedMercSpell = GetBestMercSpellForAENuke(this, tar);
|
||||||
|
|
||||||
if(selectedMercSpell.spellid == 0 && !tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned()) {
|
if(selectedMercSpell.spellid == 0 && !tar->GetSpecialAbility(SpecialAbility::StunImmunity) && !tar->IsStunned()) {
|
||||||
uint8 stunChance = 15;
|
uint8 stunChance = 15;
|
||||||
if(zone->random.Roll(stunChance)) {
|
if(zone->random.Roll(stunChance)) {
|
||||||
selectedMercSpell = GetBestMercSpellForStun(this);
|
selectedMercSpell = GetBestMercSpellForStun(this);
|
||||||
|
|||||||
+25
-25
@@ -4803,7 +4803,7 @@ bool Mob::HateSummon() {
|
|||||||
if (IsCharmed())
|
if (IsCharmed())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int summon_level = GetSpecialAbility(SPECATK_SUMMON);
|
int summon_level = GetSpecialAbility(SpecialAbility::Summon);
|
||||||
if(summon_level == 1 || summon_level == 2) {
|
if(summon_level == 1 || summon_level == 2) {
|
||||||
if(!GetTarget()) {
|
if(!GetTarget()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -4814,19 +4814,19 @@ bool Mob::HateSummon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate hp
|
// validate hp
|
||||||
int hp_ratio = GetSpecialAbilityParam(SPECATK_SUMMON, 1);
|
int hp_ratio = GetSpecialAbilityParam(SpecialAbility::Summon, 1);
|
||||||
hp_ratio = hp_ratio > 0 ? hp_ratio : 97;
|
hp_ratio = hp_ratio > 0 ? hp_ratio : 97;
|
||||||
if(GetHPRatio() > static_cast<float>(hp_ratio)) {
|
if(GetHPRatio() > static_cast<float>(hp_ratio)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now validate the timer
|
// now validate the timer
|
||||||
int summon_timer_duration = GetSpecialAbilityParam(SPECATK_SUMMON, 0);
|
int summon_timer_duration = GetSpecialAbilityParam(SpecialAbility::Summon, 0);
|
||||||
summon_timer_duration = summon_timer_duration > 0 ? summon_timer_duration : 6000;
|
summon_timer_duration = summon_timer_duration > 0 ? summon_timer_duration : 6000;
|
||||||
Timer *timer = GetSpecialAbilityTimer(SPECATK_SUMMON);
|
Timer *timer = GetSpecialAbilityTimer(SpecialAbility::Summon);
|
||||||
if (!timer)
|
if (!timer)
|
||||||
{
|
{
|
||||||
StartSpecialAbilityTimer(SPECATK_SUMMON, summon_timer_duration);
|
StartSpecialAbilityTimer(SpecialAbility::Summon, summon_timer_duration);
|
||||||
} else {
|
} else {
|
||||||
if(!timer->Check())
|
if(!timer->Check())
|
||||||
return false;
|
return false;
|
||||||
@@ -5261,20 +5261,20 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance* inst, uint16 spell_id, Mob* on,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidSpell(spell_id) || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) {
|
if (!IsValidSpell(spell_id) || on->GetSpecialAbility(SpecialAbility::HarmFromClientImmunity)) {
|
||||||
//This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging.
|
//This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsBot() && on->GetSpecialAbility(IMMUNE_DAMAGE_BOT)) {
|
if (IsBot() && on->GetSpecialAbility(SpecialAbility::BotDamageImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsClient() && on->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT)) {
|
if (IsClient() && on->GetSpecialAbility(SpecialAbility::ClientDamageImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNPC() && on->GetSpecialAbility(IMMUNE_DAMAGE_NPC)) {
|
if (IsNPC() && on->GetSpecialAbility(SpecialAbility::NPCDamageImmunity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6148,7 +6148,7 @@ void Mob::SetBottomRampageList()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mob->GetSpecialAbility(SPECATK_RAMPAGE)) {
|
if (!mob->GetSpecialAbility(SpecialAbility::Rampage)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6175,7 +6175,7 @@ void Mob::SetTopRampageList()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mob->GetSpecialAbility(SPECATK_RAMPAGE)) {
|
if (!mob->GetSpecialAbility(SpecialAbility::Rampage)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7501,7 +7501,7 @@ bool Mob::HasSpellEffect(int effect_id)
|
|||||||
|
|
||||||
int Mob::GetSpecialAbility(int ability)
|
int Mob::GetSpecialAbility(int ability)
|
||||||
{
|
{
|
||||||
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if (ability >= SpecialAbility::Max || ability < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7510,7 +7510,7 @@ int Mob::GetSpecialAbility(int ability)
|
|||||||
|
|
||||||
bool Mob::HasSpecialAbilities()
|
bool Mob::HasSpecialAbilities()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_SPECIAL_ATTACK; ++i) {
|
for (int i = 0; i < SpecialAbility::Max; ++i) {
|
||||||
if (GetSpecialAbility(i)) {
|
if (GetSpecialAbility(i)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -7520,7 +7520,7 @@ bool Mob::HasSpecialAbilities()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Mob::GetSpecialAbilityParam(int ability, int param) {
|
int Mob::GetSpecialAbilityParam(int ability, int param) {
|
||||||
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if(param >= SpecialAbility::MaxParameters || param < 0 || ability >= SpecialAbility::Max || ability < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7528,7 +7528,7 @@ int Mob::GetSpecialAbilityParam(int ability, int param) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mob::SetSpecialAbility(int ability, int level) {
|
void Mob::SetSpecialAbility(int ability, int level) {
|
||||||
if(ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if(ability >= SpecialAbility::Max || ability < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7536,7 +7536,7 @@ void Mob::SetSpecialAbility(int ability, int level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mob::SetSpecialAbilityParam(int ability, int param, int value) {
|
void Mob::SetSpecialAbilityParam(int ability, int param, int value) {
|
||||||
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if(param >= SpecialAbility::MaxParameters || param < 0 || ability >= SpecialAbility::Max || ability < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7544,7 +7544,7 @@ void Mob::SetSpecialAbilityParam(int ability, int param, int value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mob::StartSpecialAbilityTimer(int ability, uint32 time) {
|
void Mob::StartSpecialAbilityTimer(int ability, uint32 time) {
|
||||||
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if (ability >= SpecialAbility::Max || ability < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7557,7 +7557,7 @@ void Mob::StartSpecialAbilityTimer(int ability, uint32 time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mob::StopSpecialAbilityTimer(int ability) {
|
void Mob::StopSpecialAbilityTimer(int ability) {
|
||||||
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if (ability >= SpecialAbility::Max || ability < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7565,7 +7565,7 @@ void Mob::StopSpecialAbilityTimer(int ability) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Timer *Mob::GetSpecialAbilityTimer(int ability) {
|
Timer *Mob::GetSpecialAbilityTimer(int ability) {
|
||||||
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
|
if (ability >= SpecialAbility::Max || ability < 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7573,10 +7573,10 @@ Timer *Mob::GetSpecialAbilityTimer(int ability) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mob::ClearSpecialAbilities() {
|
void Mob::ClearSpecialAbilities() {
|
||||||
for(int a = 0; a < MAX_SPECIAL_ATTACK; ++a) {
|
for(int a = 0; a < SpecialAbility::Max; ++a) {
|
||||||
SpecialAbilities[a].level = 0;
|
SpecialAbilities[a].level = 0;
|
||||||
safe_delete(SpecialAbilities[a].timer);
|
safe_delete(SpecialAbilities[a].timer);
|
||||||
for(int p = 0; p < MAX_SPECIAL_ATTACK_PARAMS; ++p) {
|
for(int p = 0; p < SpecialAbility::MaxParameters; ++p) {
|
||||||
SpecialAbilities[a].params[p] = 0;
|
SpecialAbilities[a].params[p] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7599,12 +7599,12 @@ void Mob::ProcessSpecialAbilities(const std::string &str) {
|
|||||||
SetSpecialAbility(ability_id, value);
|
SetSpecialAbility(ability_id, value);
|
||||||
|
|
||||||
switch (ability_id) {
|
switch (ability_id) {
|
||||||
case SPECATK_QUAD:
|
case SpecialAbility::QuadrupleAttack:
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
SetSpecialAbility(SPECATK_TRIPLE, 1);
|
SetSpecialAbility(SpecialAbility::TripleAttack, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DESTRUCTIBLE_OBJECT:
|
case SpecialAbility::DestructibleObject:
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
SetDestructibleObject(false);
|
SetDestructibleObject(false);
|
||||||
} else {
|
} else {
|
||||||
@@ -7616,7 +7616,7 @@ void Mob::ProcessSpecialAbilities(const std::string &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 2, param_id = 0; i < sub_sp.size(); ++i, ++param_id) {
|
for (size_t i = 2, param_id = 0; i < sub_sp.size(); ++i, ++param_id) {
|
||||||
if (param_id >= MAX_SPECIAL_ATTACK_PARAMS) {
|
if (param_id >= SpecialAbility::MaxParameters) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-13
@@ -41,8 +41,6 @@
|
|||||||
|
|
||||||
char* strn0cpy(char* dest, const char* source, uint32 size);
|
char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||||
|
|
||||||
#define MAX_SPECIAL_ATTACK_PARAMS 9
|
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
class EQApplicationPacket;
|
class EQApplicationPacket;
|
||||||
class Group;
|
class Group;
|
||||||
@@ -102,22 +100,22 @@ public:
|
|||||||
CLIENT_KICKED, DISCONNECTED, CLIENT_ERROR, CLIENT_CONNECTINGALL };
|
CLIENT_KICKED, DISCONNECTED, CLIENT_ERROR, CLIENT_CONNECTINGALL };
|
||||||
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath };
|
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath };
|
||||||
|
|
||||||
struct SpecialAbility {
|
struct MobSpecialAbility {
|
||||||
SpecialAbility() {
|
MobSpecialAbility() {
|
||||||
level = 0;
|
level = 0;
|
||||||
timer = nullptr;
|
timer = nullptr;
|
||||||
for(int i = 0; i < MAX_SPECIAL_ATTACK_PARAMS; ++i) {
|
for (int i = 0; i < SpecialAbility::MaxParameters; ++i) {
|
||||||
params[i] = 0;
|
params[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~SpecialAbility() {
|
~MobSpecialAbility() {
|
||||||
safe_delete(timer);
|
safe_delete(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int level;
|
int level;
|
||||||
Timer *timer;
|
Timer *timer;
|
||||||
int params[MAX_SPECIAL_ATTACK_PARAMS];
|
int params[SpecialAbility::MaxParameters];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AuraInfo {
|
struct AuraInfo {
|
||||||
@@ -236,7 +234,13 @@ public:
|
|||||||
int compute_defense();
|
int compute_defense();
|
||||||
int GetTotalDefense(); // compute_defense + spell bonuses
|
int GetTotalDefense(); // compute_defense + spell bonuses
|
||||||
bool CheckHitChance(Mob* attacker, DamageHitInfo &hit);
|
bool CheckHitChance(Mob* attacker, DamageHitInfo &hit);
|
||||||
|
bool RollMeleeCritCheck(Mob *defender, EQ::skills::SkillType skill);
|
||||||
|
inline bool CanUndeadSlay() { return static_cast<bool>(GetUndeadSlayRate());}
|
||||||
|
inline bool IsUndeadForSlay() { return (GetBodyType() == BT_Undead || GetBodyType() == BT_SummonedUndead || GetBodyType() == BT_Vampire); }
|
||||||
|
int GetUndeadSlayRate();
|
||||||
|
void DoUndeadSlay(DamageHitInfo &hit, int crit_mod);
|
||||||
void TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
void TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
||||||
|
bool TryUndeadSlay(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
||||||
void TryPetCriticalHit(Mob *defender, DamageHitInfo &hit);
|
void TryPetCriticalHit(Mob *defender, DamageHitInfo &hit);
|
||||||
virtual bool TryFinishingBlow(Mob *defender, int64 &damage);
|
virtual bool TryFinishingBlow(Mob *defender, int64 &damage);
|
||||||
int TryHeadShot(Mob* defender, EQ::skills::SkillType skillInUse);
|
int TryHeadShot(Mob* defender, EQ::skills::SkillType skillInUse);
|
||||||
@@ -552,7 +556,7 @@ public:
|
|||||||
virtual inline uint8 GetBaseGender() const { return base_gender; }
|
virtual inline uint8 GetBaseGender() const { return base_gender; }
|
||||||
virtual uint16 GetFactionRace();
|
virtual uint16 GetFactionRace();
|
||||||
virtual inline uint16 GetDeity() const { return deity; }
|
virtual inline uint16 GetDeity() const { return deity; }
|
||||||
virtual EQ::deity::DeityTypeBit GetDeityBit() { return EQ::deity::GetDeityBitmask((EQ::deity::DeityType)deity); }
|
virtual uint32 GetDeityBit() { return Deity::GetBitmask(deity); }
|
||||||
inline uint16 GetRace() const { return race; }
|
inline uint16 GetRace() const { return race; }
|
||||||
inline uint16 GetModel() const { return (use_model == 0) ? race : use_model; }
|
inline uint16 GetModel() const { return (use_model == 0) ? race : use_model; }
|
||||||
inline uint8 GetGender() const { return gender; }
|
inline uint8 GetGender() const { return gender; }
|
||||||
@@ -1020,15 +1024,15 @@ public:
|
|||||||
int16 GetModVulnerability(const uint8 resist);
|
int16 GetModVulnerability(const uint8 resist);
|
||||||
|
|
||||||
void SetAllowBeneficial(bool value) { m_AllowBeneficial = value; }
|
void SetAllowBeneficial(bool value) { m_AllowBeneficial = value; }
|
||||||
bool GetAllowBeneficial() { if (m_AllowBeneficial || GetSpecialAbility(ALLOW_BENEFICIAL)){return true;} return false; }
|
bool GetAllowBeneficial() { if (m_AllowBeneficial || GetSpecialAbility(SpecialAbility::AllowBeneficial)){return true;} return false; }
|
||||||
void SetDisableMelee(bool value) { m_DisableMelee = value; }
|
void SetDisableMelee(bool value) { m_DisableMelee = value; }
|
||||||
bool IsMeleeDisabled() { if (m_DisableMelee || GetSpecialAbility(DISABLE_MELEE)){return true;} return false; }
|
bool IsMeleeDisabled() { if (m_DisableMelee || GetSpecialAbility(SpecialAbility::DisableMelee)){return true;} return false; }
|
||||||
|
|
||||||
bool IsOffHandAtk() const { return offhand; }
|
bool IsOffHandAtk() const { return offhand; }
|
||||||
inline void OffHandAtk(bool val) { offhand = val; }
|
inline void OffHandAtk(bool val) { offhand = val; }
|
||||||
|
|
||||||
void SetFlurryChance(uint8 value) { SetSpecialAbilityParam(SPECATK_FLURRY, 0, value); }
|
void SetFlurryChance(uint8 value) { SetSpecialAbilityParam(SpecialAbility::Flurry, 0, value); }
|
||||||
uint8 GetFlurryChance() { return GetSpecialAbilityParam(SPECATK_FLURRY, 0); }
|
uint8 GetFlurryChance() { return GetSpecialAbilityParam(SpecialAbility::Flurry, 0); }
|
||||||
|
|
||||||
static uint32 GetAppearanceValue(EmuAppearance in_appearance);
|
static uint32 GetAppearanceValue(EmuAppearance in_appearance);
|
||||||
void SendAppearancePacket(uint32 type, uint32 value, bool whole_zone = true, bool ignore_self = false, Client* target = nullptr);
|
void SendAppearancePacket(uint32 type, uint32 value, bool whole_zone = true, bool ignore_self = false, Client* target = nullptr);
|
||||||
@@ -1864,7 +1868,7 @@ protected:
|
|||||||
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);
|
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);
|
||||||
uint32 emoteid;
|
uint32 emoteid;
|
||||||
|
|
||||||
SpecialAbility SpecialAbilities[MAX_SPECIAL_ATTACK];
|
MobSpecialAbility SpecialAbilities[SpecialAbility::Max];
|
||||||
bool bEnraged;
|
bool bEnraged;
|
||||||
bool destructibleobject;
|
bool destructibleobject;
|
||||||
|
|
||||||
|
|||||||
+48
-47
@@ -570,7 +570,7 @@ void Mob::AI_ShutDown() {
|
|||||||
viral_timer.Disable();
|
viral_timer.Disable();
|
||||||
flee_timer.Disable();
|
flee_timer.Disable();
|
||||||
|
|
||||||
for (int sat = 0; sat < MAX_SPECIAL_ATTACK; ++sat) {
|
for (int sat = 0; sat < SpecialAbility::Max; ++sat) {
|
||||||
if (SpecialAbilities[sat].timer)
|
if (SpecialAbilities[sat].timer)
|
||||||
SpecialAbilities[sat].timer->Disable();
|
SpecialAbilities[sat].timer->Disable();
|
||||||
}
|
}
|
||||||
@@ -1062,7 +1062,7 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
// we are prevented from getting here if we are blind and don't have a target in range
|
// we are prevented from getting here if we are blind and don't have a target in range
|
||||||
// from above, so no extra blind checks needed
|
// from above, so no extra blind checks needed
|
||||||
if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind())
|
if ((IsRooted() && !GetSpecialAbility(SpecialAbility::IgnoreRootAggroRules)) || IsBlind())
|
||||||
SetTarget(hate_list.GetClosestEntOnHateList(this));
|
SetTarget(hate_list.GetClosestEntOnHateList(this));
|
||||||
else {
|
else {
|
||||||
if (AI_target_check_timer->Check()) {
|
if (AI_target_check_timer->Check()) {
|
||||||
@@ -1125,16 +1125,16 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto npcSpawnPoint = CastToNPC()->GetSpawnPoint();
|
auto npcSpawnPoint = CastToNPC()->GetSpawnPoint();
|
||||||
if (GetSpecialAbility(TETHER)) {
|
if (GetSpecialAbility(SpecialAbility::Tether)) {
|
||||||
float tether_range = static_cast<float>(GetSpecialAbilityParam(TETHER, 0));
|
float tether_range = static_cast<float>(GetSpecialAbilityParam(SpecialAbility::Tether, 0));
|
||||||
tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange;
|
tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange;
|
||||||
|
|
||||||
if (DistanceSquaredNoZ(m_Position, npcSpawnPoint) > tether_range) {
|
if (DistanceSquaredNoZ(m_Position, npcSpawnPoint) > tether_range) {
|
||||||
GMMove(npcSpawnPoint.x, npcSpawnPoint.y, npcSpawnPoint.z, npcSpawnPoint.w);
|
GMMove(npcSpawnPoint.x, npcSpawnPoint.y, npcSpawnPoint.z, npcSpawnPoint.w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (GetSpecialAbility(LEASH)) {
|
else if (GetSpecialAbility(SpecialAbility::Leash)) {
|
||||||
float leash_range = static_cast<float>(GetSpecialAbilityParam(LEASH, 0));
|
float leash_range = static_cast<float>(GetSpecialAbilityParam(SpecialAbility::Leash, 0));
|
||||||
leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange;
|
leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange;
|
||||||
|
|
||||||
if (DistanceSquaredNoZ(m_Position, npcSpawnPoint) > leash_range) {
|
if (DistanceSquaredNoZ(m_Position, npcSpawnPoint) > leash_range) {
|
||||||
@@ -1169,33 +1169,33 @@ void Mob::AI_Process() {
|
|||||||
TriggerDefensiveProcs(target, EQ::invslot::slotPrimary, false);
|
TriggerDefensiveProcs(target, EQ::invslot::slotPrimary, false);
|
||||||
|
|
||||||
bool specialed = false; // NPCs can only do one of these a round
|
bool specialed = false; // NPCs can only do one of these a round
|
||||||
if (GetSpecialAbility(SPECATK_FLURRY)) {
|
if (GetSpecialAbility(SpecialAbility::Flurry)) {
|
||||||
int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0);
|
int flurry_chance = GetSpecialAbilityParam(SpecialAbility::Flurry, 0);
|
||||||
flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance);
|
flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance);
|
||||||
|
|
||||||
if (zone->random.Roll(flurry_chance)) {
|
if (zone->random.Roll(flurry_chance)) {
|
||||||
ExtraAttackOptions opts;
|
ExtraAttackOptions opts;
|
||||||
int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2);
|
int cur = GetSpecialAbilityParam(SpecialAbility::Flurry, 2);
|
||||||
if (cur > 0)
|
if (cur > 0)
|
||||||
opts.damage_percent = cur / 100.0f;
|
opts.damage_percent = cur / 100.0f;
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_FLURRY, 3);
|
cur = GetSpecialAbilityParam(SpecialAbility::Flurry, 3);
|
||||||
if (cur > 0)
|
if (cur > 0)
|
||||||
opts.damage_flat = cur;
|
opts.damage_flat = cur;
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_FLURRY, 4);
|
cur = GetSpecialAbilityParam(SpecialAbility::Flurry, 4);
|
||||||
if (cur > 0)
|
if (cur > 0)
|
||||||
opts.armor_pen_percent = cur / 100.0f;
|
opts.armor_pen_percent = cur / 100.0f;
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_FLURRY, 5);
|
cur = GetSpecialAbilityParam(SpecialAbility::Flurry, 5);
|
||||||
if (cur > 0)
|
if (cur > 0)
|
||||||
opts.armor_pen_flat = cur;
|
opts.armor_pen_flat = cur;
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_FLURRY, 6);
|
cur = GetSpecialAbilityParam(SpecialAbility::Flurry, 6);
|
||||||
if (cur > 0)
|
if (cur > 0)
|
||||||
opts.crit_percent = cur / 100.0f;
|
opts.crit_percent = cur / 100.0f;
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_FLURRY, 7);
|
cur = GetSpecialAbilityParam(SpecialAbility::Flurry, 7);
|
||||||
if (cur > 0)
|
if (cur > 0)
|
||||||
opts.crit_flat = cur;
|
opts.crit_flat = cur;
|
||||||
|
|
||||||
@@ -1227,32 +1227,32 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (GetSpecialAbility(SPECATK_RAMPAGE) && !specialed) {
|
if (GetSpecialAbility(SpecialAbility::Rampage) && !specialed) {
|
||||||
int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0);
|
int rampage_chance = GetSpecialAbilityParam(SpecialAbility::Rampage, 0);
|
||||||
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
||||||
if (zone->random.Roll(rampage_chance)) {
|
if (zone->random.Roll(rampage_chance)) {
|
||||||
ExtraAttackOptions opts;
|
ExtraAttackOptions opts;
|
||||||
int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3);
|
int cur = GetSpecialAbilityParam(SpecialAbility::Rampage, 3);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.damage_flat = cur;
|
opts.damage_flat = cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 4);
|
cur = GetSpecialAbilityParam(SpecialAbility::Rampage, 4);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.armor_pen_percent = cur / 100.0f;
|
opts.armor_pen_percent = cur / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 5);
|
cur = GetSpecialAbilityParam(SpecialAbility::Rampage, 5);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.armor_pen_flat = cur;
|
opts.armor_pen_flat = cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 6);
|
cur = GetSpecialAbilityParam(SpecialAbility::Rampage, 6);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.crit_percent = cur / 100.0f;
|
opts.crit_percent = cur / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 7);
|
cur = GetSpecialAbilityParam(SpecialAbility::Rampage, 7);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.crit_flat = cur;
|
opts.crit_flat = cur;
|
||||||
}
|
}
|
||||||
@@ -1269,37 +1269,37 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(SPECATK_AREA_RAMPAGE) && !specialed) {
|
if (GetSpecialAbility(SpecialAbility::AreaRampage) && !specialed) {
|
||||||
int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0);
|
int rampage_chance = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 0);
|
||||||
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
||||||
if (zone->random.Roll(rampage_chance)) {
|
if (zone->random.Roll(rampage_chance)) {
|
||||||
ExtraAttackOptions opts;
|
ExtraAttackOptions opts;
|
||||||
int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3);
|
int cur = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 3);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.damage_flat = cur;
|
opts.damage_flat = cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 4);
|
cur = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 4);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.armor_pen_percent = cur / 100.0f;
|
opts.armor_pen_percent = cur / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 5);
|
cur = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 5);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.armor_pen_flat = cur;
|
opts.armor_pen_flat = cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 6);
|
cur = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 6);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.crit_percent = cur / 100.0f;
|
opts.crit_percent = cur / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 7);
|
cur = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 7);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.crit_flat = cur;
|
opts.crit_flat = cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 8);
|
cur = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 8);
|
||||||
if (cur > 0) {
|
if (cur > 0) {
|
||||||
opts.range_percent = cur;
|
opts.range_percent = cur;
|
||||||
}
|
}
|
||||||
@@ -1328,7 +1328,7 @@ void Mob::AI_Process() {
|
|||||||
if (!HateSummon()) {
|
if (!HateSummon()) {
|
||||||
|
|
||||||
//could not summon them, check ranged...
|
//could not summon them, check ranged...
|
||||||
if (GetSpecialAbility(SPECATK_RANGED_ATK) || HasBowAndArrowEquipped()) {
|
if (GetSpecialAbility(SpecialAbility::RangedAttack) || HasBowAndArrowEquipped()) {
|
||||||
doranged = true;
|
doranged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1961,10 +1961,10 @@ void Mob::StartEnrage()
|
|||||||
if (bEnraged)
|
if (bEnraged)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!GetSpecialAbility(SPECATK_ENRAGE))
|
if(!GetSpecialAbility(SpecialAbility::Enrage))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int hp_ratio = GetSpecialAbilityParam(SPECATK_ENRAGE, 0);
|
int hp_ratio = GetSpecialAbilityParam(SpecialAbility::Enrage, 0);
|
||||||
hp_ratio = hp_ratio > 0 ? hp_ratio : RuleI(NPC, StartEnrageValue);
|
hp_ratio = hp_ratio > 0 ? hp_ratio : RuleI(NPC, StartEnrageValue);
|
||||||
if(GetHPRatio() > static_cast<float>(hp_ratio)) {
|
if(GetHPRatio() > static_cast<float>(hp_ratio)) {
|
||||||
return;
|
return;
|
||||||
@@ -1975,13 +1975,13 @@ void Mob::StartEnrage()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE);
|
Timer *timer = GetSpecialAbilityTimer(SpecialAbility::Enrage);
|
||||||
if (timer && !timer->Check())
|
if (timer && !timer->Check())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int enraged_duration = GetSpecialAbilityParam(SPECATK_ENRAGE, 1);
|
int enraged_duration = GetSpecialAbilityParam(SpecialAbility::Enrage, 1);
|
||||||
enraged_duration = enraged_duration > 0 ? enraged_duration : EnragedDurationTimer;
|
enraged_duration = enraged_duration > 0 ? enraged_duration : EnragedDurationTimer;
|
||||||
StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_duration);
|
StartSpecialAbilityTimer(SpecialAbility::Enrage, enraged_duration);
|
||||||
|
|
||||||
// start the timer. need to call IsEnraged frequently since we dont have callback timers :-/
|
// start the timer. need to call IsEnraged frequently since we dont have callback timers :-/
|
||||||
bEnraged = true;
|
bEnraged = true;
|
||||||
@@ -1990,13 +1990,13 @@ void Mob::StartEnrage()
|
|||||||
|
|
||||||
void Mob::ProcessEnrage(){
|
void Mob::ProcessEnrage(){
|
||||||
if(IsEnraged()){
|
if(IsEnraged()){
|
||||||
Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE);
|
Timer *timer = GetSpecialAbilityTimer(SpecialAbility::Enrage);
|
||||||
if(timer && timer->Check()){
|
if(timer && timer->Check()){
|
||||||
entity_list.MessageCloseString(this, true, 200, Chat::NPCEnrage, NPC_ENRAGE_END, GetCleanName());
|
entity_list.MessageCloseString(this, true, 200, Chat::NPCEnrage, NPC_ENRAGE_END, GetCleanName());
|
||||||
|
|
||||||
int enraged_cooldown = GetSpecialAbilityParam(SPECATK_ENRAGE, 2);
|
int enraged_cooldown = GetSpecialAbilityParam(SpecialAbility::Enrage, 2);
|
||||||
enraged_cooldown = enraged_cooldown > 0 ? enraged_cooldown : EnragedTimer;
|
enraged_cooldown = enraged_cooldown > 0 ? enraged_cooldown : EnragedTimer;
|
||||||
StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_cooldown);
|
StartSpecialAbilityTimer(SpecialAbility::Enrage, enraged_cooldown);
|
||||||
bEnraged = false;
|
bEnraged = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2032,7 +2032,7 @@ bool Mob::Flurry(ExtraAttackOptions *opts)
|
|||||||
target->GetCleanName());
|
target->GetCleanName());
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1);
|
int num_attacks = GetSpecialAbilityParam(SpecialAbility::Flurry, 1);
|
||||||
num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits);
|
num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits);
|
||||||
for (int i = 0; i < num_attacks; i++)
|
for (int i = 0; i < num_attacks; i++)
|
||||||
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
Attack(target, EQ::invslot::slotPrimary, false, false, false, opts);
|
||||||
@@ -2046,7 +2046,7 @@ bool Mob::AddRampage(Mob *mob)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetSpecialAbility(SPECATK_RAMPAGE)) {
|
if (!GetSpecialAbility(SpecialAbility::Rampage)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2073,7 +2073,7 @@ void Mob::RemoveFromRampageList(Mob* mob, bool remove_feigned)
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
IsNPC() &&
|
IsNPC() &&
|
||||||
GetSpecialAbility(SPECATK_RAMPAGE) &&
|
GetSpecialAbility(SpecialAbility::Rampage) &&
|
||||||
(
|
(
|
||||||
remove_feigned ||
|
remove_feigned ||
|
||||||
mob->IsNPC() ||
|
mob->IsNPC() ||
|
||||||
@@ -2100,7 +2100,7 @@ bool Mob::Rampage(ExtraAttackOptions *opts)
|
|||||||
entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, NPC_RAMPAGE, GetCleanName());
|
entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, NPC_RAMPAGE, GetCleanName());
|
||||||
}
|
}
|
||||||
|
|
||||||
int rampage_targets = GetSpecialAbilityParam(SPECATK_RAMPAGE, 1);
|
int rampage_targets = GetSpecialAbilityParam(SpecialAbility::Rampage, 1);
|
||||||
|
|
||||||
if (rampage_targets == 0) { // if set to 0 or not set in the DB
|
if (rampage_targets == 0) { // if set to 0 or not set in the DB
|
||||||
rampage_targets = RuleI(Combat, DefaultRampageTargets);
|
rampage_targets = RuleI(Combat, DefaultRampageTargets);
|
||||||
@@ -2173,7 +2173,7 @@ void Mob::AreaRampage(ExtraAttackOptions *opts)
|
|||||||
entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, AE_RAMPAGE, GetCleanName());
|
entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, AE_RAMPAGE, GetCleanName());
|
||||||
}
|
}
|
||||||
|
|
||||||
int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1);
|
int rampage_targets = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 1);
|
||||||
rampage_targets = rampage_targets > 0 ? rampage_targets : -1;
|
rampage_targets = rampage_targets > 0 ? rampage_targets : -1;
|
||||||
m_specialattacks = eSpecialAttacks::AERampage;
|
m_specialattacks = eSpecialAttacks::AERampage;
|
||||||
index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts);
|
index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts);
|
||||||
@@ -2787,10 +2787,11 @@ void NPC::AISpellsList(Client *c)
|
|||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Spell {} | Priority: {} Recast Delay: {}",
|
"Spell {} | Priority: {} Recast Delay: {} Resist Difficulty: {}",
|
||||||
spell_slot,
|
spell_slot,
|
||||||
ai_spell.priority,
|
ai_spell.priority,
|
||||||
ai_spell.recast_delay
|
ai_spell.recast_delay,
|
||||||
|
ai_spell.resist_adjust
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2915,8 +2916,8 @@ DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 npc_spells_id)
|
|||||||
if (e.resist_adjust) {
|
if (e.resist_adjust) {
|
||||||
se.resist_adjust = e.resist_adjust;
|
se.resist_adjust = e.resist_adjust;
|
||||||
}
|
}
|
||||||
else if (IsValidSpell(e.id)) {
|
else if (IsValidSpell(e.spellid)) {
|
||||||
se.resist_adjust = spells[e.id].resist_difficulty;
|
se.resist_adjust = spells[e.spellid].resist_difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
ss.entries.push_back(se);
|
ss.entries.push_back(se);
|
||||||
|
|||||||
+141
-141
@@ -767,7 +767,7 @@ bool NPC::Process()
|
|||||||
ProcessEnrage();
|
ProcessEnrage();
|
||||||
|
|
||||||
/* Don't keep running the check every second if we don't have enrage */
|
/* Don't keep running the check every second if we don't have enrage */
|
||||||
if (!GetSpecialAbility(SPECATK_ENRAGE)) {
|
if (!GetSpecialAbility(SpecialAbility::Enrage)) {
|
||||||
enraged_timer.Disable();
|
enraged_timer.Disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1220,7 +1220,7 @@ uint32 ZoneDatabase::CreateNewNPCCommand(
|
|||||||
e.walkspeed = n->GetWalkspeed();
|
e.walkspeed = n->GetWalkspeed();
|
||||||
e.prim_melee_type = n->GetPrimSkill();
|
e.prim_melee_type = n->GetPrimSkill();
|
||||||
e.sec_melee_type = n->GetSecSkill();
|
e.sec_melee_type = n->GetSecSkill();
|
||||||
|
|
||||||
e.bodytype = n->GetBodyType();
|
e.bodytype = n->GetBodyType();
|
||||||
e.npc_faction_id = n->GetNPCFactionID();
|
e.npc_faction_id = n->GetNPCFactionID();
|
||||||
e.aggroradius = n->GetAggroRange();
|
e.aggroradius = n->GetAggroRange();
|
||||||
@@ -1235,7 +1235,7 @@ uint32 ZoneDatabase::CreateNewNPCCommand(
|
|||||||
e.WIS = n->GetWIS();
|
e.WIS = n->GetWIS();
|
||||||
e._INT = n->GetINT();
|
e._INT = n->GetINT();
|
||||||
e.CHA = n->GetCHA();
|
e.CHA = n->GetCHA();
|
||||||
|
|
||||||
e.PR = n->GetPR();
|
e.PR = n->GetPR();
|
||||||
e.MR = n->GetMR();
|
e.MR = n->GetMR();
|
||||||
e.DR = n->GetDR();
|
e.DR = n->GetDR();
|
||||||
@@ -1255,7 +1255,7 @@ uint32 ZoneDatabase::CreateNewNPCCommand(
|
|||||||
e.healscale = n->GetHealScale();
|
e.healscale = n->GetHealScale();
|
||||||
e.Avoidance = n->GetAvoidanceRating();
|
e.Avoidance = n->GetAvoidanceRating();
|
||||||
e.heroic_strikethrough = n->GetHeroicStrikethrough();
|
e.heroic_strikethrough = n->GetHeroicStrikethrough();
|
||||||
|
|
||||||
e.see_hide = n->SeeHide();
|
e.see_hide = n->SeeHide();
|
||||||
e.see_improved_hide = n->SeeImprovedHide();
|
e.see_improved_hide = n->SeeImprovedHide();
|
||||||
e.see_invis = n->SeeInvisible();
|
e.see_invis = n->SeeInvisible();
|
||||||
@@ -1863,127 +1863,127 @@ void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool rem
|
|||||||
switch(*parse)
|
switch(*parse)
|
||||||
{
|
{
|
||||||
case 'E':
|
case 'E':
|
||||||
SetSpecialAbility(SPECATK_ENRAGE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::Enrage, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
SetSpecialAbility(SPECATK_FLURRY, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::Flurry, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
SetSpecialAbility(SPECATK_RAMPAGE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::Rampage, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
SetSpecialAbility(SPECATK_AREA_RAMPAGE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::AreaRampage, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
if(remove) {
|
if(remove) {
|
||||||
SetSpecialAbility(SPECATK_SUMMON, 0);
|
SetSpecialAbility(SpecialAbility::Summon, 0);
|
||||||
StopSpecialAbilityTimer(SPECATK_SUMMON);
|
StopSpecialAbilityTimer(SpecialAbility::Summon);
|
||||||
} else {
|
} else {
|
||||||
SetSpecialAbility(SPECATK_SUMMON, 1);
|
SetSpecialAbility(SpecialAbility::Summon, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
SetSpecialAbility(SPECATK_TRIPLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::TripleAttack, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'Q':
|
case 'Q':
|
||||||
//quad requires triple to work properly
|
//quad requires triple to work properly
|
||||||
if(remove) {
|
if(remove) {
|
||||||
SetSpecialAbility(SPECATK_QUAD, 0);
|
SetSpecialAbility(SpecialAbility::QuadrupleAttack, 0);
|
||||||
} else {
|
} else {
|
||||||
SetSpecialAbility(SPECATK_TRIPLE, 1);
|
SetSpecialAbility(SpecialAbility::TripleAttack, 1);
|
||||||
SetSpecialAbility(SPECATK_QUAD, 1);
|
SetSpecialAbility(SpecialAbility::QuadrupleAttack, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
SetSpecialAbility(SPECATK_BANE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::BaneAttack, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
SetSpecialAbility(SPECATK_MAGICAL, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::MagicalAttack, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
SetSpecialAbility(UNSLOWABLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::SlowImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
SetSpecialAbility(UNMEZABLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::MesmerizeImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
SetSpecialAbility(UNCHARMABLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::CharmImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
SetSpecialAbility(UNSTUNABLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::StunImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
SetSpecialAbility(UNSNAREABLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::SnareImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
SetSpecialAbility(UNFEARABLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::FearImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'K':
|
case 'K':
|
||||||
SetSpecialAbility(UNDISPELLABLE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::DispellImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
SetSpecialAbility(IMMUNE_MELEE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::MeleeImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
SetSpecialAbility(IMMUNE_MAGIC, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::MagicImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
SetSpecialAbility(IMMUNE_FLEEING, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::FleeingImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
SetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::MeleeImmunityExceptBane, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
SetSpecialAbility(IMMUNE_MELEE_NONMAGICAL, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::MeleeImmunityExceptMagical, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
SetSpecialAbility(IMMUNE_AGGRO, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::AggroImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
SetSpecialAbility(IMMUNE_AGGRO_ON, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::BeingAggroImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
SetSpecialAbility(IMMUNE_CASTING_FROM_RANGE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::CastingFromRangeImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
SetSpecialAbility(IMMUNE_FEIGN_DEATH, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::FeignDeathImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'Y':
|
case 'Y':
|
||||||
SetSpecialAbility(SPECATK_RANGED_ATK, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::RangedAttack, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
SetSpecialAbility(SPECATK_INNATE_DW, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::DualWield, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
SetSpecialAbility(NPC_TUNNELVISION, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::TunnelVision, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
SetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::NoBuffHealFriends, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
SetSpecialAbility(IMMUNE_PACIFY, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::PacifyImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'J':
|
case 'J':
|
||||||
SetSpecialAbility(LEASH, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::Leash, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
SetSpecialAbility(TETHER, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::Tether, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
SetSpecialAbility(DESTRUCTIBLE_OBJECT, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::DestructibleObject, remove ? 0 : 1);
|
||||||
SetDestructibleObject(remove ? true : false);
|
SetDestructibleObject(remove ? true : false);
|
||||||
break;
|
break;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
SetSpecialAbility(NO_HARM_FROM_CLIENT, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::HarmFromClientImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
SetSpecialAbility(IMMUNE_TAUNT, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::TauntImmunity, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
SetSpecialAbility(ALWAYS_FLEE, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::AlwaysFlee, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
SetSpecialAbility(FLEE_PERCENT, remove ? 0 : 1);
|
SetSpecialAbility(SpecialAbility::FleePercent, remove ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -2010,147 +2010,147 @@ bool Mob::HasNPCSpecialAtk(const char* parse) {
|
|||||||
switch(*parse)
|
switch(*parse)
|
||||||
{
|
{
|
||||||
case 'E':
|
case 'E':
|
||||||
if (!GetSpecialAbility(SPECATK_ENRAGE))
|
if (!GetSpecialAbility(SpecialAbility::Enrage))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
if (!GetSpecialAbility(SPECATK_FLURRY))
|
if (!GetSpecialAbility(SpecialAbility::Flurry))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
if (!GetSpecialAbility(SPECATK_RAMPAGE))
|
if (!GetSpecialAbility(SpecialAbility::Rampage))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
if (!GetSpecialAbility(SPECATK_AREA_RAMPAGE))
|
if (!GetSpecialAbility(SpecialAbility::AreaRampage))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
if (!GetSpecialAbility(SPECATK_SUMMON))
|
if (!GetSpecialAbility(SpecialAbility::Summon))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
if (!GetSpecialAbility(SPECATK_TRIPLE))
|
if (!GetSpecialAbility(SpecialAbility::TripleAttack))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'Q':
|
case 'Q':
|
||||||
if (!GetSpecialAbility(SPECATK_QUAD))
|
if (!GetSpecialAbility(SpecialAbility::QuadrupleAttack))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
if (!GetSpecialAbility(SPECATK_BANE))
|
if (!GetSpecialAbility(SpecialAbility::BaneAttack))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
if (!GetSpecialAbility(SPECATK_MAGICAL))
|
if (!GetSpecialAbility(SpecialAbility::MagicalAttack))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
if (!GetSpecialAbility(UNSLOWABLE))
|
if (!GetSpecialAbility(SpecialAbility::SlowImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
if (!GetSpecialAbility(UNMEZABLE))
|
if (!GetSpecialAbility(SpecialAbility::MesmerizeImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
if (!GetSpecialAbility(UNCHARMABLE))
|
if (!GetSpecialAbility(SpecialAbility::CharmImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
if (!GetSpecialAbility(UNSTUNABLE))
|
if (!GetSpecialAbility(SpecialAbility::StunImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
if (!GetSpecialAbility(UNSNAREABLE))
|
if (!GetSpecialAbility(SpecialAbility::SnareImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
if (!GetSpecialAbility(UNFEARABLE))
|
if (!GetSpecialAbility(SpecialAbility::FearImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
if (!GetSpecialAbility(IMMUNE_MELEE))
|
if (!GetSpecialAbility(SpecialAbility::MeleeImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
if (!GetSpecialAbility(IMMUNE_MAGIC))
|
if (!GetSpecialAbility(SpecialAbility::MagicImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
if (!GetSpecialAbility(IMMUNE_FLEEING))
|
if (!GetSpecialAbility(SpecialAbility::FleeingImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
if (!GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE))
|
if (!GetSpecialAbility(SpecialAbility::MeleeImmunityExceptBane))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
if (!GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL))
|
if (!GetSpecialAbility(SpecialAbility::MeleeImmunityExceptMagical))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
if (!GetSpecialAbility(IMMUNE_AGGRO))
|
if (!GetSpecialAbility(SpecialAbility::AggroImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
if (!GetSpecialAbility(IMMUNE_AGGRO_ON))
|
if (!GetSpecialAbility(SpecialAbility::BeingAggroImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
if (!GetSpecialAbility(IMMUNE_CASTING_FROM_RANGE))
|
if (!GetSpecialAbility(SpecialAbility::CastingFromRangeImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (!GetSpecialAbility(IMMUNE_FEIGN_DEATH))
|
if (!GetSpecialAbility(SpecialAbility::FeignDeathImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'Y':
|
case 'Y':
|
||||||
if (!GetSpecialAbility(SPECATK_RANGED_ATK))
|
if (!GetSpecialAbility(SpecialAbility::RangedAttack))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
if (!GetSpecialAbility(SPECATK_INNATE_DW))
|
if (!GetSpecialAbility(SpecialAbility::DualWield))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
if (!GetSpecialAbility(NPC_TUNNELVISION))
|
if (!GetSpecialAbility(SpecialAbility::TunnelVision))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
if (!GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS))
|
if (!GetSpecialAbility(SpecialAbility::NoBuffHealFriends))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if(!GetSpecialAbility(IMMUNE_PACIFY))
|
if(!GetSpecialAbility(SpecialAbility::PacifyImmunity))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'J':
|
case 'J':
|
||||||
if(!GetSpecialAbility(LEASH))
|
if(!GetSpecialAbility(SpecialAbility::Leash))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
if(!GetSpecialAbility(TETHER))
|
if(!GetSpecialAbility(SpecialAbility::Tether))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if(!GetSpecialAbility(DESTRUCTIBLE_OBJECT))
|
if(!GetSpecialAbility(SpecialAbility::DestructibleObject))
|
||||||
{
|
{
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
SetDestructibleObject(false);
|
SetDestructibleObject(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
if(!GetSpecialAbility(NO_HARM_FROM_CLIENT)){
|
if(!GetSpecialAbility(SpecialAbility::HarmFromClientImmunity)){
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
if(!GetSpecialAbility(ALWAYS_FLEE))
|
if(!GetSpecialAbility(SpecialAbility::AlwaysFlee))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
if(!GetSpecialAbility(FLEE_PERCENT))
|
if(!GetSpecialAbility(SpecialAbility::FleePercent))
|
||||||
HasAllAttacks = false;
|
HasAllAttacks = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -3060,7 +3060,7 @@ int NPC::GetScore()
|
|||||||
if(HasNPCSpecialAtk("S")) { spccontrib++; } //Summon
|
if(HasNPCSpecialAtk("S")) { spccontrib++; } //Summon
|
||||||
if(HasNPCSpecialAtk("T")) { spccontrib += 2; } //Triple
|
if(HasNPCSpecialAtk("T")) { spccontrib += 2; } //Triple
|
||||||
if(HasNPCSpecialAtk("Q")) { spccontrib += 3; } //Quad
|
if(HasNPCSpecialAtk("Q")) { spccontrib += 3; } //Quad
|
||||||
if(HasNPCSpecialAtk("U")) { spccontrib += 5; } //Unslowable
|
if(HasNPCSpecialAtk("U")) { spccontrib += 5; } //SpecialAbility::SlowImmunity
|
||||||
if(HasNPCSpecialAtk("L")) { spccontrib++; } //Innate Dual Wield
|
if(HasNPCSpecialAtk("L")) { spccontrib++; } //Innate Dual Wield
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3294,7 +3294,7 @@ bool NPC::AICheckCloseBeneficialSpells(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caster->GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS)) {
|
if (caster->GetSpecialAbility(SpecialAbility::NoBuffHealFriends)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3802,56 +3802,56 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
|
|
||||||
// These abilities are simple on/off flags
|
// These abilities are simple on/off flags
|
||||||
static const std::vector<uint32> toggleable_special_abilities = {
|
static const std::vector<uint32> toggleable_special_abilities = {
|
||||||
SPECATK_TRIPLE,
|
SpecialAbility::TripleAttack,
|
||||||
SPECATK_QUAD,
|
SpecialAbility::QuadrupleAttack,
|
||||||
SPECATK_INNATE_DW,
|
SpecialAbility::DualWield,
|
||||||
SPECATK_BANE,
|
SpecialAbility::BaneAttack,
|
||||||
SPECATK_MAGICAL,
|
SpecialAbility::MagicalAttack,
|
||||||
UNSLOWABLE,
|
SpecialAbility::SlowImmunity,
|
||||||
UNMEZABLE,
|
SpecialAbility::MesmerizeImmunity,
|
||||||
UNCHARMABLE,
|
SpecialAbility::CharmImmunity,
|
||||||
UNSTUNABLE,
|
SpecialAbility::StunImmunity,
|
||||||
UNSNAREABLE,
|
SpecialAbility::SnareImmunity,
|
||||||
UNFEARABLE,
|
SpecialAbility::FearImmunity,
|
||||||
UNDISPELLABLE,
|
SpecialAbility::DispellImmunity,
|
||||||
IMMUNE_MELEE,
|
SpecialAbility::MeleeImmunity,
|
||||||
IMMUNE_MAGIC,
|
SpecialAbility::MagicImmunity,
|
||||||
IMMUNE_FLEEING,
|
SpecialAbility::FleeingImmunity,
|
||||||
IMMUNE_MELEE_EXCEPT_BANE,
|
SpecialAbility::MeleeImmunityExceptBane,
|
||||||
IMMUNE_MELEE_NONMAGICAL,
|
SpecialAbility::MeleeImmunityExceptMagical,
|
||||||
IMMUNE_AGGRO,
|
SpecialAbility::AggroImmunity,
|
||||||
IMMUNE_AGGRO_ON,
|
SpecialAbility::BeingAggroImmunity,
|
||||||
IMMUNE_CASTING_FROM_RANGE,
|
SpecialAbility::CastingFromRangeImmunity,
|
||||||
IMMUNE_FEIGN_DEATH,
|
SpecialAbility::FeignDeathImmunity,
|
||||||
IMMUNE_TAUNT,
|
SpecialAbility::TauntImmunity,
|
||||||
NPC_NO_BUFFHEAL_FRIENDS,
|
SpecialAbility::NoBuffHealFriends,
|
||||||
IMMUNE_PACIFY,
|
SpecialAbility::PacifyImmunity,
|
||||||
DESTRUCTIBLE_OBJECT,
|
SpecialAbility::DestructibleObject,
|
||||||
NO_HARM_FROM_CLIENT,
|
SpecialAbility::HarmFromClientImmunity,
|
||||||
ALWAYS_FLEE,
|
SpecialAbility::AlwaysFlee,
|
||||||
ALLOW_BENEFICIAL,
|
SpecialAbility::AllowBeneficial,
|
||||||
DISABLE_MELEE,
|
SpecialAbility::DisableMelee,
|
||||||
ALLOW_TO_TANK,
|
SpecialAbility::AllowedToTank,
|
||||||
IGNORE_ROOT_AGGRO_RULES,
|
SpecialAbility::IgnoreRootAggroRules,
|
||||||
PROX_AGGRO,
|
SpecialAbility::ProximityAggro,
|
||||||
IMMUNE_RANGED_ATTACKS,
|
SpecialAbility::RangedAttackImmunity,
|
||||||
IMMUNE_DAMAGE_CLIENT,
|
SpecialAbility::ClientDamageImmunity,
|
||||||
IMMUNE_DAMAGE_NPC,
|
SpecialAbility::NPCDamageImmunity,
|
||||||
IMMUNE_AGGRO_CLIENT,
|
SpecialAbility::ClientAggroImmunity,
|
||||||
IMMUNE_AGGRO_NPC,
|
SpecialAbility::NPCAggroImmunity,
|
||||||
IMMUNE_FADING_MEMORIES,
|
SpecialAbility::MemoryFadeImmunity,
|
||||||
IMMUNE_OPEN,
|
SpecialAbility::OpenImmunity,
|
||||||
IMMUNE_ASSASSINATE,
|
SpecialAbility::AssassinateImmunity,
|
||||||
IMMUNE_HEADSHOT,
|
SpecialAbility::HeadshotImmunity,
|
||||||
IMMUNE_AGGRO_BOT,
|
SpecialAbility::BotAggroImmunity,
|
||||||
IMMUNE_DAMAGE_BOT
|
SpecialAbility::BotDamageImmunity
|
||||||
};
|
};
|
||||||
|
|
||||||
// These abilities have parameters that need to be parsed out individually
|
// These abilities have parameters that need to be parsed out individually
|
||||||
static const std::map<uint32, std::vector<std::string>> parameter_special_abilities = {
|
static const std::map<uint32, std::vector<std::string>> parameter_special_abilities = {
|
||||||
{ SPECATK_SUMMON, { "Cooldown in Milliseconds", "Health Percentage" } },
|
{ SpecialAbility::Summon, { "Cooldown in Milliseconds", "Health Percentage" } },
|
||||||
{
|
{
|
||||||
SPECATK_ENRAGE,
|
SpecialAbility::Enrage,
|
||||||
{
|
{
|
||||||
"Health Percentage",
|
"Health Percentage",
|
||||||
"Duration in Milliseconds",
|
"Duration in Milliseconds",
|
||||||
@@ -3859,7 +3859,7 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SPECATK_RAMPAGE,
|
SpecialAbility::Rampage,
|
||||||
{
|
{
|
||||||
"Chance",
|
"Chance",
|
||||||
"Targets",
|
"Targets",
|
||||||
@@ -3871,7 +3871,7 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SPECATK_AREA_RAMPAGE,
|
SpecialAbility::AreaRampage,
|
||||||
{
|
{
|
||||||
"Targets",
|
"Targets",
|
||||||
"Normal Attack Damage Percentage",
|
"Normal Attack Damage Percentage",
|
||||||
@@ -3883,7 +3883,7 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SPECATK_FLURRY,
|
SpecialAbility::Flurry,
|
||||||
{
|
{
|
||||||
"Attacks",
|
"Attacks",
|
||||||
"Normal Attack Damage Percentage",
|
"Normal Attack Damage Percentage",
|
||||||
@@ -3895,7 +3895,7 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SPECATK_RANGED_ATK,
|
SpecialAbility::RangedAttack,
|
||||||
{
|
{
|
||||||
"Attacks",
|
"Attacks",
|
||||||
"Maximum Range",
|
"Maximum Range",
|
||||||
@@ -3904,21 +3904,21 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
"Minimum Range"
|
"Minimum Range"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ NPC_TUNNELVISION, { "Aggro Modifier on Non-Tanks" } },
|
{ SpecialAbility::TunnelVision, { "Aggro Modifier on Non-Tanks" } },
|
||||||
{ LEASH, { "Range" } },
|
{ SpecialAbility::Leash, { "Range" } },
|
||||||
{ TETHER, { "Range" } },
|
{ SpecialAbility::Tether, { "Range" } },
|
||||||
{ FLEE_PERCENT, { "Health Percentage", "Chance" } },
|
{ SpecialAbility::FleePercent, { "Health Percentage", "Chance" } },
|
||||||
{
|
{
|
||||||
NPC_CHASE_DISTANCE,
|
SpecialAbility::NPCChaseDistance,
|
||||||
{
|
{
|
||||||
"Maximum Distance",
|
"Maximum Distance",
|
||||||
"Minimum Distance",
|
"Minimum Distance",
|
||||||
"Ignore Line of Sight"
|
"Ignore Line of Sight"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ CASTING_RESIST_DIFF, { "Resist Difficulty Value" } },
|
{ SpecialAbility::CastingResistDifficulty, { "Resist Difficulty Value" } },
|
||||||
{
|
{
|
||||||
COUNTER_AVOID_DAMAGE,
|
SpecialAbility::CounterAvoidDamage,
|
||||||
{
|
{
|
||||||
"Reduction Percentage for Block, Dodge, Parry, and Riposte",
|
"Reduction Percentage for Block, Dodge, Parry, and Riposte",
|
||||||
"Reduction Percentage for Riposte",
|
"Reduction Percentage for Riposte",
|
||||||
@@ -3928,7 +3928,7 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
MODIFY_AVOID_DAMAGE,
|
SpecialAbility::ModifyAvoidDamage,
|
||||||
{
|
{
|
||||||
"Addition Percentage for Block, Dodge, Parry, and Riposte",
|
"Addition Percentage for Block, Dodge, Parry, and Riposte",
|
||||||
"Addition Percentage for Riposte",
|
"Addition Percentage for Riposte",
|
||||||
@@ -3946,7 +3946,7 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
messages.emplace_back(
|
messages.emplace_back(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} ({})",
|
"{} ({})",
|
||||||
EQ::constants::GetSpecialAbilityName(e),
|
SpecialAbility::GetName(e),
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -3963,7 +3963,7 @@ void NPC::DescribeSpecialAbilities(Client* c)
|
|||||||
messages.emplace_back(
|
messages.emplace_back(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} ({}) | {}: {}",
|
"{} ({}) | {}: {}",
|
||||||
EQ::constants::GetSpecialAbilityName(e.first),
|
SpecialAbility::GetName(e.first),
|
||||||
e.first,
|
e.first,
|
||||||
a,
|
a,
|
||||||
GetSpecialAbilityParam(e.first, slot_id)
|
GetSpecialAbilityParam(e.first, slot_id)
|
||||||
|
|||||||
@@ -2014,7 +2014,7 @@ uint16_t Perl_Client_GetClassBitmask(Client* self)
|
|||||||
|
|
||||||
uint32_t Perl_Client_GetDeityBitmask(Client* self)
|
uint32_t Perl_Client_GetDeityBitmask(Client* self)
|
||||||
{
|
{
|
||||||
return static_cast<uint32_t>(EQ::deity::GetDeityBitmask(static_cast<EQ::deity::DeityType>(self->GetDeity())));
|
return Deity::GetBitmask(self->GetDeity());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Perl_Client_GetRaceBitmask(Client* self) // @categories Stats and Attributes
|
uint16_t Perl_Client_GetRaceBitmask(Client* self) // @categories Stats and Attributes
|
||||||
|
|||||||
+1
-1
@@ -3427,7 +3427,7 @@ bool Perl_Mob_IsAlwaysAggro(Mob* self)
|
|||||||
|
|
||||||
std::string Perl_Mob_GetDeityName(Mob* self)
|
std::string Perl_Mob_GetDeityName(Mob* self)
|
||||||
{
|
{
|
||||||
return EQ::deity::GetDeityName(static_cast<EQ::deity::DeityType>(self->GetDeity()));
|
return Deity::GetName(self->GetDeity());
|
||||||
}
|
}
|
||||||
|
|
||||||
perl::array Perl_Mob_GetBuffs(Mob* self)
|
perl::array Perl_Mob_GetBuffs(Mob* self)
|
||||||
|
|||||||
@@ -288,6 +288,15 @@ perl::array Perl_QuestItem_GetAugmentIDs(EQ::ItemInstance* self)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Perl_QuestItem_GetItemLink(EQ::ItemInstance* self)
|
||||||
|
{
|
||||||
|
EQ::SayLinkEngine linker;
|
||||||
|
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
||||||
|
linker.SetItemInst(self);
|
||||||
|
|
||||||
|
return linker.GenerateLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void perl_register_questitem()
|
void perl_register_questitem()
|
||||||
{
|
{
|
||||||
@@ -313,6 +322,7 @@ void perl_register_questitem()
|
|||||||
package.add("GetItem", (EQ::ItemData*(*)(EQ::ItemInstance*))&Perl_QuestItem_GetItem);
|
package.add("GetItem", (EQ::ItemData*(*)(EQ::ItemInstance*))&Perl_QuestItem_GetItem);
|
||||||
package.add("GetItem", (EQ::ItemInstance*(*)(EQ::ItemInstance*, uint8))&Perl_QuestItem_GetItem);
|
package.add("GetItem", (EQ::ItemInstance*(*)(EQ::ItemInstance*, uint8))&Perl_QuestItem_GetItem);
|
||||||
package.add("GetItemID", &Perl_QuestItem_GetItemID);
|
package.add("GetItemID", &Perl_QuestItem_GetItemID);
|
||||||
|
package.add("GetItemLink", &Perl_QuestItem_GetItemLink);
|
||||||
package.add("GetItemScriptID", &Perl_QuestItem_GetItemScriptID);
|
package.add("GetItemScriptID", &Perl_QuestItem_GetItemScriptID);
|
||||||
package.add("GetKillsNeeded", &Perl_QuestItem_GetKillsNeeded);
|
package.add("GetKillsNeeded", &Perl_QuestItem_GetKillsNeeded);
|
||||||
package.add("GetMaxEvolveLevel", &Perl_QuestItem_GetMaxEvolveLevel);
|
package.add("GetMaxEvolveLevel", &Perl_QuestItem_GetMaxEvolveLevel);
|
||||||
|
|||||||
+1
-1
@@ -306,7 +306,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
|
|||||||
if (activiate_pet){
|
if (activiate_pet){
|
||||||
npc->AddToHateList(m_target, 1);
|
npc->AddToHateList(m_target, 1);
|
||||||
npc->SetPetTargetLockID(m_target->GetID());
|
npc->SetPetTargetLockID(m_target->GetID());
|
||||||
npc->SetSpecialAbility(IMMUNE_AGGRO, 1);
|
npc->SetSpecialAbility(SpecialAbility::AggroImmunity, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
npc->CastSpell(SPELL_UNSUMMON_SELF, npc->GetID()); //Live like behavior, damages self for 20K
|
npc->CastSpell(SPELL_UNSUMMON_SELF, npc->GetID()); //Live like behavior, damages self for 20K
|
||||||
|
|||||||
@@ -31,6 +31,12 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// an encounter can register events before the object is loaded
|
||||||
|
// examples
|
||||||
|
// eq.register_npc_event(Event.death_complete, -1, AllDeath);
|
||||||
|
// eq.register_npc_event(Event.say, -1, All_Say);
|
||||||
|
const std::string ENCOUNTER_NO_ENTITY_ID = "-1";
|
||||||
|
|
||||||
extern Zone* zone;
|
extern Zone* zone;
|
||||||
extern void MapOpcodes();
|
extern void MapOpcodes();
|
||||||
|
|
||||||
@@ -116,13 +122,7 @@ bool QuestParserCollection::HasQuestSub(uint32 npc_id, QuestEventID event_id)
|
|||||||
|
|
||||||
bool QuestParserCollection::NPCHasEncounterSub(uint32 npc_id, QuestEventID event_id)
|
bool QuestParserCollection::NPCHasEncounterSub(uint32 npc_id, QuestEventID event_id)
|
||||||
{
|
{
|
||||||
return HasEncounterSub(
|
return HasEncounterSub(event_id, fmt::format("npc_{}", npc_id)) || HasEncounterSub(event_id, "npc_" + ENCOUNTER_NO_ENTITY_ID);
|
||||||
event_id,
|
|
||||||
fmt::format(
|
|
||||||
"npc_{}",
|
|
||||||
npc_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QuestParserCollection::HasQuestSubLocal(uint32 npc_id, QuestEventID event_id)
|
bool QuestParserCollection::HasQuestSubLocal(uint32 npc_id, QuestEventID event_id)
|
||||||
@@ -234,13 +234,8 @@ bool QuestParserCollection::PlayerHasQuestSubGlobal(QuestEventID event_id)
|
|||||||
|
|
||||||
bool QuestParserCollection::SpellHasEncounterSub(uint32 spell_id, QuestEventID event_id)
|
bool QuestParserCollection::SpellHasEncounterSub(uint32 spell_id, QuestEventID event_id)
|
||||||
{
|
{
|
||||||
return HasEncounterSub(
|
return HasEncounterSub(event_id, fmt::format("spell_{}", spell_id)) ||
|
||||||
event_id,
|
HasEncounterSub(event_id, "spell_" + ENCOUNTER_NO_ENTITY_ID);
|
||||||
fmt::format(
|
|
||||||
"spell_{}",
|
|
||||||
spell_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID event_id)
|
bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID event_id)
|
||||||
@@ -272,16 +267,11 @@ bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID event
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QuestParserCollection::ItemHasEncounterSub(EQ::ItemInstance* inst, QuestEventID event_id)
|
bool QuestParserCollection::ItemHasEncounterSub(EQ::ItemInstance *inst, QuestEventID event_id)
|
||||||
{
|
{
|
||||||
if (inst) {
|
if (inst) {
|
||||||
return HasEncounterSub(
|
return HasEncounterSub(event_id, fmt::format("item_{}", inst->GetID())) ||
|
||||||
event_id,
|
HasEncounterSub(event_id, "item_" + ENCOUNTER_NO_ENTITY_ID);
|
||||||
fmt::format(
|
|
||||||
"item_{}",
|
|
||||||
inst->GetID()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+17
-2
@@ -1371,7 +1371,7 @@ void QuestManager::sfollow() {
|
|||||||
owner->SetFollowID(0);
|
owner->SetFollowID(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuestManager::changedeity(int deity_id) {
|
void QuestManager::changedeity(uint32 deity_id) {
|
||||||
QuestManagerCurrentQuestVars();
|
QuestManagerCurrentQuestVars();
|
||||||
//Changes the deity.
|
//Changes the deity.
|
||||||
if(initiator)
|
if(initiator)
|
||||||
@@ -3574,6 +3574,21 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) {
|
|||||||
return Quant; // return the quantity of itemid (0 if it was never found)
|
return Quant; // return the quantity of itemid (0 if it was never found)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string QuestManager::varlink(EQ::ItemInstance* inst)
|
||||||
|
{
|
||||||
|
QuestManagerCurrentQuestVars();
|
||||||
|
|
||||||
|
if (!inst) {
|
||||||
|
return "INVALID ITEM INSTANCE IN VARLINK";
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::SayLinkEngine linker;
|
||||||
|
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
||||||
|
linker.SetItemInst(inst);
|
||||||
|
|
||||||
|
return linker.GenerateLink();
|
||||||
|
}
|
||||||
|
|
||||||
// Item Link for use in Variables - "my $example_link = quest::varlink(item_id);"
|
// Item Link for use in Variables - "my $example_link = quest::varlink(item_id);"
|
||||||
std::string QuestManager::varlink(
|
std::string QuestManager::varlink(
|
||||||
uint32 item_id,
|
uint32 item_id,
|
||||||
@@ -4349,7 +4364,7 @@ std::string QuestManager::getgendername(uint32 gender_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string QuestManager::getdeityname(uint32 deity_id) {
|
std::string QuestManager::getdeityname(uint32 deity_id) {
|
||||||
return EQ::deity::GetDeityName(static_cast<EQ::deity::DeityType>(deity_id));
|
return Deity::GetName(deity_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string QuestManager::getinventoryslotname(int16 slot_id) {
|
std::string QuestManager::getinventoryslotname(int16 slot_id) {
|
||||||
|
|||||||
+2
-1
@@ -110,7 +110,7 @@ public:
|
|||||||
void settarget(const char *type, int target_id);
|
void settarget(const char *type, int target_id);
|
||||||
void follow(int entity_id, int distance);
|
void follow(int entity_id, int distance);
|
||||||
void sfollow();
|
void sfollow();
|
||||||
void changedeity(int deity_id);
|
void changedeity(uint32 deity_id);
|
||||||
void exp(int amt);
|
void exp(int amt);
|
||||||
void level(int newlevel);
|
void level(int newlevel);
|
||||||
void traindisc(uint32 discipline_tome_item_id);
|
void traindisc(uint32 discipline_tome_item_id);
|
||||||
@@ -284,6 +284,7 @@ public:
|
|||||||
void MovePCInstance(int zone_id, int instance_id, const glm::vec4& position);
|
void MovePCInstance(int zone_id, int instance_id, const glm::vec4& position);
|
||||||
void FlagInstanceByGroupLeader(uint32 zone, int16 version);
|
void FlagInstanceByGroupLeader(uint32 zone, int16 version);
|
||||||
void FlagInstanceByRaidLeader(uint32 zone, int16 version);
|
void FlagInstanceByRaidLeader(uint32 zone, int16 version);
|
||||||
|
std::string varlink(EQ::ItemInstance* inst);
|
||||||
std::string varlink(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false);
|
std::string varlink(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false);
|
||||||
std::string getcharnamebyid(uint32 char_id);
|
std::string getcharnamebyid(uint32 char_id);
|
||||||
uint32 getcharidbyname(const char* name);
|
uint32 getcharidbyname(const char* name);
|
||||||
|
|||||||
+26
-22
@@ -38,7 +38,6 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
|
|||||||
case EQ::skills::SkillDragonPunch:
|
case EQ::skills::SkillDragonPunch:
|
||||||
case EQ::skills::SkillEagleStrike:
|
case EQ::skills::SkillEagleStrike:
|
||||||
case EQ::skills::SkillTigerClaw:
|
case EQ::skills::SkillTigerClaw:
|
||||||
case EQ::skills::SkillRoundKick:
|
|
||||||
if (skill_level >= 25) {
|
if (skill_level >= 25) {
|
||||||
base++;
|
base++;
|
||||||
}
|
}
|
||||||
@@ -108,7 +107,8 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
|
|||||||
|
|
||||||
return static_cast<int>(ac_bonus + skill_bonus);
|
return static_cast<int>(ac_bonus + skill_bonus);
|
||||||
}
|
}
|
||||||
case EQ::skills::SkillKick: {
|
case EQ::skills::SkillKick:
|
||||||
|
case EQ::skills::SkillRoundKick: {
|
||||||
// there is some base *= 4 case in here?
|
// there is some base *= 4 case in here?
|
||||||
float skill_bonus = skill_level / 10.0f;
|
float skill_bonus = skill_level / 10.0f;
|
||||||
float ac_bonus = 0.0f;
|
float ac_bonus = 0.0f;
|
||||||
@@ -119,8 +119,12 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ac_bonus > skill_bonus) {
|
if (skill_level >= 75) {
|
||||||
ac_bonus = skill_bonus;
|
base++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skill_level >= 175) {
|
||||||
|
base++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
|
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
|
||||||
@@ -228,10 +232,10 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas
|
|||||||
if (base_damage == DMG_INVULNERABLE)
|
if (base_damage == DMG_INVULNERABLE)
|
||||||
my_hit.damage_done = DMG_INVULNERABLE;
|
my_hit.damage_done = DMG_INVULNERABLE;
|
||||||
|
|
||||||
if (who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE))
|
if (who->GetInvul() || who->GetSpecialAbility(SpecialAbility::MeleeImmunity))
|
||||||
my_hit.damage_done = DMG_INVULNERABLE;
|
my_hit.damage_done = DMG_INVULNERABLE;
|
||||||
|
|
||||||
if (who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE) && skill != EQ::skills::SkillBackstab)
|
if (who->GetSpecialAbility(SpecialAbility::MeleeImmunityExceptBane) && skill != EQ::skills::SkillBackstab)
|
||||||
my_hit.damage_done = DMG_INVULNERABLE;
|
my_hit.damage_done = DMG_INVULNERABLE;
|
||||||
|
|
||||||
int64 hate = my_hit.base_damage;
|
int64 hate = my_hit.base_damage;
|
||||||
@@ -965,7 +969,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co
|
|||||||
{
|
{
|
||||||
if ((other == nullptr ||
|
if ((other == nullptr ||
|
||||||
((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) ||
|
((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) ||
|
||||||
HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) {
|
HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(SpecialAbility::MeleeImmunity)))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1346,7 +1350,7 @@ void NPC::RangedAttack(Mob *other)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasBowAndArrowEquipped() && !GetSpecialAbility(SPECATK_RANGED_ATK))
|
if (!HasBowAndArrowEquipped() && !GetSpecialAbility(SpecialAbility::RangedAttack))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!CheckLosFN(other))
|
if (!CheckLosFN(other))
|
||||||
@@ -1356,12 +1360,12 @@ void NPC::RangedAttack(Mob *other)
|
|||||||
float min_range = static_cast<float>(RuleI(Combat, MinRangedAttackDist));
|
float min_range = static_cast<float>(RuleI(Combat, MinRangedAttackDist));
|
||||||
float max_range = 250.0f; // needs to be longer than 200(most spells)
|
float max_range = 250.0f; // needs to be longer than 200(most spells)
|
||||||
|
|
||||||
if (GetSpecialAbility(SPECATK_RANGED_ATK)) {
|
if (GetSpecialAbility(SpecialAbility::RangedAttack)) {
|
||||||
int temp_attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0);
|
int temp_attacks = GetSpecialAbilityParam(SpecialAbility::RangedAttack, 0);
|
||||||
attacks = temp_attacks > 0 ? temp_attacks : 1;
|
attacks = temp_attacks > 0 ? temp_attacks : 1;
|
||||||
|
|
||||||
int temp_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 4); // Min Range of NPC attack
|
int temp_min_range = GetSpecialAbilityParam(SpecialAbility::RangedAttack, 4); // Min Range of NPC attack
|
||||||
int temp_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); // Max Range of NPC attack
|
int temp_max_range = GetSpecialAbilityParam(SpecialAbility::RangedAttack, 1); // Max Range of NPC attack
|
||||||
if (temp_max_range)
|
if (temp_max_range)
|
||||||
max_range = static_cast<float>(temp_max_range);
|
max_range = static_cast<float>(temp_max_range);
|
||||||
if (temp_min_range)
|
if (temp_min_range)
|
||||||
@@ -1397,7 +1401,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha
|
|||||||
HasDied() ||
|
HasDied() ||
|
||||||
(!IsAttackAllowed(other)) ||
|
(!IsAttackAllowed(other)) ||
|
||||||
(other->GetInvul() ||
|
(other->GetInvul() ||
|
||||||
other->GetSpecialAbility(IMMUNE_MELEE)))
|
other->GetSpecialAbility(SpecialAbility::MeleeImmunity)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1426,14 +1430,14 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!chance_mod)
|
if (!chance_mod)
|
||||||
chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2);
|
chance_mod = GetSpecialAbilityParam(SpecialAbility::RangedAttack, 2);
|
||||||
|
|
||||||
int TotalDmg = 0;
|
int TotalDmg = 0;
|
||||||
int MaxDmg = GetBaseDamage() * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types
|
int MaxDmg = GetBaseDamage() * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types
|
||||||
int MinDmg = GetMinDamage() * RuleR(Combat, ArcheryNPCMultiplier);
|
int MinDmg = GetMinDamage() * RuleR(Combat, ArcheryNPCMultiplier);
|
||||||
|
|
||||||
if (!damage_mod)
|
if (!damage_mod)
|
||||||
damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier
|
damage_mod = GetSpecialAbilityParam(SpecialAbility::RangedAttack, 3);//Damage modifier
|
||||||
|
|
||||||
DamageHitInfo my_hit;
|
DamageHitInfo my_hit;
|
||||||
my_hit.base_damage = MaxDmg;
|
my_hit.base_damage = MaxDmg;
|
||||||
@@ -1569,7 +1573,7 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c
|
|||||||
{
|
{
|
||||||
if ((other == nullptr ||
|
if ((other == nullptr ||
|
||||||
((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) ||
|
((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) ||
|
||||||
HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) {
|
HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(SpecialAbility::MeleeImmunity)))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2179,7 +2183,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
|||||||
* Also: "The chance to taunt an NPC higher level than yourself dropped off at double the rate
|
* Also: "The chance to taunt an NPC higher level than yourself dropped off at double the rate
|
||||||
* if you were above level 60 than if you were below level 60 making it very hard to taunt creature
|
* if you were above level 60 than if you were below level 60 making it very hard to taunt creature
|
||||||
* higher level than yourself if you were above level 60."
|
* higher level than yourself if you were above level 60."
|
||||||
*
|
*
|
||||||
* See http://www.elitegamerslounge.com/home/soearchive/viewtopic.php?t=81156 */
|
* See http://www.elitegamerslounge.com/home/soearchive/viewtopic.php?t=81156 */
|
||||||
void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell, int32 bonus_hate)
|
void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell, int32 bonus_hate)
|
||||||
{
|
{
|
||||||
@@ -2200,7 +2204,7 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell
|
|||||||
if (
|
if (
|
||||||
!RuleB(Combat, TauntOverLevel) &&
|
!RuleB(Combat, TauntOverLevel) &&
|
||||||
level_difference < 0 ||
|
level_difference < 0 ||
|
||||||
who->GetSpecialAbility(IMMUNE_TAUNT)
|
who->GetSpecialAbility(SpecialAbility::TauntImmunity)
|
||||||
) {
|
) {
|
||||||
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
||||||
return;
|
return;
|
||||||
@@ -2209,7 +2213,7 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell
|
|||||||
if (always_succeed) {
|
if (always_succeed) {
|
||||||
taunt_chance = 100;
|
taunt_chance = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modern Taunt
|
// Modern Taunt
|
||||||
if (!RuleB(Combat, ClassicTauntSystem)) {
|
if (!RuleB(Combat, ClassicTauntSystem)) {
|
||||||
if (
|
if (
|
||||||
@@ -2400,7 +2404,7 @@ int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse)
|
|||||||
skillInUse == EQ::skills::SkillArchery &&
|
skillInUse == EQ::skills::SkillArchery &&
|
||||||
GetTarget() == defender &&
|
GetTarget() == defender &&
|
||||||
(defender->GetBodyType() == BT_Humanoid || !RuleB(Combat, HeadshotOnlyHumanoids)) &&
|
(defender->GetBodyType() == BT_Humanoid || !RuleB(Combat, HeadshotOnlyHumanoids)) &&
|
||||||
!defender->GetSpecialAbility(IMMUNE_HEADSHOT)
|
!defender->GetSpecialAbility(SpecialAbility::HeadshotImmunity)
|
||||||
) {
|
) {
|
||||||
uint32 HeadShot_Dmg = aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG];
|
uint32 HeadShot_Dmg = aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG];
|
||||||
uint8 HeadShot_Level = 0; // Get Highest Headshot Level
|
uint8 HeadShot_Level = 0; // Get Highest Headshot Level
|
||||||
@@ -2437,7 +2441,7 @@ int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse)
|
|||||||
GetLevel() >= RuleI(Combat, AssassinateLevelRequirement) &&
|
GetLevel() >= RuleI(Combat, AssassinateLevelRequirement) &&
|
||||||
(skillInUse == EQ::skills::SkillBackstab || skillInUse == EQ::skills::SkillThrowing) &&
|
(skillInUse == EQ::skills::SkillBackstab || skillInUse == EQ::skills::SkillThrowing) &&
|
||||||
(defender->GetBodyType() == BT_Humanoid || !RuleB(Combat, AssassinateOnlyHumanoids)) &&
|
(defender->GetBodyType() == BT_Humanoid || !RuleB(Combat, AssassinateOnlyHumanoids)) &&
|
||||||
!defender->GetSpecialAbility(IMMUNE_ASSASSINATE)
|
!defender->GetSpecialAbility(SpecialAbility::AssassinateImmunity)
|
||||||
) {
|
) {
|
||||||
int chance = GetDEX();
|
int chance = GetDEX();
|
||||||
if (skillInUse == EQ::skills::SkillBackstab) {
|
if (skillInUse == EQ::skills::SkillBackstab) {
|
||||||
@@ -2570,7 +2574,7 @@ bool Mob::CanDoSpecialAttack(Mob *other) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE))
|
if(other->GetInvul() || other->GetSpecialAbility(SpecialAbility::MeleeImmunity))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+12
-12
@@ -747,7 +747,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
max_level = RuleI(Spells, BaseImmunityLevel);
|
max_level = RuleI(Spells, BaseImmunityLevel);
|
||||||
// NPCs get to ignore max_level for their spells.
|
// NPCs get to ignore max_level for their spells.
|
||||||
// Ignore if spell is beneficial (ex. Harvest)
|
// Ignore if spell is beneficial (ex. Harvest)
|
||||||
if (IsDetrimentalSpell(spell.id) && (GetSpecialAbility(UNSTUNABLE) ||
|
if (IsDetrimentalSpell(spell.id) && (GetSpecialAbility(SpecialAbility::StunImmunity) ||
|
||||||
((GetLevel() > max_level) && caster && (!caster->IsNPC() ||
|
((GetLevel() > max_level) && caster && (!caster->IsNPC() ||
|
||||||
(caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity))))))
|
(caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity))))))
|
||||||
{
|
{
|
||||||
@@ -1103,7 +1103,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
snprintf(effect_desc, _EDLEN, "Cancel Magic: %d", effect_value);
|
snprintf(effect_desc, _EDLEN, "Cancel Magic: %d", effect_value);
|
||||||
#endif
|
#endif
|
||||||
if(GetSpecialAbility(UNDISPELLABLE)){
|
if(GetSpecialAbility(SpecialAbility::DispellImmunity)){
|
||||||
if (caster) {
|
if (caster) {
|
||||||
caster->MessageString(Chat::SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name);
|
caster->MessageString(Chat::SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name);
|
||||||
}
|
}
|
||||||
@@ -1119,7 +1119,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
snprintf(effect_desc, _EDLEN, "Dispel Detrimental: %d", effect_value);
|
snprintf(effect_desc, _EDLEN, "Dispel Detrimental: %d", effect_value);
|
||||||
#endif
|
#endif
|
||||||
if(GetSpecialAbility(UNDISPELLABLE)){
|
if(GetSpecialAbility(SpecialAbility::DispellImmunity)){
|
||||||
if (caster)
|
if (caster)
|
||||||
caster->MessageString(Chat::SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name);
|
caster->MessageString(Chat::SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name);
|
||||||
break;
|
break;
|
||||||
@@ -1150,7 +1150,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
snprintf(effect_desc, _EDLEN, "Dispel Beneficial: %d", effect_value);
|
snprintf(effect_desc, _EDLEN, "Dispel Beneficial: %d", effect_value);
|
||||||
#endif
|
#endif
|
||||||
if(GetSpecialAbility(UNDISPELLABLE)){
|
if(GetSpecialAbility(SpecialAbility::DispellImmunity)){
|
||||||
if (caster)
|
if (caster)
|
||||||
caster->MessageString(Chat::SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name);
|
caster->MessageString(Chat::SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name);
|
||||||
break;
|
break;
|
||||||
@@ -1551,7 +1551,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
max_level = RuleI(Spells, BaseImmunityLevel); // Default max is 55 level limit
|
max_level = RuleI(Spells, BaseImmunityLevel); // Default max is 55 level limit
|
||||||
|
|
||||||
// NPCs ignore level limits in their spells
|
// NPCs ignore level limits in their spells
|
||||||
if(GetSpecialAbility(UNSTUNABLE) ||
|
if(GetSpecialAbility(SpecialAbility::StunImmunity) ||
|
||||||
((GetLevel() > max_level)
|
((GetLevel() > max_level)
|
||||||
&& caster && (!caster->IsNPC() || (caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity)))))
|
&& caster && (!caster->IsNPC() || (caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity)))))
|
||||||
{
|
{
|
||||||
@@ -3043,12 +3043,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
if (!caster)
|
if (!caster)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (IsNPC() && GetSpecialAbility(UNSTUNABLE)) {
|
if (IsNPC() && GetSpecialAbility(SpecialAbility::StunImmunity)) {
|
||||||
caster->MessageString(Chat::SpellFailure, IMMUNE_STUN);
|
caster->MessageString(Chat::SpellFailure, IMMUNE_STUN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNPC() && GetSpecialAbility(UNFEARABLE)) {
|
if (IsNPC() && GetSpecialAbility(SpecialAbility::FearImmunity)) {
|
||||||
caster->MessageString(Chat::SpellFailure, IMMUNE_FEAR);
|
caster->MessageString(Chat::SpellFailure, IMMUNE_FEAR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4461,8 +4461,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
|||||||
}
|
}
|
||||||
//If owner dead, briefly setting Immmune Aggro while hatelists wipe for both pet and targets is needed to ensure no reaggroing.
|
//If owner dead, briefly setting Immmune Aggro while hatelists wipe for both pet and targets is needed to ensure no reaggroing.
|
||||||
else if (IsNPC()){
|
else if (IsNPC()){
|
||||||
bool immune_aggro = GetSpecialAbility(IMMUNE_AGGRO); //check if already immune aggro
|
bool has_aggro_immunity = GetSpecialAbility(SpecialAbility::AggroImmunity); //check if already immune aggro
|
||||||
SetSpecialAbility(IMMUNE_AGGRO, 1);
|
SetSpecialAbility(SpecialAbility::AggroImmunity, 1);
|
||||||
WipeHateList();
|
WipeHateList();
|
||||||
if (IsCasting()) {
|
if (IsCasting()) {
|
||||||
InterruptSpell(CastingSpellID());
|
InterruptSpell(CastingSpellID());
|
||||||
@@ -4478,8 +4478,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!immune_aggro) {
|
if (!has_aggro_immunity) {
|
||||||
SetSpecialAbility(IMMUNE_AGGRO, 0);
|
SetSpecialAbility(SpecialAbility::AggroImmunity, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
||||||
@@ -9904,7 +9904,7 @@ bool Mob::HarmonySpellLevelCheck(int32 spell_id, Mob *target)
|
|||||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||||
// not important to check limit on SE_Lull as it doesnt have one and if the other components won't land, then SE_Lull wont either
|
// not important to check limit on SE_Lull as it doesnt have one and if the other components won't land, then SE_Lull wont either
|
||||||
if (spells[spell_id].effect_id[i] == SE_ChangeFrenzyRad || spells[spell_id].effect_id[i] == SE_Harmony) {
|
if (spells[spell_id].effect_id[i] == SE_ChangeFrenzyRad || spells[spell_id].effect_id[i] == SE_Harmony) {
|
||||||
if ((spells[spell_id].max_value[i] != 0 && target->GetLevel() > spells[spell_id].max_value[i]) || target->GetSpecialAbility(IMMUNE_PACIFY)) {
|
if ((spells[spell_id].max_value[i] != 0 && target->GetLevel() > spells[spell_id].max_value[i]) || target->GetSpecialAbility(SpecialAbility::PacifyImmunity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -3675,7 +3675,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
|||||||
if (!will_overwrite && !IsDisciplineBuff(spell_id)) {
|
if (!will_overwrite && !IsDisciplineBuff(spell_id)) {
|
||||||
emptyslot = buffslot;
|
emptyslot = buffslot;
|
||||||
}
|
}
|
||||||
|
|
||||||
will_overwrite = true;
|
will_overwrite = true;
|
||||||
overwrite_slots.push_back(buffslot);
|
overwrite_slots.push_back(buffslot);
|
||||||
} else if (ret == 2) {
|
} else if (ret == 2) {
|
||||||
@@ -5041,7 +5041,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
|
|
||||||
if(IsMesmerizeSpell(spell_id))
|
if(IsMesmerizeSpell(spell_id))
|
||||||
{
|
{
|
||||||
if(GetSpecialAbility(UNMEZABLE)) {
|
if(GetSpecialAbility(SpecialAbility::MesmerizeImmunity)) {
|
||||||
LogSpells("We are immune to Mez spells");
|
LogSpells("We are immune to Mez spells");
|
||||||
caster->MessageString(Chat::SpellFailure, CANNOT_MEZ);
|
caster->MessageString(Chat::SpellFailure, CANNOT_MEZ);
|
||||||
int32 aggro = caster->CheckAggroAmount(spell_id, this);
|
int32 aggro = caster->CheckAggroAmount(spell_id, this);
|
||||||
@@ -5068,7 +5068,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// slow and haste spells
|
// slow and haste spells
|
||||||
if(GetSpecialAbility(UNSLOWABLE) && IsEffectInSpell(spell_id, SE_AttackSpeed))
|
if(GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SE_AttackSpeed))
|
||||||
{
|
{
|
||||||
LogSpells("We are immune to Slow spells");
|
LogSpells("We are immune to Slow spells");
|
||||||
caster->MessageString(Chat::Red, IMMUNE_ATKSPEED);
|
caster->MessageString(Chat::Red, IMMUNE_ATKSPEED);
|
||||||
@@ -5085,7 +5085,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
if(IsEffectInSpell(spell_id, SE_Fear))
|
if(IsEffectInSpell(spell_id, SE_Fear))
|
||||||
{
|
{
|
||||||
effect_index = GetSpellEffectIndex(spell_id, SE_Fear);
|
effect_index = GetSpellEffectIndex(spell_id, SE_Fear);
|
||||||
if(GetSpecialAbility(UNFEARABLE)) {
|
if(GetSpecialAbility(SpecialAbility::FearImmunity)) {
|
||||||
LogSpells("We are immune to Fear spells");
|
LogSpells("We are immune to Fear spells");
|
||||||
caster->MessageString(Chat::Red, IMMUNE_FEAR); // need to verify message type, not in MQ2Cast for easy look up
|
caster->MessageString(Chat::Red, IMMUNE_FEAR); // need to verify message type, not in MQ2Cast for easy look up
|
||||||
int32 aggro = caster->CheckAggroAmount(spell_id, this);
|
int32 aggro = caster->CheckAggroAmount(spell_id, this);
|
||||||
@@ -5124,7 +5124,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
|
|
||||||
if(IsCharmSpell(spell_id))
|
if(IsCharmSpell(spell_id))
|
||||||
{
|
{
|
||||||
if(GetSpecialAbility(UNCHARMABLE))
|
if(GetSpecialAbility(SpecialAbility::CharmImmunity))
|
||||||
{
|
{
|
||||||
LogSpells("We are immune to Charm spells");
|
LogSpells("We are immune to Charm spells");
|
||||||
caster->MessageString(Chat::Red, CANNOT_CHARM); // need to verify message type, not in MQ2Cast for easy look up
|
caster->MessageString(Chat::Red, CANNOT_CHARM); // need to verify message type, not in MQ2Cast for easy look up
|
||||||
@@ -5173,7 +5173,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
IsEffectInSpell(spell_id, SE_MovementSpeed)
|
IsEffectInSpell(spell_id, SE_MovementSpeed)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if(GetSpecialAbility(UNSNAREABLE)) {
|
if(GetSpecialAbility(SpecialAbility::SnareImmunity)) {
|
||||||
LogSpells("We are immune to Snare spells");
|
LogSpells("We are immune to Snare spells");
|
||||||
caster->MessageString(Chat::Red, IMMUNE_MOVEMENT);
|
caster->MessageString(Chat::Red, IMMUNE_MOVEMENT);
|
||||||
int32 aggro = caster->CheckAggroAmount(spell_id, this);
|
int32 aggro = caster->CheckAggroAmount(spell_id, this);
|
||||||
@@ -5263,7 +5263,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetSpecialAbility(IMMUNE_CASTING_FROM_RANGE))
|
if(GetSpecialAbility(SpecialAbility::CastingFromRangeImmunity))
|
||||||
{
|
{
|
||||||
if(!caster->CombatRange(this))
|
if(!caster->CombatRange(this))
|
||||||
{
|
{
|
||||||
@@ -5271,7 +5271,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetSpecialAbility(IMMUNE_MAGIC))
|
if(GetSpecialAbility(SpecialAbility::MagicImmunity))
|
||||||
{
|
{
|
||||||
LogSpells("We are immune to magic, so we fully resist the spell [{}]", spell_id);
|
LogSpells("We are immune to magic, so we fully resist the spell [{}]", spell_id);
|
||||||
return(0);
|
return(0);
|
||||||
@@ -5291,8 +5291,8 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(caster->GetSpecialAbility(CASTING_RESIST_DIFF))
|
if(caster->GetSpecialAbility(SpecialAbility::CastingResistDifficulty))
|
||||||
resist_modifier += caster->GetSpecialAbilityParam(CASTING_RESIST_DIFF, 0);
|
resist_modifier += caster->GetSpecialAbilityParam(SpecialAbility::CastingResistDifficulty, 0);
|
||||||
|
|
||||||
int64 focus_resist = caster->GetFocusEffect(focusResistRate, spell_id);
|
int64 focus_resist = caster->GetFocusEffect(focusResistRate, spell_id);
|
||||||
|
|
||||||
|
|||||||
@@ -204,6 +204,7 @@
|
|||||||
#define FINISHING_BLOW 1009 //%1 scores a Finishing Blow!!
|
#define FINISHING_BLOW 1009 //%1 scores a Finishing Blow!!
|
||||||
#define ASSASSINATES 1016 //%1 ASSASSINATES their victim!!
|
#define ASSASSINATES 1016 //%1 ASSASSINATES their victim!!
|
||||||
#define CRIPPLING_BLOW 1021 //%1 lands a Crippling Blow!(%2)
|
#define CRIPPLING_BLOW 1021 //%1 lands a Crippling Blow!(%2)
|
||||||
|
#define STAGGERS 1022 //%1 staggers.
|
||||||
#define CRITICAL_HIT 1023 //%1 scores a critical hit! (%2)
|
#define CRITICAL_HIT 1023 //%1 scores a critical hit! (%2)
|
||||||
#define DEADLY_STRIKE 1024 //%1 scores a Deadly Strike!(%2)
|
#define DEADLY_STRIKE 1024 //%1 scores a Deadly Strike!(%2)
|
||||||
#define RESISTS_URGE 1025 //%1 resists their urge to flee.
|
#define RESISTS_URGE 1025 //%1 resists their urge to flee.
|
||||||
|
|||||||
+2
-2
@@ -1553,7 +1553,7 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA
|
|||||||
// this appears where they do special attack dmg mods
|
// this appears where they do special attack dmg mods
|
||||||
int spec_mod = 0;
|
int spec_mod = 0;
|
||||||
if (IsSpecialAttack(eSpecialAttacks::Rampage)) {
|
if (IsSpecialAttack(eSpecialAttacks::Rampage)) {
|
||||||
int mod = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2);
|
int mod = GetSpecialAbilityParam(SpecialAbility::Rampage, 2);
|
||||||
if (mod > 0)
|
if (mod > 0)
|
||||||
spec_mod = mod;
|
spec_mod = mod;
|
||||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||||
@@ -1564,7 +1564,7 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsSpecialAttack(eSpecialAttacks::AERampage)) {
|
else if (IsSpecialAttack(eSpecialAttacks::AERampage)) {
|
||||||
int mod = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2);
|
int mod = GetSpecialAbilityParam(SpecialAbility::AreaRampage, 2);
|
||||||
if (mod > 0)
|
if (mod > 0)
|
||||||
spec_mod = mod;
|
spec_mod = mod;
|
||||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||||
|
|||||||
+60
-171
@@ -1172,7 +1172,6 @@ bool Zone::Init(bool is_static) {
|
|||||||
|
|
||||||
// make sure that anything that needs to be loaded prior to scripts is loaded before here
|
// make sure that anything that needs to be loaded prior to scripts is loaded before here
|
||||||
// this is to ensure that the scripts have access to the data they need
|
// this is to ensure that the scripts have access to the data they need
|
||||||
parse->Init();
|
|
||||||
parse->ReloadQuests(true);
|
parse->ReloadQuests(true);
|
||||||
|
|
||||||
spawn_conditions.LoadSpawnConditions(short_name, instanceid);
|
spawn_conditions.LoadSpawnConditions(short_name, instanceid);
|
||||||
@@ -2988,179 +2987,69 @@ std::string Zone::GetAAName(int aa_id)
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Zone::CompareDataBucket(uint8 bucket_comparison, const std::string& bucket_value, const std::string& player_value)
|
bool Zone::CompareDataBucket(uint8 comparison_type, const std::string& bucket, const std::string& value)
|
||||||
{
|
{
|
||||||
std::vector<std::string> bucket_checks;
|
if (!ComparisonType::IsValid(comparison_type)) {
|
||||||
bool found = false;
|
return false;
|
||||||
bool passes = false;
|
|
||||||
|
|
||||||
switch (bucket_comparison) {
|
|
||||||
case BucketComparison::BucketEqualTo:
|
|
||||||
{
|
|
||||||
if (player_value != bucket_value) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketNotEqualTo:
|
|
||||||
{
|
|
||||||
if (player_value == bucket_value) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketGreaterThanOrEqualTo:
|
|
||||||
{
|
|
||||||
if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings::ToBigInt(player_value) < Strings::ToBigInt(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketLesserThanOrEqualTo:
|
|
||||||
{
|
|
||||||
if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings::ToBigInt(player_value) > Strings::ToBigInt(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketGreaterThan:
|
|
||||||
{
|
|
||||||
if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings::ToBigInt(player_value) <= Strings::ToBigInt(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketLesserThan:
|
|
||||||
{
|
|
||||||
if (!Strings::IsNumber(player_value) || !Strings::IsNumber(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Strings::ToBigInt(player_value) >= Strings::ToBigInt(bucket_value)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketIsAny:
|
|
||||||
{
|
|
||||||
bucket_checks = Strings::Split(bucket_value, "|");
|
|
||||||
if (bucket_checks.empty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::find(bucket_checks.begin(), bucket_checks.end(), player_value) != bucket_checks.end()) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketIsNotAny:
|
|
||||||
{
|
|
||||||
bucket_checks = Strings::Split(bucket_value, "|");
|
|
||||||
if (bucket_checks.empty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::find(bucket_checks.begin(), bucket_checks.end(), player_value) != bucket_checks.end()) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketIsBetween:
|
|
||||||
{
|
|
||||||
bucket_checks = Strings::Split(bucket_value, "|");
|
|
||||||
if (bucket_checks.empty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!Strings::IsNumber(player_value) ||
|
|
||||||
!Strings::IsNumber(bucket_checks[0]) ||
|
|
||||||
!Strings::IsNumber(bucket_checks[1])
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!EQ::ValueWithin(
|
|
||||||
Strings::ToBigInt(player_value),
|
|
||||||
Strings::ToBigInt(bucket_checks[0]),
|
|
||||||
Strings::ToBigInt(bucket_checks[1])
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BucketComparison::BucketIsNotBetween:
|
|
||||||
{
|
|
||||||
bucket_checks = Strings::Split(bucket_value, "|");
|
|
||||||
if (bucket_checks.empty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!Strings::IsNumber(player_value) ||
|
|
||||||
!Strings::IsNumber(bucket_checks[0]) ||
|
|
||||||
!Strings::IsNumber(bucket_checks[1])
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
EQ::ValueWithin(
|
|
||||||
Strings::ToBigInt(player_value),
|
|
||||||
Strings::ToBigInt(bucket_checks[0]),
|
|
||||||
Strings::ToBigInt(bucket_checks[1])
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
passes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return passes;
|
if (EQ::ValueWithin(comparison_type, ComparisonType::Equal, ComparisonType::NotEqual)) {
|
||||||
|
const bool is_equal = value == bucket;
|
||||||
|
|
||||||
|
return comparison_type == ComparisonType::Equal ? is_equal : !is_equal;
|
||||||
|
} else if (EQ::ValueWithin(comparison_type, ComparisonType::GreaterOrEqual, ComparisonType::LesserOrEqual)) {
|
||||||
|
if (!Strings::IsNumber(value) || !Strings::IsNumber(bucket)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int64 p = Strings::ToBigInt(value);
|
||||||
|
const int64 b = Strings::ToBigInt(bucket);
|
||||||
|
|
||||||
|
const bool is_greater_or_equal = p >= b;
|
||||||
|
const bool is_lesser_or_equal = p <= b;
|
||||||
|
|
||||||
|
return comparison_type == ComparisonType::GreaterOrEqual ? is_greater_or_equal : is_lesser_or_equal;
|
||||||
|
} else if (EQ::ValueWithin(comparison_type, ComparisonType::Greater, ComparisonType::Lesser)) {
|
||||||
|
if (!Strings::IsNumber(value) || !Strings::IsNumber(bucket)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool is_greater = Strings::ToBigInt(value) > Strings::ToBigInt(bucket);
|
||||||
|
|
||||||
|
return comparison_type == ComparisonType::Greater ? is_greater : !is_greater;
|
||||||
|
} else if (EQ::ValueWithin(comparison_type, ComparisonType::Any, ComparisonType::NotAny)) {
|
||||||
|
const auto& values = Strings::Split(bucket, "|");
|
||||||
|
if (values.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool is_any = std::find(values.begin(), values.end(), value) != values.end();
|
||||||
|
|
||||||
|
return comparison_type == ComparisonType::Any ? is_any : !is_any;
|
||||||
|
} else if (EQ::ValueWithin(comparison_type, ComparisonType::Between, ComparisonType::NotBetween)) {
|
||||||
|
if (!Strings::IsNumber(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& values = Strings::Split(bucket, "|");
|
||||||
|
if (values.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Strings::IsNumber(values[0]) || !Strings::IsNumber(values[1])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool is_between = EQ::ValueWithin(
|
||||||
|
Strings::ToBigInt(value),
|
||||||
|
Strings::ToBigInt(values[0]),
|
||||||
|
Strings::ToBigInt(values[1])
|
||||||
|
);
|
||||||
|
|
||||||
|
return comparison_type == ComparisonType::Between ? is_between : !is_between;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::ReloadContentFlags()
|
void Zone::ReloadContentFlags()
|
||||||
|
|||||||
+1
-1
@@ -334,7 +334,7 @@ public:
|
|||||||
bool IsQuestHotReloadQueued() const;
|
bool IsQuestHotReloadQueued() const;
|
||||||
void SetQuestHotReloadQueued(bool in_quest_hot_reload_queued);
|
void SetQuestHotReloadQueued(bool in_quest_hot_reload_queued);
|
||||||
|
|
||||||
bool CompareDataBucket(uint8 bucket_comparison, const std::string& bucket_value, const std::string& player_value);
|
bool CompareDataBucket(uint8 comparison_type, const std::string& bucket, const std::string& value);
|
||||||
|
|
||||||
WaterMap *watermap;
|
WaterMap *watermap;
|
||||||
ZonePoint *GetClosestZonePoint(const glm::vec3 &location, uint32 to, Client *client, float max_distance = 40000.0f);
|
ZonePoint *GetClosestZonePoint(const glm::vec3 &location, uint32 to, Client *client, float max_distance = 40000.0f);
|
||||||
|
|||||||
Reference in New Issue
Block a user