mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fcb0a47280 | |||
| 1e50f19f7e | |||
| 33bb5aa8e5 | |||
| 6a668f8aa5 | |||
| df499b22ab | |||
| 7bc00cb466 | |||
| 51f6108aab | |||
| c13f9f80d9 | |||
| 443abf9199 | |||
| 1556e05b2f | |||
| 1d645aa5f6 | |||
| 9f42da5bad | |||
| 4a8222f243 | |||
| db4c515853 | |||
| 462656a201 | |||
| ddd98be383 |
@@ -1,3 +1,50 @@
|
|||||||
|
## [22.4.3] - 02/21/2023
|
||||||
|
|
||||||
|
### Bots
|
||||||
|
|
||||||
|
* Change HasBotItem(item_id) to return slot_id instead of bool. ([#2966](https://github.com/EQEmu/Server/pull/2966)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-19
|
||||||
|
* Change SaveTimers to Replace instead of Insert. ([#2951](https://github.com/EQEmu/Server/pull/2951)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-18
|
||||||
|
* Fix output of ^spells while ^Enforcespellsettings is enabled ([#2959](https://github.com/EQEmu/Server/pull/2959)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-18
|
||||||
|
|
||||||
|
### Crash
|
||||||
|
|
||||||
|
* Fix crash with EVENT_UNEQUIP_ITEM_BOT ([#2973](https://github.com/EQEmu/Server/pull/2973)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-20
|
||||||
|
* Fix world crash in player event processing ([#2960](https://github.com/EQEmu/Server/pull/2960)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
|
* Address deadlock in player events ([#2974](https://github.com/EQEmu/Server/pull/2974)) ([Akkadius](https://github.com/Akkadius)) 2023-02-21
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fix MIR LDoN Theme Items on LDoN Merchants ([#2971](https://github.com/EQEmu/Server/pull/2971)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-20
|
||||||
|
* Fix OOCMute not functioning ([#2970](https://github.com/EQEmu/Server/pull/2970)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-20
|
||||||
|
|
||||||
|
### Pathing
|
||||||
|
|
||||||
|
* Improvements to z-clipping, z-recovery and z-calculations ([#2975](https://github.com/EQEmu/Server/pull/2975)) ([Akkadius](https://github.com/Akkadius)) 2023-02-21
|
||||||
|
|
||||||
|
### Pets
|
||||||
|
|
||||||
|
* Client Pet summoned by NPC should not change guard location. ([#2967](https://github.com/EQEmu/Server/pull/2967)) ([noudess](https://github.com/noudess)) 2023-02-19
|
||||||
|
|
||||||
|
### Player Events
|
||||||
|
|
||||||
|
* Create new event ITEM_CREATION ([#2944](https://github.com/EQEmu/Server/pull/2944)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add client->SignalClient() overload to Perl ([#2963](https://github.com/EQEmu/Server/pull/2963)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-19
|
||||||
|
* Fix Perl SetSimpleRoamBox Overloads ([#2961](https://github.com/EQEmu/Server/pull/2961)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-19
|
||||||
|
|
||||||
|
### Reload API
|
||||||
|
|
||||||
|
* Add world handlers for certain opcodes ([#2958](https://github.com/EQEmu/Server/pull/2958)) ([Akkadius](https://github.com/Akkadius)) 2023-02-18
|
||||||
|
|
||||||
|
### SQL
|
||||||
|
|
||||||
|
* Add date to optional Drakkin Guktan Faction Update ([#2965](https://github.com/EQEmu/Server/pull/2965)) ([joligario](https://github.com/joligario)) 2023-02-19
|
||||||
|
|
||||||
## [22.4.2] - 02/18/2023
|
## [22.4.2] - 02/18/2023
|
||||||
|
|
||||||
### Content
|
### Content
|
||||||
|
|||||||
+15
-7
@@ -70,17 +70,20 @@ DBcore::~DBcore()
|
|||||||
// Sends the MySQL server a keepalive
|
// Sends the MySQL server a keepalive
|
||||||
void DBcore::ping()
|
void DBcore::ping()
|
||||||
{
|
{
|
||||||
if (!MDatabase.trylock()) {
|
if (!m_query_lock.try_lock()) {
|
||||||
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
|
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mysql_ping(&mysql);
|
mysql_ping(&mysql);
|
||||||
MDatabase.unlock();
|
m_query_lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce)
|
MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce)
|
||||||
{
|
{
|
||||||
return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
m_query_lock.lock();
|
||||||
|
auto r = QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
|
||||||
|
m_query_lock.unlock();
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DBcore::DoesTableExist(std::string table_name)
|
bool DBcore::DoesTableExist(std::string table_name)
|
||||||
@@ -95,15 +98,11 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
|
|||||||
BenchTimer timer;
|
BenchTimer timer;
|
||||||
timer.reset();
|
timer.reset();
|
||||||
|
|
||||||
LockMutex lock(&MDatabase);
|
|
||||||
|
|
||||||
// Reconnect if we are not connected before hand.
|
// Reconnect if we are not connected before hand.
|
||||||
if (pStatus != Connected) {
|
if (pStatus != Connected) {
|
||||||
Open();
|
Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// request query. != 0 indicates some kind of error.
|
// request query. != 0 indicates some kind of error.
|
||||||
if (mysql_real_query(&mysql, query, querylen) != 0) {
|
if (mysql_real_query(&mysql, query, querylen) != 0) {
|
||||||
unsigned int errorNumber = mysql_errno(&mysql);
|
unsigned int errorNumber = mysql_errno(&mysql);
|
||||||
@@ -299,3 +298,12 @@ void DBcore::SetOriginHost(const std::string &origin_host)
|
|||||||
{
|
{
|
||||||
DBcore::origin_host = origin_host;
|
DBcore::origin_host = origin_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DBcore::Escape(const std::string& s)
|
||||||
|
{
|
||||||
|
const std::size_t s_len = s.length();
|
||||||
|
std::vector<char> temp((s_len * 2) + 1, '\0');
|
||||||
|
mysql_real_escape_string(&mysql, temp.data(), s.c_str(), s_len);
|
||||||
|
|
||||||
|
return temp.data();
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class DBcore {
|
class DBcore {
|
||||||
public:
|
public:
|
||||||
@@ -27,6 +28,7 @@ public:
|
|||||||
void TransactionBegin();
|
void TransactionBegin();
|
||||||
void TransactionCommit();
|
void TransactionCommit();
|
||||||
void TransactionRollback();
|
void TransactionRollback();
|
||||||
|
std::string Escape(const std::string& s);
|
||||||
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
|
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
|
||||||
void ping();
|
void ping();
|
||||||
MYSQL *getMySQL() { return &mysql; }
|
MYSQL *getMySQL() { return &mysql; }
|
||||||
@@ -57,6 +59,8 @@ private:
|
|||||||
Mutex MDatabase;
|
Mutex MDatabase;
|
||||||
eStatus pStatus;
|
eStatus pStatus;
|
||||||
|
|
||||||
|
std::mutex m_query_lock{};
|
||||||
|
|
||||||
std::string origin_host;
|
std::string origin_host;
|
||||||
|
|
||||||
char *pHost;
|
char *pHost;
|
||||||
|
|||||||
@@ -113,7 +113,9 @@ bool PlayerEventLogs::IsEventEnabled(PlayerEvent::EventType event)
|
|||||||
// this processes any current player events on the queue
|
// this processes any current player events on the queue
|
||||||
void PlayerEventLogs::ProcessBatchQueue()
|
void PlayerEventLogs::ProcessBatchQueue()
|
||||||
{
|
{
|
||||||
|
m_batch_queue_lock.lock();
|
||||||
if (m_record_batch_queue.empty()) {
|
if (m_record_batch_queue.empty()) {
|
||||||
|
m_batch_queue_lock.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +130,6 @@ void PlayerEventLogs::ProcessBatchQueue()
|
|||||||
);
|
);
|
||||||
|
|
||||||
// empty
|
// empty
|
||||||
m_batch_queue_lock.lock();
|
|
||||||
m_record_batch_queue = {};
|
m_record_batch_queue = {};
|
||||||
m_batch_queue_lock.unlock();
|
m_batch_queue_lock.unlock();
|
||||||
}
|
}
|
||||||
@@ -139,6 +140,10 @@ void PlayerEventLogs::AddToQueue(const PlayerEventLogsRepository::PlayerEventLog
|
|||||||
m_batch_queue_lock.lock();
|
m_batch_queue_lock.lock();
|
||||||
m_record_batch_queue.emplace_back(log);
|
m_record_batch_queue.emplace_back(log);
|
||||||
m_batch_queue_lock.unlock();
|
m_batch_queue_lock.unlock();
|
||||||
|
|
||||||
|
if (m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) {
|
||||||
|
ProcessBatchQueue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fills common event data in the SendEvent function
|
// fills common event data in the SendEvent function
|
||||||
@@ -699,6 +704,7 @@ void PlayerEventLogs::SetSettingsDefaults()
|
|||||||
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
|
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
|
||||||
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
|
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
|
||||||
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
|
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
|
||||||
|
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
|
||||||
|
|
||||||
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
|
||||||
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
|
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ namespace PlayerEvent {
|
|||||||
KILLED_NPC,
|
KILLED_NPC,
|
||||||
KILLED_NAMED_NPC,
|
KILLED_NAMED_NPC,
|
||||||
KILLED_RAID_NPC,
|
KILLED_RAID_NPC,
|
||||||
|
ITEM_CREATION,
|
||||||
MAX // dont remove
|
MAX // dont remove
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,7 +111,8 @@ namespace PlayerEvent {
|
|||||||
"Possible Hack",
|
"Possible Hack",
|
||||||
"Killed NPC",
|
"Killed NPC",
|
||||||
"Killed Named NPC",
|
"Killed Named NPC",
|
||||||
"Killed Raid NPC"
|
"Killed Raid NPC",
|
||||||
|
"Item Creation"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generic struct used by all events
|
// Generic struct used by all events
|
||||||
@@ -184,6 +186,40 @@ namespace PlayerEvent {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// used in Trade event
|
||||||
|
struct ItemCreationEvent {
|
||||||
|
int64 item_id;
|
||||||
|
std::string item_name;
|
||||||
|
uint16 to_slot;
|
||||||
|
int16 charges;
|
||||||
|
uint32 aug1;
|
||||||
|
uint32 aug2;
|
||||||
|
uint32 aug3;
|
||||||
|
uint32 aug4;
|
||||||
|
uint32 aug5;
|
||||||
|
uint32 aug6;
|
||||||
|
bool attuned;
|
||||||
|
|
||||||
|
// cereal
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive &ar)
|
||||||
|
{
|
||||||
|
ar(
|
||||||
|
CEREAL_NVP(item_id),
|
||||||
|
CEREAL_NVP(item_name),
|
||||||
|
CEREAL_NVP(to_slot),
|
||||||
|
CEREAL_NVP(charges),
|
||||||
|
CEREAL_NVP(aug1),
|
||||||
|
CEREAL_NVP(aug2),
|
||||||
|
CEREAL_NVP(aug3),
|
||||||
|
CEREAL_NVP(aug4),
|
||||||
|
CEREAL_NVP(aug5),
|
||||||
|
CEREAL_NVP(aug6),
|
||||||
|
CEREAL_NVP(attuned)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// used in Trade event
|
// used in Trade event
|
||||||
struct TradeItem {
|
struct TradeItem {
|
||||||
int64 item_id;
|
int64 item_id;
|
||||||
|
|||||||
@@ -240,8 +240,8 @@ public:
|
|||||||
v.push_back(columns[7] + " = " + std::to_string(e.z));
|
v.push_back(columns[7] + " = " + std::to_string(e.z));
|
||||||
v.push_back(columns[8] + " = " + std::to_string(e.heading));
|
v.push_back(columns[8] + " = " + std::to_string(e.heading));
|
||||||
v.push_back(columns[9] + " = " + std::to_string(e.event_type_id));
|
v.push_back(columns[9] + " = " + std::to_string(e.event_type_id));
|
||||||
v.push_back(columns[10] + " = '" + Strings::Escape(e.event_type_name) + "'");
|
v.push_back(columns[10] + " = '" + db.Escape(e.event_type_name) + "'");
|
||||||
v.push_back(columns[11] + " = '" + Strings::Escape(e.event_data) + "'");
|
v.push_back(columns[11] + " = '" + db.Escape(e.event_data) + "'");
|
||||||
v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
@@ -274,8 +274,8 @@ public:
|
|||||||
v.push_back(std::to_string(e.z));
|
v.push_back(std::to_string(e.z));
|
||||||
v.push_back(std::to_string(e.heading));
|
v.push_back(std::to_string(e.heading));
|
||||||
v.push_back(std::to_string(e.event_type_id));
|
v.push_back(std::to_string(e.event_type_id));
|
||||||
v.push_back("'" + Strings::Escape(e.event_type_name) + "'");
|
v.push_back("'" + db.Escape(e.event_type_name) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.event_data) + "'");
|
v.push_back("'" + db.Escape(e.event_data) + "'");
|
||||||
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
@@ -316,8 +316,8 @@ public:
|
|||||||
v.push_back(std::to_string(e.z));
|
v.push_back(std::to_string(e.z));
|
||||||
v.push_back(std::to_string(e.heading));
|
v.push_back(std::to_string(e.heading));
|
||||||
v.push_back(std::to_string(e.event_type_id));
|
v.push_back(std::to_string(e.event_type_id));
|
||||||
v.push_back("'" + Strings::Escape(e.event_type_name) + "'");
|
v.push_back("'" + db.Escape(e.event_type_name) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.event_data) + "'");
|
v.push_back("'" + db.Escape(e.event_data) + "'");
|
||||||
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
|||||||
@@ -783,6 +783,7 @@ RULE_BOOL(Logging, PrintFileFunctionAndLine, false, "Ex: [World Server] [net.cpp
|
|||||||
RULE_BOOL(Logging, WorldGMSayLogging, true, "Relay worldserver logging to zone processes via GM say output")
|
RULE_BOOL(Logging, WorldGMSayLogging, true, "Relay worldserver logging to zone processes via GM say output")
|
||||||
RULE_BOOL(Logging, PlayerEventsQSProcess, false, "Have query server process player events instead of world. Useful when wanting to use a dedicated server and database for processing player events on separate disk")
|
RULE_BOOL(Logging, PlayerEventsQSProcess, false, "Have query server process player events instead of world. Useful when wanting to use a dedicated server and database for processing player events on separate disk")
|
||||||
RULE_INT(Logging, BatchPlayerEventProcessIntervalSeconds, 5, "This is the interval in which player events are processed in world or qs")
|
RULE_INT(Logging, BatchPlayerEventProcessIntervalSeconds, 5, "This is the interval in which player events are processed in world or qs")
|
||||||
|
RULE_INT(Logging, BatchPlayerEventProcessChunkSize, 10000, "This is the cap of events that can be inserted into the queue before a force flush. This is to keep from hitting MySQL max_allowed_packet and killing the connection")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(HotReload)
|
RULE_CATEGORY(HotReload)
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// Build variables
|
// Build variables
|
||||||
// these get injected during the build pipeline
|
// these get injected during the build pipeline
|
||||||
#define CURRENT_VERSION "22.4.2-dev" // always append -dev to the current version for custom-builds
|
#define CURRENT_VERSION "22.4.3-dev" // always append -dev to the current version for custom-builds
|
||||||
#define LOGIN_VERSION "0.8.0"
|
#define LOGIN_VERSION "0.8.0"
|
||||||
#define COMPILE_DATE __DATE__
|
#define COMPILE_DATE __DATE__
|
||||||
#define COMPILE_TIME __TIME__
|
#define COMPILE_TIME __TIME__
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eqemu-server",
|
"name": "eqemu-server",
|
||||||
"version": "22.4.2",
|
"version": "22.4.3",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EQEmu/Server.git"
|
"url": "https://github.com/EQEmu/Server.git"
|
||||||
|
|||||||
@@ -224,6 +224,13 @@ void EQEmuApiWorldDataService::reload(Json::Value &r, const std::vector<std::str
|
|||||||
else {
|
else {
|
||||||
pack = new ServerPacket(c.opcode, 0);
|
pack = new ServerPacket(c.opcode, 0);
|
||||||
message(r, fmt::format("Reloading [{}] globally", c.desc));
|
message(r, fmt::format("Reloading [{}] globally", c.desc));
|
||||||
|
|
||||||
|
if (c.opcode == ServerOP_ReloadLogs) {
|
||||||
|
LogSys.LoadLogDatabaseSettings();
|
||||||
|
}
|
||||||
|
else if (c.opcode == ServerOP_ReloadRules) {
|
||||||
|
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
found_command = true;
|
found_command = true;
|
||||||
|
|||||||
@@ -1332,6 +1332,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
case ServerOP_ItemStatus:
|
case ServerOP_ItemStatus:
|
||||||
case ServerOP_KickPlayer:
|
case ServerOP_KickPlayer:
|
||||||
case ServerOP_KillPlayer:
|
case ServerOP_KillPlayer:
|
||||||
|
case ServerOP_OOCMute:
|
||||||
case ServerOP_OOZGroupMessage:
|
case ServerOP_OOZGroupMessage:
|
||||||
case ServerOP_Petition:
|
case ServerOP_Petition:
|
||||||
case ServerOP_RaidGroupSay:
|
case ServerOP_RaidGroupSay:
|
||||||
|
|||||||
+14
-19
@@ -4478,23 +4478,19 @@ uint32 Bot::CountBotItem(uint32 item_id) {
|
|||||||
return item_count;
|
return item_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::HasBotItem(uint32 item_id) {
|
int16 Bot::HasBotItem(uint32 item_id) {
|
||||||
bool has_item = false;
|
EQ::ItemInstance const *inst = nullptr;
|
||||||
EQ::ItemInstance *inst = nullptr;
|
|
||||||
|
|
||||||
for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
for (uint16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) {
|
||||||
inst = GetBotItem(slot_id);
|
inst = GetBotItem(slot_id);
|
||||||
if (!inst || !inst->GetItem()) {
|
if (!inst || !inst->GetItem()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->GetID() == item_id) {
|
if (inst->GetID() == item_id) {
|
||||||
has_item = true;
|
return slot_id;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return INVALID_INDEX;
|
||||||
return has_item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::RemoveBotItem(uint32 item_id) {
|
void Bot::RemoveBotItem(uint32 item_id) {
|
||||||
@@ -4616,17 +4612,17 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
|
|||||||
struct ClientTrade {
|
struct ClientTrade {
|
||||||
ItemInstance* trade_item_instance;
|
ItemInstance* trade_item_instance;
|
||||||
int16 from_client_slot;
|
int16 from_client_slot;
|
||||||
int16 to_bot_slot;
|
int16 to_bot_slot = invslot::SLOT_INVALID;
|
||||||
|
|
||||||
ClientTrade(ItemInstance* item, int16 from) : trade_item_instance(item), from_client_slot(from), to_bot_slot(invslot::SLOT_INVALID) { }
|
ClientTrade(ItemInstance* item, int16 from) : trade_item_instance(item), from_client_slot(from) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClientReturn {
|
struct ClientReturn {
|
||||||
const ItemInstance* return_item_instance;
|
ItemInstance* return_item_instance;
|
||||||
int16 from_bot_slot;
|
int16 from_bot_slot;
|
||||||
int16 to_client_slot;
|
int16 to_client_slot = invslot::SLOT_INVALID;
|
||||||
|
|
||||||
ClientReturn(const ItemInstance* item, int16 from) : return_item_instance(item), from_bot_slot(from), to_client_slot(invslot::SLOT_INVALID) { }
|
ClientReturn(ItemInstance* item, int16 from) : return_item_instance(item), from_bot_slot(from) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int16 bot_equip_order[invslot::EQUIPMENT_COUNT] = {
|
static const int16 bot_equip_order[invslot::EQUIPMENT_COUNT] = {
|
||||||
@@ -4906,7 +4902,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
|
|||||||
if (trade_instance->GetItem()->IsType2HWeapon()) {
|
if (trade_instance->GetItem()->IsType2HWeapon()) {
|
||||||
if (!melee_secondary) {
|
if (!melee_secondary) {
|
||||||
melee_2h_weapon = true;
|
melee_2h_weapon = true;
|
||||||
auto equipped_secondary_weapon = m_inv[invslot::slotSecondary];
|
auto equipped_secondary_weapon = GetBotItem(invslot::slotSecondary);
|
||||||
if (equipped_secondary_weapon) {
|
if (equipped_secondary_weapon) {
|
||||||
client_return.push_back(ClientReturn(equipped_secondary_weapon, invslot::slotSecondary));
|
client_return.push_back(ClientReturn(equipped_secondary_weapon, invslot::slotSecondary));
|
||||||
}
|
}
|
||||||
@@ -4922,7 +4918,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
|
|||||||
!trade_instance->IsWeapon()
|
!trade_instance->IsWeapon()
|
||||||
) {
|
) {
|
||||||
melee_secondary = true;
|
melee_secondary = true;
|
||||||
auto equipped_primary_weapon = m_inv[invslot::slotPrimary];
|
auto equipped_primary_weapon = GetBotItem(invslot::slotPrimary);
|
||||||
if (equipped_primary_weapon && equipped_primary_weapon->GetItem()->IsType2HWeapon()) {
|
if (equipped_primary_weapon && equipped_primary_weapon->GetItem()->IsType2HWeapon()) {
|
||||||
client_return.push_back(ClientReturn(equipped_primary_weapon, invslot::slotPrimary));
|
client_return.push_back(ClientReturn(equipped_primary_weapon, invslot::slotPrimary));
|
||||||
}
|
}
|
||||||
@@ -4937,7 +4933,7 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
|
|||||||
trade_iterator.to_bot_slot = index;
|
trade_iterator.to_bot_slot = index;
|
||||||
|
|
||||||
if (m_inv[index]) {
|
if (m_inv[index]) {
|
||||||
client_return.push_back(ClientReturn(m_inv[index], index));
|
client_return.push_back(ClientReturn(GetBotItem(index), index));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -5071,9 +5067,8 @@ void Bot::PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client*
|
|||||||
client->DeleteItemInInventory(return_iterator.from_bot_slot);
|
client->DeleteItemInInventory(return_iterator.from_bot_slot);
|
||||||
} else { // successful trade returns
|
} else { // successful trade returns
|
||||||
auto return_instance = m_inv.PopItem(return_iterator.from_bot_slot);
|
auto return_instance = m_inv.PopItem(return_iterator.from_bot_slot);
|
||||||
//if (*return_instance != *return_iterator.return_item_instance) {
|
|
||||||
// // TODO: add logging
|
// // TODO: add logging
|
||||||
//}
|
|
||||||
|
|
||||||
if (!database.botdb.DeleteItemBySlot(GetBotID(), return_iterator.from_bot_slot)) {
|
if (!database.botdb.DeleteItemBySlot(GetBotID(), return_iterator.from_bot_slot)) {
|
||||||
OwnerMessage(
|
OwnerMessage(
|
||||||
@@ -9490,7 +9485,7 @@ void Bot::ListBotSpells(uint8 min_level)
|
|||||||
auto spell_count = 0;
|
auto spell_count = 0;
|
||||||
auto spell_number = 1;
|
auto spell_number = 1;
|
||||||
|
|
||||||
for (const auto& s : (AIBot_spells.size() > AIBot_spells_enforced.size()) ? AIBot_spells : AIBot_spells_enforced) {
|
for (const auto& s : (GetBotEnforceSpellSetting()) ? AIBot_spells_enforced : AIBot_spells) {
|
||||||
auto b = bot_spell_settings.find(s.spellid);
|
auto b = bot_spell_settings.find(s.spellid);
|
||||||
if (b == bot_spell_settings.end() && s.minlevel >= min_level) {
|
if (b == bot_spell_settings.end() && s.minlevel >= min_level) {
|
||||||
bot_owner->Message(
|
bot_owner->Message(
|
||||||
|
|||||||
+1
-1
@@ -720,7 +720,7 @@ public:
|
|||||||
uint32 CountBotItem(uint32 item_id);
|
uint32 CountBotItem(uint32 item_id);
|
||||||
std::map<uint16, uint32> GetBotItemSlots();
|
std::map<uint16, uint32> GetBotItemSlots();
|
||||||
uint32 GetBotItemBySlot(uint16 slot_id);
|
uint32 GetBotItemBySlot(uint16 slot_id);
|
||||||
bool HasBotItem(uint32 item_id);
|
int16 HasBotItem(uint32 item_id);
|
||||||
void RemoveBotItem(uint32 item_id);
|
void RemoveBotItem(uint32 item_id);
|
||||||
uint32 GetTotalPlayTime();
|
uint32 GetTotalPlayTime();
|
||||||
|
|
||||||
|
|||||||
@@ -9320,7 +9320,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* inst = my_bot->GetBotItem(slot_id);
|
auto* inst = my_bot->GetBotItem(slot_id);
|
||||||
if (!inst) {
|
if (!inst) {
|
||||||
std::string slot_message = "is";
|
std::string slot_message = "is";
|
||||||
switch (slot_id) {
|
switch (slot_id) {
|
||||||
|
|||||||
@@ -962,7 +962,10 @@ bool BotDatabase::SaveTimers(Bot* bot_inst)
|
|||||||
if (bot_timers[timer_index] <= Timer::GetCurrentTime())
|
if (bot_timers[timer_index] <= Timer::GetCurrentTime())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
query = StringFormat("INSERT INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('%u', '%u', '%u')", bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index]);
|
query = fmt::format(
|
||||||
|
"REPLACE INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('{}', '{}', '{}')",
|
||||||
|
bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index]
|
||||||
|
);
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = database.QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
DeleteTimers(bot_inst->GetBotID());
|
DeleteTimers(bot_inst->GetBotID());
|
||||||
|
|||||||
@@ -2144,7 +2144,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app)
|
|||||||
theme = LDoNThemes::RUJ;
|
theme = LDoNThemes::RUJ;
|
||||||
} else if (item->LDoNTheme & LDoNThemeBits::MMCBit) {
|
} else if (item->LDoNTheme & LDoNThemeBits::MMCBit) {
|
||||||
theme = LDoNThemes::MMC;
|
theme = LDoNThemes::MMC;
|
||||||
} else if (item->LDoNTheme & LDoNThemeBits::RUJBit) {
|
} else if (item->LDoNTheme & LDoNThemeBits::MIRBit) {
|
||||||
theme = LDoNThemes::MIR;
|
theme = LDoNThemes::MIR;
|
||||||
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
|
} else if (item->LDoNTheme & LDoNThemeBits::GUKBit) {
|
||||||
theme = LDoNThemes::GUK;
|
theme = LDoNThemes::GUK;
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ void command_gearup(Client *c, const Seperator *sep)
|
|||||||
if (t->IsClient()) {
|
if (t->IsClient()) {
|
||||||
has_item = t->CastToClient()->GetInv().HasItem(item_id, 1, invWhereWorn) != INVALID_INDEX;
|
has_item = t->CastToClient()->GetInv().HasItem(item_id, 1, invWhereWorn) != INVALID_INDEX;
|
||||||
} else if (t->IsBot()) {
|
} else if (t->IsBot()) {
|
||||||
has_item = t->CastToBot()->HasBotItem(item_id);
|
has_item = t->CastToBot()->HasBotItem(item_id) != INVALID_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_wear_item = false;
|
bool can_wear_item = false;
|
||||||
|
|||||||
@@ -794,6 +794,23 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_CREATION)) {
|
||||||
|
auto e = PlayerEvent::ItemCreationEvent{};
|
||||||
|
e.item_id = item->ID;
|
||||||
|
e.item_name = item->Name;
|
||||||
|
e.to_slot = to_slot;
|
||||||
|
e.charges = charges;
|
||||||
|
e.aug1 = aug1;
|
||||||
|
e.aug2 = aug2;
|
||||||
|
e.aug3 = aug3;
|
||||||
|
e.aug4 = aug4;
|
||||||
|
e.aug5 = aug5;
|
||||||
|
e.aug6 = aug6;
|
||||||
|
e.attuned = attuned;
|
||||||
|
|
||||||
|
RecordPlayerEventLog(PlayerEvent::ITEM_CREATION, e);
|
||||||
|
}
|
||||||
|
|
||||||
// put item into inventory
|
// put item into inventory
|
||||||
if (to_slot == EQ::invslot::slotCursor) {
|
if (to_slot == EQ::invslot::slotCursor) {
|
||||||
PushItemOnCursor(*inst);
|
PushItemOnCursor(*inst);
|
||||||
|
|||||||
+3
-3
@@ -65,8 +65,8 @@ Lua_Mob Lua_Bot::GetOwner() {
|
|||||||
return Lua_Mob(self->GetOwner());
|
return Lua_Mob(self->GetOwner());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lua_Bot::HasBotItem(uint32 item_id) {
|
int16 Lua_Bot::HasBotItem(uint32 item_id) {
|
||||||
Lua_Safe_Call_Bool();
|
Lua_Safe_Call_Int();
|
||||||
return self->HasBotItem(item_id);
|
return self->HasBotItem(item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,7 +507,7 @@ luabind::scope lua_register_bot() {
|
|||||||
.def("GetRawItemAC", (int(Lua_Bot::*)(void))&Lua_Bot::GetRawItemAC)
|
.def("GetRawItemAC", (int(Lua_Bot::*)(void))&Lua_Bot::GetRawItemAC)
|
||||||
.def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage)
|
.def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage)
|
||||||
.def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID)
|
.def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID)
|
||||||
.def("HasBotItem", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem)
|
.def("HasBotItem", (int16(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem)
|
||||||
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry)
|
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry)
|
||||||
.def("HasItemEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItemEquippedByID)
|
.def("HasItemEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItemEquippedByID)
|
||||||
.def("IsGrouped", (bool(Lua_Bot::*)(void))&Lua_Bot::IsGrouped)
|
.def("IsGrouped", (bool(Lua_Bot::*)(void))&Lua_Bot::IsGrouped)
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ public:
|
|||||||
uint32 GetBotItemIDBySlot(uint16 slot_id);
|
uint32 GetBotItemIDBySlot(uint16 slot_id);
|
||||||
int GetExpansionBitmask();
|
int GetExpansionBitmask();
|
||||||
Lua_Mob GetOwner();
|
Lua_Mob GetOwner();
|
||||||
bool HasBotItem(uint32 item_id);
|
int16 HasBotItem(uint32 item_id);
|
||||||
void OwnerMessage(std::string message);
|
void OwnerMessage(std::string message);
|
||||||
bool ReloadBotDataBuckets();
|
bool ReloadBotDataBuckets();
|
||||||
bool ReloadBotOwnerDataBuckets();
|
bool ReloadBotOwnerDataBuckets();
|
||||||
|
|||||||
+29
-6
@@ -103,6 +103,7 @@ Mob::Mob(
|
|||||||
attack_dw_timer(2000),
|
attack_dw_timer(2000),
|
||||||
ranged_timer(2000),
|
ranged_timer(2000),
|
||||||
hp_regen_per_second_timer(1000),
|
hp_regen_per_second_timer(1000),
|
||||||
|
m_z_clip_check_timer(1000),
|
||||||
tic_timer(6000),
|
tic_timer(6000),
|
||||||
mana_timer(2000),
|
mana_timer(2000),
|
||||||
spellend_timer(0),
|
spellend_timer(0),
|
||||||
@@ -2374,14 +2375,14 @@ void Mob::ShowBuffList(Client* client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::GMMove(float x, float y, float z, float heading) {
|
void Mob::GMMove(float x, float y, float z, float heading, bool save_guard_spot) {
|
||||||
m_Position.x = x;
|
m_Position.x = x;
|
||||||
m_Position.y = y;
|
m_Position.y = y;
|
||||||
m_Position.z = z;
|
m_Position.z = z;
|
||||||
SetHeading(heading);
|
SetHeading(heading);
|
||||||
mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny);
|
mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny);
|
||||||
|
|
||||||
if (IsNPC()) {
|
if (IsNPC() && save_guard_spot) {
|
||||||
CastToNPC()->SaveGuardSpot(glm::vec4(x, y, z, heading));
|
CastToNPC()->SaveGuardSpot(glm::vec4(x, y, z, heading));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3714,10 +3715,32 @@ bool Mob::HateSummon() {
|
|||||||
// probably should be like half melee range, but we can't get melee range nicely because reasons :)
|
// probably should be like half melee range, but we can't get melee range nicely because reasons :)
|
||||||
new_pos = target->TryMoveAlong(new_pos, 5.0f, angle);
|
new_pos = target->TryMoveAlong(new_pos, 5.0f, angle);
|
||||||
|
|
||||||
if (target->IsClient())
|
if (target->IsClient()) {
|
||||||
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), new_pos.x, new_pos.y, new_pos.z, new_pos.w, 0, SummonPC);
|
target->CastToClient()->MovePC(
|
||||||
else
|
zone->GetZoneID(),
|
||||||
target->GMMove(new_pos.x, new_pos.y, new_pos.z, new_pos.w);
|
zone->GetInstanceID(),
|
||||||
|
new_pos.x,
|
||||||
|
new_pos.y,
|
||||||
|
new_pos.z,
|
||||||
|
new_pos.w,
|
||||||
|
0,
|
||||||
|
SummonPC
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
bool target_is_client_pet = (
|
||||||
|
target->IsPet() &&
|
||||||
|
target->IsPetOwnerClient()
|
||||||
|
);
|
||||||
|
bool set_new_guard_spot = !(IsNPC() && target_is_client_pet);
|
||||||
|
|
||||||
|
target->GMMove(
|
||||||
|
new_pos.x,
|
||||||
|
new_pos.y,
|
||||||
|
new_pos.z,
|
||||||
|
new_pos.w,
|
||||||
|
set_new_guard_spot
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if(summon_level == 2) {
|
} else if(summon_level == 2) {
|
||||||
|
|||||||
+3
-1
@@ -686,7 +686,7 @@ public:
|
|||||||
float GetMovespeed() const { return IsRunning() ? GetRunspeed() : GetWalkspeed(); }
|
float GetMovespeed() const { return IsRunning() ? GetRunspeed() : GetWalkspeed(); }
|
||||||
bool IsRunning() const { return m_is_running; }
|
bool IsRunning() const { return m_is_running; }
|
||||||
void SetRunning(bool val) { m_is_running = val; }
|
void SetRunning(bool val) { m_is_running = val; }
|
||||||
virtual void GMMove(float x, float y, float z, float heading = 0.01);
|
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool save_guard_spot = true);
|
||||||
virtual void GMMove(const glm::vec4 &position);
|
virtual void GMMove(const glm::vec4 &position);
|
||||||
void SetDelta(const glm::vec4& delta);
|
void SetDelta(const glm::vec4& delta);
|
||||||
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
|
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
|
||||||
@@ -1427,6 +1427,8 @@ protected:
|
|||||||
int _GetRunSpeed() const;
|
int _GetRunSpeed() const;
|
||||||
int _GetFearSpeed() const;
|
int _GetFearSpeed() const;
|
||||||
|
|
||||||
|
Timer m_z_clip_check_timer;
|
||||||
|
|
||||||
virtual bool AI_EngagedCastCheck() { return(false); }
|
virtual bool AI_EngagedCastCheck() { return(false); }
|
||||||
virtual bool AI_PursueCastCheck() { return(false); }
|
virtual bool AI_PursueCastCheck() { return(false); }
|
||||||
virtual bool AI_IdleCastCheck() { return(false); }
|
virtual bool AI_IdleCastCheck() { return(false); }
|
||||||
|
|||||||
@@ -1071,6 +1071,14 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (engaged) {
|
if (engaged) {
|
||||||
|
if (IsNPC() && m_z_clip_check_timer.Check()) {
|
||||||
|
auto t = GetTarget();
|
||||||
|
if (t && DistanceNoZ(GetPosition(), t->GetPosition()) < 75 && std::abs(GetPosition().z - t->GetPosition().z) > 15 && !CheckLosFN(t)) {
|
||||||
|
GMMove(t->GetPosition().x, t->GetPosition().y, t->GetPosition().z, t->GetPosition().w);
|
||||||
|
FaceTarget(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)))
|
if (!(m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)))
|
||||||
SendAddPlayerState(PlayerState::Aggressive);
|
SendAddPlayerState(PlayerState::Aggressive);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -90,7 +90,7 @@ uint32 Perl_Bot_CountBotItem(Bot* self, uint32 item_id)
|
|||||||
return self->CountBotItem(item_id);
|
return self->CountBotItem(item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Perl_Bot_HasBotItem(Bot* self, uint32 item_id)
|
int16 Perl_Bot_HasBotItem(Bot* self, uint32 item_id)
|
||||||
{
|
{
|
||||||
return self->HasBotItem(item_id);
|
return self->HasBotItem(item_id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2755,6 +2755,11 @@ void Perl_Client_Signal(Client* self, int signal_id)
|
|||||||
self->Signal(signal_id);
|
self->Signal(signal_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Perl_Client_SignalClient(Client* self, int signal_id) // @categories Script Utility
|
||||||
|
{
|
||||||
|
self->Signal(signal_id);
|
||||||
|
}
|
||||||
|
|
||||||
std::string Perl_Client_GetGuildPublicNote(Client* self)
|
std::string Perl_Client_GetGuildPublicNote(Client* self)
|
||||||
{
|
{
|
||||||
return self->GetGuildPublicNote();
|
return self->GetGuildPublicNote();
|
||||||
@@ -3362,6 +3367,7 @@ void perl_register_client()
|
|||||||
package.add("SetTitleSuffix", (void(*)(Client*, std::string, bool))&Perl_Client_SetTitleSuffix);
|
package.add("SetTitleSuffix", (void(*)(Client*, std::string, bool))&Perl_Client_SetTitleSuffix);
|
||||||
package.add("SetZoneFlag", &Perl_Client_SetZoneFlag);
|
package.add("SetZoneFlag", &Perl_Client_SetZoneFlag);
|
||||||
package.add("Signal", &Perl_Client_Signal);
|
package.add("Signal", &Perl_Client_Signal);
|
||||||
|
package.add("SignalClient", &Perl_Client_SignalClient);
|
||||||
package.add("SilentMessage", &Perl_Client_SilentMessage);
|
package.add("SilentMessage", &Perl_Client_SilentMessage);
|
||||||
package.add("Sit", &Perl_Client_Sit);
|
package.add("Sit", &Perl_Client_Sit);
|
||||||
package.add("SlotConvert2", &Perl_Client_SlotConvert2);
|
package.add("SlotConvert2", &Perl_Client_SlotConvert2);
|
||||||
|
|||||||
@@ -584,6 +584,16 @@ bool Perl_NPC_GetCombatState(NPC* self) // @categories Script Utility
|
|||||||
return self->GetCombatEvent();
|
return self->GetCombatEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size) // @categories Script Utility
|
||||||
|
{
|
||||||
|
self->SetSimpleRoamBox(box_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size, float move_distance) // @categories Script Utility
|
||||||
|
{
|
||||||
|
self->SetSimpleRoamBox(box_size, move_distance);
|
||||||
|
}
|
||||||
|
|
||||||
void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size, float move_distance, int move_delay) // @categories Script Utility
|
void Perl_NPC_SetSimpleRoamBox(NPC* self, float box_size, float move_distance, int move_delay) // @categories Script Utility
|
||||||
{
|
{
|
||||||
self->SetSimpleRoamBox(box_size, move_distance, move_delay);
|
self->SetSimpleRoamBox(box_size, move_distance, move_delay);
|
||||||
|
|||||||
+13
-15
@@ -781,7 +781,19 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) {
|
|||||||
return new_z;
|
return new_z;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_z = FindDestGroundZ(destination, (-GetZOffset() / 2));
|
new_z = FindDestGroundZ(destination, ((-GetZOffset() / 2) + z_find_offset));
|
||||||
|
|
||||||
|
if (RuleB(Map, MobPathingVisualDebug)) {
|
||||||
|
DrawDebugCoordinateNode(
|
||||||
|
fmt::format("{} search z node", GetCleanName()),
|
||||||
|
glm::vec4{
|
||||||
|
m_Position.x,
|
||||||
|
m_Position.y,
|
||||||
|
((-GetZOffset() / 2) + z_find_offset),
|
||||||
|
m_Position.w
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
if (new_z != BEST_Z_INVALID) {
|
if (new_z != BEST_Z_INVALID) {
|
||||||
new_z += GetZOffset();
|
new_z += GetZOffset();
|
||||||
|
|
||||||
@@ -790,20 +802,6 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent ceiling clipping
|
|
||||||
// if client is close in distance (not counting Z) and we clipped up into a ceiling
|
|
||||||
// this helps us snap back down (or up) if it were to happen
|
|
||||||
// other fixes were put in place to prevent clipping into the ceiling to begin with
|
|
||||||
if (std::abs(new_z - m_Position.z) > 15) {
|
|
||||||
LogFixZ("TRIGGER clipping detection");
|
|
||||||
auto t = GetTarget();
|
|
||||||
if (t && DistanceNoZ(GetPosition(), t->GetPosition()) < 20) {
|
|
||||||
new_z = FindDestGroundZ(t->GetPosition(), -t->GetZOffset());
|
|
||||||
new_z += GetZOffset();
|
|
||||||
GMMove(t->GetPosition().x, t->GetPosition().y, new_z, t->GetPosition().w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto duration = timer.elapsed();
|
auto duration = timer.elapsed();
|
||||||
|
|
||||||
LogFixZ("[{}] returned [{}] at [{}] [{}] [{}] - Took [{}]",
|
LogFixZ("[{}] returned [{}] at [{}] [{}] [{}] - Took [{}]",
|
||||||
|
|||||||
Reference in New Issue
Block a user