mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-29 14:55:44 +00:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6130e10831 | |||
| c3e1c531d2 | |||
| b52719a535 | |||
| 1af252466f | |||
| 699d22fc28 | |||
| 5d1fe68906 | |||
| 52dcf35425 | |||
| a7550fbd9e | |||
| cc0171dfe1 | |||
| 913c5da70f | |||
| 40fecbfaf5 | |||
| b1646381b0 | |||
| bb1578796b | |||
| 0e5a38f072 | |||
| 39876ab858 | |||
| ff16a76481 | |||
| ffd68eb63d | |||
| 76c1da1aad | |||
| a91e03fa43 | |||
| 453106439f | |||
| 3da24fffa4 | |||
| 8d8ef6d480 | |||
| 1f9c4b3a22 | |||
| 7dfda95d86 | |||
| 40738b29e3 | |||
| 080865faa2 | |||
| e2b545991a | |||
| b7f8d0f179 | |||
| e3588781aa | |||
| e9b84f4d11 | |||
| 4f03970fd1 | |||
| 4979da6932 | |||
| 9987029791 | |||
| eece0a92e3 | |||
| 057f96796a | |||
| f475cecdb1 | |||
| 6296ed6d41 | |||
| ac0f729aa2 | |||
| 2937852cf9 | |||
| 2cf5bae571 | |||
| 2feb05be18 | |||
| 421767e1e5 |
@@ -1,3 +1,88 @@
|
||||
## [22.56.2] 9/20/2024
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix Issue with Database::ReserveName ([#4477](https://github.com/EQEmu/Server/pull/4477)) @Kinglykrab 2024-09-20
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add GrantAllAAPoints() Overload To Perl/Lua ([#4474](https://github.com/EQEmu/Server/pull/4474)) @Kinglykrab 2024-09-20
|
||||
|
||||
## [22.56.1] 9/20/2024
|
||||
|
||||
### Fixes
|
||||
|
||||
* Fix Untrained Disciplines in Client::SaveDisciplines() ([#4472](https://github.com/EQEmu/Server/pull/4472)) @Kinglykrab 2024-09-13
|
||||
* Fix Infinite Loop in Adventure::Finished() ([#4473](https://github.com/EQEmu/Server/pull/4473)) @oddx2k 2024-09-13
|
||||
|
||||
## [22.56.0] 9/12/2024
|
||||
|
||||
### Code
|
||||
|
||||
* Add IsCloseToBanker method ([#4462](https://github.com/EQEmu/Server/pull/4462)) @Akkadius 2024-08-27
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Rule to Limit Task Update Messages ([#4459](https://github.com/EQEmu/Server/pull/4459)) @Kinglykrab 2024-08-28
|
||||
* Allow NPCs to cast Sacrifice ([#4470](https://github.com/EQEmu/Server/pull/4470)) @fuzzlecutter 2024-09-12
|
||||
* Lazy Load Bank Contents ([#4453](https://github.com/EQEmu/Server/pull/4453)) @catapultam-habeo 2024-08-27
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add RULE_STRING to RuleManager::ResetRules ([#4467](https://github.com/EQEmu/Server/pull/4467)) @Kinglykrab 2024-09-07
|
||||
* Fix Bard Effect in Migration 9237 ([#4468](https://github.com/EQEmu/Server/pull/4468)) @Kinglykrab 2024-09-09
|
||||
* ModernAAScalingEnabled() Calculation Error ([#4469](https://github.com/EQEmu/Server/pull/4469)) @carolus21rex 2024-09-11
|
||||
|
||||
### Performance
|
||||
|
||||
* Move Discipline Loading to Client::CompleteConnect() ([#4466](https://github.com/EQEmu/Server/pull/4466)) @Kinglykrab 2024-09-09
|
||||
|
||||
### Rules
|
||||
|
||||
* Add a Bandolier Swap Delay Rule ([#4465](https://github.com/EQEmu/Server/pull/4465)) @Kinglykrab 2024-09-08
|
||||
|
||||
## [22.55.1] 8/26/2024
|
||||
|
||||
### Code
|
||||
|
||||
* Remove unused methods ([#4449](https://github.com/EQEmu/Server/pull/4449)) @Kinglykrab 2024-08-22
|
||||
|
||||
### Feature
|
||||
|
||||
* Add Character:DefaultGuildRank Rule ([#4438](https://github.com/EQEmu/Server/pull/4438)) @Kinglykrab 2024-08-04
|
||||
* Add Optional Return to EVENT_DAMAGE_TAKEN ([#4454](https://github.com/EQEmu/Server/pull/4454)) @Kinglykrab 2024-08-27
|
||||
* Extend Spell Buckets Functionality ([#4441](https://github.com/EQEmu/Server/pull/4441)) @Kinglykrab 2024-08-22
|
||||
|
||||
### Fixes
|
||||
|
||||
* Apply Race & Class restrictions to Auto-Combines ([#4452](https://github.com/EQEmu/Server/pull/4452)) @catapultam-habeo 2024-08-20
|
||||
* Attune Augments when Equipped ([#4446](https://github.com/EQEmu/Server/pull/4446)) @fryguy503 2024-08-10
|
||||
* Correct missed maxlevel reference in exp.cpp ([#4463](https://github.com/EQEmu/Server/pull/4463)) @N0ctrnl 2024-08-27
|
||||
* Ensure close of Tribute Item search ([#4439](https://github.com/EQEmu/Server/pull/4439)) @joligario 2024-08-04
|
||||
* Fix AddCrystals() in Perl/Lua ([#4445](https://github.com/EQEmu/Server/pull/4445)) @Kinglykrab 2024-08-10
|
||||
* Fix Bot Spell Entries IDs Capping at 32,767 ([#4444](https://github.com/EQEmu/Server/pull/4444)) @Kinglykrab 2024-08-27
|
||||
* Fix Character ID of 0 being inserted into character_stats_record ([#4458](https://github.com/EQEmu/Server/pull/4458)) @Kinglykrab 2024-08-22
|
||||
* Fix Issue with Removed #setfaction Command ([#4448](https://github.com/EQEmu/Server/pull/4448)) @Kinglykrab 2024-08-11
|
||||
* Fix Lua Client FilteredMessage ([#4437](https://github.com/EQEmu/Server/pull/4437)) @Kinglykrab 2024-07-31
|
||||
* Fix client hotbar exchanging items when zoning ([#4460](https://github.com/EQEmu/Server/pull/4460)) @neckkola 2024-08-27
|
||||
* Fix issue with killed mob coordinates ([#4457](https://github.com/EQEmu/Server/pull/4457)) @Kinglykrab 2024-08-22
|
||||
* Imitate Death should also clear zone feign aggro ([#4436](https://github.com/EQEmu/Server/pull/4436)) @fryguy503 2024-07-31
|
||||
* client_max_level allow leveling to end of level ([#4455](https://github.com/EQEmu/Server/pull/4455)) @fryguy503 2024-08-20
|
||||
|
||||
### Improvement
|
||||
|
||||
* Filtered Messages Extension ([#4435](https://github.com/EQEmu/Server/pull/4435)) @fryguy503 2024-07-31
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add AreTasksCompleted() to Perl/Lua. ([#4456](https://github.com/EQEmu/Server/pull/4456)) @Kinglykrab 2024-08-23
|
||||
* Add Area-Based Quest Methods to Perl/Lua ([#4447](https://github.com/EQEmu/Server/pull/4447)) @Kinglykrab 2024-08-27
|
||||
* Add Several Door Methods to Perl/Lua ([#4451](https://github.com/EQEmu/Server/pull/4451)) @Kinglykrab 2024-08-16
|
||||
|
||||
### World
|
||||
|
||||
* Fix slow world bootup bug ([#4461](https://github.com/EQEmu/Server/pull/4461)) @Akkadius 2024-08-27
|
||||
|
||||
## [22.54.0] 7/30/2024
|
||||
|
||||
### Code
|
||||
|
||||
+27
-9
@@ -66,6 +66,7 @@
|
||||
#endif
|
||||
|
||||
#include "database.h"
|
||||
#include "data_verification.h"
|
||||
#include "eq_packet_structs.h"
|
||||
#include "extprofile.h"
|
||||
#include "strings.h"
|
||||
@@ -284,16 +285,31 @@ bool Database::SetAccountStatus(const std::string& account_name, int16 status)
|
||||
|
||||
bool Database::ReserveName(uint32 account_id, const std::string& name)
|
||||
{
|
||||
const auto& l = CharacterDataRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"`name` = '{}'",
|
||||
Strings::Escape(name)
|
||||
)
|
||||
const std::string& where_filter = fmt::format(
|
||||
"`name` = '{}'",
|
||||
Strings::Escape(name)
|
||||
);
|
||||
|
||||
if (!l.empty()) {
|
||||
LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name);
|
||||
if (RuleB(Bots, Enabled)) {
|
||||
const auto& b = BotDataRepository::GetWhere(*this, where_filter);
|
||||
|
||||
if (!b.empty()) {
|
||||
LogInfo("Account [{}] requested name [{}] but name is already taken by a bot", account_id, name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& c = CharacterDataRepository::GetWhere(*this, where_filter);
|
||||
|
||||
if (!c.empty()) {
|
||||
LogInfo("Account [{}] requested name [{}] but name is already taken by a character", account_id, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& n = NpcTypesRepository::GetWhere(*this, where_filter);
|
||||
|
||||
if (!n.empty()) {
|
||||
LogInfo("Account [{}] requested name [{}] but name is already taken by an NPC", account_id, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -308,13 +324,15 @@ bool Database::ReserveName(uint32 account_id, const std::string& name)
|
||||
return false;
|
||||
}
|
||||
|
||||
const int guild_id = RuleI(Character, DefaultGuild);
|
||||
const uint32 guild_id = RuleI(Character, DefaultGuild);
|
||||
const uint8 guild_rank = EQ::Clamp(RuleI(Character, DefaultGuildRank), 0, 8);
|
||||
if (guild_id != 0) {
|
||||
if (e.id) {
|
||||
auto g = GuildMembersRepository::NewEntity();
|
||||
|
||||
g.char_id = e.id;
|
||||
g.guild_id = guild_id;
|
||||
g.rank_ = guild_rank;
|
||||
|
||||
GuildMembersRepository::InsertOne(*this, g);
|
||||
}
|
||||
|
||||
@@ -4947,7 +4947,7 @@ UPDATE `aa_ability` SET `auto_grant_enabled` = 1 WHERE `grant_only` = 0 AND `cha
|
||||
.version = 9237,
|
||||
.description = "2023_10_15_import_13th_floor.sql",
|
||||
.check = "SHOW COLUMNS FROM `items` LIKE 'bardeffect';",
|
||||
.condition = "contains",
|
||||
.condition = "missing",
|
||||
.match = "mediumint",
|
||||
.sql = R"(
|
||||
ALTER TABLE `items`
|
||||
@@ -5717,6 +5717,35 @@ CREATE TABLE `buyer_trade_items` (
|
||||
COLLATE='latin1_swedish_ci'
|
||||
ENGINE=InnoDB
|
||||
AUTO_INCREMENT=1;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9282,
|
||||
.description = "2024_08_02_spell_buckets_comparison.sql",
|
||||
.check = "SHOW COLUMNS FROM `spell_buckets` LIKE 'bucket_comparison'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `spell_buckets`
|
||||
CHANGE COLUMN `spellid` `spell_id` int UNSIGNED NOT NULL FIRST,
|
||||
CHANGE COLUMN `key` `bucket_name` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `spell_id`,
|
||||
CHANGE COLUMN `value` `bucket_value` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `bucket_name`,
|
||||
ADD COLUMN `bucket_comparison` tinyint UNSIGNED NOT NULL DEFAULT 0 AFTER `bucket_value`,
|
||||
DROP PRIMARY KEY,
|
||||
ADD PRIMARY KEY (`spell_id`) USING BTREE;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9283,
|
||||
.description = "2024_08_05_fix_client_hotbar",
|
||||
.check = "SHOW COLUMNS FROM `inventory` LIKE 'guid'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `inventory`
|
||||
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
|
||||
ALTER TABLE `inventory_snapshots`
|
||||
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
|
||||
)"
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
|
||||
@@ -150,6 +150,17 @@ ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_data`
|
||||
ADD COLUMN `extra_haste` mediumint(8) NOT NULL DEFAULT 0 AFTER `wis`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9045,
|
||||
.description = "2024_08_05_bot_spells_entries_unsigned_spell_id.sql",
|
||||
.check = "SHOW COLUMNS FROM `bot_spells_entries` LIKE 'spell_id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `bot_spells_entries`
|
||||
CHANGE COLUMN `spellid` `spell_id` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `npc_spells_id`;
|
||||
)"
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
|
||||
@@ -751,4 +751,9 @@ static std::map<uint32, std::string> stance_names = {
|
||||
{ Stance::AEBurn, "AE Burn" }
|
||||
};
|
||||
|
||||
namespace PCNPCOnlyFlagType {
|
||||
constexpr int PC = 1;
|
||||
constexpr int NPC = 2;
|
||||
}
|
||||
|
||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||
|
||||
@@ -758,10 +758,10 @@ typedef enum {
|
||||
FilterFocusEffects = 22, //0=show, 1=hide
|
||||
FilterPetSpells = 23, //0=show, 1=hide
|
||||
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide
|
||||
FilterUnknown25 = 25,
|
||||
FilterUnknown26 = 26,
|
||||
FilterUnknown27 = 27,
|
||||
FilterUnknown28 = 28,
|
||||
FilterItemSpeech = 25, //0=show, 1=hide // RoF2 Confirmed
|
||||
FilterStrikethrough = 26, //0=show, 1=hide // RoF2 Confirmed
|
||||
FilterStuns = 27, //0=show, 1=hide // RoF2 Confirmed
|
||||
FilterBardSongsOnPets = 28, //0=show, 1=hide // RoF2 Confirmed
|
||||
_FilterCount
|
||||
} eqFilterType;
|
||||
|
||||
|
||||
+55
-21
@@ -81,45 +81,79 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets local address - pings google to inspect what interface was used locally
|
||||
* @return
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
std::string IpUtil::GetLocalIPAddress()
|
||||
{
|
||||
char my_ip_address[16];
|
||||
unsigned int my_port;
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
char my_ip_address[INET_ADDRSTRLEN];
|
||||
struct sockaddr_in server_address{};
|
||||
struct sockaddr_in my_address{};
|
||||
int sockfd;
|
||||
int sockfd;
|
||||
|
||||
// Connect to server
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
// Create a UDP socket
|
||||
#ifdef _WIN32
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd == INVALID_SOCKET) {
|
||||
WSACleanup();
|
||||
return "";
|
||||
}
|
||||
#else
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0) {
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set server_addr
|
||||
// Set server_addr (dummy address)
|
||||
memset(&server_address, 0, sizeof(server_address));
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_addr.s_addr = inet_addr("172.217.160.99");
|
||||
server_address.sin_port = htons(80);
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_addr.s_addr = inet_addr("8.8.8.8"); // Google DNS
|
||||
server_address.sin_port = htons(53); // DNS port
|
||||
|
||||
// Connect to server
|
||||
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
|
||||
close(sockfd);
|
||||
return "";
|
||||
}
|
||||
// Perform a dummy connection to the server (UDP)
|
||||
connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
|
||||
|
||||
// Get my ip address and port
|
||||
// Get my IP address
|
||||
memset(&my_address, 0, sizeof(my_address));
|
||||
socklen_t len = sizeof(my_address);
|
||||
getsockname(sockfd, (struct sockaddr *) &my_address, &len);
|
||||
inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address));
|
||||
my_port = ntohs(my_address.sin_port);
|
||||
|
||||
return fmt::format("{}", my_ip_address);
|
||||
#ifdef _WIN32
|
||||
closesocket(sockfd);
|
||||
WSACleanup();
|
||||
#else
|
||||
close(sockfd);
|
||||
#endif
|
||||
|
||||
LogInfo("Local IP Address [{}]", my_ip_address);
|
||||
|
||||
return std::string(my_ip_address);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets public address
|
||||
* Uses various websites as options to return raw public IP back to the client
|
||||
|
||||
@@ -32,10 +32,11 @@
|
||||
|
||||
//#include <iostream>
|
||||
|
||||
int32 NextItemInstSerialNumber = 1;
|
||||
|
||||
static inline int32 GetNextItemInstSerialNumber() {
|
||||
int32 next_item_serial_number = 1;
|
||||
std::unordered_set<uint64> guids{};
|
||||
|
||||
static inline int32 GetNextItemInstSerialNumber()
|
||||
{
|
||||
// The Bazaar relies on each item a client has up for Trade having a unique
|
||||
// identifier. This 'SerialNumber' is sent in Serialized item packets and
|
||||
// is used in Bazaar packets to identify the item a player is buying or inspecting.
|
||||
@@ -46,12 +47,18 @@ static inline int32 GetNextItemInstSerialNumber() {
|
||||
// NextItemInstSerialNumber is the next one to hand out.
|
||||
//
|
||||
// It is very unlikely to reach 2,147,483,647. Maybe we should call abort(), rather than wrapping back to 1.
|
||||
if(NextItemInstSerialNumber >= INT_MAX)
|
||||
NextItemInstSerialNumber = 1;
|
||||
else
|
||||
NextItemInstSerialNumber++;
|
||||
if (next_item_serial_number >= INT32_MAX) {
|
||||
next_item_serial_number = 1;
|
||||
}
|
||||
else {
|
||||
next_item_serial_number++;
|
||||
}
|
||||
|
||||
return NextItemInstSerialNumber;
|
||||
while (guids.contains(next_item_serial_number)) {
|
||||
next_item_serial_number++;
|
||||
}
|
||||
|
||||
return next_item_serial_number;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1935,6 +1942,15 @@ int EQ::ItemInstance::GetItemSkillsStat(EQ::skills::SkillType skill, bool augmen
|
||||
return stat;
|
||||
}
|
||||
|
||||
void EQ::ItemInstance::AddGUIDToMap(uint64 existing_serial_number)
|
||||
{
|
||||
guids.emplace(existing_serial_number);
|
||||
}
|
||||
|
||||
void EQ::ItemInstance::ClearGUIDMap()
|
||||
{
|
||||
guids.clear();
|
||||
}
|
||||
//
|
||||
// class EvolveInfo
|
||||
//
|
||||
|
||||
@@ -309,6 +309,8 @@ namespace EQ
|
||||
int GetItemSkillsStat(EQ::skills::SkillType skill, bool augments = false) const;
|
||||
uint32 GetItemGuildFavor() const;
|
||||
std::vector<uint32> GetAugmentIDs() const;
|
||||
static void AddGUIDToMap(uint64 existing_serial_number);
|
||||
static void ClearGUIDMap();
|
||||
|
||||
protected:
|
||||
//////////////////////////
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
struct BotSpellsEntries {
|
||||
uint32_t id;
|
||||
int32_t npc_spells_id;
|
||||
int16_t spellid;
|
||||
uint16_t spell_id;
|
||||
uint32_t type;
|
||||
uint8_t minlevel;
|
||||
uint8_t maxlevel;
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
return {
|
||||
"id",
|
||||
"npc_spells_id",
|
||||
"spellid",
|
||||
"spell_id",
|
||||
"type",
|
||||
"minlevel",
|
||||
"maxlevel",
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
return {
|
||||
"id",
|
||||
"npc_spells_id",
|
||||
"spellid",
|
||||
"spell_id",
|
||||
"type",
|
||||
"minlevel",
|
||||
"maxlevel",
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
|
||||
e.id = 0;
|
||||
e.npc_spells_id = 0;
|
||||
e.spellid = 0;
|
||||
e.spell_id = 0;
|
||||
e.type = 0;
|
||||
e.minlevel = 0;
|
||||
e.maxlevel = 255;
|
||||
@@ -173,7 +173,7 @@ public:
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
|
||||
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
@@ -220,7 +220,7 @@ public:
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.spellid));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.spell_id));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.type));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.minlevel));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.maxlevel));
|
||||
@@ -256,7 +256,7 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.npc_spells_id));
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.minlevel));
|
||||
v.push_back(std::to_string(e.maxlevel));
|
||||
@@ -300,7 +300,7 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.npc_spells_id));
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.minlevel));
|
||||
v.push_back(std::to_string(e.maxlevel));
|
||||
@@ -348,7 +348,7 @@ public:
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
|
||||
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
@@ -387,7 +387,7 @@ public:
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
|
||||
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
@@ -476,7 +476,7 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.npc_spells_id));
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.minlevel));
|
||||
v.push_back(std::to_string(e.maxlevel));
|
||||
@@ -513,7 +513,7 @@ public:
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.npc_spells_id));
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.minlevel));
|
||||
v.push_back(std::to_string(e.maxlevel));
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
uint32_t ornamenticon;
|
||||
uint32_t ornamentidfile;
|
||||
int32_t ornament_hero_model;
|
||||
uint64_t guid;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -61,6 +62,7 @@ public:
|
||||
"ornamenticon",
|
||||
"ornamentidfile",
|
||||
"ornament_hero_model",
|
||||
"guid",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,6 +85,7 @@ public:
|
||||
"ornamenticon",
|
||||
"ornamentidfile",
|
||||
"ornament_hero_model",
|
||||
"guid",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -139,6 +142,7 @@ public:
|
||||
e.ornamenticon = 0;
|
||||
e.ornamentidfile = 0;
|
||||
e.ornament_hero_model = 0;
|
||||
e.guid = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -191,6 +195,7 @@ public:
|
||||
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
||||
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -240,6 +245,7 @@ public:
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon));
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile));
|
||||
v.push_back(columns[15] + " = " + std::to_string(e.ornament_hero_model));
|
||||
v.push_back(columns[16] + " = " + std::to_string(e.guid));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -277,6 +283,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -322,6 +329,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -371,6 +379,7 @@ public:
|
||||
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
||||
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -411,6 +420,7 @@ public:
|
||||
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
|
||||
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -501,6 +511,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -539,6 +550,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
uint32_t ornamenticon;
|
||||
uint32_t ornamentidfile;
|
||||
int32_t ornament_hero_model;
|
||||
uint64_t guid;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -63,6 +64,7 @@ public:
|
||||
"ornamenticon",
|
||||
"ornamentidfile",
|
||||
"ornament_hero_model",
|
||||
"guid",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,6 +88,7 @@ public:
|
||||
"ornamenticon",
|
||||
"ornamentidfile",
|
||||
"ornament_hero_model",
|
||||
"guid",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -143,6 +146,7 @@ public:
|
||||
e.ornamenticon = 0;
|
||||
e.ornamentidfile = 0;
|
||||
e.ornament_hero_model = 0;
|
||||
e.guid = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -196,6 +200,7 @@ public:
|
||||
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -246,6 +251,7 @@ public:
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.ornamenticon));
|
||||
v.push_back(columns[15] + " = " + std::to_string(e.ornamentidfile));
|
||||
v.push_back(columns[16] + " = " + std::to_string(e.ornament_hero_model));
|
||||
v.push_back(columns[17] + " = " + std::to_string(e.guid));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -284,6 +290,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -330,6 +337,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -380,6 +388,7 @@ public:
|
||||
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -421,6 +430,7 @@ public:
|
||||
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
|
||||
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -512,6 +522,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -551,6 +562,7 @@ public:
|
||||
v.push_back(std::to_string(e.ornamenticon));
|
||||
v.push_back(std::to_string(e.ornamentidfile));
|
||||
v.push_back(std::to_string(e.ornament_hero_model));
|
||||
v.push_back(std::to_string(e.guid));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -19,31 +19,34 @@
|
||||
class BaseSpellBucketsRepository {
|
||||
public:
|
||||
struct SpellBuckets {
|
||||
uint64_t spellid;
|
||||
std::string key_;
|
||||
std::string value;
|
||||
uint32_t spell_id;
|
||||
std::string bucket_name;
|
||||
std::string bucket_value;
|
||||
uint8_t bucket_comparison;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("spellid");
|
||||
return std::string("spell_id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"spellid",
|
||||
"`key`",
|
||||
"value",
|
||||
"spell_id",
|
||||
"bucket_name",
|
||||
"bucket_value",
|
||||
"bucket_comparison",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"spellid",
|
||||
"`key`",
|
||||
"value",
|
||||
"spell_id",
|
||||
"bucket_name",
|
||||
"bucket_value",
|
||||
"bucket_comparison",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -84,9 +87,10 @@ public:
|
||||
{
|
||||
SpellBuckets e{};
|
||||
|
||||
e.spellid = 0;
|
||||
e.key_ = "";
|
||||
e.value = "";
|
||||
e.spell_id = 0;
|
||||
e.bucket_name = "";
|
||||
e.bucket_value = "";
|
||||
e.bucket_comparison = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -97,7 +101,7 @@ public:
|
||||
)
|
||||
{
|
||||
for (auto &spell_buckets : spell_bucketss) {
|
||||
if (spell_buckets.spellid == spell_buckets_id) {
|
||||
if (spell_buckets.spell_id == spell_buckets_id) {
|
||||
return spell_buckets;
|
||||
}
|
||||
}
|
||||
@@ -123,9 +127,10 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
SpellBuckets e{};
|
||||
|
||||
e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.spell_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.bucket_name = row[1] ? row[1] : "";
|
||||
e.bucket_value = row[2] ? row[2] : "";
|
||||
e.bucket_comparison = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -159,9 +164,10 @@ public:
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[0] + " = " + std::to_string(e.spellid));
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(columns[0] + " = " + std::to_string(e.spell_id));
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.bucket_name) + "'");
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.bucket_value) + "'");
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.bucket_comparison));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -169,7 +175,7 @@ public:
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.spellid
|
||||
e.spell_id
|
||||
)
|
||||
);
|
||||
|
||||
@@ -183,9 +189,10 @@ public:
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||
v.push_back(std::to_string(e.bucket_comparison));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -196,7 +203,7 @@ public:
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.spellid = results.LastInsertedID();
|
||||
e.spell_id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -215,9 +222,10 @@ public:
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||
v.push_back(std::to_string(e.bucket_comparison));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -251,9 +259,10 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
SpellBuckets e{};
|
||||
|
||||
e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.spell_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.bucket_name = row[1] ? row[1] : "";
|
||||
e.bucket_value = row[2] ? row[2] : "";
|
||||
e.bucket_comparison = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -278,9 +287,10 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
SpellBuckets e{};
|
||||
|
||||
e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0;
|
||||
e.key_ = row[1] ? row[1] : "";
|
||||
e.value = row[2] ? row[2] : "";
|
||||
e.spell_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.bucket_name = row[1] ? row[1] : "";
|
||||
e.bucket_value = row[2] ? row[2] : "";
|
||||
e.bucket_comparison = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -355,9 +365,10 @@ public:
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||
v.push_back(std::to_string(e.bucket_comparison));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -380,9 +391,10 @@ public:
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.spellid));
|
||||
v.push_back("'" + Strings::Escape(e.key_) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back("'" + Strings::Escape(e.bucket_name) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.bucket_value) + "'");
|
||||
v.push_back(std::to_string(e.bucket_comparison));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ public:
|
||||
{.parent_command = "set", .sub_command = "endurance", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setendurance"},
|
||||
{.parent_command = "set", .sub_command = "endurance_full", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "endurance"},
|
||||
{.parent_command = "set", .sub_command = "exp", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setxp|setexp"},
|
||||
{.parent_command = "set", .sub_command = "faction", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setfaction"},
|
||||
{.parent_command = "set", .sub_command = "flymode", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "flymode"},
|
||||
{.parent_command = "set", .sub_command = "freeze", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "freeze|unfreeze"},
|
||||
{.parent_command = "set", .sub_command = "gender", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "gender"},
|
||||
|
||||
@@ -189,6 +189,8 @@ void RuleManager::ResetRules(bool reload) {
|
||||
m_RuleRealValues[ Real__##rule_name ] = default_value;
|
||||
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
||||
m_RuleBoolValues[ Bool__##rule_name ] = default_value;
|
||||
#define RULE_STRING(category_name, rule_name, default_value, notes) \
|
||||
m_RuleStringValues[ String__##rule_name ] = default_value;
|
||||
#include "ruletypes.h"
|
||||
|
||||
// restore these rules to their pre-reset values
|
||||
|
||||
@@ -178,6 +178,7 @@ RULE_BOOL(Character, NoSkillsOnHorse, false, "Enabling this will prevent Bind Wo
|
||||
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
|
||||
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
|
||||
RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated")
|
||||
RULE_INT(Character, DefaultGuildRank, 8, "Default guild rank when Character:DefaultGuild is a non-0 value, default is 8 (Recruit)")
|
||||
RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared")
|
||||
RULE_BOOL(Character, EnableCharacterEXPMods, false, "Enables character zone-based experience modifiers.")
|
||||
RULE_BOOL(Character, PVPEnableGuardFactionAssist, true, "Enables faction based assisting against the aggresor in pvp.")
|
||||
@@ -228,6 +229,7 @@ RULE_BOOL(Character, GroupInvitesRequireTarget, false, "Enable to require player
|
||||
RULE_BOOL(Character, PlayerTradingLoreFeedback, true, "If enabled, during a player to player trade, if lore items exist, it will output which items.")
|
||||
RULE_INT(Character, MendAlwaysSucceedValue, 199, "Value at which mend will always succeed its skill check. Default: 199")
|
||||
RULE_BOOL(Character, SneakAlwaysSucceedOver100, false, "When sneak skill is over 100, always succeed sneak/hide. Default: false")
|
||||
RULE_INT(Character, BandolierSwapDelay, 0, "Bandolier swap delay in milliseconds, default is 0")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Mercs)
|
||||
@@ -714,6 +716,7 @@ RULE_BOOL(TaskSystem, ExpRewardsIgnoreLevelBasedEXPMods, false, "Rewarding Level
|
||||
RULE_INT(TaskSystem, SharedTasksWorldProcessRate, 6000, "Timer interval (milliseconds) that shared tasks are processed in world")
|
||||
RULE_INT(TaskSystem, SharedTasksTerminateTimerMS, 120000, "Delay (milliseconds) until a shared task is terminated if requirements are no longer met after member removal (default: 2 minutes)")
|
||||
RULE_BOOL(TaskSystem, UpdateOneElementPerTask, true, "If true (live-like) task updates only increment the first matching activity. If false all matching elements will be incremented.")
|
||||
RULE_INT(TaskSystem, MaxUpdateMessages, 50, "Maximum update messages for non-GiveCash activity types in IncrementDoneCount")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Range)
|
||||
@@ -725,6 +728,7 @@ RULE_INT(Range, SpellParticles, 135, "The packet range in which spell particles
|
||||
RULE_INT(Range, DamageMessages, 50, "The packet range in which damage messages are sent (non-crit)")
|
||||
RULE_INT(Range, SpellMessages, 75, "The packet range in which spell damage messages are sent")
|
||||
RULE_INT(Range, SongMessages, 75, "The packet range in which song messages are sent")
|
||||
RULE_INT(Range, StunMessages, 75, "The packet range in which stun messages are sent")
|
||||
RULE_INT(Range, ClientPositionUpdates, 300, "Distance in which the own changed position is communicated to other clients")
|
||||
RULE_INT(Range, CriticalDamage, 80, "The packet range in which critical hit messages are sent")
|
||||
RULE_INT(Range, MobCloseScanDistance, 600, "Close scan distance")
|
||||
@@ -907,6 +911,7 @@ RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false, "Weapons can use any w
|
||||
RULE_BOOL(Inventory, TransformSummonedBags, false, "Transforms summoned bags into disenchanted ones instead of deleting")
|
||||
RULE_BOOL(Inventory, AllowMultipleOfSameAugment, false, "Allows multiple of the same augment to be placed in an item via #augmentitem or MQ2, set to true to allow")
|
||||
RULE_INT(Inventory, AlternateAugmentationSealer, 53, "Allows RoF+ clients to augment items from a special container type")
|
||||
RULE_BOOL(Inventory, LazyLoadBank, true, "Don't load bank during zoning, only when in proximinity to a banker. May increase zone speed and stability")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Client)
|
||||
|
||||
+99
-67
@@ -46,6 +46,7 @@
|
||||
#include "repositories/character_item_recast_repository.h"
|
||||
#include "repositories/character_corpses_repository.h"
|
||||
#include "repositories/skill_caps_repository.h"
|
||||
#include "repositories/inventory_repository.h"
|
||||
|
||||
namespace ItemField
|
||||
{
|
||||
@@ -300,15 +301,15 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQ::ItemInstance*
|
||||
// Update/Insert item
|
||||
const std::string query = StringFormat("REPLACE INTO inventory "
|
||||
"(charid, slotid, itemid, charges, instnodrop, custom_data, color, "
|
||||
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) "
|
||||
"augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model, guid) "
|
||||
"VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
|
||||
"%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)",
|
||||
"%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)",
|
||||
static_cast<unsigned long>(char_id), static_cast<unsigned long>(slot_id), static_cast<unsigned long>(inst->GetItem()->ID),
|
||||
static_cast<unsigned long>(charges), static_cast<unsigned long>(inst->IsAttuned() ? 1 : 0),
|
||||
inst->GetCustomDataString().c_str(), static_cast<unsigned long>(inst->GetColor()),
|
||||
static_cast<unsigned long>(augslot[0]), static_cast<unsigned long>(augslot[1]), static_cast<unsigned long>(augslot[2]),
|
||||
static_cast<unsigned long>(augslot[3]), static_cast<unsigned long>(augslot[4]), static_cast<unsigned long>(augslot[5]), static_cast<unsigned long>(inst->GetOrnamentationIcon()),
|
||||
static_cast<unsigned long>(inst->GetOrnamentationIDFile()), static_cast<unsigned long>(inst->GetOrnamentHeroModel()));
|
||||
static_cast<unsigned long>(inst->GetOrnamentationIDFile()), static_cast<unsigned long>(inst->GetOrnamentHeroModel()), inst->GetSerialNumber());
|
||||
const auto results = QueryDatabase(query);
|
||||
|
||||
// Save bag contents, if slot supports bag contents
|
||||
@@ -651,48 +652,67 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
||||
return false;
|
||||
|
||||
// Retrieve character inventory
|
||||
const std::string query =
|
||||
StringFormat("SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, "
|
||||
"augslot6, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model FROM "
|
||||
"inventory WHERE charid = %i ORDER BY slotid",
|
||||
char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogError("If you got an error related to the 'instnodrop' field, run the "
|
||||
"following SQL Queries:\nalter table inventory add instnodrop "
|
||||
"tinyint(1) unsigned default 0 not null;\n");
|
||||
auto results = InventoryRepository::GetWhere(*this, fmt::format("`charid` = '{}' ORDER BY `slotid`;", char_id));
|
||||
if (results.empty()) {
|
||||
LogError("Error loading inventory for char_id {} from the database.", char_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto const &row: results) {
|
||||
if (row.guid != 0) {
|
||||
EQ::ItemInstance::AddGUIDToMap(row.guid);
|
||||
}
|
||||
}
|
||||
|
||||
const auto timestamps = GetItemRecastTimestamps(char_id);
|
||||
auto cv_conflict = false;
|
||||
const auto pmask = inv->GetLookup()->PossessionsBitmask;
|
||||
const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank;
|
||||
|
||||
auto cv_conflict = false;
|
||||
const auto pmask = inv->GetLookup()->PossessionsBitmask;
|
||||
const auto bank_size = inv->GetLookup()->InventoryTypeSize.Bank;
|
||||
std::vector<InventoryRepository::Inventory> queue{};
|
||||
for (auto &row: results) {
|
||||
const int16 slot_id = row.slotid;
|
||||
const uint32 item_id = row.itemid;
|
||||
const uint16 charges = row.charges;
|
||||
const uint32 color = row.color;
|
||||
const bool instnodrop = row.instnodrop;
|
||||
const uint32 ornament_icon = row.ornamenticon;
|
||||
const uint32 ornament_idfile = row.ornamentidfile;
|
||||
const uint32 ornament_hero_model = row.ornament_hero_model;
|
||||
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
int16 slot_id = Strings::ToInt(row[0]);
|
||||
uint32 aug[EQ::invaug::SOCKET_COUNT];
|
||||
aug[0] = row.augslot1;
|
||||
aug[1] = row.augslot2;
|
||||
aug[2] = row.augslot3;
|
||||
aug[3] = row.augslot4;
|
||||
aug[4] = row.augslot5;
|
||||
aug[5] = row.augslot6;
|
||||
|
||||
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) { // Titanium thru UF check
|
||||
if (slot_id <= EQ::invslot::POSSESSIONS_END && slot_id >= EQ::invslot::POSSESSIONS_BEGIN) {
|
||||
// Titanium thru UF check
|
||||
if (((static_cast<uint64>(1) << slot_id) & pmask) == 0) {
|
||||
cv_conflict = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) { // Titanium thru UF check
|
||||
const auto parent_slot = EQ::invslot::GENERAL_BEGIN + ((slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
||||
else if (slot_id <= EQ::invbag::GENERAL_BAGS_END && slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN) {
|
||||
// Titanium thru UF check
|
||||
const auto parent_slot = EQ::invslot::GENERAL_BEGIN + (
|
||||
(slot_id - EQ::invbag::GENERAL_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
||||
if (((static_cast<uint64>(1) << parent_slot) & pmask) == 0) {
|
||||
cv_conflict = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) { // Titanium check
|
||||
else if (slot_id <= EQ::invslot::BANK_END && slot_id >= EQ::invslot::BANK_BEGIN) {
|
||||
// Titanium check
|
||||
if ((slot_id - EQ::invslot::BANK_BEGIN) >= bank_size) {
|
||||
cv_conflict = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) { // Titanium check
|
||||
else if (slot_id <= EQ::invbag::BANK_BAGS_END && slot_id >= EQ::invbag::BANK_BAGS_BEGIN) {
|
||||
// Titanium check
|
||||
const auto parent_index = ((slot_id - EQ::invbag::BANK_BAGS_BEGIN) / EQ::invbag::SLOT_COUNT);
|
||||
if (parent_index >= bank_size) {
|
||||
cv_conflict = true;
|
||||
@@ -700,64 +720,55 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
||||
}
|
||||
}
|
||||
|
||||
uint32 item_id = Strings::ToUnsignedInt(row[1]);
|
||||
const uint16 charges = Strings::ToUnsignedInt(row[2]);
|
||||
const uint32 color = Strings::ToUnsignedInt(row[3]);
|
||||
|
||||
uint32 aug[EQ::invaug::SOCKET_COUNT];
|
||||
|
||||
aug[0] = Strings::ToUnsignedInt(row[4]);
|
||||
aug[1] = Strings::ToUnsignedInt(row[5]);
|
||||
aug[2] = Strings::ToUnsignedInt(row[6]);
|
||||
aug[3] = Strings::ToUnsignedInt(row[7]);
|
||||
aug[4] = Strings::ToUnsignedInt(row[8]);
|
||||
aug[5] = Strings::ToUnsignedInt(row[9]);
|
||||
|
||||
const bool instnodrop = (row[10] && static_cast<uint16>(Strings::ToUnsignedInt(row[10])));
|
||||
|
||||
const uint32 ornament_icon = Strings::ToUnsignedInt(row[12]);
|
||||
const uint32 ornament_idfile = Strings::ToUnsignedInt(row[13]);
|
||||
uint32 ornament_hero_model = Strings::ToUnsignedInt(row[14]);
|
||||
|
||||
const EQ::ItemData *item = GetItem(item_id);
|
||||
|
||||
auto *item = GetItem(item_id);
|
||||
if (!item) {
|
||||
LogError("Warning: charid [{}] has an invalid item_id [{}] in inventory slot [{}]", char_id, item_id,
|
||||
slot_id);
|
||||
LogError(
|
||||
"Warning: charid [{}] has an invalid item_id [{}] in inventory slot [{}]",
|
||||
char_id,
|
||||
item_id,
|
||||
slot_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
EQ::ItemInstance *inst = CreateBaseItem(item, charges);
|
||||
|
||||
if (inst == nullptr)
|
||||
auto *inst = CreateBaseItem(item, charges);
|
||||
if (!inst) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (row[11]) {
|
||||
std::string data_str(row[11]);
|
||||
inst->SetCustomDataString(data_str);
|
||||
if (!row.custom_data.empty()) {
|
||||
inst->SetCustomDataString(row.custom_data);
|
||||
}
|
||||
|
||||
inst->SetOrnamentIcon(ornament_icon);
|
||||
inst->SetOrnamentationIDFile(ornament_idfile);
|
||||
inst->SetOrnamentHeroModel(item->HerosForgeModel);
|
||||
|
||||
if (instnodrop || (inst->GetItem()->Attuneable && slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <= EQ::invslot::EQUIPMENT_END))
|
||||
if (instnodrop || (inst->GetItem()->Attuneable && slot_id >= EQ::invslot::EQUIPMENT_BEGIN && slot_id <=
|
||||
EQ::invslot::EQUIPMENT_END)) {
|
||||
inst->SetAttuned(true);
|
||||
}
|
||||
|
||||
if (color > 0)
|
||||
if (color > 0) {
|
||||
inst->SetColor(color);
|
||||
}
|
||||
|
||||
if (charges == 0x7FFF)
|
||||
if (charges == 0x7FFF) {
|
||||
inst->SetCharges(-1);
|
||||
else if (charges == 0 && inst->IsStackable()) // Stackable items need a minimum charge of 1 remain moveable.
|
||||
}
|
||||
else if (charges == 0 && inst->IsStackable()) {
|
||||
// Stackable items need a minimum charge of 1 remain moveable.
|
||||
inst->SetCharges(1);
|
||||
else
|
||||
}
|
||||
else {
|
||||
inst->SetCharges(charges);
|
||||
}
|
||||
|
||||
if (item->RecastDelay) {
|
||||
if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->RecastType)) {
|
||||
inst->SetRecastTimestamp(timestamps.at(item->RecastType));
|
||||
} else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) {
|
||||
}
|
||||
else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && timestamps.count(item->ID)) {
|
||||
inst->SetRecastTimestamp(timestamps.at(item->ID));
|
||||
}
|
||||
else {
|
||||
@@ -767,35 +778,50 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
||||
|
||||
if (item->IsClassCommon()) {
|
||||
for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
|
||||
if (aug[i])
|
||||
if (aug[i]) {
|
||||
inst->PutAugment(this, i, aug[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16 put_slot_id;
|
||||
if (slot_id >= 8000 && slot_id <= 8999) {
|
||||
put_slot_id = inv->PushCursor(*inst);
|
||||
} else if (slot_id >= 3111 && slot_id <= 3179) {
|
||||
}
|
||||
else if (slot_id >= 3111 && slot_id <= 3179) {
|
||||
// Admins: please report any occurrences of this error
|
||||
LogError("Warning: Defunct location for item in inventory: charid={}, item_id={}, slot_id={} .. pushing to cursor...",
|
||||
char_id, item_id, slot_id);
|
||||
LogError(
|
||||
"Warning: Defunct location for item in inventory: charid={}, item_id={}, slot_id={} .. pushing to cursor...",
|
||||
char_id,
|
||||
item_id,
|
||||
slot_id
|
||||
);
|
||||
put_slot_id = inv->PushCursor(*inst);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
put_slot_id = inv->PutItem(slot_id, *inst);
|
||||
}
|
||||
|
||||
row.guid = inst->GetSerialNumber();
|
||||
queue.push_back(row);
|
||||
|
||||
safe_delete(inst);
|
||||
|
||||
// Save ptr to item in inventory
|
||||
if (put_slot_id == INVALID_INDEX) {
|
||||
LogError("Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]",
|
||||
char_id, item_id, slot_id);
|
||||
LogError(
|
||||
"Warning: Invalid slot_id for item in inventory: charid=[{}], item_id=[{}], slot_id=[{}]",
|
||||
char_id,
|
||||
item_id,
|
||||
slot_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (cv_conflict) {
|
||||
const std::string& char_name = GetCharName(char_id);
|
||||
LogError("ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
|
||||
const std::string &char_name = GetCharName(char_id);
|
||||
LogError(
|
||||
"ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
|
||||
char_name,
|
||||
char_id,
|
||||
EQ::versions::MobVersionName(inv->InventoryVersion()),
|
||||
@@ -803,6 +829,12 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
||||
);
|
||||
}
|
||||
|
||||
if (!queue.empty()) {
|
||||
InventoryRepository::ReplaceMany(*this, queue);
|
||||
}
|
||||
|
||||
EQ::ItemInstance::ClearGUIDMap();
|
||||
|
||||
// Retrieve shared inventory
|
||||
return GetSharedBank(char_id, inv, true);
|
||||
}
|
||||
|
||||
+3
-3
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.54.0-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.56.2-dev" // always append -dev to the current version for custom-builds
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
@@ -42,8 +42,8 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9281
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9044
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9283
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -224,6 +224,23 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
||||
if (server.db->GetLoginDataFromAccountInfo(user, db_loginserver, db_account_password_hash, db_account_id)) {
|
||||
result = VerifyLoginHash(user, db_loginserver, cred, db_account_password_hash);
|
||||
|
||||
#ifdef LSPX
|
||||
// if user updated their password on the login server, update it here by validating their credentials with the login server
|
||||
if (!result && db_loginserver == "eqemu") {
|
||||
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(user, cred);
|
||||
if (account_id > 0) {
|
||||
auto encryption_mode = server.options.GetEncryptionMode();
|
||||
server.db->UpdateLoginserverAccountPasswordHash(
|
||||
user,
|
||||
db_loginserver,
|
||||
eqcrypt_hash(user, cred, encryption_mode)
|
||||
);
|
||||
LogInfo("Updating eqemu account [{}] password hash", account_id);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LogDebug("Success [{0}]", (result ? "true" : "false"));
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "22.54.0",
|
||||
"version": "22.56.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
@@ -287,6 +287,7 @@ void Adventure::Finished(AdventureWinStatus ws)
|
||||
auto character_id = database.GetCharacterID(*iter);
|
||||
|
||||
if (character_id == 0) {
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -2185,7 +2185,7 @@ void Client::AutoGrantAAPoints() {
|
||||
SendAlternateAdvancementStats();
|
||||
}
|
||||
|
||||
void Client::GrantAllAAPoints(uint8 unlock_level)
|
||||
void Client::GrantAllAAPoints(uint8 unlock_level, bool skip_grant_only)
|
||||
{
|
||||
//iterate through every AA
|
||||
for (auto& aa : zone->aa_abilities) {
|
||||
@@ -2195,6 +2195,10 @@ void Client::GrantAllAAPoints(uint8 unlock_level)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ability->grant_only && skip_grant_only) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint8 level = unlock_level ? unlock_level : GetLevel();
|
||||
|
||||
AA::Rank* rank = ability->first;
|
||||
|
||||
+104
-50
@@ -1478,8 +1478,10 @@ int64 Mob::DoDamageCaps(int64 base_damage)
|
||||
//SYNC WITH: tune.cpp, mob.h TuneDoAttack
|
||||
void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool FromRiposte)
|
||||
{
|
||||
if (!other)
|
||||
if (!other) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogCombat("[{}]::DoAttack vs [{}] base [{}] min [{}] offense [{}] tohit [{}] skill [{}]", GetName(),
|
||||
other->GetName(), hit.base_damage, hit.min_damage, hit.offense, hit.tohit, hit.skill);
|
||||
|
||||
@@ -1491,14 +1493,22 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo
|
||||
if (!FromRiposte && other->AvoidDamage(this, hit)) {
|
||||
if (int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
|
||||
strike_through && zone->random.Roll(strike_through)) {
|
||||
MessageString(Chat::StrikeThrough,
|
||||
STRIKETHROUGH_STRING); // You strike through your opponents defenses!
|
||||
|
||||
FilteredMessageString(
|
||||
this, /* Sender */
|
||||
Chat::StrikeThrough, /* Type: 339 */
|
||||
FilterStrikethrough, /* FilterType: 12 */
|
||||
STRIKETHROUGH_STRING /* You strike through your opponent's defenses! */
|
||||
);
|
||||
|
||||
hit.damage_done = 1; // set to one, we will check this to continue
|
||||
}
|
||||
|
||||
if (hit.damage_done == DMG_RIPOSTED) {
|
||||
DoRiposte(other);
|
||||
return;
|
||||
}
|
||||
|
||||
LogCombat("Avoided/strikethrough damage with code [{}]", hit.damage_done);
|
||||
}
|
||||
|
||||
@@ -1510,9 +1520,19 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo
|
||||
int stun_resist2 = other->spellbonuses.FrontalStunResist + other->itembonuses.FrontalStunResist + other->aabonuses.FrontalStunResist;
|
||||
int stun_resist = other->spellbonuses.StunResist + other->itembonuses.StunResist + other->aabonuses.StunResist;
|
||||
if (zone->random.Roll(stun_resist2)) {
|
||||
other->MessageString(Chat::Stun, AVOID_STUNNING_BLOW);
|
||||
other->FilteredMessageString(
|
||||
this,
|
||||
Chat::Stun,
|
||||
FilterStuns,
|
||||
AVOID_STUNNING_BLOW
|
||||
);
|
||||
} else if (zone->random.Roll(stun_resist)) {
|
||||
other->MessageString(Chat::Stun, SHAKE_OFF_STUN);
|
||||
other->FilteredMessageString(
|
||||
this,
|
||||
Chat::Stun,
|
||||
FilterStuns,
|
||||
SHAKE_OFF_STUN
|
||||
);
|
||||
} else {
|
||||
other->Stun(3000); // yuck -- 3 seconds
|
||||
}
|
||||
@@ -4267,8 +4287,6 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
//final damage has been determined.
|
||||
int old_hp_ratio = (int)GetHPRatio();
|
||||
|
||||
SetHP(int64(GetHP() - damage));
|
||||
|
||||
const auto has_bot_given_event = parse->BotHasQuestSub(EVENT_DAMAGE_GIVEN);
|
||||
|
||||
const auto has_bot_taken_event = parse->BotHasQuestSub(EVENT_DAMAGE_TAKEN);
|
||||
@@ -4314,30 +4332,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
);
|
||||
|
||||
std::vector<std::any> args;
|
||||
|
||||
if (has_taken_event) {
|
||||
const auto export_string = fmt::format(
|
||||
"{} {} {} {} {} {} {} {} {}",
|
||||
attacker ? attacker->GetID() : 0,
|
||||
damage,
|
||||
spell_id,
|
||||
static_cast<int>(skill_used),
|
||||
FromDamageShield ? 1 : 0,
|
||||
avoidable ? 1 : 0,
|
||||
buffslot,
|
||||
iBuffTic ? 1 : 0,
|
||||
static_cast<int>(special)
|
||||
);
|
||||
|
||||
if (IsBot() && has_bot_taken_event) {
|
||||
parse->EventBot(EVENT_DAMAGE_TAKEN, CastToBot(), attacker ? attacker : nullptr, export_string, 0);
|
||||
} else if (IsClient() && has_player_taken_event) {
|
||||
args.push_back(attacker ? attacker : nullptr);
|
||||
parse->EventPlayer(EVENT_DAMAGE_TAKEN, CastToClient(), export_string, 0, &args);
|
||||
} else if (IsNPC() && has_npc_taken_event) {
|
||||
parse->EventNPC(EVENT_DAMAGE_TAKEN, CastToNPC(), attacker ? attacker : nullptr, export_string, 0);
|
||||
}
|
||||
}
|
||||
int64 damage_override = 0;
|
||||
|
||||
if (has_given_event && attacker) {
|
||||
const auto export_string = fmt::format(
|
||||
@@ -4363,6 +4358,38 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
}
|
||||
}
|
||||
|
||||
if (has_taken_event) {
|
||||
const auto export_string = fmt::format(
|
||||
"{} {} {} {} {} {} {} {} {}",
|
||||
attacker ? attacker->GetID() : 0,
|
||||
damage,
|
||||
spell_id,
|
||||
static_cast<int>(skill_used),
|
||||
FromDamageShield ? 1 : 0,
|
||||
avoidable ? 1 : 0,
|
||||
buffslot,
|
||||
iBuffTic ? 1 : 0,
|
||||
static_cast<int>(special)
|
||||
);
|
||||
|
||||
if (IsBot() && has_bot_taken_event) {
|
||||
damage_override = parse->EventBot(EVENT_DAMAGE_TAKEN, CastToBot(), attacker ? attacker : nullptr, export_string, 0);
|
||||
} else if (IsClient() && has_player_taken_event) {
|
||||
args.push_back(attacker ? attacker : nullptr);
|
||||
damage_override = parse->EventPlayer(EVENT_DAMAGE_TAKEN, CastToClient(), export_string, 0, &args);
|
||||
} else if (IsNPC() && has_npc_taken_event) {
|
||||
damage_override = parse->EventNPC(EVENT_DAMAGE_TAKEN, CastToNPC(), attacker ? attacker : nullptr, export_string, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (damage_override > 0) {
|
||||
damage = damage_override;
|
||||
} else if (damage_override < 0) {
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
SetHP(int64(GetHP() - damage));
|
||||
|
||||
if (HasDied()) {
|
||||
bool IsSaved = false;
|
||||
|
||||
@@ -4506,32 +4533,59 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
||||
Stun(RuleI(Combat, StunDuration));
|
||||
if (RuleB(Combat, ClientStunMessage) && attacker->IsClient()) {
|
||||
if (attacker) {
|
||||
entity_list.MessageClose(this, true, 500, Chat::Emote, "%s is stunned after being bashed by %s.", GetCleanName(), attacker->GetCleanName());
|
||||
}
|
||||
else {
|
||||
entity_list.MessageClose(this, true, 500, Chat::Emote, "%s is stunned by a bash to the head.", GetCleanName());
|
||||
entity_list.FilteredMessageClose(
|
||||
this,
|
||||
true,
|
||||
RuleI(Range, StunMessages),
|
||||
Chat::Stun,
|
||||
FilterStuns,
|
||||
"%s is stunned after being bashed by %s.",
|
||||
GetCleanName(),
|
||||
attacker->GetCleanName()
|
||||
);
|
||||
} else {
|
||||
entity_list.FilteredMessageClose(
|
||||
this,
|
||||
true,
|
||||
RuleI(Range, StunMessages),
|
||||
Chat::Stun,
|
||||
FilterStuns,
|
||||
"%s is stunned by a bash to the head.",
|
||||
GetCleanName()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// stun resist passed!
|
||||
if (IsClient())
|
||||
MessageString(Chat::Stun, SHAKE_OFF_STUN);
|
||||
if (IsClient()) {
|
||||
FilteredMessageString(
|
||||
this,
|
||||
Chat::Stun,
|
||||
FilterStuns,
|
||||
SHAKE_OFF_STUN
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// stun resist 2 passed!
|
||||
if (IsClient()) {
|
||||
FilteredMessageString(
|
||||
this,
|
||||
Chat::Stun,
|
||||
FilterStuns,
|
||||
AVOID_STUNNING_BLOW
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// stun resist 2 passed!
|
||||
if (IsClient())
|
||||
MessageString(Chat::Stun, AVOID_STUNNING_BLOW);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// main stun failed -- extra interrupt roll
|
||||
if (IsCasting() &&
|
||||
!EQ::ValueWithin(casting_spell_id, 859, 1023)) // these spells are excluded
|
||||
// 90% chance >< -- stun immune won't reach this branch though :(
|
||||
if (zone->random.Int(0, 9) > 1)
|
||||
// these spells are excluded
|
||||
// 90% chance >< -- stun immune won't reach this branch though :(
|
||||
if (IsCasting() && !EQ::ValueWithin(casting_spell_id, 859, 1023)) {
|
||||
if (zone->random.Int(0, 9) > 1) {
|
||||
InterruptSpell();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-14
@@ -3324,18 +3324,19 @@ DBbotspells_Struct* ZoneDatabase::GetBotSpells(uint32 bot_spell_id)
|
||||
if (!bse.empty()) {
|
||||
for (const auto& e : bse) {
|
||||
DBbotspells_entries_Struct entry;
|
||||
entry.spellid = e.spellid;
|
||||
entry.type = e.type;
|
||||
entry.minlevel = e.minlevel;
|
||||
entry.maxlevel = e.maxlevel;
|
||||
entry.manacost = e.manacost;
|
||||
entry.recast_delay = e.recast_delay;
|
||||
entry.priority = e.priority;
|
||||
entry.min_hp = e.min_hp;
|
||||
entry.max_hp = e.max_hp;
|
||||
entry.resist_adjust = e.resist_adjust;
|
||||
entry.bucket_name = e.bucket_name;
|
||||
entry.bucket_value = e.bucket_value;
|
||||
|
||||
entry.spellid = e.spell_id;
|
||||
entry.type = e.type;
|
||||
entry.minlevel = e.minlevel;
|
||||
entry.maxlevel = e.maxlevel;
|
||||
entry.manacost = e.manacost;
|
||||
entry.recast_delay = e.recast_delay;
|
||||
entry.priority = e.priority;
|
||||
entry.min_hp = e.min_hp;
|
||||
entry.max_hp = e.max_hp;
|
||||
entry.resist_adjust = e.resist_adjust;
|
||||
entry.bucket_name = e.bucket_name;
|
||||
entry.bucket_value = e.bucket_value;
|
||||
entry.bucket_comparison = e.bucket_comparison;
|
||||
|
||||
// some spell types don't make much since to be priority 0, so fix that
|
||||
@@ -3345,8 +3346,8 @@ DBbotspells_Struct* ZoneDatabase::GetBotSpells(uint32 bot_spell_id)
|
||||
|
||||
if (e.resist_adjust) {
|
||||
entry.resist_adjust = e.resist_adjust;
|
||||
} else if (IsValidSpell(e.spellid)) {
|
||||
entry.resist_adjust = spells[e.spellid].resist_difficulty;
|
||||
} else if (IsValidSpell(e.spell_id)) {
|
||||
entry.resist_adjust = spells[e.spell_id].resist_difficulty;
|
||||
}
|
||||
|
||||
spell_set.entries.push_back(entry);
|
||||
|
||||
+57
-10
@@ -185,7 +185,9 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
||||
position_update_timer(10000),
|
||||
consent_throttle_timer(2000),
|
||||
tmSitting(0),
|
||||
parcel_timer(RuleI(Parcel, ParcelDeliveryDelay))
|
||||
parcel_timer(RuleI(Parcel, ParcelDeliveryDelay)),
|
||||
lazy_load_bank_check_timer(1000),
|
||||
bandolier_throttle_timer(0)
|
||||
{
|
||||
for (auto client_filter = FilterNone; client_filter < _FilterCount; client_filter = eqFilterType(client_filter + 1)) {
|
||||
SetFilter(client_filter, FilterShow);
|
||||
@@ -284,6 +286,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
||||
memset(&m_epp, 0, sizeof(m_epp));
|
||||
PendingTranslocate = false;
|
||||
PendingSacrifice = false;
|
||||
sacrifice_caster_id = 0;
|
||||
controlling_boat_id = 0;
|
||||
controlled_mob_id = 0;
|
||||
qGlobals = nullptr;
|
||||
@@ -391,7 +394,6 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
||||
SetBotPrecombat(false);
|
||||
|
||||
AI_Init();
|
||||
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
@@ -3403,6 +3405,11 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){
|
||||
} else { // these clients don't have a 'self only' filter
|
||||
Filter1(FilterHealOverTime);
|
||||
}
|
||||
|
||||
Filter1(FilterItemSpeech);
|
||||
Filter1(FilterStrikethrough);
|
||||
Filter1(FilterStuns);
|
||||
Filter1(FilterBardSongsOnPets);
|
||||
}
|
||||
|
||||
// this version is for messages with no parameters
|
||||
@@ -3965,7 +3972,7 @@ void Client::SetEndurance(int32 newEnd)
|
||||
CheckManaEndUpdate();
|
||||
}
|
||||
|
||||
void Client::SacrificeConfirm(Client *caster)
|
||||
void Client::SacrificeConfirm(Mob *caster)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct));
|
||||
Sacrifice_Struct *ss = (Sacrifice_Struct *)outapp->pBuffer;
|
||||
@@ -3992,14 +3999,14 @@ void Client::SacrificeConfirm(Client *caster)
|
||||
ss->Confirm = 0;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
// We store the Caster's name, because when the packet comes back, it only has the victim's entityID in it,
|
||||
// We store the Caster's id, because when the packet comes back, it only has the victim's entityID in it,
|
||||
// not the caster.
|
||||
SacrificeCaster += caster->GetName();
|
||||
sacrifice_caster_id = caster->GetID();
|
||||
PendingSacrifice = true;
|
||||
}
|
||||
|
||||
//Essentially a special case death function
|
||||
void Client::Sacrifice(Client *caster)
|
||||
void Client::Sacrifice(Mob *caster)
|
||||
{
|
||||
if (GetLevel() >= RuleI(Spells, SacrificeMinLevel) && GetLevel() <= RuleI(Spells, SacrificeMaxLevel)) {
|
||||
int exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000);
|
||||
@@ -4047,8 +4054,11 @@ void Client::Sacrifice(Client *caster)
|
||||
}
|
||||
Save();
|
||||
GoToDeath();
|
||||
if (caster) // I guess it's possible?
|
||||
caster->SummonItem(RuleI(Spells, SacrificeItemID));
|
||||
if (caster && caster->IsClient()) {
|
||||
caster->CastToClient()->SummonItem(RuleI(Spells, SacrificeItemID));
|
||||
} else if (caster && caster->IsNPC()) {
|
||||
caster->CastToNPC()->AddItem(RuleI(Spells, SacrificeItemID), 1, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
caster->MessageString(Chat::Red, SAC_TOO_LOW); // This being is not a worthy sacrifice.
|
||||
@@ -11087,7 +11097,9 @@ void Client::SaveDisciplines()
|
||||
{
|
||||
std::vector<CharacterDisciplinesRepository::CharacterDisciplines> v;
|
||||
|
||||
for (int slot_id = 0; slot_id < MAX_PP_DISCIPLINES; slot_id++) {
|
||||
std::vector<std::string> delete_slots;
|
||||
|
||||
for (uint16 slot_id = 0; slot_id < MAX_PP_DISCIPLINES; slot_id++) {
|
||||
if (IsValidSpell(m_pp.disciplines.values[slot_id])) {
|
||||
auto e = CharacterDisciplinesRepository::NewEntity();
|
||||
|
||||
@@ -11096,9 +11108,21 @@ void Client::SaveDisciplines()
|
||||
e.disc_id = m_pp.disciplines.values[slot_id];
|
||||
|
||||
v.emplace_back(e);
|
||||
} else {
|
||||
delete_slots.emplace_back(std::to_string(slot_id));
|
||||
}
|
||||
}
|
||||
|
||||
if (!delete_slots.empty()) {
|
||||
CharacterDisciplinesRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`slot_id` IN ({})",
|
||||
Strings::Join(delete_slots, ", ")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!v.empty()) {
|
||||
CharacterDisciplinesRepository::ReplaceMany(database, v);
|
||||
}
|
||||
@@ -12700,4 +12724,27 @@ bool Client::TakeMoneyFromPPWithOverFlow(uint64 copper, bool update_client)
|
||||
SaveCurrency();
|
||||
RecalcWeight();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendTopLevelInventory()
|
||||
{
|
||||
EQ::ItemInstance* inst = nullptr;
|
||||
|
||||
static const int16 slots[][2] = {
|
||||
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
|
||||
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
|
||||
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END }
|
||||
};
|
||||
|
||||
const auto& inv = GetInv();
|
||||
|
||||
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
|
||||
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
|
||||
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
|
||||
inst = inv.GetItem(slot_id);
|
||||
if (inst) {
|
||||
SendItemPacket(slot_id, inst, ItemPacketType::ItemPacketTrade);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-6
@@ -762,8 +762,8 @@ public:
|
||||
void GetRaidAAs(RaidLeadershipAA_Struct *into) const;
|
||||
void ClearGroupAAs();
|
||||
void UpdateGroupAAs(int32 points, uint32 type);
|
||||
void SacrificeConfirm(Client* caster);
|
||||
void Sacrifice(Client* caster);
|
||||
void SacrificeConfirm(Mob* caster);
|
||||
void Sacrifice(Mob* caster);
|
||||
void GoToDeath();
|
||||
inline const int32 GetInstanceID() const { return zone->GetInstanceID(); }
|
||||
void SetZoning(bool in) { bZoning = in; }
|
||||
@@ -1025,7 +1025,7 @@ public:
|
||||
int GetSpentAA() { return m_pp.aapoints_spent; }
|
||||
uint32 GetRequiredAAExperience();
|
||||
void AutoGrantAAPoints();
|
||||
void GrantAllAAPoints(uint8 unlock_level = 0);
|
||||
void GrantAllAAPoints(uint8 unlock_level = 0, bool skip_grant_only = false);
|
||||
bool HasAlreadyPurchasedRank(AA::Rank* rank);
|
||||
void ListPurchasedAAs(Client *to, std::string search_criteria = std::string());
|
||||
|
||||
@@ -1245,7 +1245,7 @@ public:
|
||||
bool PendingTranslocate;
|
||||
time_t TranslocateTime;
|
||||
bool PendingSacrifice;
|
||||
std::string SacrificeCaster;
|
||||
uint16 sacrifice_caster_id;
|
||||
PendingTranslocate_Struct PendingTranslocateData;
|
||||
void SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID);
|
||||
|
||||
@@ -1420,7 +1420,11 @@ public:
|
||||
{
|
||||
return (task_state ? task_state->EnabledTaskCount(task_set_id) : -1);
|
||||
}
|
||||
inline int IsTaskCompleted(int task_id) { return (task_state ? task_state->IsTaskCompleted(task_id) : -1); }
|
||||
inline bool IsTaskCompleted(int task_id) { return (task_state ? task_state->IsTaskCompleted(task_id) : false); }
|
||||
inline bool AreTasksCompleted(std::vector<int> task_ids)
|
||||
{
|
||||
return (task_state ? task_state->AreTasksCompleted(task_ids) : false);
|
||||
}
|
||||
inline void ShowClientTasks(Client *client) { if (task_state) { task_state->ShowClientTasks(this, client); }}
|
||||
inline void CancelAllTasks() { if (task_state) { task_state->CancelAllTasks(this); }}
|
||||
inline int GetActiveTaskCount() { return (task_state ? task_state->GetActiveTaskCount() : 0); }
|
||||
@@ -2008,6 +2012,8 @@ private:
|
||||
void ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm);
|
||||
void ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
|
||||
|
||||
void SendTopLevelInventory();
|
||||
|
||||
glm::vec4 m_ZoneSummonLocation;
|
||||
uint16 zonesummon_id;
|
||||
uint8 zonesummon_ignorerestrictions;
|
||||
@@ -2052,6 +2058,11 @@ private:
|
||||
Timer task_request_timer;
|
||||
Timer pick_lock_timer;
|
||||
Timer parcel_timer; //Used to limit the number of parcels to one every 30 seconds (default). Changable via rule.
|
||||
Timer lazy_load_bank_check_timer;
|
||||
Timer bandolier_throttle_timer;
|
||||
|
||||
bool m_lazy_load_bank = false;
|
||||
int m_lazy_load_sent_bank_slots = 0;
|
||||
|
||||
glm::vec3 m_Proximity;
|
||||
glm::vec4 last_position_before_bulk_update;
|
||||
@@ -2171,7 +2182,6 @@ private:
|
||||
bool m_has_quest_compass = false;
|
||||
std::vector<uint32_t> m_dynamic_zone_ids;
|
||||
|
||||
|
||||
public:
|
||||
enum BotOwnerOption : size_t {
|
||||
booDeathMarquee,
|
||||
|
||||
+41
-22
@@ -934,6 +934,7 @@ void Client::CompleteConnect()
|
||||
}
|
||||
|
||||
database.LoadAuras(this); // this ends up spawning them so probably safer to load this later (here)
|
||||
database.LoadCharacterDisciplines(this);
|
||||
|
||||
entity_list.RefreshClientXTargets(this);
|
||||
|
||||
@@ -1318,7 +1319,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
database.LoadCharacterInspectMessage(cid, &m_inspect_message); /* Load Character Inspect Message */
|
||||
database.LoadCharacterSpellBook(cid, &m_pp); /* Load Character Spell Book */
|
||||
database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */
|
||||
database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */
|
||||
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
|
||||
database.LoadCharacterLeadershipAbilities(cid, &m_pp); /* Load Character Leadership AA's */
|
||||
database.LoadCharacterTribute(this); /* Load CharacterTribute */
|
||||
@@ -3285,6 +3285,10 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
|
||||
if (new_aug->GetItem()->Attuneable) {
|
||||
new_aug->SetAttuned(true);
|
||||
}
|
||||
|
||||
tobe_auged->PutAugment(in_augment->augment_index, *new_aug);
|
||||
tobe_auged->UpdateOrnamentationInfo();
|
||||
|
||||
@@ -3638,29 +3642,39 @@ void Client::Handle_OP_AutoFire(const EQApplicationPacket *app)
|
||||
void Client::Handle_OP_Bandolier(const EQApplicationPacket *app)
|
||||
{
|
||||
// Although there are three different structs for OP_Bandolier, they are all the same size.
|
||||
//
|
||||
if (app->size != sizeof(BandolierCreate_Struct)) {
|
||||
LogDebug("Size mismatch in OP_Bandolier expected [{}] got [{}]", sizeof(BandolierCreate_Struct), app->size);
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
BandolierCreate_Struct *bs = (BandolierCreate_Struct*)app->pBuffer;
|
||||
auto bs = (BandolierCreate_Struct*) app->pBuffer;
|
||||
|
||||
switch (bs->Action)
|
||||
{
|
||||
case bandolierCreate:
|
||||
CreateBandolier(app);
|
||||
break;
|
||||
case bandolierRemove:
|
||||
RemoveBandolier(app);
|
||||
break;
|
||||
case bandolierSet:
|
||||
SetBandolier(app);
|
||||
break;
|
||||
default:
|
||||
LogDebug("Unknown Bandolier action [{}]", bs->Action);
|
||||
break;
|
||||
switch (bs->Action) {
|
||||
case bandolierCreate:
|
||||
CreateBandolier(app);
|
||||
break;
|
||||
case bandolierRemove:
|
||||
RemoveBandolier(app);
|
||||
break;
|
||||
case bandolierSet:
|
||||
if (bandolier_throttle_timer.GetDuration() && !bandolier_throttle_timer.Check()) {
|
||||
Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"You may only modify your bandolier once every {}.",
|
||||
Strings::ToLower(Strings::MillisecondsToTime(RuleI(Character, BandolierSwapDelay)))
|
||||
).c_str()
|
||||
);
|
||||
SendTopLevelInventory();
|
||||
break;
|
||||
}
|
||||
|
||||
SetBandolier(app);
|
||||
break;
|
||||
default:
|
||||
LogDebug("Unknown Bandolier action [{}]", bs->Action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13667,11 +13681,11 @@ void Client::Handle_OP_Sacrifice(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
if (ss->Confirm) {
|
||||
Client *Caster = entity_list.GetClientByName(SacrificeCaster.c_str());
|
||||
Mob *Caster = entity_list.GetMob(sacrifice_caster_id);
|
||||
if (Caster) Sacrifice(Caster);
|
||||
}
|
||||
PendingSacrifice = false;
|
||||
SacrificeCaster.clear();
|
||||
sacrifice_caster_id = 0;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_SafeFallSuccess(const EQApplicationPacket *app) // bit of a misnomer, sent whenever safe fall is used (success of fail)
|
||||
@@ -16893,9 +16907,14 @@ void Client::Handle_OP_RaidClearNPCMarks(const EQApplicationPacket* app)
|
||||
|
||||
void Client::RecordStats()
|
||||
{
|
||||
const uint32 character_id = CharacterID();
|
||||
if (!character_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto r = CharacterStatsRecordRepository::FindOne(
|
||||
database,
|
||||
CharacterID()
|
||||
character_id
|
||||
);
|
||||
|
||||
r.status = Admin();
|
||||
@@ -16973,8 +16992,8 @@ void Client::RecordStats()
|
||||
if (r.character_id > 0) {
|
||||
CharacterStatsRecordRepository::UpdateOne(database, r);
|
||||
} else {
|
||||
r.character_id = CharacterID();
|
||||
r.created_at = std::time(nullptr);
|
||||
r.character_id = character_id;
|
||||
r.created_at = std::time(nullptr);
|
||||
CharacterStatsRecordRepository::InsertOne(database, r);
|
||||
}
|
||||
}
|
||||
|
||||
+58
-25
@@ -289,6 +289,37 @@ bool Client::Process() {
|
||||
entity_list.ScanCloseMobs(close_mobs, this, IsMoving());
|
||||
}
|
||||
|
||||
if (RuleB(Inventory, LazyLoadBank)) {
|
||||
// poll once a second to see if we are close to a banker and we haven't loaded the bank yet
|
||||
if (!m_lazy_load_bank && lazy_load_bank_check_timer.Check()) {
|
||||
if (m_lazy_load_sent_bank_slots <= EQ::invslot::SHARED_BANK_END && IsCloseToBanker()) {
|
||||
m_lazy_load_bank = true;
|
||||
lazy_load_bank_check_timer.Disable();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_lazy_load_bank && m_lazy_load_sent_bank_slots <= EQ::invslot::SHARED_BANK_END) {
|
||||
const EQ::ItemInstance *inst = nullptr;
|
||||
|
||||
// Jump the gaps
|
||||
if (m_lazy_load_sent_bank_slots < EQ::invslot::BANK_BEGIN) {
|
||||
m_lazy_load_sent_bank_slots = EQ::invslot::BANK_BEGIN;
|
||||
}
|
||||
else if (m_lazy_load_sent_bank_slots > EQ::invslot::BANK_END &&
|
||||
m_lazy_load_sent_bank_slots < EQ::invslot::SHARED_BANK_BEGIN) {
|
||||
m_lazy_load_sent_bank_slots = EQ::invslot::SHARED_BANK_BEGIN;
|
||||
}
|
||||
else {
|
||||
m_lazy_load_sent_bank_slots++;
|
||||
}
|
||||
|
||||
inst = m_inv[m_lazy_load_sent_bank_slots];
|
||||
if (inst) {
|
||||
SendItemPacket(m_lazy_load_sent_bank_slots, inst, ItemPacketType::ItemPacketTrade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool may_use_attacks = false;
|
||||
/*
|
||||
Things which prevent us from attacking:
|
||||
@@ -780,39 +811,41 @@ void Client::BulkSendInventoryItems()
|
||||
last_pos = ob.tellp();
|
||||
}
|
||||
|
||||
// Bank items
|
||||
for (int16 slot_id = EQ::invslot::BANK_BEGIN; slot_id <= EQ::invslot::BANK_END; slot_id++) {
|
||||
const EQ::ItemInstance* inst = m_inv[slot_id];
|
||||
if (!inst)
|
||||
continue;
|
||||
if (!RuleB(Inventory, LazyLoadBank)) {
|
||||
// Bank items
|
||||
for (int16 slot_id = EQ::invslot::BANK_BEGIN; slot_id <= EQ::invslot::BANK_END; slot_id++) {
|
||||
const EQ::ItemInstance* inst = m_inv[slot_id];
|
||||
if (!inst)
|
||||
continue;
|
||||
|
||||
inst->Serialize(ob, slot_id);
|
||||
inst->Serialize(ob, slot_id);
|
||||
|
||||
if (ob.tellp() == last_pos)
|
||||
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
|
||||
if (ob.tellp() == last_pos)
|
||||
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
|
||||
|
||||
last_pos = ob.tellp();
|
||||
}
|
||||
last_pos = ob.tellp();
|
||||
}
|
||||
|
||||
// SharedBank items
|
||||
for (int16 slot_id = EQ::invslot::SHARED_BANK_BEGIN; slot_id <= EQ::invslot::SHARED_BANK_END; slot_id++) {
|
||||
const EQ::ItemInstance* inst = m_inv[slot_id];
|
||||
if (!inst)
|
||||
continue;
|
||||
// SharedBank items
|
||||
for (int16 slot_id = EQ::invslot::SHARED_BANK_BEGIN; slot_id <= EQ::invslot::SHARED_BANK_END; slot_id++) {
|
||||
const EQ::ItemInstance* inst = m_inv[slot_id];
|
||||
if (!inst)
|
||||
continue;
|
||||
|
||||
inst->Serialize(ob, slot_id);
|
||||
inst->Serialize(ob, slot_id);
|
||||
|
||||
if (ob.tellp() == last_pos)
|
||||
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
|
||||
if (ob.tellp() == last_pos)
|
||||
LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id);
|
||||
|
||||
last_pos = ob.tellp();
|
||||
}
|
||||
last_pos = ob.tellp();
|
||||
}
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_CharInventory);
|
||||
outapp->size = ob.size();
|
||||
outapp->pBuffer = ob.detach();
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
auto outapp = new EQApplicationPacket(OP_CharInventory);
|
||||
outapp->size = ob.size();
|
||||
outapp->pBuffer = ob.detach();
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
||||
|
||||
+2
-2
@@ -542,8 +542,8 @@ void Doors::HandleClick(Client *sender, uint8 trigger)
|
||||
if (EQ::ValueWithin(m_open_type, 57, 58) && HasDestinationZone()) {
|
||||
bool has_key_required = (required_key_item && required_key_item == player_key);
|
||||
|
||||
if (sender->GetGM() && has_key_required) {
|
||||
has_key_required = false;
|
||||
if (sender->GetGM() && !has_key_required) {
|
||||
has_key_required = true;
|
||||
sender->Message(Chat::White, "Your GM flag allows you to open this door without a key.");
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,12 @@ public:
|
||||
void SetPosition(const glm::vec4 &position);
|
||||
void SetSize(uint16 size);
|
||||
void ToggleState(Mob *sender);
|
||||
inline std::string GetDestinationZoneName() { return m_destination_zone_name; }
|
||||
inline int GetDestinationInstanceID() { return m_destination_instance_id; }
|
||||
inline float GetDestinationX() { return m_destination.x; }
|
||||
inline float GetDestinationY() { return m_destination.y; }
|
||||
inline float GetDestinationZ() { return m_destination.z; }
|
||||
inline float GetDestinationHeading() { return m_destination.w; }
|
||||
|
||||
float GetX();
|
||||
float GetY();
|
||||
|
||||
+81
-123
@@ -1028,24 +1028,15 @@ void Client::SendDisciplineTimer(uint32 timer_id, uint32 duration)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param taunter
|
||||
* @param range
|
||||
* @param bonus_hate
|
||||
*/
|
||||
void EntityList::AETaunt(Client *taunter, float range, int32 bonus_hate)
|
||||
void EntityList::AETaunt(Client* taunter, float range, int bonus_hate)
|
||||
{
|
||||
|
||||
/**
|
||||
* Live AE taunt range - Hardcoded.
|
||||
*/
|
||||
if (range == 0) {
|
||||
range = 40;
|
||||
}
|
||||
|
||||
float range_squared = range * range;
|
||||
|
||||
for (auto &it : entity_list.GetCloseMobList(taunter, range)) {
|
||||
for (auto& it: entity_list.GetCloseMobList(taunter, range)) {
|
||||
Mob *them = it.second;
|
||||
if (!them) {
|
||||
continue;
|
||||
@@ -1060,9 +1051,11 @@ void EntityList::AETaunt(Client *taunter, float range, int32 bonus_hate)
|
||||
z_difference *= -1;
|
||||
}
|
||||
|
||||
if (z_difference < 10
|
||||
&& taunter->IsAttackAllowed(them)
|
||||
&& DistanceSquaredNoZ(taunter->GetPosition(), them->GetPosition()) <= range_squared) {
|
||||
if (
|
||||
z_difference < 10 &&
|
||||
taunter->IsAttackAllowed(them) &&
|
||||
DistanceSquaredNoZ(taunter->GetPosition(), them->GetPosition()) <= range_squared
|
||||
) {
|
||||
if (taunter->CheckLosFN(them)) {
|
||||
taunter->Taunt(them->CastToNPC(), true, 0, true, bonus_hate);
|
||||
}
|
||||
@@ -1070,38 +1063,31 @@ void EntityList::AETaunt(Client *taunter, float range, int32 bonus_hate)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes caster to hit every mob within dist range of center with spell_id
|
||||
*
|
||||
* @param caster_mob
|
||||
* @param center_mob
|
||||
* @param spell_id
|
||||
* @param affect_caster
|
||||
* @param resist_adjust
|
||||
* @param max_targets
|
||||
*/
|
||||
void EntityList::AESpell(
|
||||
Mob *caster_mob,
|
||||
Mob *center_mob,
|
||||
Mob* caster_mob,
|
||||
Mob* center_mob,
|
||||
uint16 spell_id,
|
||||
bool affect_caster,
|
||||
int16 resist_adjust,
|
||||
int *max_targets
|
||||
int* max_targets,
|
||||
bool is_scripted
|
||||
)
|
||||
{
|
||||
const auto &cast_target_position =
|
||||
spells[spell_id].target_type == ST_Ring ?
|
||||
caster_mob->GetTargetRingLocation() :
|
||||
static_cast<glm::vec3>(center_mob->GetPosition());
|
||||
const auto& cast_target_position = (
|
||||
(!is_scripted && spells[spell_id].target_type == ST_Ring) ?
|
||||
caster_mob->GetTargetRingLocation() :
|
||||
static_cast<glm::vec3>(center_mob->GetPosition())
|
||||
);
|
||||
|
||||
Mob* current_mob = nullptr;
|
||||
|
||||
Mob *current_mob = nullptr;
|
||||
bool is_detrimental_spell = IsDetrimentalSpell(spell_id);
|
||||
bool is_npc = caster_mob->IsNPC();
|
||||
float distance = caster_mob->GetAOERange(spell_id);
|
||||
float distance_squared = distance * distance;
|
||||
float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
|
||||
glm::vec2 min = {cast_target_position.x - distance, cast_target_position.y - distance};
|
||||
glm::vec2 max = {cast_target_position.x + distance, cast_target_position.y + distance};
|
||||
float min_range_squared = spells[spell_id].min_range * spells[spell_id].min_range;
|
||||
glm::vec2 min = { cast_target_position.x - distance, cast_target_position.y - distance };
|
||||
glm::vec2 max = { cast_target_position.x + distance, cast_target_position.y + distance };
|
||||
|
||||
/**
|
||||
* If using Old Rain Targets - there is no max target limitation
|
||||
@@ -1110,17 +1096,18 @@ void EntityList::AESpell(
|
||||
max_targets = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Max AOE targets
|
||||
*/
|
||||
int max_targets_allowed = RuleI(Range, AOEMaxTargets); // unlimited
|
||||
if (max_targets) { // rains pass this in since they need to preserve the count through waves
|
||||
max_targets_allowed = *max_targets;
|
||||
}
|
||||
else if (spells[spell_id].aoe_max_targets) {
|
||||
} else if (spells[spell_id].aoe_max_targets) {
|
||||
max_targets_allowed = spells[spell_id].aoe_max_targets;
|
||||
}
|
||||
else if (IsTargetableAESpell(spell_id) && is_detrimental_spell && !is_npc && !IsEffectInSpell(spell_id, SE_Lull) && !IsEffectInSpell(spell_id, SE_Mez)) {
|
||||
} else if (
|
||||
IsTargetableAESpell(spell_id) &&
|
||||
is_detrimental_spell &&
|
||||
!is_npc &&
|
||||
!IsEffectInSpell(spell_id, SE_Lull) &&
|
||||
!IsEffectInSpell(spell_id, SE_Mez)
|
||||
) {
|
||||
max_targets_allowed = 4;
|
||||
}
|
||||
|
||||
@@ -1133,7 +1120,7 @@ void EntityList::AESpell(
|
||||
distance
|
||||
);
|
||||
|
||||
for (auto &it : entity_list.GetCloseMobList(caster_mob, distance)) {
|
||||
for (auto& it: entity_list.GetCloseMobList(caster_mob, distance)) {
|
||||
current_mob = it.second;
|
||||
if (!current_mob) {
|
||||
continue;
|
||||
@@ -1161,16 +1148,11 @@ void EntityList::AESpell(
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check PC / NPC
|
||||
* 1 = PC
|
||||
* 2 = NPC
|
||||
*/
|
||||
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsOfClientBotMerc()) {
|
||||
if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::PC && !current_mob->IsOfClientBotMerc()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spells[spell_id].pcnpc_only_flag == 2 && current_mob->IsOfClientBotMerc()) {
|
||||
if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::NPC && current_mob->IsOfClientBotMerc()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1184,41 +1166,40 @@ void EntityList::AESpell(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (distance_to_target < min_range2) {
|
||||
if (distance_to_target < min_range_squared) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_npc && current_mob->IsNPC() &&
|
||||
spells[spell_id].target_type != ST_AreaNPCOnly) { //check npc->npc casting
|
||||
FACTION_VALUE faction_value = current_mob->GetReverseFactionCon(caster_mob);
|
||||
if (
|
||||
is_npc &&
|
||||
current_mob->IsNPC() &&
|
||||
spells[spell_id].target_type != ST_AreaNPCOnly
|
||||
) {
|
||||
const auto faction_value = current_mob->GetReverseFactionCon(caster_mob);
|
||||
if (is_detrimental_spell) {
|
||||
//affect mobs that are on our hate list, or
|
||||
//which have bad faction with us
|
||||
if (
|
||||
!(caster_mob->CheckAggro(current_mob) ||
|
||||
faction_value == FACTION_THREATENINGLY ||
|
||||
faction_value == FACTION_SCOWLS)) {
|
||||
faction_value == FACTION_THREATENINGLY ||
|
||||
faction_value == FACTION_SCOWLS)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//only affect mobs we would assist.
|
||||
} else {
|
||||
if (!(faction_value <= FACTION_AMIABLY)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finally, make sure they are within range
|
||||
*/
|
||||
if (is_detrimental_spell) {
|
||||
if (!caster_mob->IsAttackAllowed(current_mob, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (center_mob && !spells[spell_id].npc_no_los && !center_mob->CheckLosFN(current_mob)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!center_mob && !spells[spell_id].npc_no_los && !caster_mob->CheckLosFN(
|
||||
caster_mob->GetTargetRingX(),
|
||||
caster_mob->GetTargetRingY(),
|
||||
@@ -1226,9 +1207,7 @@ void EntityList::AESpell(
|
||||
current_mob->GetSize())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
/**
|
||||
* Check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
|
||||
* This does not check faction for beneficial AE buffs... only agro and attackable.
|
||||
@@ -1238,6 +1217,7 @@ void EntityList::AESpell(
|
||||
if (caster_mob->IsAttackAllowed(current_mob, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (caster_mob->CheckAggro(current_mob)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1264,40 +1244,29 @@ void EntityList::AESpell(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param caster
|
||||
* @param center
|
||||
* @param spell_id
|
||||
* @param affect_caster
|
||||
*/
|
||||
void EntityList::MassGroupBuff(
|
||||
Mob *caster,
|
||||
Mob *center,
|
||||
Mob* caster,
|
||||
Mob* center,
|
||||
uint16 spell_id,
|
||||
bool affect_caster)
|
||||
bool affect_caster
|
||||
)
|
||||
{
|
||||
Mob *current_mob = nullptr;
|
||||
Mob* current_mob = nullptr;
|
||||
float distance = caster->GetAOERange(spell_id);
|
||||
float distance_squared = distance * distance;
|
||||
bool is_detrimental_spell = IsDetrimentalSpell(spell_id);
|
||||
|
||||
for (auto &it : entity_list.GetCloseMobList(caster, distance)) {
|
||||
for (auto& it: entity_list.GetCloseMobList(caster, distance)) {
|
||||
current_mob = it.second;
|
||||
if (!current_mob) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip center
|
||||
*/
|
||||
if (current_mob == center) {
|
||||
if (current_mob == center) { // Skip Center
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip self
|
||||
*/
|
||||
if (current_mob == caster && !affect_caster) {
|
||||
if (current_mob == caster && !affect_caster) { // Skip Caster
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1305,17 +1274,13 @@ void EntityList::MassGroupBuff(
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pets
|
||||
*/
|
||||
if (current_mob->IsNPC()) {
|
||||
Mob *owner = current_mob->GetOwner();
|
||||
Mob* owner = current_mob->GetOwner();
|
||||
if (owner) {
|
||||
if (!owner->IsOfClientBot()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1328,55 +1293,48 @@ void EntityList::MassGroupBuff(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rampage - Normal and Duration rampages
|
||||
* NPCs handle it differently in Mob::Rampage
|
||||
*
|
||||
* @param attacker
|
||||
* @param distance
|
||||
* @param Hand
|
||||
* @param count
|
||||
* @param is_from_spell
|
||||
*/
|
||||
void EntityList::AEAttack(
|
||||
Mob *attacker,
|
||||
Mob* attacker,
|
||||
float distance,
|
||||
int Hand,
|
||||
int count,
|
||||
int16 slot_id,
|
||||
int hit_count,
|
||||
bool is_from_spell,
|
||||
int attack_rounds)
|
||||
int attack_rounds
|
||||
)
|
||||
{
|
||||
Mob *current_mob = nullptr;
|
||||
Mob* current_mob = nullptr;
|
||||
float distance_squared = distance * distance;
|
||||
int hit_count = 0;
|
||||
int current_hits = 0;
|
||||
|
||||
for (auto &it : entity_list.GetCloseMobList(attacker, distance)) {
|
||||
for (auto& it: entity_list.GetCloseMobList(attacker, distance)) {
|
||||
current_mob = it.second;
|
||||
if (!current_mob) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_mob->IsNPC()
|
||||
&& current_mob != attacker //this is not needed unless NPCs can use this
|
||||
&& (attacker->IsAttackAllowed(current_mob))
|
||||
&& !current_mob->IsHorse() /* dont attack mounts */
|
||||
&& (DistanceSquared(current_mob->GetPosition(), attacker->GetPosition()) <= distance_squared)
|
||||
) {
|
||||
|
||||
if (
|
||||
current_mob->IsNPC() &&
|
||||
current_mob != attacker &&
|
||||
attacker->IsAttackAllowed(current_mob) &&
|
||||
!current_mob->IsHorse() &&
|
||||
DistanceSquared(current_mob->GetPosition(), attacker->GetPosition()) <= distance_squared
|
||||
) {
|
||||
for (int i = 0; i < attack_rounds; i++) {
|
||||
if (!attacker->IsClient() || attacker->GetClass() == Class::Monk || attacker->GetClass() == Class::Ranger) {
|
||||
attacker->Attack(current_mob, Hand, false, false, is_from_spell);
|
||||
if (
|
||||
!attacker->IsClient() ||
|
||||
attacker->GetClass() == Class::Monk ||
|
||||
attacker->GetClass() == Class::Ranger
|
||||
) {
|
||||
attacker->Attack(current_mob, slot_id, false, false, is_from_spell);
|
||||
} else {
|
||||
attacker->CastToClient()->DoAttackRounds(current_mob, Hand, is_from_spell);
|
||||
attacker->CastToClient()->DoAttackRounds(current_mob, slot_id, is_from_spell);
|
||||
}
|
||||
}
|
||||
|
||||
hit_count++;
|
||||
if (count != 0 && hit_count >= count) {
|
||||
current_hits++;
|
||||
if (hit_count != 0 && current_hits >= hit_count) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-4
@@ -2064,9 +2064,14 @@ void PerlembParser::ExportEventVariables(
|
||||
Corpse* corpse = std::any_cast<Corpse*>(extra_pointers->at(0));
|
||||
if (corpse) {
|
||||
ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID());
|
||||
ExportVar(package_name.c_str(), "killed_x", corpse->GetX());
|
||||
ExportVar(package_name.c_str(), "killed_y", corpse->GetY());
|
||||
ExportVar(package_name.c_str(), "killed_z", corpse->GetZ());
|
||||
ExportVar(package_name.c_str(), "killed_h", corpse->GetHeading());
|
||||
}
|
||||
}
|
||||
|
||||
// EVENT_DEATH_ZONE only
|
||||
if (extra_pointers && extra_pointers->size() >= 2) {
|
||||
NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1));
|
||||
if (killed) {
|
||||
@@ -2076,10 +2081,6 @@ void PerlembParser::ExportEventVariables(
|
||||
killed->IsBot() ? killed->CastToBot()->GetBotID() : 0
|
||||
);
|
||||
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
|
||||
ExportVar(package_name.c_str(), "killed_x", killed->GetX());
|
||||
ExportVar(package_name.c_str(), "killed_y", killed->GetY());
|
||||
ExportVar(package_name.c_str(), "killed_z", killed->GetZ());
|
||||
ExportVar(package_name.c_str(), "killed_h", killed->GetHeading());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+13
-1
@@ -1276,7 +1276,7 @@ int Perl__tasktimeleft(int task_id)
|
||||
return quest_manager.tasktimeleft(task_id);
|
||||
}
|
||||
|
||||
int Perl__istaskcompleted(int task_id)
|
||||
bool Perl__istaskcompleted(int task_id)
|
||||
{
|
||||
return quest_manager.istaskcompleted(task_id);
|
||||
}
|
||||
@@ -5967,6 +5967,17 @@ bool Perl__send_parcel(perl::reference table_ref)
|
||||
return out;
|
||||
}
|
||||
|
||||
bool Perl__aretaskscompleted(perl::array task_ids)
|
||||
{
|
||||
std::vector<int> v;
|
||||
|
||||
for (const auto& e : task_ids) {
|
||||
v.emplace_back(static_cast<int>(e));
|
||||
}
|
||||
|
||||
return quest_manager.aretaskscompleted(v);
|
||||
}
|
||||
|
||||
void perl_register_quest()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -6290,6 +6301,7 @@ void perl_register_quest()
|
||||
package.add("addloot", (void(*)(int, int))&Perl__addloot);
|
||||
package.add("addloot", (void(*)(int, int, bool))&Perl__addloot);
|
||||
package.add("addskill", &Perl__addskill);
|
||||
package.add("aretaskscompleted", &Perl__aretaskscompleted);
|
||||
package.add("assigntask", (void(*)(int))&Perl__assigntask);
|
||||
package.add("assigntask", (void(*)(int, bool))&Perl__assigntask);
|
||||
package.add("attack", &Perl__attack);
|
||||
|
||||
+9
-8
@@ -436,23 +436,24 @@ public:
|
||||
void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
|
||||
|
||||
void AEAttack(
|
||||
Mob *attacker,
|
||||
Mob* attacker,
|
||||
float distance,
|
||||
int Hand = EQ::invslot::slotPrimary,
|
||||
int count = 0,
|
||||
int16 slot_id = EQ::invslot::slotPrimary,
|
||||
int hit_count = 0,
|
||||
bool is_from_spell = false,
|
||||
int attack_rounds = 1
|
||||
);
|
||||
void AETaunt(Client *caster, float range = 0, int32 bonus_hate = 0);
|
||||
void AETaunt(Client* caster, float range = 0, int bonus_hate = 0);
|
||||
void AESpell(
|
||||
Mob *caster,
|
||||
Mob *center,
|
||||
Mob* caster,
|
||||
Mob* center,
|
||||
uint16 spell_id,
|
||||
bool affect_caster = true,
|
||||
int16 resist_adjust = 0,
|
||||
int *max_targets = nullptr
|
||||
int* max_targets = nullptr,
|
||||
bool is_scripted = false
|
||||
);
|
||||
void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
|
||||
void MassGroupBuff(Mob* caster, Mob* center, uint16 spell_id, bool affect_caster = true);
|
||||
|
||||
//trap stuff
|
||||
Mob* GetTrapTrigger(Trap* trap);
|
||||
|
||||
+59
-51
@@ -527,7 +527,7 @@ void Client::AddEXP(ExpSource exp_source, uint64 in_add_exp, uint8 conlevel, boo
|
||||
// Are we also doing linear AA acceleration?
|
||||
if (RuleB(AA, ModernAAScalingEnabled) && aaexp > 0)
|
||||
{
|
||||
aaexp = ScaleAAXPBasedOnCurrentAATotal(GetAAPoints(), aaexp);
|
||||
aaexp = ScaleAAXPBasedOnCurrentAATotal(GetSpentAA() + GetAAPoints(), aaexp);
|
||||
}
|
||||
|
||||
// Check for AA XP Cap
|
||||
@@ -607,10 +607,10 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
Message(Chat::Red, "Error in Client::SetEXP. EXP not set.");
|
||||
return; // Must be invalid class/race
|
||||
}
|
||||
|
||||
uint32 i = 0;
|
||||
uint32 membercount = 0;
|
||||
if(GetGroup())
|
||||
{
|
||||
if(GetGroup()) {
|
||||
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||
if (GetGroup()->members[i] != nullptr) {
|
||||
membercount++;
|
||||
@@ -627,25 +627,29 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
if (RuleI(Character, ShowExpValues) >= 1) {
|
||||
if (exp_gained > 0 && aa_exp_gained > 0) {
|
||||
exp_amount_message = fmt::format("({}) ({})", exp_gained, aa_exp_gained);
|
||||
}
|
||||
else if (exp_gained > 0) {
|
||||
} else if (exp_gained > 0) {
|
||||
exp_amount_message = fmt::format("({})", exp_gained);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
exp_amount_message = fmt::format("({}) AA", aa_exp_gained);
|
||||
}
|
||||
}
|
||||
|
||||
std::string exp_percent_message = "";
|
||||
if (RuleI(Character, ShowExpValues) >= 2) {
|
||||
if (exp_gained > 0 && aa_exp_gained > 0) exp_percent_message = StringFormat("(%.3f%%, %.3f%%AA)", exp_percent, aa_exp_percent);
|
||||
else if (exp_gained > 0) exp_percent_message = StringFormat("(%.3f%%)", exp_percent);
|
||||
else exp_percent_message = StringFormat("(%.3f%%AA)", aa_exp_percent);
|
||||
if (exp_gained > 0 && aa_exp_gained > 0) {
|
||||
exp_percent_message = StringFormat("(%.3f%%, %.3f%%AA)", exp_percent, aa_exp_percent);
|
||||
} else if (exp_gained > 0) {
|
||||
exp_percent_message = StringFormat("(%.3f%%)", exp_percent);
|
||||
} else {
|
||||
exp_percent_message = StringFormat("(%.3f%%AA)", aa_exp_percent);
|
||||
}
|
||||
}
|
||||
if (isrezzexp) {
|
||||
if (RuleI(Character, ShowExpValues) > 0)
|
||||
if (RuleI(Character, ShowExpValues) > 0) {
|
||||
Message(Chat::Experience, "You regain %s experience from resurrection. %s", exp_amount_message.c_str(), exp_percent_message.c_str());
|
||||
else MessageString(Chat::Experience, REZ_REGAIN);
|
||||
} else {
|
||||
MessageString(Chat::Experience, REZ_REGAIN);
|
||||
}
|
||||
} else {
|
||||
if (membercount > 1) {
|
||||
if (RuleI(Character, ShowExpValues) > 0) {
|
||||
@@ -673,14 +677,17 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(total_add_exp < total_current_exp){ //only loss message if you lose exp, no message if you gained/lost nothing.
|
||||
} else if(total_add_exp < total_current_exp) { //only loss message if you lose exp, no message if you gained/lost nothing.
|
||||
uint64 exp_lost = current_exp - set_exp;
|
||||
float exp_percent = (float)((float)exp_lost / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100;
|
||||
|
||||
if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) Message(Chat::Yellow, "You have lost %i experience.", exp_lost);
|
||||
else if (RuleI(Character, ShowExpValues) == 2 && exp_lost > 0) Message(Chat::Yellow, "You have lost %i experience. (%.3f%%)", exp_lost, exp_percent);
|
||||
else Message(Chat::Yellow, "You have lost experience.");
|
||||
if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) {
|
||||
Message(Chat::Yellow, "You have lost %i experience.", exp_lost);
|
||||
} else if (RuleI(Character, ShowExpValues) == 2 && exp_lost > 0) {
|
||||
Message(Chat::Yellow, "You have lost %i experience. (%.3f%%)", exp_lost, exp_percent);
|
||||
} else {
|
||||
Message(Chat::Yellow, "You have lost experience.");
|
||||
}
|
||||
}
|
||||
|
||||
//check_level represents the level we should be when we have
|
||||
@@ -698,8 +705,9 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
}
|
||||
level_count++;
|
||||
|
||||
if(GetMercenaryID())
|
||||
if (GetMercenaryID()) {
|
||||
UpdateMercLevel();
|
||||
}
|
||||
}
|
||||
//see if we lost any levels
|
||||
while (set_exp < GetEXPForLevel(check_level-1)) {
|
||||
@@ -709,8 +717,9 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
break;
|
||||
}
|
||||
level_increase = false;
|
||||
if(GetMercenaryID())
|
||||
if (GetMercenaryID()) {
|
||||
UpdateMercLevel();
|
||||
}
|
||||
}
|
||||
check_level--;
|
||||
|
||||
@@ -747,12 +756,14 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
//Message(Chat::Yellow, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
|
||||
char val1[20] = { 0 };
|
||||
char val2[20] = { 0 };
|
||||
if (gained == 1 && m_pp.aapoints == 1)
|
||||
|
||||
if (gained == 1 && m_pp.aapoints == 1) {
|
||||
MessageString(Chat::Experience, GAIN_SINGLE_AA_SINGLE_AA, ConvertArray(m_pp.aapoints, val1)); //You have gained an ability point! You now have %1 ability point.
|
||||
else if (gained == 1 && m_pp.aapoints > 1)
|
||||
} else if (gained == 1 && m_pp.aapoints > 1) {
|
||||
MessageString(Chat::Experience, GAIN_SINGLE_AA_MULTI_AA, ConvertArray(m_pp.aapoints, val1)); //You have gained an ability point! You now have %1 ability points.
|
||||
else
|
||||
} else {
|
||||
MessageString(Chat::Experience, GAIN_MULTI_AA_MULTI_AA, ConvertArray(gained, val1), ConvertArray(m_pp.aapoints, val2)); //You have gained %1 ability point(s)! You now have %2 ability point(s).
|
||||
}
|
||||
|
||||
if (RuleB(AA, SoundForAAEarned)) {
|
||||
SendSound();
|
||||
@@ -765,7 +776,7 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
RecordPlayerEventLog(PlayerEvent::AA_GAIN, PlayerEvent::AAGainedEvent{gained});
|
||||
|
||||
/* QS: PlayerLogAARate */
|
||||
if (RuleB(QueryServ, PlayerLogAARate)){
|
||||
if (RuleB(QueryServ, PlayerLogAARate)) {
|
||||
int add_points = (m_pp.aapoints - last_unspentAA);
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_aa_rate_hourly` (char_id, aa_count, hour_time) VALUES (%i, %i, UNIX_TIMESTAMP() - MOD(UNIX_TIMESTAMP(), 3600)) ON DUPLICATE KEY UPDATE `aa_count` = `aa_count` + %i", CharacterID(), add_points, add_points);
|
||||
QServ->SendQuery(query.c_str());
|
||||
@@ -774,47 +785,44 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
//Message(Chat::Yellow, "You now have %d skill points available to spend.", m_pp.aapoints);
|
||||
}
|
||||
|
||||
uint8 maxlevel = RuleI(Character, MaxExpLevel) + 1;
|
||||
uint8 max_level = RuleI(Character, MaxExpLevel) + 1;
|
||||
|
||||
if(maxlevel <= 1)
|
||||
maxlevel = RuleI(Character, MaxLevel) + 1;
|
||||
|
||||
if(check_level > maxlevel) {
|
||||
check_level = maxlevel;
|
||||
|
||||
if(RuleB(Character, KeepLevelOverMax)) {
|
||||
set_exp = GetEXPForLevel(GetLevel()+1);
|
||||
}
|
||||
else {
|
||||
set_exp = GetEXPForLevel(maxlevel);
|
||||
}
|
||||
if (max_level <= 1) {
|
||||
max_level = RuleI(Character, MaxLevel) + 1;
|
||||
}
|
||||
|
||||
auto client_max_level = GetClientMaxLevel();
|
||||
if (client_max_level) {
|
||||
if (GetLevel() >= client_max_level) {
|
||||
auto exp_needed = GetEXPForLevel(client_max_level);
|
||||
if (set_exp > exp_needed) {
|
||||
set_exp = exp_needed;
|
||||
}
|
||||
max_level = client_max_level + 1;
|
||||
}
|
||||
|
||||
if (check_level > max_level) {
|
||||
check_level = max_level;
|
||||
|
||||
if (RuleB(Character, KeepLevelOverMax)) {
|
||||
set_exp = GetEXPForLevel(GetLevel()+1);
|
||||
} else {
|
||||
set_exp = GetEXPForLevel(max_level);
|
||||
}
|
||||
}
|
||||
|
||||
if ((GetLevel() != check_level) && !(check_level >= maxlevel)) {
|
||||
if ((GetLevel() != check_level) && !(check_level >= max_level)) {
|
||||
char val1[20]={0};
|
||||
if (level_increase)
|
||||
{
|
||||
if (level_count == 1)
|
||||
if (level_increase) {
|
||||
if (level_count == 1) {
|
||||
MessageString(Chat::Experience, GAIN_LEVEL, ConvertArray(check_level, val1));
|
||||
else
|
||||
} else {
|
||||
Message(Chat::Yellow, "Welcome to level %i!", check_level);
|
||||
}
|
||||
|
||||
if (check_level == RuleI(Character, DeathItemLossLevel) &&
|
||||
m_ClientVersionBit & EQ::versions::maskUFAndEarlier)
|
||||
m_ClientVersionBit & EQ::versions::maskUFAndEarlier) {
|
||||
MessageString(Chat::Yellow, CORPSE_ITEM_LOST);
|
||||
}
|
||||
|
||||
if (check_level == RuleI(Character, DeathExpLossLevel))
|
||||
if (check_level == RuleI(Character, DeathExpLossLevel)) {
|
||||
MessageString(Chat::Yellow, CORPSE_EXP_LOST);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 myoldlevel = GetLevel();
|
||||
@@ -828,9 +836,9 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
|
||||
}
|
||||
|
||||
//If were at max level then stop gaining experience if we make it to the cap
|
||||
if(GetLevel() == maxlevel - 1){
|
||||
uint32 expneeded = GetEXPForLevel(maxlevel);
|
||||
if(set_exp > expneeded) {
|
||||
if (GetLevel() == max_level - 1){
|
||||
uint32 expneeded = GetEXPForLevel(max_level);
|
||||
if (set_exp > expneeded) {
|
||||
set_exp = expneeded;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,16 @@ void command_grantaa(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8 unlock_level = sep->IsNumber(1) ? static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1])) : 0;
|
||||
const uint8 unlock_level = sep->IsNumber(1) ? static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1])) : 0;
|
||||
const bool skip_grant_only = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
|
||||
|
||||
auto t = c->GetTarget()->CastToClient();
|
||||
t->GrantAllAAPoints(unlock_level);
|
||||
t->GrantAllAAPoints(unlock_level, skip_grant_only);
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Successfully granted all Alternate Advancements for {}{}.",
|
||||
"Successfully granted all Alternate Advancements for {}{}{}.",
|
||||
c->GetTargetDescription(t),
|
||||
(
|
||||
unlock_level ?
|
||||
@@ -24,7 +25,8 @@ void command_grantaa(Client *c, const Seperator *sep)
|
||||
unlock_level
|
||||
) :
|
||||
""
|
||||
)
|
||||
),
|
||||
skip_grant_only ? "except for grant only AAs" : ""
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -160,23 +160,22 @@ void ShowInventory(Client *c, const Seperator *sep)
|
||||
|
||||
linker.SetItemInst(inst_main);
|
||||
|
||||
if (item_data) {
|
||||
if (item_data && inst_main) {
|
||||
//auto inst = c->GetInv().GetItem(scope_bit & peekWorld ? EQ::invslot::WORLD_BEGIN + index_main : index_main);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Slot {} | {} ({}/{}){}",
|
||||
((scope_bit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + index_main) : index_main),
|
||||
scope_bit & peekWorld ? EQ::invslot::WORLD_BEGIN + index_main : index_main,
|
||||
linker.GenerateLink(),
|
||||
item_data->ID,
|
||||
c->GetInv().GetItem(((scope_bit &peekWorld) ? (EQ::invslot::WORLD_BEGIN + index_main) : index_main))->GetSerialNumber(),
|
||||
(
|
||||
inst_main->IsStackable() && inst_main->GetCharges() > 0 ?
|
||||
fmt::format(
|
||||
" (Stack of {})",
|
||||
inst_main->GetCharges()
|
||||
) :
|
||||
""
|
||||
)
|
||||
inst_main->GetSerialNumber(),
|
||||
inst_main->IsStackable() && inst_main->GetCharges() > 0 ?
|
||||
fmt::format(
|
||||
" (Stack of {})",
|
||||
inst_main->GetCharges()
|
||||
) :
|
||||
""
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
@@ -239,7 +238,7 @@ void ShowInventory(Client *c, const Seperator *sep)
|
||||
sub_index,
|
||||
linker.GenerateLink(),
|
||||
item_data->ID,
|
||||
c->GetInv().GetItem(EQ::InventoryProfile::CalcSlotId(index_main, sub_index))->GetSerialNumber(),
|
||||
inst_sub->GetSerialNumber(),
|
||||
(
|
||||
inst_sub->IsStackable() && inst_sub->GetCharges() > 0 ?
|
||||
fmt::format(
|
||||
|
||||
+6
-1
@@ -3431,6 +3431,11 @@ void Client::SetBandolier(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RuleI(Character, BandolierSwapDelay) > 0) {
|
||||
bandolier_throttle_timer.Start(RuleI(Character, BandolierSwapDelay));
|
||||
}
|
||||
|
||||
// finally, recalculate any stat bonuses from the item change
|
||||
CalcBonuses();
|
||||
}
|
||||
@@ -4913,4 +4918,4 @@ bool Client::FindNumberOfFreeInventorySlotsWithSizeCheck(std::vector<BuyerLineTr
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
+76
-16
@@ -1214,25 +1214,23 @@ void Lua_Client::AddPVPPoints(uint32 points) {
|
||||
self->AddPVPPoints(points);
|
||||
}
|
||||
|
||||
void Lua_Client::AddCrystals(uint32 radiant, uint32 ebon) {
|
||||
void Lua_Client::AddCrystals(uint32 radiant_count, uint32 ebon_count) {
|
||||
Lua_Safe_Call_Void();
|
||||
|
||||
if (ebon != 0) {
|
||||
if (ebon > 0) {
|
||||
self->AddEbonCrystals(ebon);
|
||||
return;
|
||||
if (ebon_count != 0) {
|
||||
if (ebon_count > 0) {
|
||||
self->AddEbonCrystals(ebon_count);
|
||||
} else {
|
||||
self->RemoveEbonCrystals(ebon_count);
|
||||
}
|
||||
|
||||
self->RemoveEbonCrystals(ebon);
|
||||
}
|
||||
|
||||
if (radiant != 0) {
|
||||
if (radiant > 0) {
|
||||
self->AddRadiantCrystals(radiant);
|
||||
return;
|
||||
if (radiant_count != 0) {
|
||||
if (radiant_count > 0) {
|
||||
self->AddRadiantCrystals(radiant_count);
|
||||
} else {
|
||||
self->RemoveRadiantCrystals(radiant_count);
|
||||
}
|
||||
|
||||
self->RemoveRadiantCrystals(radiant);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1411,9 +1409,9 @@ void Lua_Client::FailTask(int task) {
|
||||
self->FailTask(task);
|
||||
}
|
||||
|
||||
bool Lua_Client::IsTaskCompleted(int task) {
|
||||
bool Lua_Client::IsTaskCompleted(int task_id) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsTaskCompleted(task) != 0;
|
||||
return self->IsTaskCompleted(task_id);
|
||||
}
|
||||
|
||||
bool Lua_Client::IsTaskActive(int task) {
|
||||
@@ -1771,7 +1769,7 @@ int Lua_Client::CalcATK() {
|
||||
return self->CalcATK();
|
||||
}
|
||||
|
||||
void Lua_Client::FilteredMessage(Mob *sender, uint32 type, int filter, const char *message)
|
||||
void Lua_Client::FilteredMessage(Lua_Mob sender, uint32 type, int filter, const char *message)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->FilteredMessage(sender, type, (eqFilterType)filter, message);
|
||||
@@ -3218,6 +3216,12 @@ void Lua_Client::GrantAllAAPoints(uint8 unlock_level)
|
||||
self->GrantAllAAPoints(unlock_level);
|
||||
}
|
||||
|
||||
void Lua_Client::GrantAllAAPoints(uint8 unlock_level, bool skip_grant_only)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->GrantAllAAPoints(unlock_level, skip_grant_only);
|
||||
}
|
||||
|
||||
void Lua_Client::AddEbonCrystals(uint32 amount)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
@@ -3381,6 +3385,57 @@ uint8 Lua_Client::GetSkillTrainLevel(int skill_id)
|
||||
return self->GetSkillTrainLevel(static_cast<EQ::skills::SkillType>(skill_id), self->GetClass());
|
||||
}
|
||||
|
||||
bool Lua_Client::AreTasksCompleted(luabind::object task_ids)
|
||||
{
|
||||
Lua_Safe_Call_Int();
|
||||
|
||||
if (luabind::type(task_ids) != LUA_TTABLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int> v;
|
||||
int index = 1;
|
||||
while (luabind::type(task_ids[index]) != LUA_TNIL) {
|
||||
auto current_id = task_ids[index];
|
||||
int task_id = 0;
|
||||
if (luabind::type(current_id) != LUA_TNIL) {
|
||||
try {
|
||||
task_id = luabind::object_cast<int>(current_id);
|
||||
} catch(luabind::cast_failed &) {
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
v.push_back(task_id);
|
||||
++index;
|
||||
}
|
||||
|
||||
if (v.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self->AreTasksCompleted(v);
|
||||
}
|
||||
|
||||
void Lua_Client::AreaTaunt()
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AETaunt(self);
|
||||
}
|
||||
|
||||
void Lua_Client::AreaTaunt(float range)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AETaunt(self, range);
|
||||
}
|
||||
|
||||
void Lua_Client::AreaTaunt(float range, int bonus_hate)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AETaunt(self, range, bonus_hate);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_client() {
|
||||
return luabind::class_<Lua_Client, Lua_Mob>("Client")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -3427,6 +3482,10 @@ luabind::scope lua_register_client() {
|
||||
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,int,bool))&Lua_Client::ApplySpellRaid)
|
||||
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,int,bool,bool))&Lua_Client::ApplySpellRaid)
|
||||
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,int,bool,bool,bool))&Lua_Client::ApplySpellRaid)
|
||||
.def("AreTasksCompleted", (bool(Lua_Client::*)(luabind::object))&Lua_Client::AreTasksCompleted)
|
||||
.def("AreaTaunt", (void(Lua_Client::*)(void))&Lua_Client::AreaTaunt)
|
||||
.def("AreaTaunt", (void(Lua_Client::*)(float))&Lua_Client::AreaTaunt)
|
||||
.def("AreaTaunt", (void(Lua_Client::*)(float, int))&Lua_Client::AreaTaunt)
|
||||
.def("AssignTask", (void(Lua_Client::*)(int))&Lua_Client::AssignTask)
|
||||
.def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask)
|
||||
.def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask)
|
||||
@@ -3646,6 +3705,7 @@ luabind::scope lua_register_client() {
|
||||
.def("GoFish", (void(Lua_Client::*)(void))&Lua_Client::GoFish)
|
||||
.def("GrantAllAAPoints", (void(Lua_Client::*)(void))&Lua_Client::GrantAllAAPoints)
|
||||
.def("GrantAllAAPoints", (void(Lua_Client::*)(uint8))&Lua_Client::GrantAllAAPoints)
|
||||
.def("GrantAllAAPoints", (void(Lua_Client::*)(uint8,bool))&Lua_Client::GrantAllAAPoints)
|
||||
.def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int))&Lua_Client::GrantAlternateAdvancementAbility)
|
||||
.def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int, bool))&Lua_Client::GrantAlternateAdvancementAbility)
|
||||
.def("GuildID", (uint32(Lua_Client::*)(void))&Lua_Client::GuildID)
|
||||
|
||||
+8
-3
@@ -316,7 +316,7 @@ public:
|
||||
void KeyRingAdd(uint32 item);
|
||||
bool KeyRingCheck(uint32 item);
|
||||
void AddPVPPoints(uint32 points);
|
||||
void AddCrystals(uint32 radiant, uint32 ebon);
|
||||
void AddCrystals(uint32 radiant_count, uint32 ebon_count);
|
||||
void SetEbonCrystals(uint32 value);
|
||||
void SetRadiantCrystals(uint32 value);
|
||||
uint32 GetPVPPoints();
|
||||
@@ -360,7 +360,7 @@ public:
|
||||
void AssignTask(int task_id, int npc_id);
|
||||
void AssignTask(int task_id, int npc_id, bool enforce_level_requirement);
|
||||
void FailTask(int task);
|
||||
bool IsTaskCompleted(int task);
|
||||
bool IsTaskCompleted(int task_id);
|
||||
bool IsTaskActive(int task);
|
||||
bool IsTaskActivityActive(int task, int activity);
|
||||
void LockSharedTask(bool lock);
|
||||
@@ -424,7 +424,7 @@ public:
|
||||
bool IsDead();
|
||||
int CalcCurrentWeight();
|
||||
int CalcATK();
|
||||
void FilteredMessage(Mob *sender, uint32 type, int filter, const char* message);
|
||||
void FilteredMessage(Lua_Mob sender, uint32 type, int filter, const char* message);
|
||||
void EnableAreaHPRegen(int value);
|
||||
void DisableAreaHPRegen();
|
||||
void EnableAreaManaRegen(int value);
|
||||
@@ -487,6 +487,7 @@ public:
|
||||
void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration);
|
||||
void GrantAllAAPoints();
|
||||
void GrantAllAAPoints(uint8 unlock_level);
|
||||
void GrantAllAAPoints(uint8 unlock_level, bool skip_grant_only);
|
||||
void AddEbonCrystals(uint32 amount);
|
||||
void AddRadiantCrystals(uint32 amount);
|
||||
void RemoveEbonCrystals(uint32 amount);
|
||||
@@ -505,6 +506,9 @@ public:
|
||||
void DescribeSpecialAbilities(Lua_NPC n);
|
||||
void ResetLeadershipAA();
|
||||
uint8 GetSkillTrainLevel(int skill_id);
|
||||
void AreaTaunt();
|
||||
void AreaTaunt(float range);
|
||||
void AreaTaunt(float range, int bonus_hate);
|
||||
|
||||
void ApplySpell(int spell_id);
|
||||
void ApplySpell(int spell_id, int duration);
|
||||
@@ -577,6 +581,7 @@ public:
|
||||
void CampAllBots(uint8 class_id);
|
||||
bool RemoveAAPoints(uint32 points);
|
||||
bool RemoveAlternateCurrencyValue(uint32 currency_id, uint32 amount);
|
||||
bool AreTasksCompleted(luabind::object task_ids);
|
||||
|
||||
void DialogueWindow(std::string markdown);
|
||||
|
||||
|
||||
@@ -180,6 +180,96 @@ uint32 Lua_Door::GetID() {
|
||||
return self->GetID();
|
||||
}
|
||||
|
||||
uint8 Lua_Door::GetTriggerDoorID() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetTriggerDoorID();
|
||||
}
|
||||
|
||||
uint8 Lua_Door::GetTriggerType() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetTriggerType();
|
||||
}
|
||||
|
||||
bool Lua_Door::IsLDoNDoor() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsLDoNDoor();
|
||||
}
|
||||
|
||||
uint32 Lua_Door::GetClientVersionMask() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetClientVersionMask();
|
||||
}
|
||||
|
||||
int Lua_Door::GetDoorParam() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetDoorParam();
|
||||
}
|
||||
|
||||
bool Lua_Door::HasDestinationZone() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasDestinationZone();
|
||||
}
|
||||
|
||||
bool Lua_Door::IsDestinationZoneSame() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsDestinationZoneSame();
|
||||
}
|
||||
|
||||
bool Lua_Door::IsDoorBlacklisted() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsDoorBlacklisted();
|
||||
}
|
||||
|
||||
std::string Lua_Door::GetDestinationZoneName() {
|
||||
Lua_Safe_Call_String();
|
||||
return self->GetDestinationZoneName();
|
||||
}
|
||||
|
||||
int Lua_Door::GetDestinationInstanceID() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetDestinationInstanceID();
|
||||
}
|
||||
|
||||
float Lua_Door::GetDestinationX() {
|
||||
Lua_Safe_Call_Real();
|
||||
return self->GetDestinationX();
|
||||
}
|
||||
|
||||
float Lua_Door::GetDestinationY() {
|
||||
Lua_Safe_Call_Real();
|
||||
return self->GetDestinationY();
|
||||
}
|
||||
|
||||
float Lua_Door::GetDestinationZ() {
|
||||
Lua_Safe_Call_Real();
|
||||
return self->GetDestinationZ();
|
||||
}
|
||||
|
||||
float Lua_Door::GetDestinationHeading() {
|
||||
Lua_Safe_Call_Real();
|
||||
return self->GetDestinationHeading();
|
||||
}
|
||||
|
||||
int Lua_Door::GetDzSwitchID() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetDzSwitchID();
|
||||
}
|
||||
|
||||
int Lua_Door::GetInvertState() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetInvertState();
|
||||
}
|
||||
|
||||
void Lua_Door::SetInvertState(int invert_state) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetInvertState(invert_state);
|
||||
}
|
||||
|
||||
uint32 Lua_Door::GetGuildID() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetGuildID();
|
||||
}
|
||||
|
||||
luabind::scope lua_register_door() {
|
||||
return luabind::class_<Lua_Door, Lua_Entity>("Door")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -191,24 +281,42 @@ luabind::scope lua_register_door() {
|
||||
.def("ForceOpen", (void(Lua_Door::*)(Lua_Mob))&Lua_Door::ForceOpen)
|
||||
.def("ForceOpen", (void(Lua_Door::*)(Lua_Mob,bool))&Lua_Door::ForceOpen)
|
||||
.def("GetDisableTimer", (bool(Lua_Door::*)(void))&Lua_Door::GetDisableTimer)
|
||||
.def("GetClientVersionMask", (uint32(Lua_Door::*)(void))&Lua_Door::GetClientVersionMask)
|
||||
.def("GetDestinationHeading", (float(Lua_Door::*)(void))&Lua_Door::GetDestinationHeading)
|
||||
.def("GetDestinationInstanceID", (int(Lua_Door::*)(void))&Lua_Door::GetDestinationInstanceID)
|
||||
.def("GetDestinationX", (float(Lua_Door::*)(void))&Lua_Door::GetDestinationX)
|
||||
.def("GetDestinationY", (float(Lua_Door::*)(void))&Lua_Door::GetDestinationY)
|
||||
.def("GetDestinationZ", (float(Lua_Door::*)(void))&Lua_Door::GetDestinationZ)
|
||||
.def("GetDestinationZoneName", (std::string(Lua_Door::*)(void))&Lua_Door::GetDestinationZoneName)
|
||||
.def("GetDoorDBID", (uint32(Lua_Door::*)(void))&Lua_Door::GetDoorDBID)
|
||||
.def("GetDoorID", (uint32(Lua_Door::*)(void))&Lua_Door::GetDoorID)
|
||||
.def("GetDoorName", (const char*(Lua_Door::*)(void))&Lua_Door::GetDoorName)
|
||||
.def("GetDoorParam", (int(Lua_Door::*)(void))&Lua_Door::GetDoorParam)
|
||||
.def("GetDzSwitchID", (int(Lua_Door::*)(void))&Lua_Door::GetDzSwitchID)
|
||||
.def("GetGuildID", (uint32(Lua_Door::*)(void))&Lua_Door::GetGuildID)
|
||||
.def("GetHeading", (float(Lua_Door::*)(void))&Lua_Door::GetHeading)
|
||||
.def("GetID", (uint32(Lua_Door::*)(void))&Lua_Door::GetID)
|
||||
.def("GetIncline", (uint32(Lua_Door::*)(void))&Lua_Door::GetIncline)
|
||||
.def("GetInvertState", (int(Lua_Door::*)(void))&Lua_Door::GetInvertState)
|
||||
.def("GetKeyItem", (uint32(Lua_Door::*)(void))&Lua_Door::GetKeyItem)
|
||||
.def("GetLockPick", (uint32(Lua_Door::*)(void))&Lua_Door::GetLockPick)
|
||||
.def("GetNoKeyring", (int(Lua_Door::*)(void))&Lua_Door::GetNoKeyring)
|
||||
.def("GetOpenType", (uint32(Lua_Door::*)(void))&Lua_Door::GetOpenType)
|
||||
.def("GetSize", (uint32(Lua_Door::*)(void))&Lua_Door::GetSize)
|
||||
.def("GetTriggerDoorID", (uint8(Lua_Door::*)(void))&Lua_Door::GetTriggerDoorID)
|
||||
.def("GetTriggerType", (uint8(Lua_Door::*)(void))&Lua_Door::GetTriggerType)
|
||||
.def("GetX", (float(Lua_Door::*)(void))&Lua_Door::GetX)
|
||||
.def("GetY", (float(Lua_Door::*)(void))&Lua_Door::GetY)
|
||||
.def("GetZ", (float(Lua_Door::*)(void))&Lua_Door::GetZ)
|
||||
.def("HasDestinationZone", (bool(Lua_Door::*)(void))&Lua_Door::HasDestinationZone)
|
||||
.def("IsDestinationZoneSame", (bool(Lua_Door::*)(void))&Lua_Door::IsDestinationZoneSame)
|
||||
.def("IsDoorBlacklisted", (bool(Lua_Door::*)(void))&Lua_Door::IsDoorBlacklisted)
|
||||
.def("IsLDoNDoor", (bool(Lua_Door::*)(void))&Lua_Door::IsLDoNDoor)
|
||||
.def("SetDisableTimer", (void(Lua_Door::*)(bool))&Lua_Door::SetDisableTimer)
|
||||
.def("SetDoorName", (void(Lua_Door::*)(const char*))&Lua_Door::SetDoorName)
|
||||
.def("SetHeading", (void(Lua_Door::*)(float))&Lua_Door::SetHeading)
|
||||
.def("SetIncline", (void(Lua_Door::*)(uint32))&Lua_Door::SetIncline)
|
||||
.def("SetInvertState", (void(Lua_Door::*)(int))&Lua_Door::SetInvertState)
|
||||
.def("SetKeyItem", (void(Lua_Door::*)(uint32))&Lua_Door::SetKeyItem)
|
||||
.def("SetLocation", (void(Lua_Door::*)(float,float,float))&Lua_Door::SetLocation)
|
||||
.def("SetLockPick", (void(Lua_Door::*)(uint32))&Lua_Door::SetLockPick)
|
||||
|
||||
@@ -63,6 +63,24 @@ public:
|
||||
void ForceClose(Lua_Mob sender);
|
||||
void ForceClose(Lua_Mob sender, bool alt_mode);
|
||||
uint32 GetID();
|
||||
uint8 GetTriggerDoorID();
|
||||
uint8 GetTriggerType();
|
||||
bool IsLDoNDoor();
|
||||
uint32 GetClientVersionMask();
|
||||
int GetDoorParam();
|
||||
bool HasDestinationZone();
|
||||
bool IsDestinationZoneSame();
|
||||
bool IsDoorBlacklisted();
|
||||
std::string GetDestinationZoneName();
|
||||
int GetDestinationInstanceID();
|
||||
float GetDestinationX();
|
||||
float GetDestinationY();
|
||||
float GetDestinationZ();
|
||||
float GetDestinationHeading();
|
||||
int GetDzSwitchID();
|
||||
int GetInvertState();
|
||||
void SetInvertState(int invert_state);
|
||||
uint32 GetGuildID();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -680,11 +680,107 @@ Lua_Mob_List Lua_EntityList::GetCloseMobList(Lua_Mob mob, float distance, bool i
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AEAttack(attacker, distance);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AEAttack(attacker, distance, slot_id);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AEAttack(attacker, distance, slot_id, count);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AEAttack(attacker, distance, slot_id, count, is_from_spell);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AEAttack(attacker, distance, slot_id, count, is_from_spell, attack_rounds);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AESpell(caster, center, spell_id);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AESpell(caster, center, spell_id, affect_caster);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust, &max_targets);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaTaunt(Lua_Client caster)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AETaunt(caster);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaTaunt(Lua_Client caster, float range)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AETaunt(caster, range);
|
||||
}
|
||||
|
||||
void Lua_EntityList::AreaTaunt(Lua_Client caster, float range, int bonus_hate)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->AETaunt(caster, range, bonus_hate);
|
||||
}
|
||||
|
||||
void Lua_EntityList::MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->MassGroupBuff(caster, center, spell_id);
|
||||
}
|
||||
|
||||
void Lua_EntityList::MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
self->MassGroupBuff(caster, center, spell_id, affect_caster);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_entity_list() {
|
||||
return luabind::class_<Lua_EntityList>("EntityList")
|
||||
.def(luabind::constructor<>())
|
||||
.property("null", &Lua_EntityList::Null)
|
||||
.property("valid", &Lua_EntityList::Valid)
|
||||
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float))&Lua_EntityList::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16))&Lua_EntityList::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16, int))&Lua_EntityList::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16, int, bool))&Lua_EntityList::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16, int, bool, int))&Lua_EntityList::AreaAttack)
|
||||
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16))&Lua_EntityList::AreaSpell)
|
||||
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool))&Lua_EntityList::AreaSpell)
|
||||
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool, int16))&Lua_EntityList::AreaSpell)
|
||||
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool, int16, int))&Lua_EntityList::AreaSpell)
|
||||
.def("AreaTaunt", (void(Lua_EntityList::*)(Lua_Client))&Lua_EntityList::AreaTaunt)
|
||||
.def("AreaTaunt", (void(Lua_EntityList::*)(Lua_Client, float))&Lua_EntityList::AreaTaunt)
|
||||
.def("AreaTaunt", (void(Lua_EntityList::*)(Lua_Client, float, int))&Lua_EntityList::AreaTaunt)
|
||||
.def("CanAddHateForMob", (bool(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::CanAddHateForMob)
|
||||
.def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob, int, uint8, const char*))&Lua_EntityList::ChannelMessage)
|
||||
.def("ClearClientPetitionQueue", (void(Lua_EntityList::*)(void))&Lua_EntityList::ClearClientPetitionQueue)
|
||||
@@ -759,6 +855,8 @@ luabind::scope lua_register_entity_list() {
|
||||
.def("Marquee", (void(Lua_EntityList::*)(uint32, std::string))&Lua_EntityList::Marquee)
|
||||
.def("Marquee", (void(Lua_EntityList::*)(uint32, std::string, uint32))&Lua_EntityList::Marquee)
|
||||
.def("Marquee", (void(Lua_EntityList::*)(uint32, uint32, uint32, uint32, uint32, std::string))&Lua_EntityList::Marquee)
|
||||
.def("MassGroupBuff", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16))&Lua_EntityList::MassGroupBuff)
|
||||
.def("MassGroupBuff", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool))&Lua_EntityList::MassGroupBuff)
|
||||
.def("Message", (void(Lua_EntityList::*)(uint32, uint32, const char*))&Lua_EntityList::Message)
|
||||
.def("MessageClose", (void(Lua_EntityList::*)(Lua_Mob, bool, float, uint32, const char*))&Lua_EntityList::MessageClose)
|
||||
.def("MessageGroup", (void(Lua_EntityList::*)(Lua_Mob, bool, uint32, const char*))&Lua_EntityList::MessageGroup)
|
||||
|
||||
@@ -142,6 +142,21 @@ public:
|
||||
Lua_Mob_List GetCloseMobList(Lua_Mob mob);
|
||||
Lua_Mob_List GetCloseMobList(Lua_Mob mob, float distance);
|
||||
Lua_Mob_List GetCloseMobList(Lua_Mob mob, float distance, bool ignore_self);
|
||||
void AreaAttack(Lua_Mob attacker, float distance);
|
||||
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id);
|
||||
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count);
|
||||
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell);
|
||||
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds);
|
||||
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id);
|
||||
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster);
|
||||
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust);
|
||||
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets);
|
||||
void AreaTaunt(Lua_Client caster);
|
||||
void AreaTaunt(Lua_Client caster, float range);
|
||||
void AreaTaunt(Lua_Client caster, float range, int bonus_hate);
|
||||
void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id);
|
||||
void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+36
-4
@@ -5604,6 +5604,37 @@ uint32 lua_get_zone_uptime()
|
||||
return Timer::GetCurrentTime() / 1000;
|
||||
}
|
||||
|
||||
int lua_are_tasks_completed(luabind::object task_ids)
|
||||
{
|
||||
if (luabind::type(task_ids) != LUA_TTABLE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<int> v;
|
||||
int index = 1;
|
||||
while (luabind::type(task_ids[index]) != LUA_TNIL) {
|
||||
auto current_id = task_ids[index];
|
||||
int task_id = 0;
|
||||
if (luabind::type(current_id) != LUA_TNIL) {
|
||||
try {
|
||||
task_id = luabind::object_cast<int>(current_id);
|
||||
} catch(luabind::cast_failed &) {
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
v.push_back(task_id);
|
||||
++index;
|
||||
}
|
||||
|
||||
if (v.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return quest_manager.aretaskscompleted(v);
|
||||
}
|
||||
|
||||
#define LuaCreateNPCParse(name, c_type, default_value) do { \
|
||||
cur = table[#name]; \
|
||||
if(luabind::type(cur) != LUA_TNIL) { \
|
||||
@@ -6410,6 +6441,7 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("get_zone_short_name_by_long_name", &lua_get_zone_short_name_by_long_name),
|
||||
luabind::def("send_parcel", &lua_send_parcel),
|
||||
luabind::def("get_zone_uptime", &lua_get_zone_uptime),
|
||||
luabind::def("are_tasks_completed", &lua_are_tasks_completed),
|
||||
/*
|
||||
Cross Zone
|
||||
*/
|
||||
@@ -7256,10 +7288,10 @@ luabind::scope lua_register_filters() {
|
||||
luabind::value("FocusEffects", FilterFocusEffects),
|
||||
luabind::value("PetSpells", FilterPetSpells),
|
||||
luabind::value("HealOverTime", FilterHealOverTime),
|
||||
luabind::value("Unknown25", FilterUnknown25),
|
||||
luabind::value("Unknown26", FilterUnknown26),
|
||||
luabind::value("Unknown27", FilterUnknown27),
|
||||
luabind::value("Unknown28", FilterUnknown28)
|
||||
luabind::value("ItemSpeech", FilterItemSpeech),
|
||||
luabind::value("Strikethrough", FilterStrikethrough),
|
||||
luabind::value("Stuns", FilterStuns),
|
||||
luabind::value("BardSongsOnPets", FilterBardSongsOnPets)
|
||||
)];
|
||||
}
|
||||
|
||||
|
||||
@@ -3380,6 +3380,72 @@ int Lua_Mob::GetExtraHaste()
|
||||
return self->GetExtraHaste();
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaAttack(float distance)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AEAttack(self, distance);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaAttack(float distance, int16 slot_id)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AEAttack(self, distance, slot_id);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaAttack(float distance, int16 slot_id, int count)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AEAttack(self, distance, slot_id, count);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell, attack_rounds);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AESpell(self, center, spell_id);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AESpell(self, center, spell_id, affect_caster);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust);
|
||||
}
|
||||
|
||||
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust, &max_targets);
|
||||
}
|
||||
|
||||
void Lua_Mob::MassGroupBuff(Lua_Mob center, uint16 spell_id)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.MassGroupBuff(self, center, spell_id);
|
||||
}
|
||||
|
||||
void Lua_Mob::MassGroupBuff(Lua_Mob center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
Lua_Safe_Call_Void();
|
||||
entity_list.MassGroupBuff(self, center, spell_id, affect_caster);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_mob() {
|
||||
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -3393,6 +3459,15 @@ luabind::scope lua_register_mob() {
|
||||
.def("ApplySpellBuff", (void(Lua_Mob::*)(int))&Lua_Mob::ApplySpellBuff)
|
||||
.def("ApplySpellBuff", (void(Lua_Mob::*)(int,int))&Lua_Mob::ApplySpellBuff)
|
||||
.def("ApplySpellBuff", (void(Lua_Mob::*)(int,int,int))&Lua_Mob::ApplySpellBuff)
|
||||
.def("AreaAttack", (void(Lua_Mob::*)(float))&Lua_Mob::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_Mob::*)(float, int16))&Lua_Mob::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_Mob::*)(float, int16, int))&Lua_Mob::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_Mob::*)(float, int16, int, bool))&Lua_Mob::AreaAttack)
|
||||
.def("AreaAttack", (void(Lua_Mob::*)(float, int16, int, bool, int))&Lua_Mob::AreaAttack)
|
||||
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16))&Lua_Mob::AreaSpell)
|
||||
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16, bool))&Lua_Mob::AreaSpell)
|
||||
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16, bool, int16))&Lua_Mob::AreaSpell)
|
||||
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16, bool, int16, int))&Lua_Mob::AreaSpell)
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::Attack)
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int))&Lua_Mob::Attack)
|
||||
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool))&Lua_Mob::Attack)
|
||||
@@ -3808,6 +3883,8 @@ luabind::scope lua_register_mob() {
|
||||
.def("IsWarriorClass", &Lua_Mob::IsWarriorClass)
|
||||
.def("IsWisdomCasterClass", &Lua_Mob::IsWisdomCasterClass)
|
||||
.def("Kill", (void(Lua_Mob::*)(void))&Lua_Mob::Kill)
|
||||
.def("MassGroupBuff", (void(Lua_Mob::*)(Lua_Mob, uint16))&Lua_Mob::MassGroupBuff)
|
||||
.def("MassGroupBuff", (void(Lua_Mob::*)(Lua_Mob, uint16, bool))&Lua_Mob::MassGroupBuff)
|
||||
.def("Mesmerize", (void(Lua_Mob::*)(void))&Lua_Mob::Mesmerize)
|
||||
.def("Message", &Lua_Mob::Message)
|
||||
.def("MessageString", &Lua_Mob::MessageString)
|
||||
|
||||
@@ -594,6 +594,17 @@ public:
|
||||
int GetExtraHaste();
|
||||
void SetExtraHaste(int haste);
|
||||
void SetExtraHaste(int haste, bool need_to_save);
|
||||
void AreaAttack(float distance);
|
||||
void AreaAttack(float distance, int16 slot_id);
|
||||
void AreaAttack(float distance, int16 slot_id, int count);
|
||||
void AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell);
|
||||
void AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds);
|
||||
void AreaSpell(Lua_Mob center, uint16 spell_id);
|
||||
void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster);
|
||||
void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust);
|
||||
void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets);
|
||||
void MassGroupBuff(Lua_Mob center, uint16 spell_id);
|
||||
void MassGroupBuff(Lua_Mob center, uint16 spell_id, bool affect_caster);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+13
-1
@@ -5491,7 +5491,7 @@ int Mob::GetHaste()
|
||||
}
|
||||
}
|
||||
else {
|
||||
h += spellbonuses.hastetype3;
|
||||
h += spellbonuses.hastetype3;
|
||||
}
|
||||
|
||||
h += extra_haste; //GM granted haste.
|
||||
@@ -8611,3 +8611,15 @@ void Mob::SetExtraHaste(int haste, bool need_to_save)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::IsCloseToBanker()
|
||||
{
|
||||
for (auto &e: entity_list.GetCloseMobList(this)) {
|
||||
auto mob = e.second;
|
||||
if (mob && mob->IsNPC() && mob->GetClass() == Class::Banker) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1477,6 +1477,8 @@ public:
|
||||
|
||||
DataBucketKey GetScopedBucketKeys();
|
||||
|
||||
bool IsCloseToBanker();
|
||||
|
||||
protected:
|
||||
void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
|
||||
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
|
||||
|
||||
@@ -2931,25 +2931,6 @@ DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 npc_spells_id)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::GetMaxNPCSpellsID() {
|
||||
|
||||
std::string query = "SELECT max(id) from npc_spells";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
if (!row[0])
|
||||
return 0;
|
||||
|
||||
return Strings::ToInt(row[0]);
|
||||
}
|
||||
|
||||
DBnpcspellseffects_Struct *ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID)
|
||||
{
|
||||
if (iDBSpellsEffectsID == 0)
|
||||
|
||||
+40
-6
@@ -1162,19 +1162,17 @@ void Perl_Client_AddCrystals(Client* self, uint32 radiant_count, uint32 ebon_cou
|
||||
if (ebon_count != 0) {
|
||||
if (ebon_count > 0) {
|
||||
self->AddEbonCrystals(ebon_count);
|
||||
return;
|
||||
} else {
|
||||
self->RemoveEbonCrystals(ebon_count);
|
||||
}
|
||||
|
||||
self->RemoveEbonCrystals(ebon_count);
|
||||
}
|
||||
|
||||
if (radiant_count != 0) {
|
||||
if (radiant_count > 0) {
|
||||
self->AddRadiantCrystals(radiant_count);
|
||||
return;
|
||||
} else {
|
||||
self->RemoveRadiantCrystals(radiant_count);
|
||||
}
|
||||
|
||||
self->RemoveRadiantCrystals(radiant_count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3033,6 +3031,11 @@ void Perl_Client_GrantAllAAPoints(Client* self, uint8 unlock_level)
|
||||
self->GrantAllAAPoints(unlock_level);
|
||||
}
|
||||
|
||||
void Perl_Client_GrantAllAAPoints(Client* self, uint8 unlock_level, bool skip_grant_only)
|
||||
{
|
||||
self->GrantAllAAPoints(unlock_level, skip_grant_only);
|
||||
}
|
||||
|
||||
void Perl_Client_AddEbonCrystals(Client* self, uint32 amount)
|
||||
{
|
||||
self->AddEbonCrystals(amount);
|
||||
@@ -3178,6 +3181,32 @@ uint8 Perl_Client_GetSkillTrainLevel(Client* self, int skill_id)
|
||||
return self->GetSkillTrainLevel(static_cast<EQ::skills::SkillType>(skill_id), self->GetClass());
|
||||
}
|
||||
|
||||
bool Perl_Client_AreTasksCompleted(Client* self, perl::array task_ids)
|
||||
{
|
||||
std::vector<int> v;
|
||||
|
||||
for (const auto& e : task_ids) {
|
||||
v.push_back(static_cast<int>(e));
|
||||
}
|
||||
|
||||
return self->AreTasksCompleted(v);
|
||||
}
|
||||
|
||||
void Perl_Client_AreaTaunt(Client* self)
|
||||
{
|
||||
entity_list.AETaunt(self);
|
||||
}
|
||||
|
||||
void Perl_Client_AreaTaunt(Client* self, float range)
|
||||
{
|
||||
entity_list.AETaunt(self, range);
|
||||
}
|
||||
|
||||
void Perl_Client_AreaTaunt(Client* self, float range, int bonus_hate)
|
||||
{
|
||||
entity_list.AETaunt(self, range, bonus_hate);
|
||||
}
|
||||
|
||||
void perl_register_client()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -3227,6 +3256,10 @@ void perl_register_client()
|
||||
package.add("ApplySpellRaid", (void(*)(Client*, int, int, int, bool))&Perl_Client_ApplySpellRaid);
|
||||
package.add("ApplySpellRaid", (void(*)(Client*, int, int, int, bool, bool))&Perl_Client_ApplySpellRaid);
|
||||
package.add("ApplySpellRaid", (void(*)(Client*, int, int, int, bool, bool, bool))&Perl_Client_ApplySpellRaid);
|
||||
package.add("AreTasksCompleted", (bool(*)(Client*, perl::array))&Perl_Client_AreTasksCompleted);
|
||||
package.add("AreaTaunt", (void(*)(Client*))&Perl_Client_AreaTaunt);
|
||||
package.add("AreaTaunt", (void(*)(Client*, float))&Perl_Client_AreaTaunt);
|
||||
package.add("AreaTaunt", (void(*)(Client*, float, int))&Perl_Client_AreaTaunt);
|
||||
package.add("AssignTask", (void(*)(Client*, int))&Perl_Client_AssignTask);
|
||||
package.add("AssignTask", (void(*)(Client*, int, int))&Perl_Client_AssignTask);
|
||||
package.add("AssignTask", (void(*)(Client*, int, int, bool))&Perl_Client_AssignTask);
|
||||
@@ -3443,6 +3476,7 @@ void perl_register_client()
|
||||
package.add("GoFish", &Perl_Client_GoFish);
|
||||
package.add("GrantAllAAPoints", (void(*)(Client*))&Perl_Client_GrantAllAAPoints);
|
||||
package.add("GrantAllAAPoints", (void(*)(Client*, uint8))&Perl_Client_GrantAllAAPoints);
|
||||
package.add("GrantAllAAPoints", (void(*)(Client*, uint8, bool))&Perl_Client_GrantAllAAPoints);
|
||||
package.add("GrantAlternateAdvancementAbility", (bool(*)(Client*, int, int))&Perl_Client_GrantAlternateAdvancementAbility);
|
||||
package.add("GrantAlternateAdvancementAbility", (bool(*)(Client*, int, int, bool))&Perl_Client_GrantAlternateAdvancementAbility);
|
||||
package.add("GuildID", &Perl_Client_GuildID);
|
||||
|
||||
@@ -179,6 +179,96 @@ void Perl_Doors_SetDisableTimer(Doors* self, bool disable_timer)
|
||||
self->SetDisableTimer(disable_timer);
|
||||
}
|
||||
|
||||
uint8 Perl_Doors_GetTriggerDoorID(Doors* self)
|
||||
{
|
||||
return self->GetTriggerDoorID();
|
||||
}
|
||||
|
||||
uint8 Perl_Doors_GetTriggerType(Doors* self)
|
||||
{
|
||||
return self->GetTriggerType();
|
||||
}
|
||||
|
||||
bool Perl_Doors_IsLDoNDoor(Doors* self)
|
||||
{
|
||||
return self->IsLDoNDoor();
|
||||
}
|
||||
|
||||
uint32 Perl_Doors_GetClientVersionMask(Doors* self)
|
||||
{
|
||||
return self->GetClientVersionMask();
|
||||
}
|
||||
|
||||
int Perl_Doors_GetDoorParam(Doors* self)
|
||||
{
|
||||
return self->GetDoorParam();
|
||||
}
|
||||
|
||||
bool Perl_Doors_HasDestinationZone(Doors* self)
|
||||
{
|
||||
return self->HasDestinationZone();
|
||||
}
|
||||
|
||||
bool Perl_Doors_IsDestinationZoneSame(Doors* self)
|
||||
{
|
||||
return self->IsDestinationZoneSame();
|
||||
}
|
||||
|
||||
bool Perl_Doors_IsDoorBlacklisted(Doors* self)
|
||||
{
|
||||
return self->IsDoorBlacklisted();
|
||||
}
|
||||
|
||||
std::string Perl_Doors_GetDestinationZoneName(Doors* self)
|
||||
{
|
||||
return self->GetDestinationZoneName();
|
||||
}
|
||||
|
||||
int Perl_Doors_GetDestinationInstanceID(Doors* self)
|
||||
{
|
||||
return self->GetDestinationInstanceID();
|
||||
}
|
||||
|
||||
float Perl_Doors_GetDestinationX(Doors* self)
|
||||
{
|
||||
return self->GetDestinationX();
|
||||
}
|
||||
|
||||
float Perl_Doors_GetDestinationY(Doors* self)
|
||||
{
|
||||
return self->GetDestinationY();
|
||||
}
|
||||
|
||||
float Perl_Doors_GetDestinationZ(Doors* self)
|
||||
{
|
||||
return self->GetDestinationZ();
|
||||
}
|
||||
|
||||
float Perl_Doors_GetDestinationHeading(Doors* self)
|
||||
{
|
||||
return self->GetDestinationHeading();
|
||||
}
|
||||
|
||||
int Perl_Doors_GetDzSwitchID(Doors* self)
|
||||
{
|
||||
return self->GetDzSwitchID();
|
||||
}
|
||||
|
||||
int Perl_Doors_GetInvertState(Doors* self)
|
||||
{
|
||||
return self->GetInvertState();
|
||||
}
|
||||
|
||||
void Perl_Doors_SetInvertState(Doors* self, int invert_state)
|
||||
{
|
||||
self->SetInvertState(invert_state);
|
||||
}
|
||||
|
||||
uint32 Perl_Doors_GetGuildID(Doors* self)
|
||||
{
|
||||
return self->GetGuildID();
|
||||
}
|
||||
|
||||
void perl_register_doors()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -189,24 +279,42 @@ void perl_register_doors()
|
||||
package.add("ForceClose", (void(*)(Doors*, Mob*, bool))&Perl_Doors_ForceClose);
|
||||
package.add("ForceOpen", (void(*)(Doors*, Mob*))&Perl_Doors_ForceOpen);
|
||||
package.add("ForceOpen", (void(*)(Doors*, Mob*, bool))&Perl_Doors_ForceOpen);
|
||||
package.add("GetClientVersionMask", &Perl_Doors_GetClientVersionMask);
|
||||
package.add("GetDestinationHeading", &Perl_Doors_GetDestinationHeading);
|
||||
package.add("GetDestinationInstanceID", &Perl_Doors_GetDestinationInstanceID);
|
||||
package.add("GetDestinationX", &Perl_Doors_GetDestinationX);
|
||||
package.add("GetDestinationY", &Perl_Doors_GetDestinationY);
|
||||
package.add("GetDestinationZ", &Perl_Doors_GetDestinationZ);
|
||||
package.add("GetDestinationZoneName", &Perl_Doors_GetDestinationZoneName);
|
||||
package.add("GetDisableTimer", &Perl_Doors_GetDisableTimer);
|
||||
package.add("GetDoorDBID", &Perl_Doors_GetDoorDBID);
|
||||
package.add("GetDoorID", &Perl_Doors_GetDoorID);
|
||||
package.add("GetDoorParam", &Perl_Doors_GetDoorParam);
|
||||
package.add("GetDzSwitchID", &Perl_Doors_GetDzSwitchID);
|
||||
package.add("GetGuildID", &Perl_Doors_GetGuildID);
|
||||
package.add("GetHeading", &Perl_Doors_GetHeading);
|
||||
package.add("GetID", &Perl_Doors_GetID);
|
||||
package.add("GetIncline", &Perl_Doors_GetIncline);
|
||||
package.add("GetInvertState", &Perl_Doors_GetInvertState);
|
||||
package.add("GetKeyItem", &Perl_Doors_GetKeyItem);
|
||||
package.add("GetLockPick", &Perl_Doors_GetLockPick);
|
||||
package.add("GetModelName", &Perl_Doors_GetModelName);
|
||||
package.add("GetNoKeyring", &Perl_Doors_GetNoKeyring);
|
||||
package.add("GetOpenType", &Perl_Doors_GetOpenType);
|
||||
package.add("GetSize", &Perl_Doors_GetSize);
|
||||
package.add("GetTriggerDoorID", &Perl_Doors_GetTriggerDoorID);
|
||||
package.add("GetTriggerType", &Perl_Doors_GetTriggerType);
|
||||
package.add("GetX", &Perl_Doors_GetX);
|
||||
package.add("GetY", &Perl_Doors_GetY);
|
||||
package.add("GetZ", &Perl_Doors_GetZ);
|
||||
package.add("HasDestinationZone", &Perl_Doors_HasDestinationZone);
|
||||
package.add("IsDestinationZoneSame", &Perl_Doors_IsDestinationZoneSame);
|
||||
package.add("IsDoorBlacklisted", &Perl_Doors_IsDoorBlacklisted);
|
||||
package.add("IsLDoNDoor", &Perl_Doors_IsLDoNDoor);
|
||||
package.add("SetDisableTimer", &Perl_Doors_SetDisableTimer);
|
||||
package.add("SetHeading", &Perl_Doors_SetHeading);
|
||||
package.add("SetIncline", &Perl_Doors_SetIncline);
|
||||
package.add("SetInvertState", &Perl_Doors_SetInvertState);
|
||||
package.add("SetKeyItem", &Perl_Doors_SetKeyItem);
|
||||
package.add("SetLocation", &Perl_Doors_SetLocation);
|
||||
package.add("SetLockPick", &Perl_Doors_SetLockPick);
|
||||
|
||||
@@ -669,11 +669,93 @@ perl::array Perl_EntityList_GetSpawnList(EntityList* self) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance)
|
||||
{
|
||||
self->AEAttack(attacker, distance);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id)
|
||||
{
|
||||
self->AEAttack(attacker, distance, slot_id);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id, int count)
|
||||
{
|
||||
self->AEAttack(attacker, distance, slot_id, count);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id, int count, bool is_from_spell)
|
||||
{
|
||||
self->AEAttack(attacker, distance, slot_id, count, is_from_spell);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
|
||||
{
|
||||
self->AEAttack(attacker, distance, slot_id, count, is_from_spell, attack_rounds);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id)
|
||||
{
|
||||
self->AESpell(caster, center, spell_id);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
self->AESpell(caster, center, spell_id, affect_caster);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
|
||||
{
|
||||
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
|
||||
{
|
||||
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust, &max_targets);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaTaunt(EntityList* self, Client* caster)
|
||||
{
|
||||
self->AETaunt(caster);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaTaunt(EntityList* self, Client* caster, float range)
|
||||
{
|
||||
self->AETaunt(caster, range);
|
||||
}
|
||||
|
||||
void Perl_EntityList_AreaTaunt(EntityList* self, Client* caster, float range, int bonus_hate)
|
||||
{
|
||||
self->AETaunt(caster, range, bonus_hate);
|
||||
}
|
||||
|
||||
void Perl_EntityList_MassGroupBuff(EntityList* self, Mob* caster, Mob* center, uint16 spell_id)
|
||||
{
|
||||
self->MassGroupBuff(caster, center, spell_id);
|
||||
}
|
||||
|
||||
void Perl_EntityList_MassGroupBuff(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
self->MassGroupBuff(caster, center, spell_id, affect_caster);
|
||||
}
|
||||
|
||||
void perl_register_entitylist()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
|
||||
auto package = perl.new_class<EntityList>("EntityList");
|
||||
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float))&Perl_EntityList_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16))&Perl_EntityList_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16, int))&Perl_EntityList_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16, int, bool))&Perl_EntityList_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16, int, bool, int))&Perl_EntityList_AreaAttack);
|
||||
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16))&Perl_EntityList_AreaSpell);
|
||||
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16, bool))&Perl_EntityList_AreaSpell);
|
||||
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16, bool, int16))&Perl_EntityList_AreaSpell);
|
||||
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16, bool, int16, int))&Perl_EntityList_AreaSpell);
|
||||
package.add("AreaTaunt", (void(*)(EntityList*, Client*))&Perl_EntityList_AreaTaunt);
|
||||
package.add("AreaTaunt", (void(*)(EntityList*, Client*, float))&Perl_EntityList_AreaTaunt);
|
||||
package.add("AreaTaunt", (void(*)(EntityList*, Client*, float, int))&Perl_EntityList_AreaTaunt);
|
||||
package.add("CanAddHateForMob", &Perl_EntityList_CanAddHateForMob);
|
||||
package.add("Clear", &Perl_EntityList_Clear);
|
||||
package.add("ClearClientPetitionQueue", &Perl_EntityList_ClearClientPetitionQueue);
|
||||
@@ -747,6 +829,8 @@ void perl_register_entitylist()
|
||||
package.add("Marquee", (void(*)(EntityList*, uint32, std::string))&Perl_EntityList_Marquee);
|
||||
package.add("Marquee", (void(*)(EntityList*, uint32, std::string, uint32))&Perl_EntityList_Marquee);
|
||||
package.add("Marquee", (void(*)(EntityList*, uint32, uint32, uint32, uint32, uint32, std::string))&Perl_EntityList_Marquee);
|
||||
package.add("MassGroupBuff", (void(*)(EntityList*, Mob*, Mob*, uint16))&Perl_EntityList_MassGroupBuff);
|
||||
package.add("MassGroupBuff", (void(*)(EntityList*, Mob*, Mob*, uint16, bool))&Perl_EntityList_MassGroupBuff);
|
||||
package.add("Message", &Perl_EntityList_Message);
|
||||
package.add("MessageClose", &Perl_EntityList_MessageClose);
|
||||
package.add("MessageGroup", &Perl_EntityList_MessageGroup);
|
||||
|
||||
@@ -3488,6 +3488,61 @@ std::string Perl_Mob_GetConsiderColor(Mob* self, uint8 other_level)
|
||||
return EQ::constants::GetConsiderColorName(self->GetLevelCon(other_level));
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaAttack(Mob* self, float distance)
|
||||
{
|
||||
entity_list.AEAttack(self, distance);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id)
|
||||
{
|
||||
entity_list.AEAttack(self, distance, slot_id);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id, int count)
|
||||
{
|
||||
entity_list.AEAttack(self, distance, slot_id, count);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id, int count, bool is_from_spell)
|
||||
{
|
||||
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
|
||||
{
|
||||
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell, attack_rounds);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id)
|
||||
{
|
||||
entity_list.AESpell(self, center, spell_id, true, 0, nullptr, true);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
entity_list.AESpell(self, center, spell_id, affect_caster, 0, nullptr, true);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
|
||||
{
|
||||
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust, nullptr, true);
|
||||
}
|
||||
|
||||
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
|
||||
{
|
||||
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust, &max_targets, true);
|
||||
}
|
||||
|
||||
void Perl_Mob_MassGroupBuff(Mob* self, Mob* center, uint16 spell_id)
|
||||
{
|
||||
entity_list.MassGroupBuff(self, center, spell_id);
|
||||
}
|
||||
|
||||
void Perl_Mob_MassGroupBuff(Mob* self, Mob* center, uint16 spell_id, bool affect_caster)
|
||||
{
|
||||
entity_list.MassGroupBuff(self, center, spell_id, affect_caster);
|
||||
}
|
||||
|
||||
void perl_register_mob()
|
||||
{
|
||||
perl::interpreter perl(PERL_GET_THX);
|
||||
@@ -3504,6 +3559,15 @@ void perl_register_mob()
|
||||
package.add("ApplySpellBuff", (void(*)(Mob*, int))&Perl_Mob_ApplySpellBuff);
|
||||
package.add("ApplySpellBuff", (void(*)(Mob*, int, int))&Perl_Mob_ApplySpellBuff);
|
||||
package.add("ApplySpellBuff", (void(*)(Mob*, int, int, int))&Perl_Mob_ApplySpellBuff);
|
||||
package.add("AreaAttack", (void(*)(Mob*, float))&Perl_Mob_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(Mob*, float, int16))&Perl_Mob_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(Mob*, float, int16, int))&Perl_Mob_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(Mob*, float, int16, int, bool))&Perl_Mob_AreaAttack);
|
||||
package.add("AreaAttack", (void(*)(Mob*, float, int16, int, bool, int))&Perl_Mob_AreaAttack);
|
||||
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16))&Perl_Mob_AreaSpell);
|
||||
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16, bool))&Perl_Mob_AreaSpell);
|
||||
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16, bool, int16))&Perl_Mob_AreaSpell);
|
||||
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16, bool, int16, int))&Perl_Mob_AreaSpell);
|
||||
package.add("Attack", (bool(*)(Mob*, Mob*))&Perl_Mob_Attack);
|
||||
package.add("Attack", (bool(*)(Mob*, Mob*, int))&Perl_Mob_Attack);
|
||||
package.add("Attack", (bool(*)(Mob*, Mob*, int, bool))&Perl_Mob_Attack);
|
||||
@@ -3928,6 +3992,8 @@ void perl_register_mob()
|
||||
package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32))&Perl_Mob_MakeTempPet);
|
||||
package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32, Mob*))&Perl_Mob_MakeTempPet);
|
||||
package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32, Mob*, bool))&Perl_Mob_MakeTempPet);
|
||||
package.add("MassGroupBuff", (void(*)(Mob*, Mob*, uint16))&Perl_Mob_MassGroupBuff);
|
||||
package.add("MassGroupBuff", (void(*)(Mob*, Mob*, uint16, bool))&Perl_Mob_MassGroupBuff);
|
||||
package.add("Mesmerize", &Perl_Mob_Mesmerize);
|
||||
package.add("Message", &Perl_Mob_Message);
|
||||
package.add("Message_StringID", (void(*)(Mob*, uint32, uint32))&Perl_Mob_Message_StringID);
|
||||
|
||||
+17
-4
@@ -3251,13 +3251,26 @@ int QuestManager::activespeakactivity(int taskid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QuestManager::istaskcompleted(int taskid) {
|
||||
bool QuestManager::istaskcompleted(int task_id)
|
||||
{
|
||||
QuestManagerCurrentQuestVars();
|
||||
|
||||
if(RuleB(TaskSystem, EnableTaskSystem) && initiator)
|
||||
return initiator->IsTaskCompleted(taskid);
|
||||
if (initiator && RuleB(TaskSystem, EnableTaskSystem)) {
|
||||
return initiator->IsTaskCompleted(task_id);
|
||||
}
|
||||
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestManager::aretaskscompleted(const std::vector<int>& task_ids)
|
||||
{
|
||||
QuestManagerCurrentQuestVars();
|
||||
|
||||
if (initiator && RuleB(TaskSystem, EnableTaskSystem)) {
|
||||
return initiator->AreTasksCompleted(task_ids);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int QuestManager::activetasksinset(int taskset) {
|
||||
|
||||
+2
-1
@@ -225,7 +225,8 @@ public:
|
||||
void assigntask(int taskid, bool enforce_level_requirement = false);
|
||||
void failtask(int taskid);
|
||||
int tasktimeleft(int taskid);
|
||||
int istaskcompleted(int taskid);
|
||||
bool istaskcompleted(int task_id);
|
||||
bool aretaskscompleted(const std::vector<int>& task_ids);
|
||||
int enabledtaskcount(int taskset);
|
||||
int firsttaskinset(int taskset);
|
||||
int lasttaskinset(int taskset);
|
||||
|
||||
@@ -2202,10 +2202,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Sacrifice");
|
||||
#endif
|
||||
if(!caster || !IsClient() || !caster->IsClient()){
|
||||
if(!caster || !IsClient() ){
|
||||
break;
|
||||
}
|
||||
CastToClient()->SacrificeConfirm(caster->CastToClient());
|
||||
CastToClient()->SacrificeConfirm(caster);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2318,8 +2318,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
else if (spells[spell_id].max_value[i]) {
|
||||
if (spells[spell_id].max_value[i] >= 1000) {
|
||||
max_level = 1000 - spells[spell_id].max_value[i];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
max_level = GetLevel() + spells[spell_id].max_value[i];
|
||||
}
|
||||
}
|
||||
@@ -2329,6 +2328,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
if (IsClient()) {
|
||||
int pre_aggro_count = CastToClient()->GetAggroCount();
|
||||
entity_list.RemoveFromTargetsFadingMemories(this, true, max_level);
|
||||
entity_list.ClearZoneFeignAggro(this);
|
||||
|
||||
if (spellbonuses.ShroudofStealth || aabonuses.ShroudofStealth || itembonuses.ShroudofStealth) {
|
||||
improved_hidden = true;
|
||||
@@ -2341,15 +2341,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
if (pre_aggro_count == post_aggro_count) {
|
||||
Message(Chat::SpellFailure, "You failed to escape from all your opponents.");
|
||||
break;
|
||||
}
|
||||
else if (post_aggro_count) {
|
||||
} else if (post_aggro_count) {
|
||||
Message(Chat::SpellFailure, "You failed to escape from combat but you evade some of your opponents.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
MessageString(Chat::Skills, ESCAPE);
|
||||
}
|
||||
else{
|
||||
} else{
|
||||
entity_list.RemoveFromTargets(caster);
|
||||
SetInvisible(Invisibility::Invisible);
|
||||
}
|
||||
|
||||
+14
-58
@@ -78,6 +78,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "../common/repositories/character_corpses_repository.h"
|
||||
#include "../common/repositories/spell_buckets_repository.h"
|
||||
|
||||
#include "data_bucket.h"
|
||||
#include "quest_parser_collection.h"
|
||||
@@ -885,13 +886,13 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
|
||||
*/
|
||||
if (!ignore_on_casting) {
|
||||
if (spells[spell_id].pcnpc_only_flag && spells[spell_id].target_type != ST_AETargetHateList && spells[spell_id].target_type != ST_HateList) {
|
||||
if (spells[spell_id].pcnpc_only_flag == 1 && !spell_target->IsClient() && !spell_target->IsMerc() && !spell_target->IsBot()) {
|
||||
if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::PC && !spell_target->IsClient() && !spell_target->IsMerc() && !spell_target->IsBot()) {
|
||||
if (check_on_casting) {
|
||||
Message(Chat::SpellFailure, "This spell only works on other PCs");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (spells[spell_id].pcnpc_only_flag == 2 && (spell_target->IsClient() || spell_target->IsMerc() || spell_target->IsBot())) {
|
||||
else if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::NPC && (spell_target->IsClient() || spell_target->IsMerc() || spell_target->IsBot())) {
|
||||
if (check_on_casting) {
|
||||
Message(Chat::SpellFailure, "This spell only works on NPCs.");
|
||||
}
|
||||
@@ -3946,12 +3947,12 @@ bool Mob::SpellOnTarget(
|
||||
spells[spell_id].target_type != ST_HateList
|
||||
) {
|
||||
if (
|
||||
spells[spell_id].pcnpc_only_flag == 1 &&
|
||||
spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::PC &&
|
||||
!spelltar->IsOfClientBotMerc()
|
||||
) {
|
||||
return false;
|
||||
} else if (
|
||||
spells[spell_id].pcnpc_only_flag == 2 &&
|
||||
spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::NPC &&
|
||||
(
|
||||
spelltar->IsOfClientBotMerc()
|
||||
)
|
||||
@@ -6239,65 +6240,20 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 character_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) {
|
||||
auto query = fmt::format(
|
||||
"SELECT `key`, value FROM spell_buckets WHERE spellid = {}",
|
||||
spell_id
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false; // Query failed, do not allow scribing.
|
||||
bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id)
|
||||
{
|
||||
const auto& e = SpellBucketsRepository::FindOne(database, spell_id);
|
||||
if (!e.spell_id || e.bucket_name.empty() || e.bucket_value.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!results.RowCount()) {
|
||||
return true; // Spell ID isn't listed in the spell_buckets table, allow scribing.
|
||||
}
|
||||
auto k = GetScopedBucketKeys();
|
||||
|
||||
auto row = results.begin();
|
||||
std::string spell_bucket_name = row[0];
|
||||
std::string spell_bucket_value = row[1];
|
||||
k.key = e.bucket_name;
|
||||
|
||||
if (spell_bucket_name.empty()) {
|
||||
return true; // If the entry in the spell_buckets table has nothing set for the qglobal name, allow scribing.
|
||||
}
|
||||
const auto& b = DataBucket::GetData(k);
|
||||
|
||||
DataBucketKey k = GetScopedBucketKeys();
|
||||
k.key = spell_bucket_name;
|
||||
|
||||
auto b = DataBucket::GetData(k);
|
||||
if (!b.value.empty()) {
|
||||
if (Strings::IsNumber(b.value) && Strings::IsNumber(spell_bucket_value)) {
|
||||
if (Strings::ToInt(b.value) >= Strings::ToInt(spell_bucket_value)) {
|
||||
return true; // If value is greater than or equal to spell bucket value, allow scribing.
|
||||
}
|
||||
} else {
|
||||
if (b.value == spell_bucket_value) {
|
||||
return true; // If value is equal to spell bucket value, allow scribing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto old_bucket_name = fmt::format(
|
||||
"{}-{}",
|
||||
character_id,
|
||||
spell_bucket_name
|
||||
);
|
||||
|
||||
std::string bucket_value = DataBucket::GetData(old_bucket_name);
|
||||
if (!bucket_value.empty()) {
|
||||
if (Strings::IsNumber(bucket_value) && Strings::IsNumber(spell_bucket_value)) {
|
||||
if (Strings::ToInt(bucket_value) >= Strings::ToInt(spell_bucket_value)) {
|
||||
return true; // If value is greater than or equal to spell bucket value, allow scribing.
|
||||
}
|
||||
} else {
|
||||
if (bucket_value == spell_bucket_value) {
|
||||
return true; // If value is equal to spell bucket value, allow scribing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return zone->CompareDataBucket(e.bucket_comparison, e.bucket_value, b.value);
|
||||
}
|
||||
|
||||
// TODO get rid of this
|
||||
|
||||
+29
-14
@@ -869,7 +869,12 @@ int ClientTaskState::IncrementDoneCount(
|
||||
if (task_data->type != TaskType::Shared) {
|
||||
// live messages for each increment of non-shared tasks
|
||||
auto activity_type = task_data->activity_information[activity_id].activity_type;
|
||||
int msg_count = activity_type == TaskActivityType::GiveCash ? 1 : count;
|
||||
int msg_count = 1;
|
||||
|
||||
if (activity_type != TaskActivityType::GiveCash) {
|
||||
msg_count = std::min(count, RuleI(TaskSystem, MaxUpdateMessages));
|
||||
}
|
||||
|
||||
for (int i = 0; i < msg_count; ++i) {
|
||||
client->MessageString(Chat::DefaultText, TASK_UPDATED, task_data->title.c_str());
|
||||
}
|
||||
@@ -1578,25 +1583,35 @@ int ClientTaskState::TaskTimeLeft(int task_id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ClientTaskState::IsTaskCompleted(int task_id)
|
||||
bool ClientTaskState::IsTaskCompleted(int task_id)
|
||||
{
|
||||
|
||||
// Returns: -1 if RecordCompletedTasks is not true
|
||||
// +1 if the task has been completed
|
||||
// 0 if the task has not been completed
|
||||
|
||||
if (!(RuleB(TaskSystem, RecordCompletedTasks))) {
|
||||
return -1;
|
||||
if (!RuleB(TaskSystem, RecordCompletedTasks)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto &completed_task : m_completed_tasks) {
|
||||
LogTasks("Comparing completed task [{}] with [{}]", completed_task.task_id, task_id);
|
||||
if (completed_task.task_id == task_id) {
|
||||
return 1;
|
||||
for (const auto& e : m_completed_tasks) {
|
||||
LogTasks("Comparing completed task [{}] with [{}]", e.task_id, task_id);
|
||||
if (e.task_id == task_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientTaskState::AreTasksCompleted(const std::vector<int>& task_ids)
|
||||
{
|
||||
if (!RuleB(TaskSystem, RecordCompletedTasks)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& e : task_ids) {
|
||||
if (!IsTaskCompleted(e)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientTaskState::TaskOutOfTime(TaskType task_type, int index)
|
||||
|
||||
@@ -45,7 +45,8 @@ public:
|
||||
void AcceptNewTask(Client *client, int task_id, int npc_type_id, time_t accept_time, bool enforce_level_requirement = false);
|
||||
void FailTask(Client *client, int task_id);
|
||||
int TaskTimeLeft(int task_id);
|
||||
int IsTaskCompleted(int task_id);
|
||||
bool IsTaskCompleted(int task_id);
|
||||
bool AreTasksCompleted(const std::vector<int>& task_ids);
|
||||
bool IsTaskActive(int task_id);
|
||||
bool IsTaskActivityActive(int task_id, int activity_id);
|
||||
ActivityState GetTaskActivityState(TaskType task_type, int index, int activity_id);
|
||||
|
||||
@@ -625,6 +625,41 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac
|
||||
return;
|
||||
}
|
||||
|
||||
if (spec.tradeskill == EQ::skills::SkillAlchemy) {
|
||||
if (!user->GetClass() == Class::Shaman) {
|
||||
user->Message(Chat::Red, "This tradeskill can only be performed by a shaman.");
|
||||
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
|
||||
user->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
else if (user->GetLevel() < MIN_LEVEL_ALCHEMY) {
|
||||
user->Message(Chat::Red, "You cannot perform alchemy until you reach level %i.", MIN_LEVEL_ALCHEMY);
|
||||
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
|
||||
user->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (spec.tradeskill == EQ::skills::SkillTinkering) {
|
||||
if (user->GetRace() != GNOME) {
|
||||
user->Message(Chat::Red, "Only gnomes can tinker.");
|
||||
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
|
||||
user->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (spec.tradeskill == EQ::skills::SkillMakePoison) {
|
||||
if (!user->GetClass() == Class::Rogue) {
|
||||
user->Message(Chat::Red, "Only rogues can mix poisons.");
|
||||
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
|
||||
user->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//pull the list of components
|
||||
const auto query = fmt::format("SELECT item_id, componentcount "
|
||||
"FROM tradeskill_recipe_entries "
|
||||
|
||||
+1
-1
@@ -3495,7 +3495,7 @@ void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicati
|
||||
ps.item_slot = parcel_out.slot_id;
|
||||
strn0cpy(ps.send_to, GetCleanName(), sizeof(ps.send_to));
|
||||
|
||||
if (trader_item.item_charges == tbs->quantity) {
|
||||
if (trader_item.item_charges <= static_cast<int32>(tbs->quantity)) {
|
||||
TraderRepository::DeleteOne(database, trader_item.id);
|
||||
} else {
|
||||
TraderRepository::UpdateQuantity(
|
||||
|
||||
+5
-5
@@ -340,7 +340,7 @@ bool ZoneDatabase::LoadTributes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
for (auto &row = results.begin(); row != results.end(); ++row) {
|
||||
uint32 id = Strings::ToUnsignedInt(row[0]);
|
||||
tributeData.name = row[1];
|
||||
tributeData.description = row[2];
|
||||
@@ -358,7 +358,7 @@ bool ZoneDatabase::LoadTributes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
for (auto &row = results.begin(); row != results.end(); ++row) {
|
||||
uint32 id = Strings::ToUnsignedInt(row[0]);
|
||||
|
||||
if (tribute_list.count(id) != 1) {
|
||||
@@ -635,11 +635,11 @@ uint32 Client::LookupTributeItemID(uint32 tribute_id, uint32 tier)
|
||||
if (tribute_list.contains(tribute_id)) {
|
||||
auto tribute = tribute_list.find(tribute_id);
|
||||
auto item_id = tribute->second.tiers[tier].tribute_item_id;
|
||||
if (!item_id) {
|
||||
return 0;
|
||||
if (item_id) {
|
||||
return item_id;
|
||||
}
|
||||
return item_id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+19
-9
@@ -671,12 +671,16 @@ bool ZoneDatabase::LoadCharacterLeadershipAbilities(uint32 character_id, PlayerP
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){
|
||||
bool ZoneDatabase::LoadCharacterDisciplines(Client* c)
|
||||
{
|
||||
if (!c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& l = CharacterDisciplinesRepository::GetWhere(
|
||||
database, fmt::format(
|
||||
"`id` = {} ORDER BY `slot_id`",
|
||||
character_id
|
||||
c->CharacterID()
|
||||
)
|
||||
);
|
||||
|
||||
@@ -684,16 +688,18 @@ bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_S
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int slot_id = 0; slot_id < MAX_PP_DISCIPLINES; slot_id++) { // Initialize Disciplines
|
||||
pp->disciplines.values[slot_id] = 0;
|
||||
for (int slot_id = 0; slot_id < MAX_PP_DISCIPLINES; slot_id++) {
|
||||
c->GetPP().disciplines.values[slot_id] = 0;
|
||||
}
|
||||
|
||||
for (const auto& e : l) {
|
||||
if (IsValidSpell(e.disc_id) && e.slot_id < MAX_PP_DISCIPLINES) {
|
||||
pp->disciplines.values[e.slot_id] = e.disc_id;
|
||||
c->GetPP().disciplines.values[e.slot_id] = e.disc_id;
|
||||
}
|
||||
}
|
||||
|
||||
c->SendDisciplineUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1327,7 +1333,8 @@ bool ZoneDatabase::SaveCharacterInvSnapshot(uint32 character_id) {
|
||||
" `custom_data`,"
|
||||
" `ornamenticon`,"
|
||||
" `ornamentidfile`,"
|
||||
" `ornament_hero_model`"
|
||||
" `ornament_hero_model`,"
|
||||
" `guid`"
|
||||
") "
|
||||
"SELECT"
|
||||
" %u,"
|
||||
@@ -1346,7 +1353,8 @@ bool ZoneDatabase::SaveCharacterInvSnapshot(uint32 character_id) {
|
||||
" `custom_data`,"
|
||||
" `ornamenticon`,"
|
||||
" `ornamentidfile`,"
|
||||
" `ornament_hero_model` "
|
||||
" `ornament_hero_model`,"
|
||||
" `guid` "
|
||||
"FROM"
|
||||
" `inventory` "
|
||||
"WHERE"
|
||||
@@ -1607,7 +1615,8 @@ bool ZoneDatabase::RestoreCharacterInvSnapshot(uint32 character_id, uint32 times
|
||||
" `custom_data`,"
|
||||
" `ornamenticon`,"
|
||||
" `ornamentidfile`,"
|
||||
" `ornament_hero_model`"
|
||||
" `ornament_hero_model`,"
|
||||
" `guid`"
|
||||
") "
|
||||
"SELECT"
|
||||
" `charid`,"
|
||||
@@ -1625,7 +1634,8 @@ bool ZoneDatabase::RestoreCharacterInvSnapshot(uint32 character_id, uint32 times
|
||||
" `custom_data`,"
|
||||
" `ornamenticon`,"
|
||||
" `ornamentidfile`,"
|
||||
" `ornament_hero_model` "
|
||||
" `ornament_hero_model`, "
|
||||
" `guid` "
|
||||
"FROM"
|
||||
" `inventory_snapshots` "
|
||||
"WHERE"
|
||||
|
||||
+1
-4
@@ -436,7 +436,7 @@ public:
|
||||
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterDisciplines(Client* c);
|
||||
bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
|
||||
bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterLeadershipAbilities(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
@@ -561,9 +561,6 @@ public:
|
||||
bool GetPoweredPetEntry(const std::string& pet_type, int16 pet_power, PetRecord* r);
|
||||
bool GetBasePetItems(int32 equipmentset, uint32 *items);
|
||||
BeastlordPetData::PetStruct GetBeastlordPetData(uint16 race_id);
|
||||
void AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat);
|
||||
void AddLootDropToNPC(NPC* npc, uint32 lootdrop_id, ItemList* item_list, uint8 droplimit, uint8 mindrop);
|
||||
uint32 GetMaxNPCSpellsID();
|
||||
uint32 GetMaxNPCSpellsEffectsID();
|
||||
bool GetAuraEntry(uint16 spell_id, AuraRecord &record);
|
||||
void LoadGlobalLoot();
|
||||
|
||||
Reference in New Issue
Block a user