mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-29 14:55:44 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 871f320311 | |||
| a222128599 | |||
| 45b249e33d | |||
| c24834de5d | |||
| 841d7f2700 | |||
| 56c29154f0 | |||
| 6466c2ff21 | |||
| 16dc210cd8 | |||
| 77045f558e | |||
| e1fa2d5bc5 | |||
| b03f52de18 | |||
| 226cc3d6cb | |||
| 7f54e26dec | |||
| 11a81d8e8a | |||
| e719aa43cf | |||
| 22994e3264 | |||
| cfbdecad19 | |||
| 2427f7e034 | |||
| 9a6403b196 | |||
| d8953c5156 | |||
| 33b40e83b7 | |||
| e75c31d524 | |||
| cf1f8d5460 | |||
| 690cacdaab | |||
| f9f45eedcd | |||
| 93ddffa57f | |||
| c9993fb698 | |||
| aa0fbb8b45 | |||
| 62532c6bdd | |||
| f8c3c03185 | |||
| 692a90f3f0 | |||
| 3a49d851ca | |||
| fdc5c27061 | |||
| 56be69ddb1 | |||
| 9477ff72ac | |||
| 6d8e80b1e5 | |||
| ebeaef598b | |||
| 60b65da7f2 | |||
| 100e6698ea | |||
| 2bd94ab7a2 |
@@ -1,3 +1,88 @@
|
||||
## [22.35.0] - 12/10/2023
|
||||
|
||||
### Bots
|
||||
|
||||
* Add BotHealOnLevel to fully heal/mana on level. ([#3745](https://github.com/EQEmu/Server/pull/3745)) @nytmyr 2023-12-08
|
||||
* Fix bots learning spells on level ([#3744](https://github.com/EQEmu/Server/pull/3744)) @nytmyr 2023-12-08
|
||||
|
||||
### Bug
|
||||
|
||||
* Fix blocked spells regression from #3638 ([#3753](https://github.com/EQEmu/Server/pull/3753)) @joligario 2023-12-11
|
||||
* PR 3638 Missed the blocked spells repository updates ([#3748](https://github.com/EQEmu/Server/pull/3748)) @fryguy503 2023-12-08
|
||||
|
||||
### CMake
|
||||
|
||||
* Update minimum version of CMake ([#3743](https://github.com/EQEmu/Server/pull/3743)) @joligario 2023-12-08
|
||||
|
||||
### Code
|
||||
|
||||
* Remove hard-coded Status Checks ([#3727](https://github.com/EQEmu/Server/pull/3727)) @Kinglykrab 2023-12-03
|
||||
|
||||
### Commands
|
||||
|
||||
* #guild set CharName 0 did not remove char from guild. ([#3717](https://github.com/EQEmu/Server/pull/3717)) @noudess 2023-11-25
|
||||
* #petname changes PC to Nobody if selected. ([#3720](https://github.com/EQEmu/Server/pull/3720)) @noudess 2023-11-26
|
||||
* Add #show aas Command ([#3710](https://github.com/EQEmu/Server/pull/3710)) @Kinglykrab 2023-11-26
|
||||
* Add #task complete Command ([#3711](https://github.com/EQEmu/Server/pull/3711)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #acceptrules Command ([#3716](https://github.com/EQEmu/Server/pull/3716)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #disarmtrap Command ([#3713](https://github.com/EQEmu/Server/pull/3713)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #list Command ([#3714](https://github.com/EQEmu/Server/pull/3714)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #movement Command ([#3715](https://github.com/EQEmu/Server/pull/3715)) @Kinglykrab 2023-11-26
|
||||
* Cleanup #object Command ([#3722](https://github.com/EQEmu/Server/pull/3722)) @Kinglykrab 2023-12-03
|
||||
* Cleanup #zonebootup and #zoneshutdown Commands ([#3729](https://github.com/EQEmu/Server/pull/3729)) @Kinglykrab 2023-12-03
|
||||
* Fix formatting of #wpinfo output. ([#3728](https://github.com/EQEmu/Server/pull/3728)) @noudess 2023-12-01
|
||||
|
||||
### Database
|
||||
|
||||
* Add primary key to keyring table ([#3746](https://github.com/EQEmu/Server/pull/3746)) @Kinglykrab 2023-12-08
|
||||
* Consolidate Starting Items Table ([#3723](https://github.com/EQEmu/Server/pull/3723)) @Kinglykrab 2023-11-30
|
||||
* Extra whitespace in #3723 ([#3730](https://github.com/EQEmu/Server/pull/3730)) @joligario 2023-12-02
|
||||
* Minor adjustment to #3726 ([#3732](https://github.com/EQEmu/Server/pull/3732)) @joligario 2023-12-03
|
||||
* Modify `updated` column in `items` table with proper default. ([#3726](https://github.com/EQEmu/Server/pull/3726)) @joligario 2023-12-02
|
||||
* Pull Spell Group Cache from Content DB ([#3749](https://github.com/EQEmu/Server/pull/3749)) @fryguy503 2023-12-08
|
||||
|
||||
### Faction
|
||||
|
||||
* Alliance line is only allowed 1 faction change at a time. ([#3718](https://github.com/EQEmu/Server/pull/3718)) @noudess 2023-11-26
|
||||
|
||||
### Fixes
|
||||
|
||||
* Changing Group Leader Invalidated GetLeaderName() ([#3712](https://github.com/EQEmu/Server/pull/3712)) @Kinglykrab 2023-11-26
|
||||
* Fix 9245 SQL ([#3740](https://github.com/EQEmu/Server/pull/3740)) @Kinglykrab 2023-12-05
|
||||
* Fix Swarm Pets Requiring NPC Aggros Flag ([#3738](https://github.com/EQEmu/Server/pull/3738)) @Kinglykrab 2023-12-05
|
||||
* Guild Message Limits ([#3724](https://github.com/EQEmu/Server/pull/3724)) @neckkola 2023-11-29
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add EVENT_AA_GAIN to AddAAPoints() ([#3733](https://github.com/EQEmu/Server/pull/3733)) @Kinglykrab 2023-12-03
|
||||
* Add GMMove Overloads to Perl/Lua ([#3719](https://github.com/EQEmu/Server/pull/3719)) @Kinglykrab 2023-11-25
|
||||
|
||||
### Scripts
|
||||
|
||||
* Import items into `items_new` table instead of writing directly to the existing `items` table. ([#3725](https://github.com/EQEmu/Server/pull/3725)) @joligario 2023-11-30
|
||||
* Revert database engine change from #3702. ([#3736](https://github.com/EQEmu/Server/pull/3736)) @joligario 2023-12-03
|
||||
* Update 13th Floor Import Tool ([#3702](https://github.com/EQEmu/Server/pull/3702)) @joligario 2023-11-26
|
||||
|
||||
## [22.34.2] - 11/23/2023
|
||||
|
||||
### Admin
|
||||
|
||||
* Update date in changelog ([#3698](https://github.com/EQEmu/Server/pull/3698)) @joligario 2023-11-19
|
||||
|
||||
### Code
|
||||
|
||||
* Fix typo in #giveitem ([#3704](https://github.com/EQEmu/Server/pull/3704)) @Kinglykrab 2023-11-22
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() ([#3705](https://github.com/EQEmu/Server/pull/3705)) @jcr4990 2023-11-23
|
||||
* Fix bots/Mercenaries being removed from hatelist ([#3708](https://github.com/EQEmu/Server/pull/3708)) @Kinglykrab 2023-11-23
|
||||
* Fix some spell types failing IsValidSpellRange check ([#3707](https://github.com/EQEmu/Server/pull/3707)) @nytmyr 2023-11-23
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Update ticket login table structure ([#3703](https://github.com/EQEmu/Server/pull/3703)) @KimLS 2023-11-22
|
||||
|
||||
## [22.34.1] - 11/20/2023
|
||||
|
||||
### EQTime
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
|
||||
|
||||
add_subdirectory(import)
|
||||
add_subdirectory(export)
|
||||
|
||||
+12
-15
@@ -29,6 +29,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/repositories/account_repository.h"
|
||||
|
||||
// Disgrace: for windows compile
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
@@ -1643,25 +1645,20 @@ void Database::ClearGroupLeader(uint32 gid) {
|
||||
std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl;
|
||||
}
|
||||
|
||||
uint8 Database::GetAgreementFlag(uint32 acctid) {
|
||||
|
||||
std::string query = StringFormat("SELECT rulesflag FROM account WHERE id=%i",acctid);
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
uint8 Database::GetAgreementFlag(uint32 account_id)
|
||||
{
|
||||
const auto& e = AccountRepository::FindOne(*this, account_id);
|
||||
if (!e.id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return Strings::ToUnsignedInt(row[0]);
|
||||
return e.rulesflag;
|
||||
}
|
||||
|
||||
void Database::SetAgreementFlag(uint32 acctid) {
|
||||
std::string query = StringFormat("UPDATE account SET rulesflag=1 where id=%i", acctid);
|
||||
QueryDatabase(query);
|
||||
void Database::SetAgreementFlag(uint32 account_id) {
|
||||
auto e = AccountRepository::FindOne(*this, account_id);
|
||||
e.rulesflag = 1;
|
||||
AccountRepository::UpdateOne(*this, e);
|
||||
}
|
||||
|
||||
void Database::ClearRaid(uint32 rid) {
|
||||
|
||||
+2
-2
@@ -188,10 +188,10 @@ public:
|
||||
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
|
||||
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
|
||||
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
|
||||
uint8 GetAgreementFlag(uint32 acctid);
|
||||
uint8 GetAgreementFlag(uint32 account_id);
|
||||
|
||||
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
||||
void SetAgreementFlag(uint32 acctid);
|
||||
void SetAgreementFlag(uint32 account_id);
|
||||
|
||||
int GetIPExemption(std::string account_ip);
|
||||
void SetIPExemption(std::string account_ip, int exemption_amount);
|
||||
|
||||
@@ -5019,17 +5019,106 @@ ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9242,
|
||||
.description = "2023_11_7_mintime_maxtime_spawnentry.sql",
|
||||
.check = "SHOW COLUMNS FROM `spawnentry` LIKE 'min_time'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
.version = 9242,
|
||||
.description = "2023_11_7_mintime_maxtime_spawnentry.sql",
|
||||
.check = "SHOW COLUMNS FROM `spawnentry` LIKE 'min_time'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `spawnentry`
|
||||
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
|
||||
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
|
||||
)"
|
||||
},
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9243,
|
||||
.description = "2023_11_27_starting_items_revamp.sql",
|
||||
.check = "SHOW COLUMNS FROM `starting_items` LIKE 'race_list'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `starting_items_backup_9243` LIKE `starting_items`;
|
||||
INSERT INTO `starting_items_backup_9243` SELECT * FROM `starting_items`;
|
||||
|
||||
CREATE TABLE `starting_items_new` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`race_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`deity_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`zone_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
|
||||
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
|
||||
`gm` mediumint(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`slot` mediumint(9) NOT NULL DEFAULT -1,
|
||||
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
||||
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
|
||||
`content_flags` varchar(100) NULL,
|
||||
`content_flags_disabled` varchar(100) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
INSERT INTO
|
||||
`starting_items_new`
|
||||
(
|
||||
SELECT
|
||||
0 AS `id`,
|
||||
GROUP_CONCAT(DISTINCT `class` ORDER BY class ASC SEPARATOR '|') AS `class_list`,
|
||||
GROUP_CONCAT(DISTINCT `race` ORDER BY race ASC SEPARATOR '|') AS `race_list`,
|
||||
GROUP_CONCAT(DISTINCT `deityid` ORDER BY deityid ASC SEPARATOR '|') AS `deity_list`,
|
||||
GROUP_CONCAT(DISTINCT `zoneid` ORDER BY zoneid ASC SEPARATOR '|') AS `zone_list`,
|
||||
`itemid`,
|
||||
`item_charges`,
|
||||
`gm`,
|
||||
`slot`,
|
||||
`min_expansion`,
|
||||
`max_expansion`,
|
||||
`content_flags`,
|
||||
`content_flags_disabled`
|
||||
FROM
|
||||
`starting_items`
|
||||
GROUP BY
|
||||
`itemid`
|
||||
);
|
||||
|
||||
DROP TABLE `starting_items`;
|
||||
RENAME TABLE `starting_items_new` TO `starting_items`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9244,
|
||||
.description = "2023_11_30_items_table_schema.sql",
|
||||
.check = "SHOW COLUMNS FROM `items` LIKE 'updated'",
|
||||
.condition = "contains",
|
||||
.match = "0000-00-00 00:00:00",
|
||||
.sql = R"(
|
||||
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9245,
|
||||
.description = "2023_12_03_object_incline.sql",
|
||||
.check = "SHOW COLUMNS FROM `object` LIKE 'incline'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
|
||||
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
|
||||
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9246,
|
||||
.description = "2023_12_07_keyring_id.sql",
|
||||
.check = "SHOW COLUMNS FROM `keyring` LIKE 'id'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `keyring`
|
||||
ADD COLUMN `id` int UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
|
||||
ADD PRIMARY KEY (`id`);
|
||||
)"
|
||||
}
|
||||
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
|
||||
@@ -2594,11 +2594,11 @@ struct BookButton_Struct
|
||||
struct Object_Struct {
|
||||
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
|
||||
/*08*/ float size; //
|
||||
/*10*/ uint16 solidtype; //
|
||||
/*10*/ uint16 solid_type; //
|
||||
/*12*/ uint32 drop_id; // Unique object id for zone
|
||||
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
|
||||
/*18*/ uint16 zone_instance; //
|
||||
/*20*/ uint32 unknown020; //
|
||||
/*20*/ uint32 incline; //
|
||||
/*24*/ uint32 unknown024; //
|
||||
/*28*/ float tilt_x;
|
||||
/*32*/ float tilt_y;
|
||||
|
||||
@@ -238,25 +238,6 @@ enum { //some random constants
|
||||
// Timer to update aggrometer
|
||||
#define AGGRO_METER_UPDATE_MS 1000
|
||||
|
||||
//Some hard coded statuses from commands and other places:
|
||||
enum {
|
||||
minStatusToBeGM = 40,
|
||||
minStatusToUseGMCommands = 80,
|
||||
minStatusToKick = 150,
|
||||
minStatusToAvoidFalling = 100,
|
||||
minStatusToIgnoreZoneFlags = 80,
|
||||
minStatusToSeeOthersZoneFlags = 80,
|
||||
minStatusToEditOtherGuilds = 80,
|
||||
commandMovecharSelfOnly = 80, //below this == only self move allowed
|
||||
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
|
||||
commandCastSpecials = 100, //can cast special spells
|
||||
commandDoAnimOthers = 100, //can #doanim on others
|
||||
commandEditPlayerCorpses = 150, //can Edit Player Corpses
|
||||
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
|
||||
commandInvSnapshot = 150 //ability to clear/restore snapshots
|
||||
};
|
||||
|
||||
|
||||
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
|
||||
#define SAYLINK_ITEM_ID 0xFFFFF
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseBlockedSpellsRepository {
|
||||
public:
|
||||
struct BlockedSpells {
|
||||
@@ -31,6 +32,10 @@ public:
|
||||
float z_diff;
|
||||
std::string message;
|
||||
std::string description;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -53,6 +58,10 @@ public:
|
||||
"z_diff",
|
||||
"message",
|
||||
"description",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -71,6 +80,10 @@ public:
|
||||
"z_diff",
|
||||
"message",
|
||||
"description",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -111,18 +124,22 @@ public:
|
||||
{
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = 0;
|
||||
e.spellid = 0;
|
||||
e.type = 0;
|
||||
e.zoneid = 0;
|
||||
e.x = 0;
|
||||
e.y = 0;
|
||||
e.z = 0;
|
||||
e.x_diff = 0;
|
||||
e.y_diff = 0;
|
||||
e.z_diff = 0;
|
||||
e.message = "";
|
||||
e.description = "";
|
||||
e.id = 0;
|
||||
e.spellid = 0;
|
||||
e.type = 0;
|
||||
e.zoneid = 0;
|
||||
e.x = 0;
|
||||
e.y = 0;
|
||||
e.z = 0;
|
||||
e.x_diff = 0;
|
||||
e.y_diff = 0;
|
||||
e.z_diff = 0;
|
||||
e.message = "";
|
||||
e.description = "";
|
||||
e.min_expansion = -1;
|
||||
e.max_expansion = -1;
|
||||
e.content_flags = "";
|
||||
e.content_flags_disabled = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -148,8 +165,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
blocked_spells_id
|
||||
)
|
||||
);
|
||||
@@ -158,18 +176,22 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -214,6 +236,10 @@ public:
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.z_diff));
|
||||
v.push_back(columns[10] + " = '" + Strings::Escape(e.message) + "'");
|
||||
v.push_back(columns[11] + " = '" + Strings::Escape(e.description) + "'");
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -247,6 +273,10 @@ public:
|
||||
v.push_back(std::to_string(e.z_diff));
|
||||
v.push_back("'" + Strings::Escape(e.message) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.description) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -288,6 +318,10 @@ public:
|
||||
v.push_back(std::to_string(e.z_diff));
|
||||
v.push_back("'" + Strings::Escape(e.message) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.description) + "'");
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -321,18 +355,22 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -357,18 +395,22 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BlockedSpells e{};
|
||||
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.id = static_cast<int32_t>(atoi(row[0]));
|
||||
e.spellid = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
e.type = static_cast<int8_t>(atoi(row[2]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.x = strtof(row[4], nullptr);
|
||||
e.y = strtof(row[5], nullptr);
|
||||
e.z = strtof(row[6], nullptr);
|
||||
e.x_diff = strtof(row[7], nullptr);
|
||||
e.y_diff = strtof(row[8], nullptr);
|
||||
e.z_diff = strtof(row[9], nullptr);
|
||||
e.message = row[10] ? row[10] : "";
|
||||
e.description = row[11] ? row[11] : "";
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
int32_t damageshield;
|
||||
int32_t deity;
|
||||
int32_t delay;
|
||||
int32_t augdistiller;
|
||||
uint32_t augdistiller;
|
||||
int32_t dotshielding;
|
||||
int32_t dr;
|
||||
int32_t clicktype;
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
int32_t focusunk5;
|
||||
std::string focusunk6;
|
||||
int32_t focusunk7;
|
||||
int32_t scrollunk1;
|
||||
uint32_t scrollunk1;
|
||||
int32_t scrollunk2;
|
||||
int32_t scrollunk3;
|
||||
int32_t scrollunk4;
|
||||
@@ -266,10 +266,10 @@ public:
|
||||
std::string created;
|
||||
int16_t elitematerial;
|
||||
int16_t ldonsellbackrate;
|
||||
int16_t scriptfileid;
|
||||
int32_t scriptfileid;
|
||||
int16_t expendablearrow;
|
||||
int16_t powersourcecapacity;
|
||||
int16_t bardeffect;
|
||||
int32_t powersourcecapacity;
|
||||
int32_t bardeffect;
|
||||
int16_t bardeffecttype;
|
||||
int16_t bardlevel2;
|
||||
int16_t bardlevel;
|
||||
@@ -1307,7 +1307,7 @@ public:
|
||||
e.damageshield = static_cast<int32_t>(atoi(row[52]));
|
||||
e.deity = static_cast<int32_t>(atoi(row[53]));
|
||||
e.delay = static_cast<int32_t>(atoi(row[54]));
|
||||
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
|
||||
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
|
||||
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
|
||||
e.dr = static_cast<int32_t>(atoi(row[57]));
|
||||
e.clicktype = static_cast<int32_t>(atoi(row[58]));
|
||||
@@ -1459,7 +1459,7 @@ public:
|
||||
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
|
||||
e.focusunk6 = row[205] ? row[205] : "";
|
||||
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
|
||||
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
|
||||
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
|
||||
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
|
||||
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
|
||||
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
|
||||
@@ -1498,10 +1498,10 @@ public:
|
||||
e.created = row[243] ? row[243] : "";
|
||||
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
|
||||
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
|
||||
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
|
||||
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
|
||||
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
|
||||
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
|
||||
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
|
||||
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
|
||||
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
|
||||
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
|
||||
@@ -2563,7 +2563,7 @@ public:
|
||||
e.damageshield = static_cast<int32_t>(atoi(row[52]));
|
||||
e.deity = static_cast<int32_t>(atoi(row[53]));
|
||||
e.delay = static_cast<int32_t>(atoi(row[54]));
|
||||
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
|
||||
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
|
||||
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
|
||||
e.dr = static_cast<int32_t>(atoi(row[57]));
|
||||
e.clicktype = static_cast<int32_t>(atoi(row[58]));
|
||||
@@ -2715,7 +2715,7 @@ public:
|
||||
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
|
||||
e.focusunk6 = row[205] ? row[205] : "";
|
||||
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
|
||||
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
|
||||
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
|
||||
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
|
||||
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
|
||||
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
|
||||
@@ -2754,10 +2754,10 @@ public:
|
||||
e.created = row[243] ? row[243] : "";
|
||||
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
|
||||
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
|
||||
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
|
||||
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
|
||||
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
|
||||
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
|
||||
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
|
||||
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
|
||||
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
|
||||
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
|
||||
@@ -2872,7 +2872,7 @@ public:
|
||||
e.damageshield = static_cast<int32_t>(atoi(row[52]));
|
||||
e.deity = static_cast<int32_t>(atoi(row[53]));
|
||||
e.delay = static_cast<int32_t>(atoi(row[54]));
|
||||
e.augdistiller = static_cast<int32_t>(atoi(row[55]));
|
||||
e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
|
||||
e.dotshielding = static_cast<int32_t>(atoi(row[56]));
|
||||
e.dr = static_cast<int32_t>(atoi(row[57]));
|
||||
e.clicktype = static_cast<int32_t>(atoi(row[58]));
|
||||
@@ -3024,7 +3024,7 @@ public:
|
||||
e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
|
||||
e.focusunk6 = row[205] ? row[205] : "";
|
||||
e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
|
||||
e.scrollunk1 = static_cast<int32_t>(atoi(row[207]));
|
||||
e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
|
||||
e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
|
||||
e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
|
||||
e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
|
||||
@@ -3063,10 +3063,10 @@ public:
|
||||
e.created = row[243] ? row[243] : "";
|
||||
e.elitematerial = static_cast<int16_t>(atoi(row[244]));
|
||||
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
|
||||
e.scriptfileid = static_cast<int16_t>(atoi(row[246]));
|
||||
e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
|
||||
e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
|
||||
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int16_t>(atoi(row[249]));
|
||||
e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
|
||||
e.bardeffect = static_cast<int32_t>(atoi(row[249]));
|
||||
e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
|
||||
e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
|
||||
e.bardlevel = static_cast<int16_t>(atoi(row[252]));
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_KEYRING_REPOSITORY_H
|
||||
#define EQEMU_BASE_KEYRING_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseKeyringRepository {
|
||||
public:
|
||||
struct Keyring {
|
||||
uint32_t id;
|
||||
int32_t char_id;
|
||||
int32_t item_id;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"char_id",
|
||||
"item_id",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"char_id",
|
||||
"item_id",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("keyring");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static Keyring NewEntity()
|
||||
{
|
||||
Keyring e{};
|
||||
|
||||
e.id = 0;
|
||||
e.char_id = 0;
|
||||
e.item_id = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static Keyring GetKeyring(
|
||||
const std::vector<Keyring> &keyrings,
|
||||
int keyring_id
|
||||
)
|
||||
{
|
||||
for (auto &keyring : keyrings) {
|
||||
if (keyring.id == keyring_id) {
|
||||
return keyring;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static Keyring FindOne(
|
||||
Database& db,
|
||||
int keyring_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
keyring_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
Keyring e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.char_id = static_cast<int32_t>(atoi(row[1]));
|
||||
e.item_id = static_cast<int32_t>(atoi(row[2]));
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int keyring_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
keyring_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const Keyring &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static Keyring InsertOne(
|
||||
Database& db,
|
||||
Keyring e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<Keyring> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.char_id));
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<Keyring> All(Database& db)
|
||||
{
|
||||
std::vector<Keyring> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Keyring e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.char_id = static_cast<int32_t>(atoi(row[1]));
|
||||
e.item_id = static_cast<int32_t>(atoi(row[2]));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<Keyring> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<Keyring> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Keyring e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.char_id = static_cast<int32_t>(atoi(row[1]));
|
||||
e.item_id = static_cast<int32_t>(atoi(row[2]));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_KEYRING_REPOSITORY_H
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseObjectRepository {
|
||||
public:
|
||||
struct Object {
|
||||
@@ -31,9 +32,9 @@ public:
|
||||
std::string objectname;
|
||||
int32_t type;
|
||||
int32_t icon;
|
||||
int32_t unknown08;
|
||||
int32_t unknown10;
|
||||
int32_t unknown20;
|
||||
float size_percentage;
|
||||
int32_t solid_type;
|
||||
int32_t incline;
|
||||
int32_t unknown24;
|
||||
int32_t unknown60;
|
||||
int32_t unknown64;
|
||||
@@ -71,9 +72,9 @@ public:
|
||||
"objectname",
|
||||
"type",
|
||||
"icon",
|
||||
"unknown08",
|
||||
"unknown10",
|
||||
"unknown20",
|
||||
"size_percentage",
|
||||
"solid_type",
|
||||
"incline",
|
||||
"unknown24",
|
||||
"unknown60",
|
||||
"unknown64",
|
||||
@@ -107,9 +108,9 @@ public:
|
||||
"objectname",
|
||||
"type",
|
||||
"icon",
|
||||
"unknown08",
|
||||
"unknown10",
|
||||
"unknown20",
|
||||
"size_percentage",
|
||||
"solid_type",
|
||||
"incline",
|
||||
"unknown24",
|
||||
"unknown60",
|
||||
"unknown64",
|
||||
@@ -177,9 +178,9 @@ public:
|
||||
e.objectname = "";
|
||||
e.type = 0;
|
||||
e.icon = 0;
|
||||
e.unknown08 = 0;
|
||||
e.unknown10 = 0;
|
||||
e.unknown20 = 0;
|
||||
e.size_percentage = 0;
|
||||
e.solid_type = 0;
|
||||
e.incline = 0;
|
||||
e.unknown24 = 0;
|
||||
e.unknown60 = 0;
|
||||
e.unknown64 = 0;
|
||||
@@ -220,8 +221,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
object_id
|
||||
)
|
||||
);
|
||||
@@ -242,9 +244,9 @@ public:
|
||||
e.objectname = row[9] ? row[9] : "";
|
||||
e.type = static_cast<int32_t>(atoi(row[10]));
|
||||
e.icon = static_cast<int32_t>(atoi(row[11]));
|
||||
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
|
||||
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
|
||||
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
|
||||
e.size_percentage = strtof(row[12], nullptr);
|
||||
e.solid_type = static_cast<int32_t>(atoi(row[13]));
|
||||
e.incline = static_cast<int32_t>(atoi(row[14]));
|
||||
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
|
||||
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
|
||||
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
|
||||
@@ -304,9 +306,9 @@ public:
|
||||
v.push_back(columns[9] + " = '" + Strings::Escape(e.objectname) + "'");
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.type));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.icon));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.unknown08));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.unknown10));
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.unknown20));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.size_percentage));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.solid_type));
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.incline));
|
||||
v.push_back(columns[15] + " = " + std::to_string(e.unknown24));
|
||||
v.push_back(columns[16] + " = " + std::to_string(e.unknown60));
|
||||
v.push_back(columns[17] + " = " + std::to_string(e.unknown64));
|
||||
@@ -355,9 +357,9 @@ public:
|
||||
v.push_back("'" + Strings::Escape(e.objectname) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.icon));
|
||||
v.push_back(std::to_string(e.unknown08));
|
||||
v.push_back(std::to_string(e.unknown10));
|
||||
v.push_back(std::to_string(e.unknown20));
|
||||
v.push_back(std::to_string(e.size_percentage));
|
||||
v.push_back(std::to_string(e.solid_type));
|
||||
v.push_back(std::to_string(e.incline));
|
||||
v.push_back(std::to_string(e.unknown24));
|
||||
v.push_back(std::to_string(e.unknown60));
|
||||
v.push_back(std::to_string(e.unknown64));
|
||||
@@ -414,9 +416,9 @@ public:
|
||||
v.push_back("'" + Strings::Escape(e.objectname) + "'");
|
||||
v.push_back(std::to_string(e.type));
|
||||
v.push_back(std::to_string(e.icon));
|
||||
v.push_back(std::to_string(e.unknown08));
|
||||
v.push_back(std::to_string(e.unknown10));
|
||||
v.push_back(std::to_string(e.unknown20));
|
||||
v.push_back(std::to_string(e.size_percentage));
|
||||
v.push_back(std::to_string(e.solid_type));
|
||||
v.push_back(std::to_string(e.incline));
|
||||
v.push_back(std::to_string(e.unknown24));
|
||||
v.push_back(std::to_string(e.unknown60));
|
||||
v.push_back(std::to_string(e.unknown64));
|
||||
@@ -477,9 +479,9 @@ public:
|
||||
e.objectname = row[9] ? row[9] : "";
|
||||
e.type = static_cast<int32_t>(atoi(row[10]));
|
||||
e.icon = static_cast<int32_t>(atoi(row[11]));
|
||||
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
|
||||
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
|
||||
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
|
||||
e.size_percentage = strtof(row[12], nullptr);
|
||||
e.solid_type = static_cast<int32_t>(atoi(row[13]));
|
||||
e.incline = static_cast<int32_t>(atoi(row[14]));
|
||||
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
|
||||
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
|
||||
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
|
||||
@@ -531,9 +533,9 @@ public:
|
||||
e.objectname = row[9] ? row[9] : "";
|
||||
e.type = static_cast<int32_t>(atoi(row[10]));
|
||||
e.icon = static_cast<int32_t>(atoi(row[11]));
|
||||
e.unknown08 = static_cast<int32_t>(atoi(row[12]));
|
||||
e.unknown10 = static_cast<int32_t>(atoi(row[13]));
|
||||
e.unknown20 = static_cast<int32_t>(atoi(row[14]));
|
||||
e.size_percentage = strtof(row[12], nullptr);
|
||||
e.solid_type = static_cast<int32_t>(atoi(row[13]));
|
||||
e.incline = static_cast<int32_t>(atoi(row[14]));
|
||||
e.unknown24 = static_cast<int32_t>(atoi(row[15]));
|
||||
e.unknown60 = static_cast<int32_t>(atoi(row[16]));
|
||||
e.unknown64 = static_cast<int32_t>(atoi(row[17]));
|
||||
|
||||
@@ -16,17 +16,18 @@
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
class BaseStartingItemsRepository {
|
||||
public:
|
||||
struct StartingItems {
|
||||
uint32_t id;
|
||||
int32_t race;
|
||||
int32_t class_;
|
||||
int32_t deityid;
|
||||
int32_t zoneid;
|
||||
int32_t itemid;
|
||||
std::string race_list;
|
||||
std::string class_list;
|
||||
std::string deity_list;
|
||||
std::string zone_id_list;
|
||||
uint32_t item_id;
|
||||
uint8_t item_charges;
|
||||
int8_t gm;
|
||||
uint8_t gm;
|
||||
int32_t slot;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
@@ -43,11 +44,11 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"race",
|
||||
"`class`",
|
||||
"deityid",
|
||||
"zoneid",
|
||||
"itemid",
|
||||
"race_list",
|
||||
"class_list",
|
||||
"deity_list",
|
||||
"zone_id_list",
|
||||
"item_id",
|
||||
"item_charges",
|
||||
"gm",
|
||||
"slot",
|
||||
@@ -62,11 +63,11 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"race",
|
||||
"`class`",
|
||||
"deityid",
|
||||
"zoneid",
|
||||
"itemid",
|
||||
"race_list",
|
||||
"class_list",
|
||||
"deity_list",
|
||||
"zone_id_list",
|
||||
"item_id",
|
||||
"item_charges",
|
||||
"gm",
|
||||
"slot",
|
||||
@@ -115,11 +116,11 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = 0;
|
||||
e.race = 0;
|
||||
e.class_ = 0;
|
||||
e.deityid = 0;
|
||||
e.zoneid = 0;
|
||||
e.itemid = 0;
|
||||
e.race_list = "";
|
||||
e.class_list = "";
|
||||
e.deity_list = "";
|
||||
e.zone_id_list = "";
|
||||
e.item_id = 0;
|
||||
e.item_charges = 1;
|
||||
e.gm = 0;
|
||||
e.slot = -1;
|
||||
@@ -152,8 +153,9 @@ public:
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
starting_items_id
|
||||
)
|
||||
);
|
||||
@@ -163,13 +165,13 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.race = static_cast<int32_t>(atoi(row[1]));
|
||||
e.class_ = static_cast<int32_t>(atoi(row[2]));
|
||||
e.deityid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[4]));
|
||||
e.itemid = static_cast<int32_t>(atoi(row[5]));
|
||||
e.race_list = row[1] ? row[1] : "";
|
||||
e.class_list = row[2] ? row[2] : "";
|
||||
e.deity_list = row[3] ? row[3] : "";
|
||||
e.zone_id_list = row[4] ? row[4] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
|
||||
e.gm = static_cast<int8_t>(atoi(row[7]));
|
||||
e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
|
||||
@@ -208,11 +210,11 @@ public:
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.race));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.class_));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.deityid));
|
||||
v.push_back(columns[4] + " = " + std::to_string(e.zoneid));
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.itemid));
|
||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.race_list) + "'");
|
||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.class_list) + "'");
|
||||
v.push_back(columns[3] + " = '" + Strings::Escape(e.deity_list) + "'");
|
||||
v.push_back(columns[4] + " = '" + Strings::Escape(e.zone_id_list) + "'");
|
||||
v.push_back(columns[5] + " = " + std::to_string(e.item_id));
|
||||
v.push_back(columns[6] + " = " + std::to_string(e.item_charges));
|
||||
v.push_back(columns[7] + " = " + std::to_string(e.gm));
|
||||
v.push_back(columns[8] + " = " + std::to_string(e.slot));
|
||||
@@ -242,11 +244,11 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.class_));
|
||||
v.push_back(std::to_string(e.deityid));
|
||||
v.push_back(std::to_string(e.zoneid));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back("'" + Strings::Escape(e.race_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.class_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.deity_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.item_charges));
|
||||
v.push_back(std::to_string(e.gm));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
@@ -284,11 +286,11 @@ public:
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.id));
|
||||
v.push_back(std::to_string(e.race));
|
||||
v.push_back(std::to_string(e.class_));
|
||||
v.push_back(std::to_string(e.deityid));
|
||||
v.push_back(std::to_string(e.zoneid));
|
||||
v.push_back(std::to_string(e.itemid));
|
||||
v.push_back("'" + Strings::Escape(e.race_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.class_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.deity_list) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
|
||||
v.push_back(std::to_string(e.item_id));
|
||||
v.push_back(std::to_string(e.item_charges));
|
||||
v.push_back(std::to_string(e.gm));
|
||||
v.push_back(std::to_string(e.slot));
|
||||
@@ -330,13 +332,13 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.race = static_cast<int32_t>(atoi(row[1]));
|
||||
e.class_ = static_cast<int32_t>(atoi(row[2]));
|
||||
e.deityid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[4]));
|
||||
e.itemid = static_cast<int32_t>(atoi(row[5]));
|
||||
e.race_list = row[1] ? row[1] : "";
|
||||
e.class_list = row[2] ? row[2] : "";
|
||||
e.deity_list = row[3] ? row[3] : "";
|
||||
e.zone_id_list = row[4] ? row[4] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
|
||||
e.gm = static_cast<int8_t>(atoi(row[7]));
|
||||
e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
|
||||
@@ -367,13 +369,13 @@ public:
|
||||
StartingItems e{};
|
||||
|
||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.race = static_cast<int32_t>(atoi(row[1]));
|
||||
e.class_ = static_cast<int32_t>(atoi(row[2]));
|
||||
e.deityid = static_cast<int32_t>(atoi(row[3]));
|
||||
e.zoneid = static_cast<int32_t>(atoi(row[4]));
|
||||
e.itemid = static_cast<int32_t>(atoi(row[5]));
|
||||
e.race_list = row[1] ? row[1] : "";
|
||||
e.class_list = row[2] ? row[2] : "";
|
||||
e.deity_list = row[3] ? row[3] : "";
|
||||
e.zone_id_list = row[4] ? row[4] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
|
||||
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
|
||||
e.gm = static_cast<int8_t>(atoi(row[7]));
|
||||
e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
|
||||
e.slot = static_cast<int32_t>(atoi(row[8]));
|
||||
e.min_expansion = static_cast<int8_t>(atoi(row[9]));
|
||||
e.max_expansion = static_cast<int8_t>(atoi(row[10]));
|
||||
|
||||
@@ -120,6 +120,7 @@ public:
|
||||
{.parent_command = "set", .sub_command = "title_suffix", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "titlesuffix"},
|
||||
{.parent_command = "set", .sub_command = "weather", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "weather"},
|
||||
{.parent_command = "set", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zclip|zcolor|zheader|zonelock|zsafecoords|zsky|zunderworld"},
|
||||
{.parent_command = "show", .sub_command = "aas", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaas"},
|
||||
{.parent_command = "show", .sub_command = "aa_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaapoints|showaapts"},
|
||||
{.parent_command = "show", .sub_command = "aggro", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "aggro"},
|
||||
{.parent_command = "show", .sub_command = "buffs", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showbuffs"},
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EQEMU_KEYRING_REPOSITORY_H
|
||||
#define EQEMU_KEYRING_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_keyring_repository.h"
|
||||
|
||||
class KeyringRepository: public BaseKeyringRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* KeyringRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* KeyringRepository::GetWhereNeverExpires()
|
||||
* KeyringRepository::GetWhereXAndY()
|
||||
* KeyringRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_KEYRING_REPOSITORY_H
|
||||
@@ -304,6 +304,7 @@ RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools gl
|
||||
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
|
||||
RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30")
|
||||
RULE_INT(World, BootHour, 0, "Sets the in-game hour world will set when it first boots. 0-24 are valid options, where 0 disables this rule")
|
||||
RULE_BOOL(World, UseItemLinksForKeyRing, false, "Uses item links for Key Ring Listing instead of item name")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Zone)
|
||||
@@ -649,6 +650,7 @@ RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on
|
||||
RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell")
|
||||
RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell")
|
||||
RULE_BOOL(Bots, AllowPickpocketCommand, true, "Allows the use of the bot command 'pickpocket'")
|
||||
RULE_BOOL(Bots, BotHealOnLevel, false, "Setting whether a bot should heal completely when leveling. Default FALSE.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Chat)
|
||||
|
||||
+6
-6
@@ -461,12 +461,12 @@ struct SPackSendQueue {
|
||||
uchar buffer[0];
|
||||
};
|
||||
|
||||
struct ServerZoneStateChange_struct {
|
||||
uint32 ZoneServerID;
|
||||
char adminname[64];
|
||||
uint32 zoneid;
|
||||
uint16 instanceid;
|
||||
bool makestatic;
|
||||
struct ServerZoneStateChange_Struct {
|
||||
uint32 zone_server_id;
|
||||
uint32 zone_id;
|
||||
uint16 instance_id;
|
||||
bool is_static;
|
||||
char admin_name[64];
|
||||
};
|
||||
|
||||
struct ServerZoneIncomingClient_Struct {
|
||||
|
||||
+65
-28
@@ -41,6 +41,7 @@
|
||||
#include "repositories/criteria/content_filter_criteria.h"
|
||||
#include "repositories/account_repository.h"
|
||||
#include "repositories/faction_association_repository.h"
|
||||
#include "repositories/starting_items_repository.h"
|
||||
#include "path_manager.h"
|
||||
#include "repositories/loottable_repository.h"
|
||||
|
||||
@@ -446,45 +447,81 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQ::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
|
||||
bool SharedDatabase::SetStartingItems(
|
||||
PlayerProfile_Struct *pp,
|
||||
EQ::InventoryProfile *inv,
|
||||
uint32 si_race,
|
||||
uint32 si_class,
|
||||
uint32 si_deity,
|
||||
uint32 si_current_zone,
|
||||
char *si_name,
|
||||
int admin_level
|
||||
)
|
||||
{
|
||||
const EQ::ItemData *item_data;
|
||||
|
||||
const EQ::ItemData *myitem;
|
||||
const auto &l = StartingItemsRepository::All(*this);
|
||||
|
||||
const std::string query = StringFormat(
|
||||
"SELECT itemid, item_charges, slot FROM starting_items "
|
||||
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
|
||||
"(deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND "
|
||||
"gm <= %i %s ORDER BY id",
|
||||
si_race,
|
||||
si_class,
|
||||
si_deity,
|
||||
si_current_zone,
|
||||
admin_level,
|
||||
ContentFilterCriteria::apply().c_str()
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<StartingItemsRepository::StartingItems> v;
|
||||
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
const int32 itemid = Strings::ToInt(row[0]);
|
||||
const int32 charges = Strings::ToInt(row[1]);
|
||||
int32 slot = Strings::ToInt(row[2]);
|
||||
myitem = GetItem(itemid);
|
||||
for (const auto &e : l) {
|
||||
const auto &classes = Strings::Split(e.class_list, "|");
|
||||
const auto &deities = Strings::Split(e.deity_list, "|");
|
||||
const auto &races = Strings::Split(e.race_list, "|");
|
||||
const auto &zones = Strings::Split(e.zone_id_list, "|");
|
||||
|
||||
if(!myitem)
|
||||
const std::string &all = std::to_string(0);
|
||||
|
||||
if (classes[0] != all) {
|
||||
if (!Strings::Contains(classes, std::to_string(si_class))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (deities[0] != all) {
|
||||
if (!Strings::Contains(deities, std::to_string(si_deity))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (races[0] != all) {
|
||||
if (!Strings::Contains(races, std::to_string(si_race))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (zones[0] != all) {
|
||||
if (!Strings::Contains(zones, std::to_string(si_current_zone))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
v.emplace_back(e);
|
||||
}
|
||||
|
||||
for (const auto &e : v) {
|
||||
const uint32 item_id = e.item_id;
|
||||
const uint8 item_charges = e.item_charges;
|
||||
int32 slot = e.slot;
|
||||
|
||||
item_data = GetItem(item_id);
|
||||
|
||||
if (!item_data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const EQ::ItemInstance* myinst = CreateBaseItem(myitem, charges);
|
||||
const auto *inst = CreateBaseItem(item_data, item_charges);
|
||||
|
||||
if(slot < 0)
|
||||
slot = inv->FindFreeSlot(0, 0);
|
||||
if (slot < EQ::invslot::slotCharm) {
|
||||
slot = inv->FindFreeSlot(false, false);
|
||||
}
|
||||
|
||||
inv->PutItem(slot, *myinst);
|
||||
safe_delete(myinst);
|
||||
inv->PutItem(slot, *inst);
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.34.1-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.35.0-dev" // always append -dev to the current version for custom-builds
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
@@ -42,7 +42,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9242
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9246
|
||||
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040
|
||||
|
||||
|
||||
+10
-28
@@ -121,43 +121,25 @@ bool Database::GetLoginTokenDataFromToken(
|
||||
std::string &user
|
||||
)
|
||||
{
|
||||
auto query = fmt::format(
|
||||
"SELECT tbllogintokens.Id, tbllogintokens.IpAddress, tbllogintokenclaims.Name, tbllogintokenclaims.Value FROM tbllogintokens "
|
||||
"JOIN tbllogintokenclaims ON tbllogintokens.Id = tbllogintokenclaims.TokenId WHERE tbllogintokens.Expires > NOW() "
|
||||
"AND tbllogintokens.Id='{0}' AND tbllogintokens.IpAddress='{1}'",
|
||||
auto query = fmt::format("SELECT login_server, username, account_id FROM login_tickets WHERE expires > NOW()"
|
||||
" AND id='{0}' AND ip_address='{1}' LIMIT 1",
|
||||
Strings::Escape(token),
|
||||
Strings::Escape(ip)
|
||||
);
|
||||
Strings::Escape(ip));
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (results.RowCount() == 0 || !results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found_username = false;
|
||||
bool found_login_id = false;
|
||||
bool found_login_server_name = false;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (strcmp(row[2], "username") == 0) {
|
||||
user = row[3];
|
||||
found_username = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(row[2], "login_server_id") == 0) {
|
||||
db_account_id = Strings::ToUnsignedInt(row[3]);
|
||||
found_login_id = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(row[2], "login_server_name") == 0) {
|
||||
db_loginserver = row[3];
|
||||
found_login_server_name = true;
|
||||
continue;
|
||||
}
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
db_loginserver = row[0];
|
||||
user = row[1];
|
||||
db_account_id = Strings::ToUnsignedInt(row[2]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return found_username && found_login_id && found_login_server_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
DROP TABLE IF EXISTS `login_tickets`;
|
||||
CREATE TABLE `login_tickets` (
|
||||
`id` VARCHAR(128) NOT NULL,
|
||||
`login_server` TEXT NOT NULL,
|
||||
`username` TEXT NOT NULL,
|
||||
`account_id` INT(10) UNSIGNED NOT NULL,
|
||||
`ip_address` VARCHAR(45) NOT NULL,
|
||||
`expires` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
)
|
||||
ENGINE=InnoDB;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "22.34.1",
|
||||
"version": "22.35.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
|
||||
########################################################################
|
||||
#::: 13th floor import script
|
||||
#::: Current Source: http://items.sodeq.org/download.php
|
||||
#::: Authors: (Natedog, Akkadius)
|
||||
#::: Items Source: http://items.sodeq.org/download.php
|
||||
#::: How To:
|
||||
#::: 1. Place this script with your server eqemu_config.json
|
||||
#::: 2. Download the items.txt file and place with this script
|
||||
#::: 3. Run this script with Perl
|
||||
#::: 4. Review new and updated items in the items_new table
|
||||
#::: 5. Make any desired changes and replace the items table contents
|
||||
########################################################################
|
||||
|
||||
use DBI;
|
||||
@@ -16,6 +21,7 @@ my $db_user = "";
|
||||
my $db_pass = "";
|
||||
my $total_items = 0;
|
||||
my $read_items_file = "items.txt"; #default
|
||||
my $keep_temp_items_table = 0; #keeps the imported items table
|
||||
|
||||
read_eqemu_config_json();
|
||||
|
||||
@@ -24,7 +30,7 @@ my $dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;port=$db_port"
|
||||
read_items_file_from_13th_floor_text();
|
||||
update_items_table();
|
||||
|
||||
print "\n\nImport complete!\n\n";
|
||||
print "\n\nImport complete! Review items_new table before replacing into items table.\n\n";
|
||||
|
||||
sub read_eqemu_config_json {
|
||||
use JSON;
|
||||
@@ -139,7 +145,12 @@ sub read_items_file_from_13th_floor_text {
|
||||
|
||||
sub update_items_table {
|
||||
|
||||
print "Updating items table...\n";
|
||||
#::: Establish items_new table
|
||||
print "Setting up new items table...\n";
|
||||
$dbh->do("DROP TABLE IF EXISTS items_new");
|
||||
$dbh->do("CREATE TABLE items_new AS SELECT * FROM items");
|
||||
|
||||
print "Updating new items table...\n";
|
||||
|
||||
my @matching_table;
|
||||
my @missing_items_table;
|
||||
@@ -147,7 +158,7 @@ sub update_items_table {
|
||||
|
||||
print "Comparing table structure...\n";
|
||||
#::: Get columns from `items`
|
||||
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items`;");
|
||||
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items_new`;");
|
||||
$sth->execute();
|
||||
my @items_table;
|
||||
while (my @row = $sth->fetchrow_array()) {
|
||||
@@ -230,7 +241,7 @@ sub update_items_table {
|
||||
}
|
||||
|
||||
my $update_query = "
|
||||
INSERT INTO items (" . $items_field_list . ")
|
||||
INSERT INTO items_new (" . $items_field_list . ")
|
||||
SELECT " . $items_floor_field_list . "
|
||||
FROM items_floor fi
|
||||
ON DUPLICATE KEY UPDATE " . $update_fields;
|
||||
@@ -257,14 +268,20 @@ sub update_items_table {
|
||||
|
||||
#::: Update stackables
|
||||
print "Updating stackable field...\n";
|
||||
$dbh->do("UPDATE items i SET i.stackable = 1 WHERE i.stacksize > 1");
|
||||
$dbh->do("UPDATE items_new i SET i.stackable = 1 WHERE i.stacksize > 1");
|
||||
|
||||
#::: Update legacy research tome bagtypes
|
||||
print "Updating legacy research tomes...\n";
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 24 WHERE i.id IN (17655, 17903)"); #RESEARCHWIZ
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 25 WHERE i.id IN (17502, 17653)"); #RESEARCHMAG
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 26 WHERE i.id IN (17501, 17654)"); #RESEARCHNEC
|
||||
$dbh->do("UPDATE items i SET i.bagtype = 27 WHERE i.id IN (17500, 17652)"); #RESEARCHENC
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 24 WHERE i.id IN (17655, 17903)"); #RESEARCHWIZ
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 25 WHERE i.id IN (17502, 17653)"); #RESEARCHMAG
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 26 WHERE i.id IN (17501, 17654)"); #RESEARCHNEC
|
||||
$dbh->do("UPDATE items_new i SET i.bagtype = 27 WHERE i.id IN (17500, 17652)"); #RESEARCHENC
|
||||
|
||||
#::: Remove temp table
|
||||
if (!$keep_temp_items_table) {
|
||||
print "Cleaning up temp items table...\n";
|
||||
$dbh->do("DROP TABLE items_floor");
|
||||
}
|
||||
}
|
||||
|
||||
sub trim($) {
|
||||
|
||||
+10
-10
@@ -578,25 +578,25 @@ void ConsoleZoneShutdown(
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
|
||||
auto pack = new ServerPacket;
|
||||
pack->size = sizeof(ServerZoneStateChange_struct);
|
||||
pack->size = sizeof(ServerZoneStateChange_Struct);
|
||||
pack->pBuffer = new uchar[pack->size];
|
||||
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct));
|
||||
ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer;
|
||||
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_Struct));
|
||||
auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
|
||||
pack->opcode = ServerOP_ZoneShutdown;
|
||||
strcpy(s->adminname, tmpname);
|
||||
strcpy(s->admin_name, tmpname);
|
||||
if (Strings::IsNumber(args[0])) {
|
||||
s->ZoneServerID = Strings::ToInt(args[0]);
|
||||
s->zone_server_id = Strings::ToInt(args[0]);
|
||||
}
|
||||
else {
|
||||
s->zoneid = ZoneID(args[0].c_str());
|
||||
s->zone_id = ZoneID(args[0].c_str());
|
||||
}
|
||||
|
||||
ZoneServer *zs = 0;
|
||||
if (s->ZoneServerID != 0) {
|
||||
zs = zoneserver_list.FindByID(s->ZoneServerID);
|
||||
if (s->zone_server_id != 0) {
|
||||
zs = zoneserver_list.FindByID(s->zone_server_id);
|
||||
}
|
||||
else if (s->zoneid != 0) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zoneid));
|
||||
else if (s->zone_id != 0) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zone_id));
|
||||
}
|
||||
else {
|
||||
connection->SendLine("Error: ZoneShutdown: neither ID nor name specified");
|
||||
|
||||
+21
-18
@@ -720,15 +720,15 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneShutdown: {
|
||||
auto s = (ServerZoneStateChange_struct*) pack->pBuffer;
|
||||
auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
|
||||
ZoneServer* zs = 0;
|
||||
if (s->ZoneServerID) {
|
||||
zs = zoneserver_list.FindByID(s->ZoneServerID);
|
||||
} else if (s->zoneid) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zoneid));
|
||||
if (s->zone_server_id) {
|
||||
zs = zoneserver_list.FindByID(s->zone_server_id);
|
||||
} else if (s->zone_id) {
|
||||
zs = zoneserver_list.FindByName(ZoneName(s->zone_id));
|
||||
} else {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
s->adminname,
|
||||
s->admin_name,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
@@ -738,7 +738,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
|
||||
if (!zs) {
|
||||
zoneserver_list.SendEmoteMessage(
|
||||
s->adminname,
|
||||
s->admin_name,
|
||||
0,
|
||||
AccountStatus::Player,
|
||||
Chat::White,
|
||||
@@ -751,8 +751,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneBootup: {
|
||||
auto s = (ServerZoneStateChange_struct*) pack->pBuffer;
|
||||
zoneserver_list.SOPZoneBootup(s->adminname, s->ZoneServerID, ZoneName(s->zoneid), s->makestatic);
|
||||
auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
|
||||
zoneserver_list.SOPZoneBootup(s->admin_name, s->zone_server_id, ZoneName(s->zone_id), s->is_static);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneStatus: {
|
||||
@@ -1606,20 +1606,23 @@ void ZoneServer::ChangeWID(uint32 iCharID, uint32 iWID) {
|
||||
|
||||
|
||||
void ZoneServer::TriggerBootup(uint32 in_zone_id, uint32 in_instance_id, const char* admin_name, bool is_static_zone) {
|
||||
is_booting_up = true;
|
||||
is_booting_up = true;
|
||||
zone_server_zone_id = in_zone_id;
|
||||
instance_id = in_instance_id;
|
||||
instance_id = in_instance_id;
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_Struct));
|
||||
auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
|
||||
|
||||
s->zone_server_id = zone_server_id;
|
||||
|
||||
s->zone_id = in_zone_id ? in_zone_id : GetZoneID();
|
||||
s->instance_id = in_instance_id;
|
||||
s->is_static = is_static_zone;
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct));
|
||||
auto s = (ServerZoneStateChange_struct*) pack->pBuffer;
|
||||
s->ZoneServerID = zone_server_id;
|
||||
if (admin_name) {
|
||||
strn0cpy(s->adminname, admin_name, sizeof(s->adminname));
|
||||
strn0cpy(s->admin_name, admin_name, sizeof(s->admin_name));
|
||||
}
|
||||
|
||||
s->zoneid = in_zone_id ? in_zone_id : GetZoneID();
|
||||
s->instanceid = in_instance_id;
|
||||
s->makestatic = is_static_zone;
|
||||
SendPacket(pack);
|
||||
delete pack;
|
||||
LSBootUpdate(in_zone_id, in_instance_id);
|
||||
|
||||
+94
@@ -2207,3 +2207,97 @@ bool Client::HasAlreadyPurchasedRank(AA::Rank* rank) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::ListPurchasedAAs(Client *to, std::string search_criteria)
|
||||
{
|
||||
if (!to) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::string, uint8> client_aa_ranks;
|
||||
|
||||
for (auto &aa : zone->aa_abilities) {
|
||||
AA::Ability *ability = aa.second.get();
|
||||
|
||||
AA::Rank *rank = ability->first;
|
||||
while (rank) {
|
||||
if (!CanUseAlternateAdvancementRank(rank)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (HasAlreadyPurchasedRank(rank)) {
|
||||
const std::string aa_name = zone->GetAAName(rank->id);
|
||||
if (
|
||||
search_criteria.empty() ||
|
||||
Strings::Contains(
|
||||
Strings::ToLower(aa_name),
|
||||
Strings::ToLower(search_criteria)
|
||||
)
|
||||
) {
|
||||
if (client_aa_ranks.find(aa_name) == client_aa_ranks.end()) {
|
||||
client_aa_ranks[aa_name] = 1;
|
||||
} else {
|
||||
client_aa_ranks[aa_name]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rank = rank->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (client_aa_ranks.empty()) {
|
||||
to->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} {} no purchased AAs{}.",
|
||||
to->GetTargetDescription(this, TargetDescriptionType::UCYou),
|
||||
this == to ? "have" : "has",
|
||||
(
|
||||
!search_criteria.empty() ?
|
||||
fmt::format(
|
||||
" matching '{}'",
|
||||
search_criteria
|
||||
) :
|
||||
""
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
int aa_number = 1;
|
||||
|
||||
for (const auto &aa : client_aa_ranks) {
|
||||
to->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{}. {} (Rank {})",
|
||||
aa_number,
|
||||
aa.first,
|
||||
aa.second
|
||||
).c_str()
|
||||
);
|
||||
|
||||
aa_number++;
|
||||
}
|
||||
|
||||
to->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} {} {} purchased AA{}{}.",
|
||||
to->GetTargetDescription(this, TargetDescriptionType::UCYou),
|
||||
this == to ? "have" : "has",
|
||||
client_aa_ranks.size(),
|
||||
client_aa_ranks.size() > 1 ? "s" : "",
|
||||
(
|
||||
!search_criteria.empty() ?
|
||||
fmt::format(
|
||||
" matching '{}'",
|
||||
search_criteria
|
||||
) :
|
||||
""
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
+17
-1
@@ -3634,13 +3634,29 @@ void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) {
|
||||
|
||||
for (auto biter = blist.begin(); biter != blist.end(); ++biter) {
|
||||
Bot* bot = *biter;
|
||||
|
||||
if (bot && (bot->GetLevel() != client->GetLevel())) {
|
||||
bot->SetPetChooser(false); // not sure what this does, but was in bot 'update' code
|
||||
bot->CalcBotStats(client->GetBotOption(Client::booStatsUpdate));
|
||||
if (sendlvlapp)
|
||||
|
||||
if (sendlvlapp) {
|
||||
bot->SendLevelAppearance();
|
||||
}
|
||||
// modified from Client::SetLevel()
|
||||
if (!RuleB(Bots, BotHealOnLevel)) {
|
||||
int mhp = bot->CalcMaxHP();
|
||||
if (bot->GetHP() > mhp) {
|
||||
bot->SetHP(mhp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bot->SetHP(bot->CalcMaxHP());
|
||||
bot->SetMana(bot->CalcMaxMana());
|
||||
}
|
||||
|
||||
bot->SendHPUpdate();
|
||||
bot->SendAppearancePacket(AT_WhoLevel, level, true, true); // who level change
|
||||
bot->AI_AddBotSpells(bot->GetBotSpellID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpel
|
||||
if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0)
|
||||
continue;
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar)) {
|
||||
if (IsValidSpellRange(iter.SpellId, tar)) {
|
||||
casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost);
|
||||
}
|
||||
if (casted_spell) {
|
||||
@@ -328,7 +328,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar)) {
|
||||
if (IsValidSpellRange(iter.SpellId, tar)) {
|
||||
casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost);
|
||||
}
|
||||
|
||||
@@ -447,7 +447,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
|
||||
|
||||
uint32 TempDontDotMeBefore = tar->DontDotMeBefore();
|
||||
|
||||
if (IsValidSpellRange(botSpell.SpellId, tar)) {
|
||||
if (IsValidSpellRange(s.SpellId, tar)) {
|
||||
casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontDotMeBefore);
|
||||
}
|
||||
|
||||
|
||||
+75
-32
@@ -65,6 +65,7 @@ extern volatile bool RunLoops;
|
||||
#include "../common/repositories/character_disciplines_repository.h"
|
||||
#include "../common/repositories/character_data_repository.h"
|
||||
#include "../common/repositories/discovered_items_repository.h"
|
||||
#include "../common/repositories/keyring_repository.h"
|
||||
#include "../common/events/player_events.h"
|
||||
#include "../common/events/player_event_logs.h"
|
||||
#include "dialogue_window.h"
|
||||
@@ -4087,54 +4088,87 @@ void Client::SendWindow(
|
||||
|
||||
void Client::KeyRingLoad()
|
||||
{
|
||||
std::string query = StringFormat("SELECT item_id FROM keyring "
|
||||
"WHERE char_id = '%i' ORDER BY item_id", character_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
const auto &l = KeyringRepository::GetWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`char_id` = {} ORDER BY `item_id`",
|
||||
character_id
|
||||
)
|
||||
);
|
||||
|
||||
if (l.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
keyring.push_back(Strings::ToInt(row[0]));
|
||||
|
||||
for (const auto &e : l) {
|
||||
keyring.emplace_back(e.item_id);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::KeyRingAdd(uint32 item_id)
|
||||
{
|
||||
if(0==item_id)
|
||||
return;
|
||||
|
||||
bool found = KeyRingCheck(item_id);
|
||||
if (found)
|
||||
return;
|
||||
|
||||
std::string query = StringFormat("INSERT INTO keyring(char_id, item_id) VALUES(%i, %i)", character_id, item_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
if (!item_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
Message(Chat::LightBlue,"Added to keyring.");
|
||||
const bool found = KeyRingCheck(item_id);
|
||||
if (found) {
|
||||
return;
|
||||
}
|
||||
|
||||
keyring.push_back(item_id);
|
||||
auto e = KeyringRepository::NewEntity();
|
||||
|
||||
e.char_id = CharacterID();
|
||||
e.item_id = item_id;
|
||||
|
||||
e = KeyringRepository::InsertOne(database, e);
|
||||
|
||||
if (!e.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
keyring.emplace_back(item_id);
|
||||
|
||||
if (!RuleB(World, UseItemLinksForKeyRing)) {
|
||||
Message(Chat::LightBlue, "Added to keyring.");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string &item_link = database.CreateItemLink(item_id);
|
||||
|
||||
Message(
|
||||
Chat::LightBlue,
|
||||
fmt::format(
|
||||
"Added {} to keyring.",
|
||||
item_link
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
bool Client::KeyRingCheck(uint32 item_id)
|
||||
{
|
||||
for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) {
|
||||
if(*iter == item_id)
|
||||
for (const auto &e : keyring) {
|
||||
if (e == item_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::KeyRingList()
|
||||
{
|
||||
Message(Chat::LightBlue,"Keys on Keyring:");
|
||||
Message(Chat::LightBlue, "Keys on Keyring:");
|
||||
|
||||
const EQ::ItemData *item = nullptr;
|
||||
for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) {
|
||||
if ((item = database.GetItem(*iter))!=nullptr) {
|
||||
Message(Chat::LightBlue,item->Name);
|
||||
|
||||
for (const auto &e : keyring) {
|
||||
item = database.GetItem(e);
|
||||
if (item) {
|
||||
const std::string &item_string = RuleB(World, UseItemLinksForKeyRing) ? database.CreateItemLink(e) : item->Name;
|
||||
|
||||
Message(Chat::LightBlue, item_string.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10355,6 +10389,16 @@ void Client::SetDoorToolEntityId(uint16 door_tool_entity_id)
|
||||
Client::m_door_tool_entity_id = door_tool_entity_id;
|
||||
}
|
||||
|
||||
uint16 Client::GetObjectToolEntityId() const
|
||||
{
|
||||
return m_object_tool_entity_id;
|
||||
}
|
||||
|
||||
void Client::SetObjectToolEntityId(uint16 object_tool_entity_id)
|
||||
{
|
||||
Client::m_object_tool_entity_id = object_tool_entity_id;
|
||||
}
|
||||
|
||||
int Client::GetIPExemption()
|
||||
{
|
||||
return database.GetIPExemption(GetIPString());
|
||||
@@ -11127,16 +11171,15 @@ void Client::AddAAPoints(uint32 points)
|
||||
{
|
||||
m_pp.aapoints += points;
|
||||
|
||||
if (points == 1 && m_pp.aapoints == 1)
|
||||
{
|
||||
if (parse->PlayerHasQuestSub(EVENT_AA_GAIN)) {
|
||||
parse->EventPlayer(EVENT_AA_GAIN, this, std::to_string(points), 0);
|
||||
}
|
||||
|
||||
if (points == 1 && m_pp.aapoints == 1) {
|
||||
MessageString(Chat::Yellow, GAIN_SINGLE_AA_SINGLE_AA, fmt::format_int(m_pp.aapoints).c_str());
|
||||
}
|
||||
else if (points == 1 && m_pp.aapoints > 1)
|
||||
{
|
||||
} else if (points == 1 && m_pp.aapoints > 1) {
|
||||
MessageString(Chat::Yellow, GAIN_SINGLE_AA_MULTI_AA, fmt::format_int(m_pp.aapoints).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
MessageString(Chat::Yellow, GAIN_MULTI_AA_MULTI_AA, fmt::format_int(points).c_str(), fmt::format_int(m_pp.aapoints).c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -908,6 +908,7 @@ public:
|
||||
void AutoGrantAAPoints();
|
||||
void GrantAllAAPoints(uint8 unlock_level = 0);
|
||||
bool HasAlreadyPurchasedRank(AA::Rank* rank);
|
||||
void ListPurchasedAAs(Client *to, std::string search_criteria = std::string());
|
||||
|
||||
bool SendGMCommand(std::string message, bool ignore_status = false);
|
||||
|
||||
@@ -1274,6 +1275,10 @@ public:
|
||||
}
|
||||
else { return 0; }
|
||||
}
|
||||
inline bool CompleteTask(uint32 task_id)
|
||||
{
|
||||
return task_state ? task_state->CompleteTask(this, task_id) : false;
|
||||
}
|
||||
inline void FailTask(int task_id) { if (task_state) { task_state->FailTask(this, task_id); }}
|
||||
inline int TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); }
|
||||
inline int EnabledTaskCount(int task_set_id)
|
||||
@@ -1809,9 +1814,12 @@ private:
|
||||
bool dev_tools_enabled;
|
||||
|
||||
uint16 m_door_tool_entity_id;
|
||||
uint16 m_object_tool_entity_id;
|
||||
public:
|
||||
uint16 GetDoorToolEntityId() const;
|
||||
void SetDoorToolEntityId(uint16 door_tool_entity_id);
|
||||
uint16 GetObjectToolEntityId() const;
|
||||
void SetObjectToolEntityId(uint16 object_tool_entity_id);
|
||||
private:
|
||||
|
||||
int32 max_end;
|
||||
|
||||
+216
-188
@@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||
#include "../common/shared_tasks.h"
|
||||
#include "gm_commands/door_manipulation.h"
|
||||
#include "gm_commands/object_manipulation.h"
|
||||
#include "client.h"
|
||||
#include "../common/repositories/account_repository.h"
|
||||
|
||||
@@ -1385,10 +1386,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
|
||||
InitInnates();
|
||||
|
||||
/* If GM not set in DB, and does not meet min status to be GM, reset */
|
||||
if (m_pp.gm && admin < minStatusToBeGM)
|
||||
m_pp.gm = 0;
|
||||
|
||||
/* Load Guild */
|
||||
if (!IsInAGuild()) {
|
||||
m_pp.guild_id = GUILD_NONE;
|
||||
@@ -1702,8 +1699,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
this is not quite where live sends inventory, they do it after tribute
|
||||
*/
|
||||
if (loaditems) { /* Don't load if a length error occurs */
|
||||
if (admin >= minStatusToBeGM)
|
||||
if (m_pp.gm) {
|
||||
m_inv.SetGMInventory(true); // set to true to allow expansion-restricted packets through
|
||||
}
|
||||
|
||||
BulkSendInventoryItems();
|
||||
/* Send stuff on the cursor which isn't sent in bulk */
|
||||
@@ -4653,6 +4651,20 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app)
|
||||
std::vector<std::any> args = { object };
|
||||
parse->EventPlayer(EVENT_CLICK_OBJECT, this, std::to_string(click_object->drop_id), GetID(), &args);
|
||||
}
|
||||
|
||||
if (IsDevToolsEnabled()) {
|
||||
SetObjectToolEntityId(entity->GetID());
|
||||
ObjectManipulation::CommandHeader(this);
|
||||
Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Object ({}) [{}] [{}]",
|
||||
entity->CastToObject()->GetDBID(),
|
||||
Saylink::Silent("#object edit", "Edit"),
|
||||
Saylink::Silent("#object delete", "Delete")
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Observed in RoF after OP_ClickObjectAction:
|
||||
@@ -6238,7 +6250,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
|
||||
damage = 31337;
|
||||
}
|
||||
|
||||
if (admin >= minStatusToAvoidFalling && GetGM()) {
|
||||
if (GetGM()) {
|
||||
Message(
|
||||
Chat::Red,
|
||||
fmt::format(
|
||||
@@ -6446,84 +6458,90 @@ void Client::Handle_OP_GetGuildsList(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_GMBecomeNPC(const EQApplicationPacket *app)
|
||||
{
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /becomenpc when they shouldn't be able to"});
|
||||
return;
|
||||
}
|
||||
|
||||
if (app->size != sizeof(BecomeNPC_Struct)) {
|
||||
LogError("Wrong size: OP_GMBecomeNPC, size=[{}], expected [{}]", app->size, sizeof(BecomeNPC_Struct));
|
||||
return;
|
||||
}
|
||||
//entity_list.QueueClients(this, app, false);
|
||||
BecomeNPC_Struct* bnpc = (BecomeNPC_Struct*)app->pBuffer;
|
||||
|
||||
Mob* cli = (Mob*)entity_list.GetMob(bnpc->id);
|
||||
if (cli == nullptr) {
|
||||
auto *b = (BecomeNPC_Struct *) app->pBuffer;
|
||||
|
||||
Mob *m = entity_list.GetMob(b->id);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli->IsClient()) {
|
||||
Client* target = cli->CastToClient();
|
||||
target->QueuePacket(app);
|
||||
if(target->GetGM()) {
|
||||
target->SetInvul(false);
|
||||
target->SetHideMe(false);
|
||||
target->SetGM(false);
|
||||
if (m->IsClient()) {
|
||||
Client *t = m->CastToClient();
|
||||
t->QueuePacket(app);
|
||||
if (t->GetGM()) {
|
||||
t->SetInvul(false);
|
||||
t->SetHideMe(false);
|
||||
t->SetGM(false);
|
||||
}
|
||||
|
||||
cli->SendAppearancePacket(AT_NPCName, 1, true);
|
||||
target->SetBecomeNPC(true);
|
||||
target->SetBecomeNPCLevel(bnpc->maxlevel);
|
||||
cli->MessageString(Chat::White, TOGGLE_OFF);
|
||||
target->tellsoff = true;
|
||||
target->UpdateWho();
|
||||
m->SendAppearancePacket(AT_NPCName, 1, true);
|
||||
t->SetBecomeNPC(true);
|
||||
t->SetBecomeNPCLevel(b->maxlevel);
|
||||
m->MessageString(Chat::White, TOGGLE_OFF);
|
||||
t->tellsoff = true;
|
||||
t->UpdateWho();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMDelCorpse(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(GMDelCorpse_Struct))
|
||||
if (app->size != sizeof(GMDelCorpse_Struct)) {
|
||||
return;
|
||||
if (Admin() < commandEditPlayerCorpses) {
|
||||
}
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /delcorpse"});
|
||||
return;
|
||||
}
|
||||
GMDelCorpse_Struct* dc = (GMDelCorpse_Struct *)app->pBuffer;
|
||||
Mob* corpse = entity_list.GetMob(dc->corpsename);
|
||||
if (corpse == 0) {
|
||||
|
||||
auto *c = (GMDelCorpse_Struct *) app->pBuffer;
|
||||
Mob *corpse = entity_list.GetMob(c->corpsename);
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
if (corpse->IsCorpse() != true) {
|
||||
|
||||
if (!corpse->IsCorpse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
corpse->CastToCorpse()->Delete();
|
||||
std::cout << name << " deleted corpse " << dc->corpsename << std::endl;
|
||||
Message(Chat::Red, "Corpse %s deleted.", dc->corpsename);
|
||||
return;
|
||||
Message(Chat::Red, fmt::format("Corpse {} deleted.", c->corpsename).c_str());
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMEmoteZone(const EQApplicationPacket *app)
|
||||
{
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(GMEmoteZone_Struct)) {
|
||||
LogError("Wrong size: OP_GMEmoteZone, size=[{}], expected [{}]", app->size, sizeof(GMEmoteZone_Struct));
|
||||
return;
|
||||
}
|
||||
GMEmoteZone_Struct* gmez = (GMEmoteZone_Struct*)app->pBuffer;
|
||||
char* newmessage = nullptr;
|
||||
if (strstr(gmez->text, "^") == 0)
|
||||
entity_list.Message(Chat::White, 15, gmez->text);
|
||||
else {
|
||||
for (newmessage = strtok((char*)gmez->text, "^"); newmessage != nullptr; newmessage = strtok(nullptr, "^"))
|
||||
entity_list.Message(Chat::White, 15, newmessage);
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /emote"});
|
||||
return;
|
||||
}
|
||||
|
||||
auto *gmez = (GMEmoteZone_Struct*)app->pBuffer;
|
||||
char *newmessage = nullptr;
|
||||
if (strstr(gmez->text, "^") == 0) {
|
||||
entity_list.Message(0, Chat::White, gmez->text);
|
||||
} else {
|
||||
for (newmessage = strtok((char *) gmez->text, "^"); newmessage != nullptr; newmessage = strtok(nullptr, "^")) {
|
||||
entity_list.Message(0, Chat::White, newmessage);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMEndTraining(const EQApplicationPacket *app)
|
||||
@@ -6533,154 +6551,149 @@ void Client::Handle_OP_GMEndTraining(const EQApplicationPacket *app)
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
OPGMEndTraining(app);
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMFind(const EQApplicationPacket *app)
|
||||
{
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"});
|
||||
return;
|
||||
}
|
||||
|
||||
if (app->size != sizeof(GMFind_Struct)) {
|
||||
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMFind_Struct));
|
||||
return;
|
||||
}
|
||||
|
||||
//Break down incoming
|
||||
auto* request = (GMFind_Struct*) app->pBuffer;
|
||||
//Create a new outgoing
|
||||
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMFind_Struct));
|
||||
auto* foundplayer = (GMFind_Struct*) outapp->pBuffer;
|
||||
//Copy the constants
|
||||
strcpy(foundplayer->charname, request->charname);
|
||||
strcpy(foundplayer->gmname, request->gmname);
|
||||
//Check if the NPC exits intrazone...
|
||||
auto* gt = entity_list.GetMob(request->charname);
|
||||
if (gt) {
|
||||
foundplayer->success = 1;
|
||||
foundplayer->x = gt->GetX();
|
||||
foundplayer->y = gt->GetY();
|
||||
foundplayer->z = gt->GetZ();
|
||||
foundplayer->zoneID = zone->GetZoneID();
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"});
|
||||
return;
|
||||
}
|
||||
//Send the packet...
|
||||
|
||||
auto *r = (GMFind_Struct *) app->pBuffer;
|
||||
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMFind_Struct));
|
||||
auto *f = (GMFind_Struct *) outapp->pBuffer;
|
||||
|
||||
strcpy(f->charname, r->charname);
|
||||
strcpy(f->gmname, r->gmname);
|
||||
|
||||
auto* gt = entity_list.GetMob(r->charname);
|
||||
if (gt) {
|
||||
f->success = 1;
|
||||
f->x = gt->GetX();
|
||||
f->y = gt->GetY();
|
||||
f->z = gt->GetZ();
|
||||
f->zoneID = zone->GetZoneID();
|
||||
}
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMGoto(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(GMSummon_Struct)) {
|
||||
std::cout << "Wrong size on OP_GMGoto. Got: " << app->size << ", Expected: " << sizeof(GMSummon_Struct) << std::endl;
|
||||
LogError("Wrong size: OP_GMGoto, size=[{}], expected [{}]", app->size, sizeof(GMSummon_Struct));
|
||||
return;
|
||||
}
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /goto"});
|
||||
return;
|
||||
}
|
||||
GMSummon_Struct* gmg = (GMSummon_Struct*)app->pBuffer;
|
||||
Mob* gt = entity_list.GetMob(gmg->charname);
|
||||
if (gt != nullptr) {
|
||||
|
||||
auto *gmg = (GMSummon_Struct *) app->pBuffer;
|
||||
Mob *gt = entity_list.GetMob(gmg->charname);
|
||||
if (!gt) {
|
||||
MovePC(zone->GetZoneID(), zone->GetInstanceID(), gt->GetX(), gt->GetY(), gt->GetZ(), gt->GetHeading());
|
||||
}
|
||||
else if (!worldserver.Connected())
|
||||
} else if (!worldserver.Connected()) {
|
||||
Message(Chat::Red, "Error: World server disconnected.");
|
||||
else {
|
||||
} else {
|
||||
auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct));
|
||||
memset(pack->pBuffer, 0, pack->size);
|
||||
ServerGMGoto_Struct* wsgmg = (ServerGMGoto_Struct*)pack->pBuffer;
|
||||
ServerGMGoto_Struct *wsgmg = (ServerGMGoto_Struct *) pack->pBuffer;
|
||||
strcpy(wsgmg->myname, GetName());
|
||||
strcpy(wsgmg->gotoname, gmg->charname);
|
||||
wsgmg->admin = admin;
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMHideMe(const EQApplicationPacket *app)
|
||||
{
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /hideme"});
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(SpawnAppearance_Struct)) {
|
||||
LogError("Wrong size: OP_GMHideMe, size=[{}], expected [{}]", app->size, sizeof(SpawnAppearance_Struct));
|
||||
return;
|
||||
}
|
||||
SpawnAppearance_Struct* sa = (SpawnAppearance_Struct*)app->pBuffer;
|
||||
Message(Chat::Red, "#: %i, %i", sa->type, sa->parameter);
|
||||
SetHideMe(!sa->parameter);
|
||||
return;
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /hideme"});
|
||||
return;
|
||||
}
|
||||
|
||||
auto *sa = (SpawnAppearance_Struct *) app->pBuffer;
|
||||
SetHideMe(!sa->parameter);
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMKick(const EQApplicationPacket *app)
|
||||
{
|
||||
if (app->size != sizeof(GMKick_Struct))
|
||||
if (app->size != sizeof(GMKick_Struct)) {
|
||||
return;
|
||||
if (Admin() < minStatusToKick) {
|
||||
}
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kick"});
|
||||
return;
|
||||
}
|
||||
GMKick_Struct* gmk = (GMKick_Struct *)app->pBuffer;
|
||||
|
||||
Client* client = entity_list.GetClientByName(gmk->name);
|
||||
if (client == 0) {
|
||||
if (!worldserver.Connected())
|
||||
auto *gmk = (GMKick_Struct *)app->pBuffer;
|
||||
Client *c = entity_list.GetClientByName(gmk->name);
|
||||
if (!c) {
|
||||
if (!worldserver.Connected()) {
|
||||
Message(Chat::Red, "Error: World server disconnected");
|
||||
else {
|
||||
} else {
|
||||
auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
|
||||
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack->pBuffer;
|
||||
auto *skp = (ServerKickPlayer_Struct *) pack->pBuffer;
|
||||
strcpy(skp->adminname, gmk->gmname);
|
||||
strcpy(skp->name, gmk->name);
|
||||
skp->adminrank = Admin();
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
entity_list.QueueClients(this, app);
|
||||
//client->Kick();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMKill(const EQApplicationPacket *app)
|
||||
{
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kill"});
|
||||
return;
|
||||
}
|
||||
if (app->size != sizeof(GMKill_Struct)) {
|
||||
LogError("Wrong size: OP_GMKill, size=[{}], expected [{}]", app->size, sizeof(GMKill_Struct));
|
||||
return;
|
||||
}
|
||||
GMKill_Struct* gmk = (GMKill_Struct *)app->pBuffer;
|
||||
Mob* obj = entity_list.GetMob(gmk->name);
|
||||
Client* client = entity_list.GetClientByName(gmk->name);
|
||||
if (obj != 0) {
|
||||
if (client != 0) {
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kill"});
|
||||
return;
|
||||
}
|
||||
|
||||
auto *gmk = (GMKill_Struct *) app->pBuffer;
|
||||
Mob *obj = entity_list.GetMob(gmk->name);
|
||||
Client *c = entity_list.GetClientByName(gmk->name);
|
||||
if (obj) {
|
||||
if (c) {
|
||||
entity_list.QueueClients(this, app);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
obj->Kill();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!worldserver.Connected())
|
||||
} else {
|
||||
if (!worldserver.Connected()) {
|
||||
Message(Chat::Red, "Error: World server disconnected");
|
||||
else {
|
||||
} else {
|
||||
auto pack = new ServerPacket(ServerOP_KillPlayer, sizeof(ServerKillPlayer_Struct));
|
||||
ServerKillPlayer_Struct* skp = (ServerKillPlayer_Struct*)pack->pBuffer;
|
||||
auto *skp = (ServerKillPlayer_Struct *) pack->pBuffer;
|
||||
strcpy(skp->gmname, gmk->gmname);
|
||||
strcpy(skp->target, gmk->name);
|
||||
skp->admin = Admin();
|
||||
@@ -6688,7 +6701,6 @@ void Client::Handle_OP_GMKill(const EQApplicationPacket *app)
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMLastName(const EQApplicationPacket *app)
|
||||
@@ -6697,32 +6709,30 @@ void Client::Handle_OP_GMLastName(const EQApplicationPacket *app)
|
||||
std::cout << "Wrong size on OP_GMLastName. Got: " << app->size << ", Expected: " << sizeof(GMLastName_Struct) << std::endl;
|
||||
return;
|
||||
}
|
||||
GMLastName_Struct* gmln = (GMLastName_Struct*)app->pBuffer;
|
||||
if (strlen(gmln->lastname) >= 64) {
|
||||
Message(Chat::Red, "/LastName: New last name too long. (max=63)");
|
||||
}
|
||||
else {
|
||||
Client* client = entity_list.GetClientByName(gmln->name);
|
||||
if (client == 0) {
|
||||
Message(Chat::Red, "/LastName: %s not found", gmln->name);
|
||||
}
|
||||
else {
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /lastname"});
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
client->ChangeLastName(gmln->lastname);
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /lastname"});
|
||||
return;
|
||||
}
|
||||
|
||||
auto *gmln = (GMLastName_Struct *) app->pBuffer;
|
||||
if (strlen(gmln->lastname) >= 64) {
|
||||
Message(Chat::Red, "/LastName: New last name too long. Max length is 63.");
|
||||
} else {
|
||||
Client *c = entity_list.GetClientByName(gmln->name);
|
||||
if (!c) {
|
||||
Message(Chat::Red, fmt::format("/LastName: {} not found", gmln->name).c_str());
|
||||
} else {
|
||||
c->ChangeLastName(gmln->lastname);
|
||||
}
|
||||
|
||||
gmln->unknown[0] = 1;
|
||||
gmln->unknown[1] = 1;
|
||||
gmln->unknown[2] = 1;
|
||||
gmln->unknown[3] = 1;
|
||||
entity_list.QueueClients(this, app, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app)
|
||||
@@ -6731,44 +6741,49 @@ void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app)
|
||||
LogError("Wrong size: OP_GMNameChange, size=[{}], expected [{}]", app->size, sizeof(GMName_Struct));
|
||||
return;
|
||||
}
|
||||
const GMName_Struct* gmn = (const GMName_Struct *)app->pBuffer;
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
|
||||
auto *gmn = (GMName_Struct *) app->pBuffer;
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /name"});
|
||||
return;
|
||||
}
|
||||
Client* client = entity_list.GetClientByName(gmn->oldname);
|
||||
LogInfo("GM([{}]) changeing players name. Old:[{}] New:[{}]", GetName(), gmn->oldname, gmn->newname);
|
||||
bool usedname = database.CheckUsedName(gmn->newname);
|
||||
if (client == 0) {
|
||||
Message(Chat::Red, "%s not found for name change. Operation failed!", gmn->oldname);
|
||||
return;
|
||||
}
|
||||
if ((strlen(gmn->newname) > 63) || (strlen(gmn->newname) == 0)) {
|
||||
Message(Chat::Red, "Invalid number of characters in new name (%s).", gmn->newname);
|
||||
return;
|
||||
}
|
||||
if (!usedname) {
|
||||
Message(Chat::Red, "%s is already in use. Operation failed!", gmn->newname);
|
||||
return;
|
||||
|
||||
Client *c = entity_list.GetClientByName(gmn->oldname);
|
||||
LogInfo("GM([{}]) changeing players name. Old:[{}] New:[{}]", GetName(), gmn->oldname, gmn->newname);
|
||||
|
||||
const bool used_name = database.CheckUsedName(gmn->newname);
|
||||
if (!c) {
|
||||
Message(Chat::Red, fmt::format("{} not found for name change. Operation failed!", gmn->oldname).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(gmn->newname) > 63 || strlen(gmn->newname) == 0) {
|
||||
Message(Chat::Red, fmt::format("Invalid number of characters in new name '{}'.", gmn->newname).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!used_name) {
|
||||
Message(Chat::Red, fmt::format("{} is already in use. Operation failed!", gmn->newname).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
database.UpdateName(gmn->oldname, gmn->newname);
|
||||
strcpy(client->name, gmn->newname);
|
||||
client->Save();
|
||||
strcpy(c->name, gmn->newname);
|
||||
c->Save();
|
||||
|
||||
if (gmn->badname == 1) {
|
||||
database.AddToNameFilter(gmn->oldname);
|
||||
}
|
||||
EQApplicationPacket* outapp = app->Copy();
|
||||
GMName_Struct* gmn2 = (GMName_Struct*)outapp->pBuffer;
|
||||
|
||||
auto *outapp = app->Copy();
|
||||
auto *gmn2 = (GMName_Struct *) outapp->pBuffer;
|
||||
gmn2->unknown[0] = 1;
|
||||
gmn2->unknown[1] = 1;
|
||||
gmn2->unknown[2] = 1;
|
||||
entity_list.QueueClients(this, outapp, false);
|
||||
safe_delete(outapp);
|
||||
UpdateWho();
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app)
|
||||
@@ -6863,6 +6878,13 @@ void Client::Handle_OP_GMSummon(const EQApplicationPacket *app)
|
||||
std::cout << "Wrong size on OP_GMSummon. Got: " << app->size << ", Expected: " << sizeof(GMSummon_Struct) << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /summon"});
|
||||
return;
|
||||
}
|
||||
|
||||
OPGMSummon(app);
|
||||
return;
|
||||
}
|
||||
@@ -6873,12 +6895,14 @@ void Client::Handle_OP_GMToggle(const EQApplicationPacket *app)
|
||||
std::cout << "Wrong size on OP_GMToggle. Got: " << app->size << ", Expected: " << sizeof(GMToggle_Struct) << std::endl;
|
||||
return;
|
||||
}
|
||||
if (Admin() < minStatusToUseGMCommands) {
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /toggle"});
|
||||
return;
|
||||
}
|
||||
GMToggle_Struct *ts = (GMToggle_Struct *)app->pBuffer;
|
||||
|
||||
auto *ts = (GMToggle_Struct *)app->pBuffer;
|
||||
if (ts->toggle == 0) {
|
||||
MessageString(Chat::White, TOGGLE_OFF);
|
||||
tellsoff = true;
|
||||
@@ -6886,10 +6910,10 @@ void Client::Handle_OP_GMToggle(const EQApplicationPacket *app)
|
||||
MessageString(Chat::White, TOGGLE_ON);
|
||||
tellsoff = false;
|
||||
} else {
|
||||
Message(Chat::White, "Unkown value in /toggle packet");
|
||||
Message(Chat::White, "Unknown value in /toggle packet.");
|
||||
}
|
||||
|
||||
UpdateWho();
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMTraining(const EQApplicationPacket *app)
|
||||
@@ -6899,6 +6923,7 @@ void Client::Handle_OP_GMTraining(const EQApplicationPacket *app)
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
OPGMTraining(app);
|
||||
return;
|
||||
}
|
||||
@@ -6910,6 +6935,7 @@ void Client::Handle_OP_GMTrainSkill(const EQApplicationPacket *app)
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
OPGMTrainSkill(app);
|
||||
return;
|
||||
}
|
||||
@@ -6920,27 +6946,30 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
|
||||
std::cout << "Wrong size on OP_GMZoneRequest. Got: " << app->size << ", Expected: " << sizeof(GMZoneRequest_Struct) << std::endl;
|
||||
return;
|
||||
}
|
||||
if (Admin() < minStatusToBeGM) {
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"});
|
||||
return;
|
||||
}
|
||||
|
||||
auto* gmzr = (GMZoneRequest_Struct*)app->pBuffer;
|
||||
auto *gmzr = (GMZoneRequest_Struct *) app->pBuffer;
|
||||
float target_x = -1, target_y = -1, target_z = -1, target_heading;
|
||||
|
||||
int16 min_status = AccountStatus::Player;
|
||||
uint8 min_level = 0;
|
||||
char target_zone[32];
|
||||
uint16 zone_id = gmzr->zone_id;
|
||||
if (gmzr->zone_id == 0)
|
||||
int16 min_status = AccountStatus::Player;
|
||||
uint8 min_level = 0;
|
||||
char target_zone[32];
|
||||
uint16 zone_id = gmzr->zone_id;
|
||||
if (gmzr->zone_id == 0) {
|
||||
zone_id = zonesummon_id;
|
||||
}
|
||||
|
||||
const char* zone_short_name = ZoneName(zone_id);
|
||||
if (zone_short_name == nullptr)
|
||||
const char *zone_short_name = ZoneName(zone_id);
|
||||
if (zone_short_name == nullptr) {
|
||||
target_zone[0] = 0;
|
||||
else
|
||||
} else {
|
||||
strcpy(target_zone, zone_short_name);
|
||||
}
|
||||
|
||||
// this both loads the safe points and does a sanity check on zone name
|
||||
auto z = GetZone(target_zone, 0);
|
||||
@@ -6954,41 +6983,40 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_GMZoneRequest, sizeof(GMZoneRequest_Struct));
|
||||
auto* gmzr2 = (GMZoneRequest_Struct*)outapp->pBuffer;
|
||||
auto *gmzr2 = (GMZoneRequest_Struct *) outapp->pBuffer;
|
||||
strcpy(gmzr2->charname, GetName());
|
||||
gmzr2->zone_id = gmzr->zone_id;
|
||||
gmzr2->x = target_x;
|
||||
gmzr2->y = target_y;
|
||||
gmzr2->z = target_z;
|
||||
gmzr2->x = target_x;
|
||||
gmzr2->y = target_y;
|
||||
gmzr2->z = target_z;
|
||||
gmzr2->heading = target_heading;
|
||||
// Next line stolen from ZoneChange as well... - This gives us a nicer message than the normal "zone is down" message...
|
||||
if (target_zone[0] != 0 && admin >= min_status && GetLevel() >= min_level)
|
||||
|
||||
if (target_zone[0] != 0 && admin >= min_status && GetLevel() >= min_level) {
|
||||
gmzr2->success = 1;
|
||||
else {
|
||||
std::cout << "GetZoneSafeCoords failed. zoneid = " << gmzr->zone_id << "; czone = " << zone->GetZoneID() << std::endl;
|
||||
} else {
|
||||
LogError("GetZoneSafeCoords failed. Zone ID [{}] Current Zone [{}]", gmzr->zone_id, zone->GetZoneID());
|
||||
gmzr2->success = 0;
|
||||
}
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GMZoneRequest2(const EQApplicationPacket *app)
|
||||
{
|
||||
if (Admin() < minStatusToBeGM) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"});
|
||||
return;
|
||||
}
|
||||
if (app->size < sizeof(uint32)) {
|
||||
LogError("OP size error: OP_GMZoneRequest2 expected:[{}] got:[{}]", sizeof(uint32), app->size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetGM()) {
|
||||
Message(Chat::Red, "Your account has been reported for hacking.");
|
||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"});
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 zonereq = *((uint32 *)app->pBuffer);
|
||||
GoToSafeCoords(zonereq, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GroupAcknowledge(const EQApplicationPacket *app)
|
||||
|
||||
@@ -866,6 +866,7 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/nukebuffs.cpp"
|
||||
#include "gm_commands/nukeitem.cpp"
|
||||
#include "gm_commands/object.cpp"
|
||||
#include "gm_commands/object_manipulation.cpp"
|
||||
#include "gm_commands/path.cpp"
|
||||
#include "gm_commands/peqzone.cpp"
|
||||
#include "gm_commands/petitems.cpp"
|
||||
|
||||
+1
-1
@@ -277,7 +277,7 @@ void Doors::HandleClick(Client *sender, uint8 trigger)
|
||||
// enforce flags before they hit zoning process
|
||||
auto z = GetZone(m_destination_zone_name, 0);
|
||||
if (z && !z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && Strings::ToInt(z->flag_needed) == 1) {
|
||||
if (sender->Admin() < minStatusToIgnoreZoneFlags && !sender->HasZoneFlag(z->zoneidnumber)) {
|
||||
if (!sender->GetGM() && !sender->HasZoneFlag(z->zoneidnumber)) {
|
||||
LogInfo(
|
||||
"Character [{}] does not have the flag to be in this zone [{}]!",
|
||||
sender->GetCleanName(),
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
void command_acceptrules(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!database.GetAgreementFlag(c->AccountID())) {
|
||||
database.SetAgreementFlag(c->AccountID());
|
||||
c->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
||||
c->Message(Chat::White, "It is recorded you have agreed to the rules.");
|
||||
if (database.GetAgreementFlag(c->AccountID())) {
|
||||
c->Message(Chat::White, "You have already agreed to the rules.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
database.SetAgreementFlag(c->AccountID());
|
||||
c->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
||||
c->Message(Chat::White, "It is recorded you have agreed to the rules.");
|
||||
}
|
||||
|
||||
@@ -23,10 +23,7 @@ void command_castspell(Client *c, const Seperator *sep)
|
||||
|
||||
const uint16 spell_id = Strings::ToUnsignedInt(sep->arg[1]);
|
||||
|
||||
if (IsCastRestrictedSpell(spell_id) && c->Admin() < commandCastSpecials) {
|
||||
c->Message(Chat::White, "Unable to cast spell.");
|
||||
return;
|
||||
} else if (spell_id >= SPDAT_RECORDS) {
|
||||
if (spell_id >= SPDAT_RECORDS) {
|
||||
c->Message(Chat::White, "Invalid Spell ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
+113
-182
@@ -9,18 +9,22 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"
|
||||
);
|
||||
c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse");
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance");
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
}
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"
|
||||
);
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,72 +63,57 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"
|
||||
);
|
||||
c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse");
|
||||
c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse");
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance");
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
}
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
|
||||
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
|
||||
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
|
||||
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"
|
||||
);
|
||||
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (is_delete_player_corpses) {
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
auto corpses_deleted = entity_list.DeletePlayerCorpses();
|
||||
auto deleted_string = (
|
||||
corpses_deleted ?
|
||||
fmt::format(
|
||||
"{} Player corpse{} deleted.",
|
||||
corpses_deleted,
|
||||
corpses_deleted != 1 ? "s" : ""
|
||||
) :
|
||||
"There are no player corpses to delete."
|
||||
);
|
||||
c->Message(Chat::White, deleted_string.c_str());
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to delete player corpses.");
|
||||
return;
|
||||
}
|
||||
auto corpses_deleted = entity_list.DeletePlayerCorpses();
|
||||
auto deleted_string = (
|
||||
corpses_deleted ?
|
||||
fmt::format(
|
||||
"{} Player corpse{} deleted.",
|
||||
corpses_deleted,
|
||||
corpses_deleted != 1 ? "s" : ""
|
||||
) :
|
||||
"There are no player corpses to delete."
|
||||
);
|
||||
c->Message(Chat::White, deleted_string.c_str());
|
||||
} else if (is_delete) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
c->Message(Chat::White, "You must target a corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to delete a player corpse.");
|
||||
return;
|
||||
}
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Deleting {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (
|
||||
target->IsNPCCorpse() ||
|
||||
c->Admin() >= commandEditPlayerCorpses
|
||||
) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Deleting {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
target->CastToCorpse()->Delete();
|
||||
}
|
||||
target->CastToCorpse()->Delete();
|
||||
} else if (is_list_npc) {
|
||||
entity_list.ListNPCCorpses(c);
|
||||
} else if (is_list_player) {
|
||||
if (c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to list player corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
entity_list.ListPlayerCorpses(c);
|
||||
} else if (is_delete_npc_corpses) {
|
||||
auto corpses_deleted = entity_list.DeleteNPCCorpses();
|
||||
@@ -139,42 +128,32 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
);
|
||||
c->Message(Chat::White, deleted_string.c_str());
|
||||
} else if (is_character_id) {
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
if (!target || !target->IsPlayerCorpse()) {
|
||||
c->Message(Chat::White, "You must target a player corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
return;
|
||||
}
|
||||
|
||||
auto character_id = Strings::ToInt(sep->arg[2]);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Setting the owner to {} ({}) for the player corpse {}.",
|
||||
database.GetCharNameByID(character_id),
|
||||
target->CastToCorpse()->SetCharID(character_id),
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to modify a player corpse's owner.");
|
||||
if (!target || !target->IsPlayerCorpse()) {
|
||||
c->Message(Chat::White, "You must target a player corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32 character_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Setting the owner to {} ({}) for the player corpse {}.",
|
||||
database.GetCharNameByID(character_id),
|
||||
target->CastToCorpse()->SetCharID(character_id),
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
} else if (is_reset_looter) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
c->Message(Chat::White, "You must target a corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to reset looter on a player corpse.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->ResetLooter();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -190,36 +169,22 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to remove cash from a player corpse.");
|
||||
return;
|
||||
}
|
||||
target->CastToCorpse()->RemoveCash();
|
||||
|
||||
if (
|
||||
target->IsNPCCorpse() ||
|
||||
c->Admin() >= commandEditPlayerCorpses
|
||||
) {
|
||||
target->CastToCorpse()->RemoveCash();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Removed cash from {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Removed cash from {} corpse {}.",
|
||||
target->IsNPCCorpse() ? "NPC" : "player",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
} else if (is_inspect_loot) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
c->Message(Chat::White, "You must target a corpse to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to inspect the loot of a player corpse.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->QueryLoot(c);
|
||||
} else if (is_lock) {
|
||||
if (!target || !target->IsCorpse()) {
|
||||
@@ -227,11 +192,6 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to lock player corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->Lock();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -247,11 +207,6 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
|
||||
c->Message(Chat::White, "Your status is not high enough to unlock player corpses.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->CastToCorpse()->UnLock();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -267,30 +222,20 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
bool bury_corpse = (
|
||||
sep->IsNumber(2) ?
|
||||
(
|
||||
Strings::ToInt(sep->arg[2]) != 0 ?
|
||||
true :
|
||||
false
|
||||
) :
|
||||
false
|
||||
);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping player corpse {}.",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
target->CastToCorpse()->DepopPlayerCorpse();
|
||||
if (bury_corpse) {
|
||||
target->CastToCorpse()->Bury();
|
||||
}
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to depop a player corpse.");
|
||||
return;
|
||||
const bool bury_corpse = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping player corpse {}.",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
target->CastToCorpse()->DepopPlayerCorpse();
|
||||
|
||||
if (bury_corpse) {
|
||||
target->CastToCorpse()->Bury();
|
||||
}
|
||||
} else if (is_depop_all) {
|
||||
if (!target || !target->IsClient()) {
|
||||
@@ -298,50 +243,36 @@ void command_corpse(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
bool bury_corpse = (
|
||||
sep->IsNumber(2) ?
|
||||
(
|
||||
Strings::ToInt(sep->arg[2]) != 0 ?
|
||||
true :
|
||||
false
|
||||
) :
|
||||
false
|
||||
);
|
||||
const bool bury_corpse = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping all player corpses for {}.",
|
||||
c->GetTargetDescription(target)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
target->CastToClient()->DepopAllCorpses();
|
||||
|
||||
if (bury_corpse) {
|
||||
target->CastToClient()->BuryPlayerCorpses();
|
||||
}
|
||||
} else if (is_move_all_to_graveyard) {
|
||||
const int moved_count = entity_list.MovePlayerCorpsesToGraveyard(true);
|
||||
if (moved_count) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Depopping all player corpses for {}.",
|
||||
c->GetTargetDescription(target)
|
||||
"Moved {} player corpse{} to graveyard in {} ({}).",
|
||||
moved_count,
|
||||
moved_count != 1 ? "s" : "",
|
||||
ZoneLongName(zone->GetZoneID()),
|
||||
ZoneName(zone->GetZoneID())
|
||||
).c_str()
|
||||
);
|
||||
target->CastToClient()->DepopAllCorpses();
|
||||
if (bury_corpse) {
|
||||
target->CastToClient()->BuryPlayerCorpses();
|
||||
}
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to depop all of a player's corpses.");
|
||||
return;
|
||||
}
|
||||
} else if (is_move_all_to_graveyard) {
|
||||
int moved_count = entity_list.MovePlayerCorpsesToGraveyard(true);
|
||||
if (c->Admin() >= commandEditPlayerCorpses) {
|
||||
if (moved_count) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Moved {} player corpse{} to graveyard in {} ({}).",
|
||||
moved_count,
|
||||
moved_count != 1 ? "s" : "",
|
||||
ZoneLongName(zone->GetZoneID()),
|
||||
ZoneName(zone->GetZoneID())
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
c->Message(Chat::White, "There are no player corpses to move to the graveyard.");
|
||||
}
|
||||
} else {
|
||||
c->Message(Chat::White, "Your status is not high enough to move all player corpses to the graveyard.");
|
||||
c->Message(Chat::White, "There are no player corpses to move to the graveyard.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,27 @@
|
||||
|
||||
void command_disarmtrap(Client *c, const Seperator *sep)
|
||||
{
|
||||
Mob *target = c->GetTarget();
|
||||
|
||||
if (!target) {
|
||||
c->Message(Chat::Red, "You must have a target.");
|
||||
Mob *t = c->GetTarget();
|
||||
if (!t || !t->IsNPC()) {
|
||||
c->Message(Chat::White, "You must target an NPC to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (target->IsNPC()) {
|
||||
if (c->HasSkill(EQ::skills::SkillDisarmTraps)) {
|
||||
if (DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) {
|
||||
c->Message(Chat::Red, "%s is too far away.", target->GetCleanName());
|
||||
return;
|
||||
}
|
||||
c->HandleLDoNDisarm(target->CastToNPC(), c->GetSkill(EQ::skills::SkillDisarmTraps), LDoNTypeMechanical);
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::Red, "You do not have the disarm trap skill.");
|
||||
}
|
||||
if (!c->HasSkill(EQ::skills::SkillDisarmTraps)) {
|
||||
c->Message(Chat::White, "You do not have the Disarm Trap skill.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (DistanceSquaredNoZ(c->GetPosition(), t->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} is too far away.",
|
||||
t->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
c->HandleLDoNDisarm(t->CastToNPC(), c->GetSkill(EQ::skills::SkillDisarmTraps), LDoNTypeMechanical);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ void command_doanim(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
Mob* t = c;
|
||||
if (c->GetTarget() && c->Admin() >= commandDoAnimOthers) {
|
||||
if (c->GetTarget()) {
|
||||
t = c->GetTarget();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../client.h"
|
||||
#include "door_manipulation.h"
|
||||
#include "../doors.h"
|
||||
|
||||
void command_door(Client *c, const Seperator *sep)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
void command_giveitem(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!c->GetTarget() || !!c->GetTarget()->IsClient()) {
|
||||
if (!c->GetTarget() || !c->GetTarget()->IsClient()) {
|
||||
c->Message(Chat::White, "You must target a player to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -81,11 +81,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
if (c->Admin() < minStatusToEditOtherGuilds) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto guild_name = sep->argplus[3];
|
||||
auto guild_id = guild_mgr.CreateGuild(sep->argplus[3], leader_id);
|
||||
|
||||
@@ -144,16 +139,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() < minStatusToEditOtherGuilds) {
|
||||
if (c->GuildID() != guild_id) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
return;
|
||||
} else if (!guild_mgr.CheckGMStatus(guild_id, c->Admin())) {
|
||||
c->Message(Chat::White, "You cannot edit your current guild, your status is not high enough.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LogGuilds(
|
||||
"[{}]: Deleting guild [{}] ([{}]) with GM command",
|
||||
c->GetName(),
|
||||
@@ -175,16 +160,10 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
SendGuildSubCommands(c);
|
||||
} else if (is_info) {
|
||||
if (arguments != 2 && c->IsInAGuild()) {
|
||||
if (c->Admin() >= minStatusToEditOtherGuilds) {
|
||||
c->Message(Chat::White, "#guild info [Guild ID]");
|
||||
} else {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
}
|
||||
c->Message(Chat::White, "#guild info [Guild ID]");
|
||||
} else {
|
||||
auto guild_id = GUILD_NONE;
|
||||
if (arguments != 2 || !sep->IsNumber(2)) {
|
||||
guild_id = c->GuildID();
|
||||
} else if (c->Admin() >= minStatusToEditOtherGuilds) {
|
||||
if (sep->IsNumber(2)) {
|
||||
guild_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
}
|
||||
|
||||
@@ -193,11 +172,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
} else if (is_list) {
|
||||
if (c->Admin() < minStatusToEditOtherGuilds) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
return;
|
||||
}
|
||||
|
||||
guild_mgr.ListGuilds(c, std::string());
|
||||
} else if (is_rename) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
@@ -215,16 +189,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() < minStatusToEditOtherGuilds) {
|
||||
if (c->GuildID() != guild_id) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
return;
|
||||
} else if (!guild_mgr.CheckGMStatus(guild_id, c->Admin())) {
|
||||
c->Message(Chat::White, "You cannot edit your current guild, your status is not high enough.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto new_guild_name = sep->argplus[3];
|
||||
LogGuilds(
|
||||
"[{}]: Renaming guild [{}] ([{}]) to [{}] with GM command",
|
||||
@@ -293,11 +257,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() < minStatusToEditOtherGuilds && guild_id != c->GuildID()) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!guild_id || guild_id == GUILD_NONE) {
|
||||
LogGuilds(
|
||||
"[{}]: Removing [{}] ([{}]) from guild with GM command",
|
||||
@@ -329,6 +288,7 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
guild_mgr.SetGuild(character_id, GUILD_NONE, 0);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -389,16 +349,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() < minStatusToEditOtherGuilds) {
|
||||
if (c->GuildID() != guild_id) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
return;
|
||||
} else if (!guild_mgr.CheckGMStatus(guild_id, c->Admin())) {
|
||||
c->Message(Chat::White, "You cannot edit your current guild, your status is not high enough.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LogGuilds(
|
||||
"[{}]: Setting leader of guild [{}] ([{}]) to [{}] with GM command",
|
||||
c->GetName(),
|
||||
@@ -460,11 +410,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() < minStatusToEditOtherGuilds && character_id != c->CharacterID()) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
return;
|
||||
}
|
||||
|
||||
LogGuilds(
|
||||
"[{}]: Setting [{}] ([{}])'s guild rank to [{}] with GM command",
|
||||
c->GetName(),
|
||||
@@ -497,8 +442,6 @@ void command_guild(Client *c, const Seperator *sep)
|
||||
);
|
||||
if (!client) {
|
||||
c->Message(Chat::White, "You must target someone or specify a character name.");
|
||||
} else if (c->Admin() < minStatusToEditOtherGuilds && client->GuildID() != c->GuildID()) {
|
||||
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
|
||||
} else {
|
||||
if (!client->IsInAGuild()) {
|
||||
c->Message(
|
||||
|
||||
@@ -15,20 +15,13 @@ void command_interrogateinv(Client *c, const Seperator *sep)
|
||||
// same or not.
|
||||
|
||||
if (strcasecmp(sep->arg[1], "help") == 0) {
|
||||
if (c->Admin() < commandInterrogateInv) {
|
||||
c->Message(Chat::White, "Usage: #interrogateinv");
|
||||
c->Message(Chat::White, " Displays your inventory's current in-memory nested storage references");
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Usage: #interrogateinv [log] [silent]");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
" Displays your or your Player target inventory's current in-memory nested storage references"
|
||||
);
|
||||
c->Message(Chat::White, " [log] - Logs interrogation to file");
|
||||
c->Message(Chat::White, " [silent] - Omits the in-game message portion of the interrogation");
|
||||
}
|
||||
return;
|
||||
c->Message(Chat::White, "Usage: #interrogateinv [log] [silent]");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
" Displays your or your Player target inventory's current in-memory nested storage references"
|
||||
);
|
||||
c->Message(Chat::White, " [log] - Logs interrogation to file");
|
||||
c->Message(Chat::White, " [silent] - Omits the in-game message portion of the interrogation");
|
||||
}
|
||||
|
||||
Client *target = nullptr;
|
||||
@@ -38,33 +31,20 @@ void command_interrogateinv(Client *c, const Seperator *sep)
|
||||
bool error = false;
|
||||
bool allowtrip = false;
|
||||
|
||||
if (c->Admin() < commandInterrogateInv) {
|
||||
if (c->GetInterrogateInvState()) {
|
||||
c->Message(Chat::Red, "The last use of #interrogateinv on this inventory instance discovered an error...");
|
||||
c->Message(Chat::Red, "Logging out, zoning or re-arranging items at this point will result in item loss!");
|
||||
return;
|
||||
}
|
||||
target = c;
|
||||
allowtrip = true;
|
||||
if (c->GetTarget() == nullptr) {
|
||||
target = c;
|
||||
} else if (c->GetTarget()->IsClient()) {
|
||||
target = c->GetTarget()->CastToClient();
|
||||
} else {
|
||||
c->Message(Chat::Default, "Use of this command is limited to Client entities");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (c->GetTarget() == nullptr) {
|
||||
target = c;
|
||||
}
|
||||
else if (c->GetTarget()->IsClient()) {
|
||||
target = c->GetTarget()->CastToClient();
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::Default, "Use of this command is limited to Client entities");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(sep->arg[1], "log") == 0) {
|
||||
log = true;
|
||||
}
|
||||
if (strcasecmp(sep->arg[2], "silent") == 0) {
|
||||
silent = true;
|
||||
}
|
||||
if (strcasecmp(sep->arg[1], "log") == 0) {
|
||||
log = true;
|
||||
}
|
||||
if (strcasecmp(sep->arg[2], "silent") == 0) {
|
||||
silent = true;
|
||||
}
|
||||
|
||||
bool success = target->InterrogateInventory(c, log, silent, allowtrip, error);
|
||||
|
||||
+278
-297
@@ -27,50 +27,48 @@ void command_invsnapshot(Client *c, const Seperator *sep)
|
||||
"<td><c \"#AAAAAA\">takes snapshot of character inventory</td>"
|
||||
"</tr>";
|
||||
|
||||
if (c->Admin() >= commandInvSnapshot) {
|
||||
window_text.append(
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">gcount</td>"
|
||||
"<td></td>"
|
||||
"<td><c \"#AAAAAA\">returns global snapshot count</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">gclear</td>"
|
||||
"<td><c \"#FFFF00\"><br>now</td>"
|
||||
"<td><c \"#AAAAAA\">delete all snapshots - rule<br>delete all snapshots - now</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">count</td>"
|
||||
"<td></td>"
|
||||
"<td><c \"#AAAAAA\">returns character snapshot count</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">clear</td>"
|
||||
"<td><c \"#FFFF00\"><br>now</td>"
|
||||
"<td><c \"#AAAAAA\">delete character snapshots - rule<br>delete character snapshots - now</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">list</td>"
|
||||
"<td><br><c \"#FFFF00\">count</td>"
|
||||
"<td><c \"#AAAAAA\">lists entry ids for current character<br>limits to count</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">parse</td>"
|
||||
"<td><c \"#00FF00\">tstmp</td>"
|
||||
"<td><c \"#AAAAAA\">displays slots and items in snapshot</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">compare</td>"
|
||||
"<td><c \"#00FF00\">tstmp</td>"
|
||||
"<td><c \"#AAAAAA\">compares inventory against snapshot</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">restore</td>"
|
||||
"<td><c \"#00FF00\">tstmp</td>"
|
||||
"<td><c \"#AAAAAA\">restores slots and items in snapshot</td>"
|
||||
"</tr>"
|
||||
);
|
||||
}
|
||||
window_text.append(
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">gcount</td>"
|
||||
"<td></td>"
|
||||
"<td><c \"#AAAAAA\">returns global snapshot count</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">gclear</td>"
|
||||
"<td><c \"#FFFF00\"><br>now</td>"
|
||||
"<td><c \"#AAAAAA\">delete all snapshots - rule<br>delete all snapshots - now</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">count</td>"
|
||||
"<td></td>"
|
||||
"<td><c \"#AAAAAA\">returns character snapshot count</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">clear</td>"
|
||||
"<td><c \"#FFFF00\"><br>now</td>"
|
||||
"<td><c \"#AAAAAA\">delete character snapshots - rule<br>delete character snapshots - now</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">list</td>"
|
||||
"<td><br><c \"#FFFF00\">count</td>"
|
||||
"<td><c \"#AAAAAA\">lists entry ids for current character<br>limits to count</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">parse</td>"
|
||||
"<td><c \"#00FF00\">tstmp</td>"
|
||||
"<td><c \"#AAAAAA\">displays slots and items in snapshot</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">compare</td>"
|
||||
"<td><c \"#00FF00\">tstmp</td>"
|
||||
"<td><c \"#AAAAAA\">compares inventory against snapshot</td>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><c \"#00FF00\">restore</td>"
|
||||
"<td><c \"#00FF00\">tstmp</td>"
|
||||
"<td><c \"#AAAAAA\">restores slots and items in snapshot</td>"
|
||||
"</tr>"
|
||||
);
|
||||
|
||||
window_text.append(
|
||||
"</table>"
|
||||
@@ -81,34 +79,30 @@ void command_invsnapshot(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() >= commandInvSnapshot) { // global arguments
|
||||
if (strcmp(sep->arg[1], "gcount") == 0) {
|
||||
auto is_count = database.CountInvSnapshots();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"There %s %i inventory snapshot%s.",
|
||||
(is_count == 1 ? "is" : "are"),
|
||||
is_count,
|
||||
(is_count == 1 ? "" : "s"));
|
||||
|
||||
if (strcmp(sep->arg[1], "gcount") == 0) {
|
||||
auto is_count = database.CountInvSnapshots();
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "gclear") == 0) {
|
||||
if (strcmp(sep->arg[2], "now") == 0) {
|
||||
database.ClearInvSnapshots(true);
|
||||
c->Message(Chat::White, "Inventory snapshots cleared using current time.");
|
||||
} else {
|
||||
database.ClearInvSnapshots();
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"There %s %i inventory snapshot%s.",
|
||||
(is_count == 1 ? "is" : "are"),
|
||||
is_count,
|
||||
(is_count == 1 ? "" : "s"));
|
||||
|
||||
return;
|
||||
Chat::White, "Inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).",
|
||||
RuleI(Character, InvSnapshotHistoryD), (RuleI(Character, InvSnapshotHistoryD) == 1 ? "" : "s"));
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "gclear") == 0) {
|
||||
if (strcmp(sep->arg[2], "now") == 0) {
|
||||
database.ClearInvSnapshots(true);
|
||||
c->Message(Chat::White, "Inventory snapshots cleared using current time.");
|
||||
}
|
||||
else {
|
||||
database.ClearInvSnapshots();
|
||||
c->Message(
|
||||
Chat::White, "Inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).",
|
||||
RuleI(Character, InvSnapshotHistoryD), (RuleI(Character, InvSnapshotHistoryD) == 1 ? "" : "s"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c->GetTarget() || !c->GetTarget()->IsClient()) {
|
||||
@@ -127,8 +121,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
|
||||
tc->GetName(),
|
||||
RuleI(Character, InvSnapshotMinIntervalM),
|
||||
(RuleI(Character, InvSnapshotMinIntervalM) == 1 ? "" : "s"));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinRetryM));
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -141,278 +134,266 @@ void command_invsnapshot(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->Admin() >= commandInvSnapshot) {
|
||||
if (strcmp(sep->arg[1], "count") == 0) {
|
||||
auto is_count = database.CountCharacterInvSnapshots(tc->CharacterID());
|
||||
if (strcmp(sep->arg[1], "count") == 0) {
|
||||
auto is_count = database.CountCharacterInvSnapshots(tc->CharacterID());
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"%s (id: %u) has %i inventory snapshot%s.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
is_count,
|
||||
(is_count == 1 ? "" : "s"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "clear") == 0) {
|
||||
if (strcmp(sep->arg[2], "now") == 0) {
|
||||
database.ClearCharacterInvSnapshots(tc->CharacterID(), true);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"%s (id: %u) has %i inventory snapshot%s.",
|
||||
"%s\'s (id: %u) inventory snapshots cleared using current time.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID());
|
||||
} else {
|
||||
database.ClearCharacterInvSnapshots(tc->CharacterID());
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"%s\'s (id: %u) inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
is_count,
|
||||
(is_count == 1 ? "" : "s"));
|
||||
RuleI(Character, InvSnapshotHistoryD),
|
||||
(RuleI(Character, InvSnapshotHistoryD) == 1 ? "" : "s"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "list") == 0) {
|
||||
std::list<std::pair<uint32, int>> is_list;
|
||||
database.ListCharacterInvSnapshots(tc->CharacterID(), is_list);
|
||||
|
||||
if (is_list.empty()) {
|
||||
c->Message(Chat::White, "No inventory snapshots for %s (id: %u)", tc->GetName(), tc->CharacterID());
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "clear") == 0) {
|
||||
if (strcmp(sep->arg[2], "now") == 0) {
|
||||
database.ClearCharacterInvSnapshots(tc->CharacterID(), true);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"%s\'s (id: %u) inventory snapshots cleared using current time.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID());
|
||||
}
|
||||
else {
|
||||
database.ClearCharacterInvSnapshots(tc->CharacterID());
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"%s\'s (id: %u) inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
RuleI(Character, InvSnapshotHistoryD),
|
||||
(RuleI(Character, InvSnapshotHistoryD) == 1 ? "" : "s"));
|
||||
}
|
||||
|
||||
return;
|
||||
auto list_count = 0;
|
||||
if (sep->IsNumber(2)) {
|
||||
list_count = Strings::ToInt(sep->arg[2]);
|
||||
}
|
||||
if (list_count < 1 || list_count > is_list.size()) {
|
||||
list_count = is_list.size();
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "list") == 0) {
|
||||
std::list<std::pair<uint32, int>> is_list;
|
||||
database.ListCharacterInvSnapshots(tc->CharacterID(), is_list);
|
||||
std::string window_title = StringFormat("Snapshots for %s", tc->GetName());
|
||||
|
||||
if (is_list.empty()) {
|
||||
c->Message(Chat::White, "No inventory snapshots for %s (id: %u)", tc->GetName(), tc->CharacterID());
|
||||
return;
|
||||
}
|
||||
|
||||
auto list_count = 0;
|
||||
if (sep->IsNumber(2)) {
|
||||
list_count = Strings::ToInt(sep->arg[2]);
|
||||
}
|
||||
if (list_count < 1 || list_count > is_list.size()) {
|
||||
list_count = is_list.size();
|
||||
}
|
||||
|
||||
std::string window_title = StringFormat("Snapshots for %s", tc->GetName());
|
||||
|
||||
std::string window_text =
|
||||
"<table>"
|
||||
"<tr>"
|
||||
"<td>Timestamp</td>"
|
||||
"<td>Entry Count</td>"
|
||||
"</tr>";
|
||||
|
||||
for (auto iter : is_list) {
|
||||
if (!list_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
window_text.append(
|
||||
StringFormat(
|
||||
std::string window_text =
|
||||
"<table>"
|
||||
"<tr>"
|
||||
"<td>%u</td>"
|
||||
"<td>%i</td>"
|
||||
"</tr>",
|
||||
iter.first,
|
||||
iter.second
|
||||
));
|
||||
"<td>Timestamp</td>"
|
||||
"<td>Entry Count</td>"
|
||||
"</tr>";
|
||||
|
||||
--list_count;
|
||||
for (auto iter: is_list) {
|
||||
if (!list_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
window_text.append(
|
||||
"</table>"
|
||||
);
|
||||
|
||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "parse") == 0) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "A timestamp is required to use this option.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
|
||||
if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"No inventory snapshots for %s (id: %u) exist at %u.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
timestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<std::pair<int16, uint32>> parse_list;
|
||||
database.ParseCharacterInvSnapshot(tc->CharacterID(), timestamp, parse_list);
|
||||
|
||||
std::string window_title = StringFormat("Snapshot Parse for %s @ %u", tc->GetName(), timestamp);
|
||||
|
||||
std::string window_text = "Slot: ItemID - Description<br>";
|
||||
|
||||
for (auto iter : parse_list) {
|
||||
auto item_data = database.GetItem(iter.second);
|
||||
std::string window_line = StringFormat(
|
||||
"%i: %u - %s<br>",
|
||||
StringFormat(
|
||||
"<tr>"
|
||||
"<td>%u</td>"
|
||||
"<td>%i</td>"
|
||||
"</tr>",
|
||||
iter.first,
|
||||
iter.second,
|
||||
(item_data ? item_data->Name : "[error]"));
|
||||
iter.second
|
||||
));
|
||||
|
||||
if (window_text.length() + window_line.length() < 4095) {
|
||||
window_text.append(window_line);
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Too many snapshot entries to list...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
--list_count;
|
||||
}
|
||||
|
||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
||||
window_text.append(
|
||||
"</table>"
|
||||
);
|
||||
|
||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "parse") == 0) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "A timestamp is required to use this option.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "compare") == 0) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "A timestamp is required to use this option.");
|
||||
return;
|
||||
uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
|
||||
if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"No inventory snapshots for %s (id: %u) exist at %u.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
timestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<std::pair<int16, uint32>> parse_list;
|
||||
database.ParseCharacterInvSnapshot(tc->CharacterID(), timestamp, parse_list);
|
||||
|
||||
std::string window_title = StringFormat("Snapshot Parse for %s @ %u", tc->GetName(), timestamp);
|
||||
|
||||
std::string window_text = "Slot: ItemID - Description<br>";
|
||||
|
||||
for (auto iter: parse_list) {
|
||||
auto item_data = database.GetItem(iter.second);
|
||||
std::string window_line = StringFormat(
|
||||
"%i: %u - %s<br>",
|
||||
iter.first,
|
||||
iter.second,
|
||||
(item_data ? item_data->Name : "[error]"));
|
||||
|
||||
if (window_text.length() + window_line.length() < 4095) {
|
||||
window_text.append(window_line);
|
||||
} else {
|
||||
c->Message(Chat::White, "Too many snapshot entries to list...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
||||
|
||||
if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"No inventory snapshots for %s (id: %u) exist at %u.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
timestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<std::pair<int16, uint32>> inv_compare_list;
|
||||
database.DivergeCharacterInventoryFromInvSnapshot(tc->CharacterID(), timestamp, inv_compare_list);
|
||||
if (strcmp(sep->arg[1], "compare") == 0) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "A timestamp is required to use this option.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<std::pair<int16, uint32>> iss_compare_list;
|
||||
database.DivergeCharacterInvSnapshotFromInventory(tc->CharacterID(), timestamp, iss_compare_list);
|
||||
uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
|
||||
std::string window_title = StringFormat("Snapshot Comparison for %s @ %u", tc->GetName(), timestamp);
|
||||
if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"No inventory snapshots for %s (id: %u) exist at %u.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
timestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string window_text = "Slot: (action) Snapshot -> Inventory<br>";
|
||||
std::list<std::pair<int16, uint32>> inv_compare_list;
|
||||
database.DivergeCharacterInventoryFromInvSnapshot(tc->CharacterID(), timestamp, inv_compare_list);
|
||||
|
||||
auto inv_iter = inv_compare_list.begin();
|
||||
auto iss_iter = iss_compare_list.begin();
|
||||
std::list<std::pair<int16, uint32>> iss_compare_list;
|
||||
database.DivergeCharacterInvSnapshotFromInventory(tc->CharacterID(), timestamp, iss_compare_list);
|
||||
|
||||
while (true) {
|
||||
std::string window_line;
|
||||
std::string window_title = StringFormat("Snapshot Comparison for %s @ %u", tc->GetName(), timestamp);
|
||||
|
||||
if (inv_iter == inv_compare_list.end() && iss_iter == iss_compare_list.end()) {
|
||||
break;
|
||||
}
|
||||
else if (inv_iter != inv_compare_list.end() && iss_iter == iss_compare_list.end()) {
|
||||
window_line = StringFormat("%i: (delete) [empty] -> %u<br>", inv_iter->first, inv_iter->second);
|
||||
std::string window_text = "Slot: (action) Snapshot -> Inventory<br>";
|
||||
|
||||
auto inv_iter = inv_compare_list.begin();
|
||||
auto iss_iter = iss_compare_list.begin();
|
||||
|
||||
while (true) {
|
||||
std::string window_line;
|
||||
|
||||
if (inv_iter == inv_compare_list.end() && iss_iter == iss_compare_list.end()) {
|
||||
break;
|
||||
} else if (inv_iter != inv_compare_list.end() && iss_iter == iss_compare_list.end()) {
|
||||
window_line = StringFormat("%i: (delete) [empty] -> %u<br>", inv_iter->first, inv_iter->second);
|
||||
++inv_iter;
|
||||
} else if (inv_iter == inv_compare_list.end() && iss_iter != iss_compare_list.end()) {
|
||||
window_line = StringFormat("%i: (insert) %u -> [empty]<br>", iss_iter->first, iss_iter->second);
|
||||
++iss_iter;
|
||||
} else {
|
||||
if (inv_iter->first < iss_iter->first) {
|
||||
window_line = StringFormat(
|
||||
"%i: (delete) [empty] -> %u<br>",
|
||||
inv_iter->first,
|
||||
inv_iter->second
|
||||
);
|
||||
++inv_iter;
|
||||
} else if (inv_iter->first > iss_iter->first) {
|
||||
window_line = StringFormat(
|
||||
"%i: (insert) %u -> [empty]<br>",
|
||||
iss_iter->first,
|
||||
iss_iter->second
|
||||
);
|
||||
++iss_iter;
|
||||
} else {
|
||||
window_line = StringFormat(
|
||||
"%i: (replace) %u -> %u<br>",
|
||||
iss_iter->first,
|
||||
iss_iter->second,
|
||||
inv_iter->second
|
||||
);
|
||||
++inv_iter;
|
||||
}
|
||||
else if (inv_iter == inv_compare_list.end() && iss_iter != iss_compare_list.end()) {
|
||||
window_line = StringFormat("%i: (insert) %u -> [empty]<br>", iss_iter->first, iss_iter->second);
|
||||
++iss_iter;
|
||||
}
|
||||
else {
|
||||
if (inv_iter->first < iss_iter->first) {
|
||||
window_line = StringFormat(
|
||||
"%i: (delete) [empty] -> %u<br>",
|
||||
inv_iter->first,
|
||||
inv_iter->second
|
||||
);
|
||||
++inv_iter;
|
||||
}
|
||||
else if (inv_iter->first > iss_iter->first) {
|
||||
window_line = StringFormat(
|
||||
"%i: (insert) %u -> [empty]<br>",
|
||||
iss_iter->first,
|
||||
iss_iter->second
|
||||
);
|
||||
++iss_iter;
|
||||
}
|
||||
else {
|
||||
window_line = StringFormat(
|
||||
"%i: (replace) %u -> %u<br>",
|
||||
iss_iter->first,
|
||||
iss_iter->second,
|
||||
inv_iter->second
|
||||
);
|
||||
++inv_iter;
|
||||
++iss_iter;
|
||||
}
|
||||
}
|
||||
|
||||
if (window_text.length() + window_line.length() < 4095) {
|
||||
window_text.append(window_line);
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Too many comparison entries to list...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
||||
if (window_text.length() + window_line.length() < 4095) {
|
||||
window_text.append(window_line);
|
||||
} else {
|
||||
c->Message(Chat::White, "Too many comparison entries to list...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "restore") == 0) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "A timestamp is required to use this option.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(sep->arg[1], "restore") == 0) {
|
||||
if (!sep->IsNumber(2)) {
|
||||
c->Message(Chat::White, "A timestamp is required to use this option.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
|
||||
if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"No inventory snapshots for %s (id: %u) exist at %u.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
timestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (database.SaveCharacterInvSnapshot(tc->CharacterID())) {
|
||||
tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM));
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Red, "Failed to take pre-restore inventory snapshot of %s (id: %u).",
|
||||
tc->GetName(), tc->CharacterID());
|
||||
return;
|
||||
}
|
||||
|
||||
if (database.RestoreCharacterInvSnapshot(tc->CharacterID(), timestamp)) {
|
||||
// cannot delete all valid item slots from client..so, we worldkick
|
||||
tc->WorldKick(); // self restores update before the 'kick' is processed
|
||||
|
||||
c->Message(
|
||||
Chat::White, "Successfully applied snapshot %u to %s's (id: %u) inventory.",
|
||||
timestamp, tc->GetName(), tc->CharacterID());
|
||||
}
|
||||
else {
|
||||
c->Message(
|
||||
Chat::Red, "Failed to apply snapshot %u to %s's (id: %u) inventory.",
|
||||
timestamp, tc->GetName(), tc->CharacterID());
|
||||
}
|
||||
uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
|
||||
if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"No inventory snapshots for %s (id: %u) exist at %u.",
|
||||
tc->GetName(),
|
||||
tc->CharacterID(),
|
||||
timestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (database.SaveCharacterInvSnapshot(tc->CharacterID())) {
|
||||
tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM));
|
||||
} else {
|
||||
c->Message(
|
||||
Chat::Red, "Failed to take pre-restore inventory snapshot of %s (id: %u).",
|
||||
tc->GetName(), tc->CharacterID());
|
||||
return;
|
||||
}
|
||||
|
||||
if (database.RestoreCharacterInvSnapshot(tc->CharacterID(), timestamp)) {
|
||||
// cannot delete all valid item slots from client..so, we worldkick
|
||||
tc->WorldKick(); // self restores update before the 'kick' is processed
|
||||
|
||||
c->Message(
|
||||
Chat::White, "Successfully applied snapshot %u to %s's (id: %u) inventory.",
|
||||
timestamp, tc->GetName(), tc->CharacterID());
|
||||
} else {
|
||||
c->Message(
|
||||
Chat::Red, "Failed to apply snapshot %u to %s's (id: %u) inventory.",
|
||||
timestamp, tc->GetName(), tc->CharacterID());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+252
-216
@@ -3,237 +3,273 @@
|
||||
#include "../object.h"
|
||||
#include "../doors.h"
|
||||
|
||||
struct UniqueEntity {
|
||||
uint16 entity_id;
|
||||
std::string entity_name;
|
||||
uint32 unique_id;
|
||||
glm::vec4 position;
|
||||
};
|
||||
|
||||
void command_list(Client *c, const Seperator *sep)
|
||||
{
|
||||
const int arguments = sep->argnum;
|
||||
if (!arguments) {
|
||||
c->Message(Chat::White, "Usage: #list [corpses|doors|npcs|objects|players] [search]");
|
||||
c->Message(Chat::White, "Example: #list npcs (Blank for all)");
|
||||
return;
|
||||
}
|
||||
|
||||
const bool is_corpses = !strcasecmp(sep->arg[1], "corpses");
|
||||
const bool is_doors = !strcasecmp(sep->arg[1], "doors");
|
||||
const bool is_npcs = !strcasecmp(sep->arg[1], "npcs");
|
||||
const bool is_objects = !strcasecmp(sep->arg[1], "objects");
|
||||
const bool is_players = !strcasecmp(sep->arg[1], "players");
|
||||
|
||||
if (
|
||||
!is_corpses &&
|
||||
!is_doors &&
|
||||
!is_npcs &&
|
||||
!is_objects &&
|
||||
!is_players
|
||||
) {
|
||||
c->Message(Chat::White, "Usage: #list [npcs|players|corpses|doors|objects] [search]");
|
||||
c->Message(Chat::White, "Example: #list npcs (Blank for all)");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string search_type;
|
||||
if (strcasecmp(sep->arg[1], "npcs") == 0) {
|
||||
search_type = "npcs";
|
||||
std::string unique_type;
|
||||
|
||||
if (is_corpses) {
|
||||
search_type = "corpse";
|
||||
unique_type = "Corpse ID";
|
||||
} else if (is_doors) {
|
||||
search_type = "door";
|
||||
unique_type = "Door ID";
|
||||
} else if (is_npcs) {
|
||||
search_type = "NPC";
|
||||
unique_type = "NPC ID";
|
||||
} else if (is_objects) {
|
||||
search_type = "object";
|
||||
unique_type = "Object ID";
|
||||
} else if (is_players) {
|
||||
search_type = "player";
|
||||
unique_type = "Character ID";
|
||||
}
|
||||
|
||||
if (strcasecmp(sep->arg[1], "players") == 0) {
|
||||
search_type = "players";
|
||||
}
|
||||
uint32 entity_count = 0;
|
||||
uint32 found_count = 0;
|
||||
|
||||
if (strcasecmp(sep->arg[1], "corpses") == 0) {
|
||||
search_type = "corpses";
|
||||
}
|
||||
const std::string &search_string = sep->arg[2] ? Strings::ToLower(sep->arg[2]) : std::string();
|
||||
|
||||
if (strcasecmp(sep->arg[1], "doors") == 0) {
|
||||
search_type = "doors";
|
||||
}
|
||||
std::vector<UniqueEntity> unique_entities;
|
||||
|
||||
if (strcasecmp(sep->arg[1], "objects") == 0) {
|
||||
search_type = "objects";
|
||||
}
|
||||
if (is_corpses) {
|
||||
const auto &l = entity_list.GetCorpseList();
|
||||
|
||||
if (search_type.length() > 0) {
|
||||
for (const auto &e : l) {
|
||||
Corpse *entity = e.second;
|
||||
|
||||
int entity_count = 0;
|
||||
int found_count = 0;
|
||||
entity_count++;
|
||||
|
||||
std::string search_string;
|
||||
|
||||
if (sep->arg[2]) {
|
||||
search_string = Strings::ToLower(sep->arg[2]);
|
||||
}
|
||||
|
||||
// NPC
|
||||
if (search_type.find("npcs") != std::string::npos) {
|
||||
auto &entity_list_search = entity_list.GetMobList();
|
||||
|
||||
for (auto &itr : entity_list_search) {
|
||||
Mob *entity = itr.second;
|
||||
if (!entity->IsNPC()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entity_count++;
|
||||
|
||||
std::string entity_name = Strings::ToLower(entity->GetName());
|
||||
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string saylink = StringFormat(
|
||||
"#goto %.0f %0.f %.0f",
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ() + (entity->IsBoat() ? 50 : 0));
|
||||
|
||||
c->Message(
|
||||
0,
|
||||
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
|
||||
Saylink::Silent(saylink, "Goto").c_str(),
|
||||
entity->GetID(),
|
||||
entity->GetName(),
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ()
|
||||
);
|
||||
|
||||
found_count++;
|
||||
const std::string &entity_name = Strings::ToLower(entity->GetName());
|
||||
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Client
|
||||
if (search_type.find("players") != std::string::npos) {
|
||||
auto &entity_list_search = entity_list.GetClientList();
|
||||
|
||||
for (auto &itr : entity_list_search) {
|
||||
Client *entity = itr.second;
|
||||
|
||||
entity_count++;
|
||||
|
||||
std::string entity_name = Strings::ToLower(entity->GetName());
|
||||
|
||||
/**
|
||||
* Filter by name
|
||||
*/
|
||||
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
unique_entities.emplace_back(
|
||||
UniqueEntity{
|
||||
.entity_id = entity->GetID(),
|
||||
.entity_name = entity->GetName(),
|
||||
.unique_id = entity->GetCorpseDBID(),
|
||||
.position = entity->GetPosition()
|
||||
}
|
||||
|
||||
std::string saylink = StringFormat(
|
||||
"#goto %.0f %0.f %.0f",
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ());
|
||||
|
||||
c->Message(
|
||||
0,
|
||||
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
|
||||
Saylink::Silent(saylink, "Goto").c_str(),
|
||||
entity->GetID(),
|
||||
entity->GetName(),
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ()
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Corpse
|
||||
if (search_type.find("corpses") != std::string::npos) {
|
||||
auto &entity_list_search = entity_list.GetCorpseList();
|
||||
|
||||
for (auto &itr : entity_list_search) {
|
||||
Corpse *entity = itr.second;
|
||||
|
||||
entity_count++;
|
||||
|
||||
std::string entity_name = Strings::ToLower(entity->GetName());
|
||||
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string saylink = StringFormat(
|
||||
"#goto %.0f %0.f %.0f",
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ());
|
||||
|
||||
c->Message(
|
||||
0,
|
||||
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
|
||||
Saylink::Silent(saylink, "Goto").c_str(),
|
||||
entity->GetID(),
|
||||
entity->GetName(),
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ()
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Doors
|
||||
if (search_type.find("doors") != std::string::npos) {
|
||||
auto &entity_list_search = entity_list.GetDoorsList();
|
||||
|
||||
for (auto &itr : entity_list_search) {
|
||||
Doors *entity = itr.second;
|
||||
|
||||
entity_count++;
|
||||
|
||||
std::string entity_name = Strings::ToLower(entity->GetDoorName());
|
||||
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string saylink = StringFormat(
|
||||
"#goto %.0f %0.f %.0f",
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ());
|
||||
|
||||
c->Message(
|
||||
0,
|
||||
"| %s | Entity ID %5d | Door ID %i | %s | x %.0f | y %0.f | z %.0f",
|
||||
Saylink::Silent(saylink, "Goto").c_str(),
|
||||
entity->GetID(),
|
||||
entity->GetDoorID(),
|
||||
entity->GetDoorName(),
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ()
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Objects
|
||||
if (search_type.find("objects") != std::string::npos) {
|
||||
auto &entity_list_search = entity_list.GetObjectList();
|
||||
|
||||
for (auto &itr : entity_list_search) {
|
||||
Object *entity = itr.second;
|
||||
|
||||
entity_count++;
|
||||
|
||||
std::string entity_name = Strings::ToLower(entity->GetModelName());
|
||||
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string saylink = StringFormat(
|
||||
"#goto %.0f %0.f %.0f",
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ());
|
||||
|
||||
c->Message(
|
||||
0,
|
||||
"| %s | Entity ID %5d | Object DBID %i | %s | x %.0f | y %0.f | z %.0f",
|
||||
Saylink::Silent(saylink, "Goto").c_str(),
|
||||
entity->GetID(),
|
||||
entity->GetDBID(),
|
||||
entity->GetModelName(),
|
||||
entity->GetX(),
|
||||
entity->GetY(),
|
||||
entity->GetZ()
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_count) {
|
||||
c->Message(
|
||||
0, "Found (%i) of type (%s) in zone (%i) total",
|
||||
found_count,
|
||||
search_type.c_str(),
|
||||
entity_count
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
} else if (is_doors) {
|
||||
const auto &l = entity_list.GetDoorsList();
|
||||
|
||||
for (const auto &e : l) {
|
||||
Doors *entity = e.second;
|
||||
|
||||
entity_count++;
|
||||
|
||||
const std::string &entity_name = Strings::ToLower(entity->GetDoorName());
|
||||
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unique_entities.emplace_back(
|
||||
UniqueEntity{
|
||||
.entity_id = entity->GetID(),
|
||||
.entity_name = entity->GetDoorName(),
|
||||
.unique_id = entity->GetDoorID(),
|
||||
.position = entity->GetPosition()
|
||||
}
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
} else if (is_npcs) {
|
||||
const auto &l = entity_list.GetMobList();
|
||||
|
||||
for (const auto &e : l) {
|
||||
Mob *entity = e.second;
|
||||
if (!entity->IsNPC()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entity_count++;
|
||||
|
||||
const std::string &entity_name = Strings::ToLower(entity->GetName());
|
||||
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unique_entities.emplace_back(
|
||||
UniqueEntity{
|
||||
.entity_id = entity->GetID(),
|
||||
.entity_name = entity->GetName(),
|
||||
.unique_id = entity->GetNPCTypeID(),
|
||||
.position = entity->GetPosition()
|
||||
}
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
} else if (is_objects) {
|
||||
const auto &l = entity_list.GetObjectList();
|
||||
|
||||
for (const auto &e : l) {
|
||||
Object *entity = e.second;
|
||||
|
||||
entity_count++;
|
||||
|
||||
const std::string &entity_name = Strings::ToLower(entity->GetModelName());
|
||||
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unique_entities.emplace_back(
|
||||
UniqueEntity{
|
||||
.entity_id = entity->GetID(),
|
||||
.entity_name = entity->GetModelName(),
|
||||
.unique_id = entity->GetDBID(),
|
||||
.position = glm::vec4(entity->GetX(), entity->GetY(), entity->GetZ(), 0.0f)
|
||||
}
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
} else if (is_players) {
|
||||
const auto &l = entity_list.GetClientList();
|
||||
|
||||
for (const auto &e : l) {
|
||||
Client *entity = e.second;
|
||||
|
||||
entity_count++;
|
||||
|
||||
const std::string &entity_name = Strings::ToLower(entity->GetName());
|
||||
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unique_entities.emplace_back(
|
||||
UniqueEntity{
|
||||
.entity_id = entity->GetID(),
|
||||
.entity_name = entity->GetName(),
|
||||
.unique_id = entity->CharacterID(),
|
||||
.position = entity->GetPosition()
|
||||
}
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Usage of #list");
|
||||
c->Message(Chat::White, "- #list [npcs|players|corpses|doors|objects] [search]");
|
||||
c->Message(Chat::White, "- Example: #list npcs (Blank for all)");
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_count) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Could not find any {}{}.",
|
||||
search_type,
|
||||
(
|
||||
!search_string.empty() ?
|
||||
fmt::format(
|
||||
" matching '{}'",
|
||||
search_string
|
||||
) :
|
||||
""
|
||||
)
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
std::sort(unique_entities.begin(), unique_entities.end(), [](UniqueEntity a, UniqueEntity b) {
|
||||
if (a.entity_id && b.entity_id) {
|
||||
return a.entity_id < b.entity_id;
|
||||
} else {
|
||||
return a.unique_id < b.unique_id;
|
||||
}
|
||||
});
|
||||
|
||||
for (const auto& e : unique_entities) {
|
||||
const std::string &saylink = Saylink::Silent(
|
||||
fmt::format(
|
||||
"#goto {:.2f} {:.2f} {:.2f}",
|
||||
e.position.x,
|
||||
e.position.y,
|
||||
e.position.z
|
||||
),
|
||||
"Goto"
|
||||
);
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"| {}{}{} | {} |",
|
||||
saylink,
|
||||
(
|
||||
e.entity_id ?
|
||||
fmt::format(
|
||||
" | ID {}",
|
||||
e.entity_id
|
||||
) :
|
||||
""
|
||||
),
|
||||
(
|
||||
e.unique_id ?
|
||||
fmt::format(
|
||||
" | {} {}",
|
||||
unique_type,
|
||||
e.unique_id
|
||||
) :
|
||||
""
|
||||
),
|
||||
e.entity_name
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Found {} {}{}{}, {} total.",
|
||||
found_count,
|
||||
search_type,
|
||||
found_count != 1 ? "s" : "",
|
||||
(
|
||||
!search_string.empty() ?
|
||||
fmt::format(
|
||||
" matching '{}'",
|
||||
search_string
|
||||
) :
|
||||
""
|
||||
),
|
||||
entity_count
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
void command_movechar(Client *c, const Seperator *sep)
|
||||
{
|
||||
int arguments = sep->argnum;
|
||||
const int arguments = sep->argnum;
|
||||
if (arguments < 2) {
|
||||
c->Message(Chat::White, "Usage: #movechar [Character ID|Character Name] [Zone ID|Zone Short Name]");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string character_name = (
|
||||
const std::string &character_name = (
|
||||
sep->IsNumber(1) ?
|
||||
database.GetCharNameByID(Strings::ToUnsignedInt(sep->arg[1])) :
|
||||
sep->arg[1]
|
||||
);
|
||||
auto character_id = database.GetCharacterID(character_name.c_str());
|
||||
const uint32 character_id = database.GetCharacterID(character_name.c_str());
|
||||
if (!character_id) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -25,15 +25,15 @@ void command_movechar(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
auto account_id = database.GetAccountIDByChar(character_name.c_str());
|
||||
const uint32 account_id = database.GetAccountIDByChar(character_name.c_str());
|
||||
|
||||
std::string zone_short_name = Strings::ToLower(
|
||||
const std::string &zone_short_name = Strings::ToLower(
|
||||
sep->IsNumber(2) ?
|
||||
ZoneName(Strings::ToUnsignedInt(sep->arg[2]), true) :
|
||||
sep->arg[2]
|
||||
);
|
||||
|
||||
bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos;
|
||||
const bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos;
|
||||
if (is_unknown_zone) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -45,63 +45,34 @@ void command_movechar(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
auto zone_id = ZoneID(zone_short_name);
|
||||
auto z = GetZone(zone_id);
|
||||
const uint32 zone_id = ZoneID(zone_short_name);
|
||||
auto z = GetZone(zone_id);
|
||||
|
||||
if (!z) {
|
||||
c->Message(Chat::Red, "Invalid zone.");
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_special_zone = (
|
||||
zone_short_name.find("cshome") != std::string::npos ||
|
||||
zone_short_name.find("load") != std::string::npos ||
|
||||
zone_short_name.find("load2") != std::string::npos
|
||||
const bool moved = database.MoveCharacterToZone(character_name.c_str(), zone_id);
|
||||
std::string moved_string = moved ? "Succeeded" : "Failed";
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Character Move {} | Character: {} ({})",
|
||||
moved_string,
|
||||
character_name,
|
||||
character_id
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (c->Admin() < commandMovecharToSpecials && is_special_zone) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} ({}) is a special zone and you cannot move someone there.",
|
||||
z->long_name,
|
||||
zone_short_name
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
c->Admin() >= commandMovecharSelfOnly ||
|
||||
account_id == c->AccountID()
|
||||
) {
|
||||
bool moved = database.MoveCharacterToZone(character_name.c_str(), zone_id);
|
||||
std::string moved_string = (
|
||||
moved ?
|
||||
"Succeeded" :
|
||||
"Failed"
|
||||
);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Character Move {} | Character: {} ({})",
|
||||
moved_string,
|
||||
character_name,
|
||||
character_id
|
||||
).c_str()
|
||||
);
|
||||
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Character Move {} | Zone: {} ({}) ID: {}",
|
||||
moved_string,
|
||||
z->long_name,
|
||||
zone_short_name,
|
||||
zone_id
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
c->Message(Chat::White, "You cannot move characters that are not on your account.");
|
||||
}
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Character Move {} | Zone: {} ({}) ID: {}",
|
||||
moved_string,
|
||||
z->long_name,
|
||||
zone_short_name,
|
||||
zone_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,74 +3,84 @@
|
||||
|
||||
void command_movement(Client *c, const Seperator *sep)
|
||||
{
|
||||
auto &mgr = MobMovementManager::Get();
|
||||
|
||||
if (sep->arg[1][0] == 0) {
|
||||
c->Message(Chat::White, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop/packet");
|
||||
const int arguments = sep->argnum;
|
||||
if (!arguments) {
|
||||
c->Message(Chat::White, "Usage: #movement [clear|packet|rotate|run|stats|stop|walk]");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(sep->arg[1], "stats") == 0) {
|
||||
mgr.DumpStats(c);
|
||||
const bool is_clear = !strcasecmp(sep->arg[1], "clear");
|
||||
const bool is_packet = !strcasecmp(sep->arg[1], "packet");
|
||||
const bool is_rotate = !strcasecmp(sep->arg[1], "rotate");
|
||||
const bool is_run = !strcasecmp(sep->arg[1], "run");
|
||||
const bool is_stats = !strcasecmp(sep->arg[1], "stats");
|
||||
const bool is_stop = !strcasecmp(sep->arg[1], "stop");
|
||||
const bool is_walk = !strcasecmp(sep->arg[1], "walk");
|
||||
|
||||
if (
|
||||
!is_clear &&
|
||||
!is_packet &&
|
||||
!is_rotate &&
|
||||
!is_run &&
|
||||
!is_stats &&
|
||||
!is_stop &&
|
||||
!is_walk
|
||||
) {
|
||||
c->Message(Chat::White, "Usage: #movement [clear|packet|rotate|run|stats|stop|walk]");
|
||||
return;
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "clearstats") == 0) {
|
||||
mgr.ClearStats();
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "walkto") == 0) {
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(Chat::White, "No target found.");
|
||||
|
||||
auto &m = MobMovementManager::Get();
|
||||
|
||||
if (is_clear) {
|
||||
m.ClearStats();
|
||||
} else if (is_packet) {
|
||||
Mob *t = c->GetTarget();
|
||||
if (!t) {
|
||||
c->Message(Chat::White, "You must have a target to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->WalkTo(c->GetX(), c->GetY(), c->GetZ());
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "runto") == 0) {
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(Chat::White, "No target found.");
|
||||
const float x = sep->IsNumber(2) ? Strings::ToFloat(sep->arg[2]) : 0.0f;
|
||||
const float y = sep->IsNumber(3) ? Strings::ToFloat(sep->arg[3]) : 0.0f;
|
||||
const float z = sep->IsNumber(4) ? Strings::ToFloat(sep->arg[4]) : 0.0f;
|
||||
const float heading = sep->IsNumber(5) ? Strings::ToFloat(sep->arg[5]) : 0.0f;
|
||||
const int animation = sep->IsNumber(6) ? Strings::ToInt(sep->arg[6]) : 0.0f;
|
||||
|
||||
m.SendCommandToClients(t, x, y, z, heading, animation, ClientRangeAny);
|
||||
} else if (is_rotate) {
|
||||
Mob *t = c->GetTarget();
|
||||
if (!t) {
|
||||
c->Message(Chat::White, "You must have a target to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->RunTo(c->GetX(), c->GetY(), c->GetZ());
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "rotateto") == 0) {
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(Chat::White, "No target found.");
|
||||
t->RotateToWalking(t->CalculateHeadingToTarget(c->GetX(), c->GetY()));
|
||||
} else if (is_run) {
|
||||
Mob *t = c->GetTarget();
|
||||
if (!t) {
|
||||
c->Message(Chat::White, "You must have a target to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->RotateToWalking(target->CalculateHeadingToTarget(c->GetX(), c->GetY()));
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "stop") == 0) {
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(Chat::White, "No target found.");
|
||||
t->RunTo(c->GetX(), c->GetY(), c->GetZ());
|
||||
} else if (is_stats) {
|
||||
m.DumpStats(c);
|
||||
} else if (is_stop) {
|
||||
Mob *t = c->GetTarget();
|
||||
if (!t) {
|
||||
c->Message(Chat::White, "You must have a target to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->StopNavigation();
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "packet") == 0) {
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(Chat::White, "No target found.");
|
||||
t->StopNavigation();
|
||||
} else if (is_walk) {
|
||||
Mob *t = c->GetTarget();
|
||||
if (!t) {
|
||||
c->Message(Chat::White, "You must have a target to use this command.");
|
||||
return;
|
||||
}
|
||||
|
||||
mgr.SendCommandToClients(
|
||||
target,
|
||||
Strings::ToFloat(sep->arg[2]),
|
||||
Strings::ToFloat(sep->arg[3]),
|
||||
Strings::ToFloat(sep->arg[4]),
|
||||
Strings::ToFloat(sep->arg[5]),
|
||||
Strings::ToInt(sep->arg[6]),
|
||||
ClientRangeAny
|
||||
);
|
||||
}
|
||||
else {
|
||||
c->Message(Chat::White, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop/packet");
|
||||
t->WalkTo(c->GetX(), c->GetY(), c->GetZ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1258
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
#ifndef EQEMU_OBJECT_MANIPULATION_H
|
||||
#define EQEMU_OBJECT_MANIPULATION_H
|
||||
|
||||
#include "../client.h"
|
||||
|
||||
class ObjectManipulation {
|
||||
|
||||
public:
|
||||
static void CommandHandler(Client *c, const Seperator *sep);
|
||||
static void CommandHeader(Client *c);
|
||||
static void SendSubcommands(Client *c);
|
||||
};
|
||||
|
||||
|
||||
#endif //EQEMU_OBJECT_MANIPULATION_H
|
||||
@@ -5,10 +5,10 @@ void command_petname(Client *c, const Seperator *sep)
|
||||
Mob *target;
|
||||
target = c->GetTarget();
|
||||
|
||||
if (!target) {
|
||||
c->Message(Chat::White, "Usage: #petname newname (requires a target)");
|
||||
if (!target || !target->IsPet()) {
|
||||
c->Message(Chat::White, "Usage: #petname newname (requires a pet target)");
|
||||
}
|
||||
else if (target->IsPet() && (target->GetOwnerID() == c->GetID()) && strlen(sep->arg[1]) > 0) {
|
||||
else if (target->GetOwnerID() == c->GetID() && strlen(sep->arg[1]) > 0) {
|
||||
char *oldname = strdup(target->GetName());
|
||||
target->TempName(sep->arg[1]);
|
||||
c->Message(Chat::White, "Renamed %s to %s", oldname, sep->arg[1]);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../client.h"
|
||||
#include "show/aas.cpp"
|
||||
#include "show/aa_points.cpp"
|
||||
#include "show/aggro.cpp"
|
||||
#include "show/buffs.cpp"
|
||||
@@ -56,6 +57,7 @@ void command_show(Client *c, const Seperator *sep)
|
||||
};
|
||||
|
||||
std::vector<Cmd> commands = {
|
||||
Cmd{.cmd = "aas", .u = "aas", .fn = ShowAAs, .a = {"#showaas"}},
|
||||
Cmd{.cmd = "aa_points", .u = "aa_points", .fn = ShowAAPoints, .a = {"#showaapoints", "#showaapts"}},
|
||||
Cmd{.cmd = "aggro", .u = "aggro [Distance] [-v] (-v is verbose Faction Information)", .fn = ShowAggro, .a = {"#aggro"}},
|
||||
Cmd{.cmd = "buffs", .u = "buffs", .fn = ShowBuffs, .a = {"#showbuffs"}},
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "../../client.h"
|
||||
|
||||
void ShowAAs(Client *c, const Seperator *sep)
|
||||
{
|
||||
Client *t = c;
|
||||
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
||||
t = c->GetTarget()->CastToClient();
|
||||
}
|
||||
|
||||
const std::string& search_criteria = sep->argnum >= 2 ? sep->argplus[2] : std::string();
|
||||
|
||||
t->ListPurchasedAAs(c, search_criteria);
|
||||
}
|
||||
@@ -2,13 +2,8 @@
|
||||
|
||||
void ShowFlags(Client *c, const Seperator *sep)
|
||||
{
|
||||
auto t = c;
|
||||
|
||||
if (
|
||||
c->GetTarget() &&
|
||||
c->GetTarget()->IsClient() &&
|
||||
c->Admin() >= minStatusToSeeOthersZoneFlags
|
||||
) {
|
||||
Client *t = c;
|
||||
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
||||
t = c->GetTarget()->CastToClient();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
|
||||
void ShowPEQZoneFlags(Client *c, const Seperator *sep)
|
||||
{
|
||||
auto t = c;
|
||||
if (
|
||||
c->GetTarget() &&
|
||||
c->GetTarget()->IsClient() &&
|
||||
c->Admin() >= minStatusToSeeOthersZoneFlags
|
||||
) {
|
||||
Client *t = c;
|
||||
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
||||
t = c->GetTarget()->CastToClient();
|
||||
}
|
||||
|
||||
|
||||
+113
-63
@@ -8,7 +8,7 @@ extern WorldServer worldserver;
|
||||
|
||||
void command_task(Client *c, const Seperator *sep)
|
||||
{
|
||||
int arguments = sep->argnum;
|
||||
const int arguments = sep->argnum;
|
||||
if (!arguments) {
|
||||
c->Message(Chat::White, "Syntax: #task [subcommand]");
|
||||
c->Message(Chat::White, "------------------------------------------------");
|
||||
@@ -23,6 +23,7 @@ void command_task(Client *c, const Seperator *sep)
|
||||
);
|
||||
c->Message(Chat::White, "--- update <task_id> <activity_id> [count] | Updates task");
|
||||
c->Message(Chat::White, "--- assign <task_id> | Assigns task to client");
|
||||
c->Message(Chat::White, "--- complete <task_id> | Completes a task if a client has it assigned to them");
|
||||
c->Message(Chat::White, "--- uncomplete <task_id> | Uncompletes a task if a client has completed it");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
@@ -73,22 +74,24 @@ void command_task(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
Client *target = c;
|
||||
Client *t = c;
|
||||
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
||||
target = c->GetTarget()->CastToClient();
|
||||
t = c->GetTarget()->CastToClient();
|
||||
}
|
||||
|
||||
bool is_assign = !strcasecmp(sep->arg[1], "assign");
|
||||
bool is_purgetimers = !strcasecmp(sep->arg[1], "purgetimers");
|
||||
bool is_reload = !strcasecmp(sep->arg[1], "reload");
|
||||
bool is_reloadall = !strcasecmp(sep->arg[1], "reloadall");
|
||||
bool is_sharedpurge = !strcasecmp(sep->arg[1], "sharedpurge");
|
||||
bool is_show = !strcasecmp(sep->arg[1], "show");
|
||||
bool is_uncomplete = !strcasecmp(sep->arg[1], "uncomplete");
|
||||
bool is_update = !strcasecmp(sep->arg[1], "update");
|
||||
const bool is_assign = !strcasecmp(sep->arg[1], "assign");
|
||||
const bool is_complete = !strcasecmp(sep->arg[1], "complete");
|
||||
const bool is_purgetimers = !strcasecmp(sep->arg[1], "purgetimers");
|
||||
const bool is_reload = !strcasecmp(sep->arg[1], "reload");
|
||||
const bool is_reloadall = !strcasecmp(sep->arg[1], "reloadall");
|
||||
const bool is_sharedpurge = !strcasecmp(sep->arg[1], "sharedpurge");
|
||||
const bool is_show = !strcasecmp(sep->arg[1], "show");
|
||||
const bool is_uncomplete = !strcasecmp(sep->arg[1], "uncomplete");
|
||||
const bool is_update = !strcasecmp(sep->arg[1], "update");
|
||||
|
||||
if (
|
||||
!is_assign &&
|
||||
!is_complete &&
|
||||
!is_purgetimers &&
|
||||
!is_reload &&
|
||||
!is_reloadall &&
|
||||
@@ -161,70 +164,117 @@ void command_task(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
if (is_assign) {
|
||||
auto task_id = std::strtoul(sep->arg[2], nullptr, 10);
|
||||
const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
if (task_id) {
|
||||
target->AssignTask(task_id, 0, false);
|
||||
t->AssignTask(task_id, 0, false);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Assigned task ID {} to {}.",
|
||||
"Assigned {} (ID {}) to {}.",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id,
|
||||
c->GetTargetDescription(target)
|
||||
c->GetTargetDescription(t)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
return;
|
||||
} else if (is_complete) {
|
||||
if (sep->IsNumber(2)) {
|
||||
const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
if (!task_id) {
|
||||
c->Message(Chat::White, "Invalid task ID specified.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (t->IsTaskActive(task_id)) {
|
||||
const bool did_complete = t->CompleteTask(task_id);
|
||||
if (did_complete) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Successfully completed {} (ID {}) for {}.",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id,
|
||||
c->GetTargetDescription(t)
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Failed to complete {} (ID {}) for {}.",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id,
|
||||
c->GetTargetDescription(t)
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} {} not have not {} (ID {}) assigned to them.",
|
||||
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
|
||||
c == t ? "do" : "does",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (is_purgetimers) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Task timers have been purged for {}.",
|
||||
c->GetTargetDescription(target)
|
||||
c->GetTargetDescription(t)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (c != target) {
|
||||
target->Message(Chat::Yellow, "Your task timers have been purged by a GM.");
|
||||
if (c != t) {
|
||||
t->Message(Chat::White, "Your task timers have been purged by a GM.");
|
||||
}
|
||||
|
||||
target->PurgeTaskTimers();
|
||||
return;
|
||||
t->PurgeTaskTimers();
|
||||
} else if (is_reload) {
|
||||
if (arguments >= 2) {
|
||||
if (!strcasecmp(sep->arg[2], "sets")) {
|
||||
c->Message(Chat::Yellow, "Attempting to reload task sets.");
|
||||
const bool is_sets = !strcasecmp(sep->arg[2], "sets");
|
||||
const bool is_task = !strcasecmp(sep->arg[2], "task");
|
||||
|
||||
if (is_sets) {
|
||||
c->Message(Chat::White, "Attempting to reload task sets.");
|
||||
worldserver.SendReloadTasks(RELOADTASKSETS);
|
||||
c->Message(Chat::Yellow, "Successfully reloaded task sets.");
|
||||
return;
|
||||
} else if (!strcasecmp(sep->arg[2], "task") && arguments == 3) {
|
||||
int task_id = std::strtoul(sep->arg[3], nullptr, 10);
|
||||
c->Message(Chat::White, "Successfully reloaded task sets.");
|
||||
} else if (is_task && arguments == 3 && sep->IsNumber(3)) {
|
||||
const uint32 task_id = Strings::ToUnsignedInt(sep->arg[3]);
|
||||
if (task_id) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Attempted to reload task ID {}.",
|
||||
"Attempting to reload {} (ID {}).",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id
|
||||
).c_str()
|
||||
);
|
||||
worldserver.SendReloadTasks(RELOADTASKS, task_id);
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Successfully reloaded task ID {}.",
|
||||
"Successfully reloaded {} (ID {}).",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (is_reloadall) {
|
||||
c->Message(Chat::Yellow, "Attempting to reload tasks.");
|
||||
c->Message(Chat::White, "Attempting to reload tasks.");
|
||||
worldserver.SendReloadTasks(RELOADTASKS);
|
||||
c->Message(Chat::Yellow, "Successfully reloaded tasks.");
|
||||
return;
|
||||
c->Message(Chat::White, "Successfully reloaded tasks.");
|
||||
} else if (is_sharedpurge) {
|
||||
if (!strcasecmp(sep->arg[2], "confirm")) {
|
||||
const bool is_confirm = !strcasecmp(sep->arg[2], "confirm");
|
||||
|
||||
if (is_confirm) {
|
||||
LogTasksDetail("Sending purge request");
|
||||
auto pack = new ServerPacket(ServerOP_SharedTaskPurgeAllCommand, 0);
|
||||
worldserver.SendPacket(pack);
|
||||
@@ -239,14 +289,11 @@ void command_task(Client *c, const Seperator *sep)
|
||||
Saylink::Silent("#task sharedpurge confirm", "confirm")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
return;
|
||||
} else if (is_show) {
|
||||
target->ShowClientTasks(c);
|
||||
return;
|
||||
t->ShowClientTasks(c);
|
||||
} else if (is_uncomplete) {
|
||||
if (sep->IsNumber(2)) {
|
||||
auto task_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
if (!task_id) {
|
||||
c->Message(Chat::White, "Invalid task ID specified.");
|
||||
return;
|
||||
@@ -257,57 +304,60 @@ void command_task(Client *c, const Seperator *sep)
|
||||
database,
|
||||
fmt::format(
|
||||
"charid = {} AND taskid = {}",
|
||||
target->CharacterID(),
|
||||
task_id
|
||||
t->CharacterID(),
|
||||
task_id
|
||||
)
|
||||
)
|
||||
) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Successfully uncompleted task ID {} for {}.",
|
||||
"Successfully uncompleted {} (ID {}) for {}.",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id,
|
||||
c->GetTargetDescription(target)
|
||||
c->GetTargetDescription(t)
|
||||
).c_str()
|
||||
);
|
||||
} else {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"{} {} not completed task ID {}.",
|
||||
c->GetTargetDescription(target, TargetDescriptionType::UCYou),
|
||||
c == target ? "have" : "has",
|
||||
"{} {} not completed {} (ID {}).",
|
||||
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
|
||||
c == t ? "have" : "has",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (is_update) {
|
||||
if (arguments >= 3) {
|
||||
auto task_id = std::strtoul(sep->arg[2], nullptr, 10);
|
||||
auto activity_id = std::strtoul(sep->arg[3], nullptr, 10);
|
||||
int count = 1;
|
||||
if (arguments >= 3 && sep->IsNumber(2) && sep->IsNumber(3)) {
|
||||
const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||
const uint32 activity_id = Strings::ToUnsignedInt(sep->arg[3]);
|
||||
int count = 1;
|
||||
|
||||
if (arguments >= 4) {
|
||||
count = std::strtol(sep->arg[4], nullptr, 10);
|
||||
if (arguments == 4 && sep->IsNumber(4)) {
|
||||
count = Strings::ToInt(sep->arg[4]);
|
||||
if (count <= 0) {
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Updating task ID {}, activity {} with a count of {} for {}.",
|
||||
"Updating {} (ID {}), activity {} with a count of {} for {}.",
|
||||
task_manager->GetTaskName(task_id),
|
||||
task_id,
|
||||
activity_id,
|
||||
count,
|
||||
c->GetTargetDescription(target)
|
||||
c->GetTargetDescription(t)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
target->UpdateTaskActivity(task_id, activity_id, count);
|
||||
target->ShowClientTasks(c);
|
||||
t->UpdateTaskActivity(task_id, activity_id, count);
|
||||
t->ShowClientTasks(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,21 +5,43 @@ extern WorldServer worldserver;
|
||||
|
||||
void command_zonebootup(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!worldserver.Connected()) {
|
||||
c->Message(Chat::White, "Error: World server disconnected");
|
||||
const int arguments = sep->argnum;
|
||||
if (arguments < 2 || !sep->IsNumber(1)) {
|
||||
c->Message(Chat::White, "Usage: #zonebootup [Zone Server ID] [Zone ID|Zone Short Name] [Instance ID]");
|
||||
return;
|
||||
}
|
||||
else if (sep->arg[2][0] == 0) {
|
||||
c->Message(Chat::White, "Usage: #zonebootup ZoneServerID# zoneshortname");
|
||||
}
|
||||
else {
|
||||
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct));
|
||||
ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer;
|
||||
s->ZoneServerID = Strings::ToInt(sep->arg[1]);
|
||||
strcpy(s->adminname, c->GetName());
|
||||
s->zoneid = ZoneID(sep->arg[2]);
|
||||
s->makestatic = (bool) (strcasecmp(sep->arg[3], "static") == 0);
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
|
||||
if (!worldserver.Connected()) {
|
||||
c->Message(Chat::White, "World server disconnected.");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32 zone_server_id = Strings::ToUnsignedInt(sep->arg[1]);
|
||||
const uint32 zone_id = Strings::IsNumber(sep->arg[2]) ? Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]);
|
||||
const bool is_static = arguments > 2 ? !strcasecmp(sep->arg[3], "static") : false;
|
||||
const uint16 instance_id = arguments > 3 ? static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[4])) : 0;
|
||||
|
||||
if (!zone_id) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Zone '{}' does not exist.",
|
||||
sep->arg[1]
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_Struct));
|
||||
auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
|
||||
|
||||
s->zone_server_id = zone_server_id;
|
||||
s->zone_id = zone_id;
|
||||
s->instance_id = instance_id;
|
||||
s->is_static = is_static;
|
||||
|
||||
strn0cpy(s->admin_name, c->GetName(), sizeof(s->admin_name));
|
||||
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
@@ -5,26 +5,37 @@ extern WorldServer worldserver;
|
||||
|
||||
void command_zoneshutdown(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!worldserver.Connected()) {
|
||||
c->Message(Chat::White, "Error: World server disconnected");
|
||||
const int arguments = sep->argnum;
|
||||
if (!arguments) {
|
||||
c->Message(Chat::White, "Usage: #zoneshutdown [Zone ID|Zone Short Name]");
|
||||
return;
|
||||
}
|
||||
else if (sep->arg[1][0] == 0) {
|
||||
c->Message(Chat::White, "Usage: #zoneshutdown zoneshortname");
|
||||
}
|
||||
else {
|
||||
auto pack = new ServerPacket(
|
||||
ServerOP_ZoneShutdown,
|
||||
sizeof(ServerZoneStateChange_struct));
|
||||
ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer;
|
||||
strcpy(s->adminname, c->GetName());
|
||||
if (sep->arg[1][0] >= '0' && sep->arg[1][0] <= '9') {
|
||||
s->ZoneServerID = Strings::ToInt(sep->arg[1]);
|
||||
}
|
||||
else {
|
||||
s->zoneid = ZoneID(sep->arg[1]);
|
||||
}
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
|
||||
if (!worldserver.Connected()) {
|
||||
c->Message(Chat::White, "World server disconnected.");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32 zone_id = sep->IsNumber(1) ? Strings::ToUnsignedInt(sep->arg[1]) : ZoneID(sep->arg[1]);
|
||||
|
||||
if (!zone_id) {
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Zone '{}' does not exist.",
|
||||
sep->arg[1]
|
||||
).c_str()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ZoneShutdown, sizeof(ServerZoneStateChange_Struct));
|
||||
auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
|
||||
|
||||
s->zone_id = zone_id;
|
||||
|
||||
strn0cpy(s->admin_name, c->GetName(), sizeof(s->admin_name));
|
||||
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
@@ -2510,3 +2510,9 @@ bool Group::IsLeader(const char* name) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Group::GetGroupLeaderName(uint32 group_id) {
|
||||
char leader_name_buffer[64] = { 0 };
|
||||
database.GetGroupLeadershipInfo(group_id, leader_name_buffer);
|
||||
return std::string(leader_name_buffer);
|
||||
}
|
||||
|
||||
+3
-1
@@ -76,7 +76,7 @@ public:
|
||||
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
|
||||
inline void SetLeader(Mob* c){ leader = c; };
|
||||
inline Mob* GetLeader() { return leader; };
|
||||
const char* GetLeaderName() { return membername[0]; };
|
||||
const char* GetLeaderName() { return GetGroupLeaderName(GetID()).c_str(); };
|
||||
void SendHPManaEndPacketsTo(Mob* newmember);
|
||||
void SendHPPacketsFrom(Mob* member);
|
||||
void SendManaPacketFrom(Mob* member);
|
||||
@@ -177,6 +177,8 @@ private:
|
||||
int mentor_percent;
|
||||
|
||||
XTargetAutoHaters m_autohatermgr;
|
||||
|
||||
std::string GetGroupLeaderName(uint32 group_id);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+10
-2
@@ -46,7 +46,14 @@ void HateList::WipeHateList(bool npc_only) {
|
||||
auto iterator = list.begin();
|
||||
while (iterator != list.end()) {
|
||||
Mob *m = (*iterator)->entity_on_hatelist;
|
||||
if (m && (m->IsClient() || (m->IsPet() && m->GetOwner()->IsClient())) && npc_only) {
|
||||
if (
|
||||
m &&
|
||||
(
|
||||
m->IsOfClientBotMerc() ||
|
||||
(m->IsPet() && m->GetOwner() && m->GetOwner()->IsOfClientBotMerc())
|
||||
) &&
|
||||
npc_only
|
||||
) {
|
||||
iterator++;
|
||||
} else {
|
||||
if (m) {
|
||||
@@ -58,6 +65,7 @@ void HateList::WipeHateList(bool npc_only) {
|
||||
m->CastToClient()->DecrementAggroCount();
|
||||
m->CastToClient()->RemoveXTarget(hate_owner, true);
|
||||
}
|
||||
|
||||
delete (*iterator);
|
||||
iterator = list.erase(iterator);
|
||||
}
|
||||
@@ -733,7 +741,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
|
||||
caster->CombatRange(h->entity_on_hatelist, 1.0, true, opts)) {
|
||||
id_list.push_back(h->entity_on_hatelist->GetID());
|
||||
}
|
||||
|
||||
|
||||
if (count != -1 && id_list.size() > count) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -285,6 +285,11 @@ void Lua_Mob::GMMove(double x, double y, double z, double heading) {
|
||||
self->GMMove(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading));
|
||||
}
|
||||
|
||||
void Lua_Mob::GMMove(double x, double y, double z, double heading, bool save_guard_spot) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->GMMove(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading), save_guard_spot);
|
||||
}
|
||||
|
||||
void Lua_Mob::TryMoveAlong(float distance, float angle) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->TryMoveAlong(distance, angle);
|
||||
@@ -3350,6 +3355,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("FindType", (bool(Lua_Mob::*)(int,bool,int))&Lua_Mob::FindType)
|
||||
.def("GMMove", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::GMMove)
|
||||
.def("GMMove", (void(Lua_Mob::*)(double,double,double,double))&Lua_Mob::GMMove)
|
||||
.def("GMMove", (void(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::GMMove)
|
||||
.def("GetAA", (int(Lua_Mob::*)(int))&Lua_Mob::GetAA)
|
||||
.def("GetAABonuses", &Lua_Mob::GetAABonuses)
|
||||
.def("GetAAByAAID", (int(Lua_Mob::*)(int))&Lua_Mob::GetAAByAAID)
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
bool RandomizeFeatures(bool send_illusion, bool save_variables);
|
||||
void GMMove(double x, double y, double z);
|
||||
void GMMove(double x, double y, double z, double heading);
|
||||
void GMMove(double x, double y, double z, double heading, bool save_guard_spot);
|
||||
void TryMoveAlong(float distance, float heading);
|
||||
void TryMoveAlong(float distance, float heading, bool send);
|
||||
bool HasProcs();
|
||||
|
||||
+8
-23
@@ -515,6 +515,7 @@ Mob::Mob(
|
||||
|
||||
is_boat = IsBoat();
|
||||
|
||||
current_alliance_faction = -1;
|
||||
}
|
||||
|
||||
Mob::~Mob()
|
||||
@@ -5315,7 +5316,7 @@ int Mob::GetHaste()
|
||||
h += spellbonuses.hastetype2 > 10 ? 10 : spellbonuses.hastetype2;
|
||||
|
||||
// 26+ no cap, 1-25 10
|
||||
if (level > 25) // 26+
|
||||
if (level > 25 || (IsClient() && RuleB(Character, IgnoreLevelBasedHasteCaps))) // 26+
|
||||
h += itembonuses.haste;
|
||||
else // 1-25
|
||||
h += itembonuses.haste > 10 ? 10 : itembonuses.haste;
|
||||
@@ -5337,7 +5338,7 @@ int Mob::GetHaste()
|
||||
h = cap;
|
||||
|
||||
// 51+ 25 (despite there being higher spells...), 1-50 10
|
||||
if (level > 50) { // 51+
|
||||
if (level > 50 || (IsClient() && RuleB(Character, IgnoreLevelBasedHasteCaps))) { // 51+
|
||||
cap = RuleI(Character, Hastev3Cap);
|
||||
if (spellbonuses.hastetype3 > cap) {
|
||||
h += cap;
|
||||
@@ -7126,24 +7127,10 @@ int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) {
|
||||
return effect_value;
|
||||
}
|
||||
|
||||
// Faction Mods for Alliance type spells
|
||||
// Faction Mods for Alliance type spells (only 1 ever active)
|
||||
void Mob::AddFactionBonus(uint32 pFactionID,int32 bonus) {
|
||||
std::map <uint32, int32> :: const_iterator faction_bonus;
|
||||
typedef std::pair <uint32, int32> NewFactionBonus;
|
||||
|
||||
faction_bonus = faction_bonuses.find(pFactionID);
|
||||
if(faction_bonus == faction_bonuses.end())
|
||||
{
|
||||
faction_bonuses.emplace(NewFactionBonus(pFactionID,bonus));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(faction_bonus->second<bonus)
|
||||
{
|
||||
faction_bonuses.erase(pFactionID);
|
||||
faction_bonuses.emplace(NewFactionBonus(pFactionID,bonus));
|
||||
}
|
||||
}
|
||||
current_alliance_faction = pFactionID;
|
||||
current_alliance_mod = bonus;
|
||||
}
|
||||
|
||||
// Faction Mods from items
|
||||
@@ -7167,11 +7154,9 @@ void Mob::AddItemFactionBonus(uint32 pFactionID,int32 bonus) {
|
||||
}
|
||||
|
||||
int32 Mob::GetFactionBonus(uint32 pFactionID) {
|
||||
std::map <uint32, int32> :: const_iterator faction_bonus;
|
||||
faction_bonus = faction_bonuses.find(pFactionID);
|
||||
if(faction_bonus != faction_bonuses.end())
|
||||
if(current_alliance_faction == pFactionID)
|
||||
{
|
||||
return (*faction_bonus).second;
|
||||
return current_alliance_mod;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+3
-2
@@ -1774,8 +1774,9 @@ protected:
|
||||
uint32 time_until_can_move;
|
||||
HateList hate_list;
|
||||
std::set<uint32> feign_memory_list;
|
||||
// This is to keep track of mobs we cast faction mod spells on
|
||||
std::map<uint32,int32> faction_bonuses; // Primary FactionID, Bonus
|
||||
// This is to keep track of the current (one only) faction mod (alliance)
|
||||
uint32 current_alliance_faction;
|
||||
int32 current_alliance_mod;
|
||||
void AddFactionBonus(uint32 pFactionID,int32 bonus);
|
||||
int32 GetFactionBonus(uint32 pFactionID);
|
||||
// This is to keep track of item faction modifiers
|
||||
|
||||
+8
-3
@@ -1062,10 +1062,15 @@ void Mob::AI_Process() {
|
||||
SetTarget(hate_list.GetClosestEntOnHateList(this));
|
||||
else {
|
||||
if (AI_target_check_timer->Check()) {
|
||||
if (IsNPC() && (!IsPet() || (HasOwner() && GetOwner()->IsNPC())) && !CastToNPC()->WillAggroNPCs()) {
|
||||
if (
|
||||
IsNPC() &&
|
||||
!CastToNPC()->GetSwarmInfo() &&
|
||||
(!IsPet() || (HasOwner() && GetOwner()->IsNPC())) &&
|
||||
!CastToNPC()->WillAggroNPCs()
|
||||
) {
|
||||
WipeHateList(true); // wipe NPCs from hate list to prevent faction war
|
||||
}
|
||||
|
||||
|
||||
if (IsFocused()) {
|
||||
if (!target) {
|
||||
SetTarget(hate_list.GetEntWithMostHateOnList(this));
|
||||
@@ -1293,7 +1298,7 @@ void Mob::AI_Process() {
|
||||
if (cur > 0) {
|
||||
opts.range_percent = cur;
|
||||
}
|
||||
|
||||
|
||||
AreaRampage(&opts);
|
||||
specialed = true;
|
||||
}
|
||||
|
||||
+25
-19
@@ -40,19 +40,24 @@ extern EntityList entity_list;
|
||||
extern WorldServer worldserver;
|
||||
|
||||
// Loading object from database
|
||||
Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const EQ::ItemInstance* inst)
|
||||
: respawn_timer(0), decay_timer(300000)
|
||||
Object::Object(
|
||||
uint32 id,
|
||||
uint32 type,
|
||||
uint32 icon,
|
||||
const Object_Struct &object,
|
||||
const EQ::ItemInstance *inst
|
||||
) : respawn_timer(0), decay_timer(300000)
|
||||
{
|
||||
|
||||
user = nullptr;
|
||||
user = nullptr;
|
||||
last_user = nullptr;
|
||||
|
||||
// Initialize members
|
||||
m_id = id;
|
||||
m_type = type;
|
||||
m_icon = icon;
|
||||
m_inst = nullptr;
|
||||
m_ground_spawn=false;
|
||||
m_id = id;
|
||||
m_type = type;
|
||||
m_icon = icon;
|
||||
m_inst = nullptr;
|
||||
m_ground_spawn = false;
|
||||
|
||||
// Copy object data
|
||||
memcpy(&m_data, &object, sizeof(Object_Struct));
|
||||
if (inst) {
|
||||
@@ -61,13 +66,14 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object,
|
||||
} else {
|
||||
decay_timer.Disable();
|
||||
}
|
||||
|
||||
respawn_timer.Disable();
|
||||
|
||||
// Set drop_id to zero - it will be set when added to zone with SetID()
|
||||
m_data.drop_id = 0;
|
||||
m_data.size = object.size;
|
||||
m_data.tilt_x = object.tilt_x;
|
||||
m_data.tilt_y = object.tilt_y;
|
||||
m_data.size = object.size;
|
||||
m_data.tilt_x = object.tilt_x;
|
||||
m_data.tilt_y = object.tilt_y;
|
||||
|
||||
FixZ();
|
||||
}
|
||||
@@ -85,7 +91,7 @@ Object::Object(const EQ::ItemInstance* inst, char* name,float max_x,float min_x,
|
||||
m_min_y=min_y;
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : nullptr;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_type = ObjectTypes::Temporary;
|
||||
m_icon = 0;
|
||||
m_ground_spawn = true;
|
||||
decay_timer.Disable();
|
||||
@@ -116,7 +122,7 @@ Object::Object(Client* client, const EQ::ItemInstance* inst)
|
||||
// Initialize members
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : nullptr;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_type = ObjectTypes::Temporary;
|
||||
m_icon = 0;
|
||||
m_ground_spawn = false;
|
||||
// Set as much struct data as we can
|
||||
@@ -179,7 +185,7 @@ Object::Object(const EQ::ItemInstance *inst, float x, float y, float z, float he
|
||||
// Initialize members
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : nullptr;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_type = ObjectTypes::Temporary;
|
||||
m_icon = 0;
|
||||
m_ground_spawn = false;
|
||||
// Set as much struct data as we can
|
||||
@@ -436,7 +442,7 @@ void Object::CreateDeSpawnPacket(EQApplicationPacket* app)
|
||||
}
|
||||
|
||||
bool Object::Process(){
|
||||
if(m_type == OT_DROPPEDITEM && decay_timer.Enabled() && decay_timer.Check()) {
|
||||
if(m_type == ObjectTypes::Temporary && decay_timer.Enabled() && decay_timer.Check()) {
|
||||
// Send click to all clients (removes entity on client)
|
||||
auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct));
|
||||
ClickObject_Struct* click_object = (ClickObject_Struct*)outapp->pBuffer;
|
||||
@@ -497,7 +503,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
||||
if(m_ground_spawn) {//This is a Cool Groundspawn
|
||||
respawn_timer.Start();
|
||||
}
|
||||
if (m_type == OT_DROPPEDITEM) {
|
||||
if (m_type == ObjectTypes::Temporary) {
|
||||
bool cursordelete = false;
|
||||
bool duplicate_lore = false;
|
||||
if (m_inst && sender) {
|
||||
@@ -969,7 +975,7 @@ void Object::SetSize(float size)
|
||||
|
||||
void Object::SetSolidType(uint16 solidtype)
|
||||
{
|
||||
m_data.solidtype = solidtype;
|
||||
m_data.solid_type = solidtype;
|
||||
auto app = new EQApplicationPacket();
|
||||
auto app2 = new EQApplicationPacket();
|
||||
CreateDeSpawnPacket(app);
|
||||
@@ -987,7 +993,7 @@ float Object::GetSize()
|
||||
|
||||
uint16 Object::GetSolidType()
|
||||
{
|
||||
return m_data.solidtype;
|
||||
return m_data.solid_type;
|
||||
}
|
||||
|
||||
const char* Object::GetModelName()
|
||||
|
||||
+45
-2
@@ -73,8 +73,6 @@ IT10714_ACTORDEF=Augmentation Sealer
|
||||
IT10725_ACTORDEF=Shuriken
|
||||
*/
|
||||
|
||||
#define OT_DROPPEDITEM EQ::item::BagTypeLargeBag
|
||||
|
||||
// Icon values:
|
||||
//0x0453 a pie
|
||||
//0x0454 cookies?
|
||||
@@ -89,6 +87,51 @@ IT10725_ACTORDEF=Shuriken
|
||||
//0x045D is a hammer
|
||||
//0x045E is a wierd rope shape
|
||||
|
||||
enum ObjectTypes {
|
||||
StaticLocked = 0,
|
||||
Temporary = 1,
|
||||
ToolBox = 10,
|
||||
Research = 11,
|
||||
Mortar = 12,
|
||||
SelfDusting = 13,
|
||||
Baking1 = 14,
|
||||
Baking2 = 15,
|
||||
Tailoring = 16,
|
||||
Forge = 17,
|
||||
Fletching = 18,
|
||||
BrewBarrel = 19,
|
||||
Jewelcrafting = 20,
|
||||
PotteryWheel = 21,
|
||||
PotteryKiln = 22,
|
||||
WizardResearch = 24,
|
||||
MagicianResearch = 25,
|
||||
NecromancerResearch = 26,
|
||||
EnchanterResearch = 27,
|
||||
Invalid1 = 28,
|
||||
Invalid2 = 29,
|
||||
Experimental = 30,
|
||||
HighElfForge = 31,
|
||||
DarkElfForge = 32,
|
||||
OgreForge = 33,
|
||||
DwarfForge = 34,
|
||||
GnomeForge = 35,
|
||||
BarbarianForge = 36,
|
||||
IksarForge = 38,
|
||||
HumanForge = 39,
|
||||
HumanForge2 = 40,
|
||||
HalflingTailoring = 41,
|
||||
EruditeTailoring = 42,
|
||||
WoodElfTailoring = 43,
|
||||
WoodElfFletching = 44,
|
||||
IksarPotteryWheel = 45,
|
||||
TrollForge = 47,
|
||||
WoodElfForge = 48,
|
||||
HalflingForge = 49,
|
||||
EruditeForge = 50,
|
||||
AugmentationPool = 53,
|
||||
StaticUnlocked = 255
|
||||
};
|
||||
|
||||
class Object: public Entity
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -326,6 +326,11 @@ void Perl_Mob_GMMove(Mob* self, float x, float y, float z, float heading) // @ca
|
||||
self->GMMove(x, y, z, heading);
|
||||
}
|
||||
|
||||
void Perl_Mob_GMMove(Mob* self, float x, float y, float z, float heading, bool save_guard_spot) // @categories Script Utility
|
||||
{
|
||||
self->GMMove(x, y, z, heading, save_guard_spot);
|
||||
}
|
||||
|
||||
bool Perl_Mob_HasProcs(Mob* self) // @categories Stats and Attributes
|
||||
{
|
||||
return self->HasProcs();
|
||||
@@ -3469,6 +3474,7 @@ void perl_register_mob()
|
||||
package.add("FindType", (bool(*)(Mob*, uint16_t, bool, uint16_t))&Perl_Mob_FindType);
|
||||
package.add("GMMove", (void(*)(Mob*, float, float, float))&Perl_Mob_GMMove);
|
||||
package.add("GMMove", (void(*)(Mob*, float, float, float, float))&Perl_Mob_GMMove);
|
||||
package.add("GMMove", (void(*)(Mob*, float, float, float, float, bool))&Perl_Mob_GMMove);
|
||||
package.add("Gate", &Perl_Mob_Gate);
|
||||
package.add("GetAA", &Perl_Mob_GetAA);
|
||||
package.add("GetAABonuses", &Perl_Mob_GetAABonuses);
|
||||
|
||||
+1
-1
@@ -5811,7 +5811,7 @@ std::unordered_map<uint32, std::vector<uint16>> Client::LoadSpellGroupCache(uint
|
||||
m_pp.class_, min_level, max_level
|
||||
);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
auto results = content_db.QueryDatabase(query);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return spell_group_cache;
|
||||
}
|
||||
|
||||
@@ -1396,6 +1396,28 @@ void ClientTaskState::ResetTaskActivity(Client *client, int task_id, int activit
|
||||
);
|
||||
}
|
||||
|
||||
bool ClientTaskState::CompleteTask(Client *c, uint32 task_id)
|
||||
{
|
||||
const auto task_data = task_manager->GetTaskData(task_id);
|
||||
if (!task_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (
|
||||
int activity_id = 0;
|
||||
activity_id < task_manager->GetActivityCount(task_id);
|
||||
activity_id++
|
||||
) {
|
||||
c->UpdateTaskActivity(
|
||||
task_id,
|
||||
activity_id,
|
||||
task_data->activity_information[activity_id].goal_count
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientTaskState::ShowClientTaskInfoMessage(ClientTaskInformation *task, Client *c)
|
||||
{
|
||||
const auto task_data = task_manager->GetTaskData(task->task_id);
|
||||
@@ -1565,7 +1587,7 @@ int ClientTaskState::IsTaskCompleted(int task_id)
|
||||
}
|
||||
|
||||
for (auto &completed_task : m_completed_tasks) {
|
||||
LogTasks("Comparing compelted task [{}] with [{}]", completed_task.task_id, task_id);
|
||||
LogTasks("Comparing completed task [{}] with [{}]", completed_task.task_id, task_id);
|
||||
if (completed_task.task_id == task_id) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ public:
|
||||
bool CanAcceptNewTask(Client* client, int task_id, int npc_entity_id) const;
|
||||
bool HasExploreTask(Client* client) const;
|
||||
void EndSharedTask(Client* client, bool send_fail);
|
||||
bool CompleteTask(Client *c, uint32 task_id);
|
||||
|
||||
inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; }
|
||||
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ void NPC::DisplayWaypointInfo(Client *client) {
|
||||
(
|
||||
current_waypoint.pause ?
|
||||
fmt::format(
|
||||
"{} ({})",
|
||||
" {} ({})",
|
||||
Strings::SecondsToTime(current_waypoint.pause),
|
||||
current_waypoint.pause
|
||||
) :
|
||||
|
||||
+25
-24
@@ -550,15 +550,14 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneShutdown: {
|
||||
if (pack->size != sizeof(ServerZoneStateChange_struct)) {
|
||||
std::cout << "Wrong size on ServerOP_ZoneShutdown. Got: " << pack->size << ", Expected: " << sizeof(ServerZoneStateChange_struct) << std::endl;
|
||||
if (pack->size != sizeof(ServerZoneStateChange_Struct)) {
|
||||
LogError("Wrong size on ServerOP_ZoneShutdown. Got: [{}] Expected: [{}]", pack->size, sizeof(ServerZoneStateChange_Struct));
|
||||
break;
|
||||
}
|
||||
// Annouce the change to the world
|
||||
|
||||
if (!is_zone_loaded) {
|
||||
SetZoneData(0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
@@ -569,27 +568,24 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
).c_str()
|
||||
);
|
||||
|
||||
ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *)pack->pBuffer;
|
||||
std::cout << "Zone shutdown by " << zst->adminname << std::endl;
|
||||
auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
|
||||
LogInfo("Zone shutdown by {}.", s->admin_name);
|
||||
Zone::Shutdown();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneBootup: {
|
||||
if (pack->size != sizeof(ServerZoneStateChange_struct)) {
|
||||
std::cout << "Wrong size on ServerOP_ZoneBootup. Got: " << pack->size << ", Expected: " << sizeof(ServerZoneStateChange_struct) << std::endl;
|
||||
if (pack->size != sizeof(ServerZoneStateChange_Struct)) {
|
||||
LogError("Wrong size on ServerOP_ZoneShutdown. Got: [{}] Expected: [{}]", pack->size, sizeof(ServerZoneStateChange_Struct));
|
||||
break;
|
||||
}
|
||||
ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *)pack->pBuffer;
|
||||
|
||||
auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
|
||||
if (is_zone_loaded) {
|
||||
SetZoneData(zone->GetZoneID(), zone->GetInstanceID());
|
||||
if (zst->zoneid == zone->GetZoneID()) {
|
||||
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
|
||||
// zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
|
||||
}
|
||||
else {
|
||||
if (s->zone_id != zone->GetZoneID()) {
|
||||
SendEmoteMessage(
|
||||
zst->adminname,
|
||||
s->admin_name,
|
||||
0,
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -601,10 +597,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
break;
|
||||
}
|
||||
|
||||
if (zst->adminname[0] != 0)
|
||||
std::cout << "Zone bootup by " << zst->adminname << std::endl;
|
||||
if (s->admin_name[0] != 0) {
|
||||
LogInfo("Zone bootup by {}.", s->admin_name);
|
||||
}
|
||||
|
||||
Zone::Bootup(zst->zoneid, zst->instanceid, zst->makestatic);
|
||||
Zone::Bootup(s->zone_id, s->instance_id, s->is_static);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneIncClient: {
|
||||
@@ -3393,17 +3390,20 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
|
||||
bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, uint8 lang_skill, const char* message, ...) {
|
||||
if (!worldserver.Connected())
|
||||
if (!worldserver.Connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
va_list argptr;
|
||||
char buffer[512];
|
||||
auto length = strlen(message) + 1;
|
||||
char* buffer = new char[length];
|
||||
|
||||
va_start(argptr, message);
|
||||
vsnprintf(buffer, 512, message, argptr);
|
||||
vsnprintf(buffer, length, message, argptr);
|
||||
va_end(argptr);
|
||||
buffer[511] = '\0';
|
||||
buffer[length - 1] = '\0';
|
||||
|
||||
auto pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen(buffer) + 1);
|
||||
auto pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + length);
|
||||
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*)pack->pBuffer;
|
||||
|
||||
if (from == 0) {
|
||||
@@ -3432,6 +3432,7 @@ bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_nu
|
||||
|
||||
bool ret = SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
safe_delete_array(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+74
-80
@@ -56,6 +56,7 @@
|
||||
#include "zone_reload.h"
|
||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||
#include "../common/repositories/merchantlist_repository.h"
|
||||
#include "../common/repositories/object_repository.h"
|
||||
#include "../common/repositories/rule_sets_repository.h"
|
||||
#include "../common/serverinfo.h"
|
||||
|
||||
@@ -172,101 +173,94 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool is_static) {
|
||||
//this really loads the objects into entity_list
|
||||
bool Zone::LoadZoneObjects()
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, "
|
||||
"unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name "
|
||||
"FROM object WHERE zoneid = %i AND (version = %u OR version = -1) %s",
|
||||
zoneid,
|
||||
instanceversion,
|
||||
ContentFilterCriteria::apply().c_str()
|
||||
const auto &l = ObjectRepository::GetWhere(
|
||||
content_db,
|
||||
fmt::format(
|
||||
"zoneid = {} AND (version = {} OR version = -1) {}",
|
||||
zoneid,
|
||||
instanceversion,
|
||||
ContentFilterCriteria::apply()
|
||||
)
|
||||
);
|
||||
auto results = content_db.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogError("Error Loading Objects from DB: [{}]",
|
||||
results.ErrorMessage().c_str());
|
||||
if (l.empty()) {
|
||||
LogError("Error Loading Objects for Zone [{}] Version [{}]", zoneid, instanceversion);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (Strings::ToInt(row[9]) == 0) {
|
||||
// Type == 0 - Static Object
|
||||
const char *shortname = ZoneName(Strings::ToInt(row[1]), false); // zoneid -> zone_shortname
|
||||
for (const auto &e : l) {
|
||||
if (e.type == ObjectTypes::StaticLocked) {
|
||||
const std::string &zone_short_name = ZoneName(e.zoneid, false);
|
||||
|
||||
if (!shortname)
|
||||
if (zone_short_name.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo: clean up duplicate code with command_object
|
||||
auto d = DoorsRepository::NewEntity();
|
||||
|
||||
d.zone = shortname;
|
||||
d.id = 1000000000 + Strings::ToInt(row[0]); // Out of range of normal use for doors.id
|
||||
d.doorid = -1; // Client doesn't care if these are all the same door_id
|
||||
d.pos_x = Strings::ToFloat(row[2]); // xpos
|
||||
d.pos_y = Strings::ToFloat(row[3]); // ypos
|
||||
d.pos_z = Strings::ToFloat(row[4]); // zpos
|
||||
d.heading = Strings::ToFloat(row[5]); // heading
|
||||
d.zone = zone_short_name;
|
||||
d.id = 1000000000 + e.id;
|
||||
d.doorid = -1;
|
||||
d.pos_x = e.xpos;
|
||||
d.pos_y = e.ypos;
|
||||
d.pos_z = e.zpos;
|
||||
d.heading = e.heading;
|
||||
d.name = Strings::Replace(e.objectname, "_ACTORDEF", "");
|
||||
d.dest_zone = "NONE";
|
||||
d.incline = e.incline;
|
||||
d.client_version_mask = 0xFFFFFFFF;
|
||||
|
||||
d.name = row[8]; // objectname
|
||||
|
||||
// Strip trailing "_ACTORDEF" if present. Client won't accept it for doors.
|
||||
int pos = d.name.size() - strlen("_ACTORDEF");
|
||||
if (pos > 0 && d.name.compare(pos, std::string::npos, "_ACTORDEF") == 0)
|
||||
{
|
||||
d.name.erase(pos);
|
||||
}
|
||||
|
||||
d.dest_zone = "NONE";
|
||||
|
||||
if ((d.size = Strings::ToInt(row[11])) == 0) // unknown08 = optional size percentage
|
||||
if (e.size_percentage == 0) {
|
||||
d.size = 100;
|
||||
|
||||
switch (d.opentype = Strings::ToInt(row[12])) // unknown10 = optional request_nonsolid (0 or 1 or experimental number)
|
||||
{
|
||||
case 0:
|
||||
d.opentype = 31;
|
||||
break;
|
||||
case 1:
|
||||
d.opentype = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
d.incline = Strings::ToInt(row[13]); // unknown20 = optional model incline value
|
||||
d.client_version_mask = 0xFFFFFFFF; // We should load the mask from the zone.
|
||||
switch (d.opentype = e.solid_type)
|
||||
{
|
||||
case 0:
|
||||
d.opentype = 31;
|
||||
break;
|
||||
case 1:
|
||||
d.opentype = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
auto door = new Doors(d);
|
||||
entity_list.AddDoor(door);
|
||||
}
|
||||
|
||||
Object_Struct data = {0};
|
||||
uint32 id = 0;
|
||||
uint32 icon = 0;
|
||||
uint32 type = 0;
|
||||
uint32 itemid = 0;
|
||||
uint32 idx = 0;
|
||||
int16 charges = 0;
|
||||
Object_Struct data = {0};
|
||||
uint32 id = 0;
|
||||
uint32 icon = 0;
|
||||
uint32 type = 0;
|
||||
uint32 itemid = 0;
|
||||
uint32 idx = 0;
|
||||
int16 charges = 0;
|
||||
|
||||
id = e.id;
|
||||
|
||||
data.zone_id = e.zoneid;
|
||||
data.x = e.xpos;
|
||||
data.y = e.ypos;
|
||||
data.z = e.zpos;
|
||||
data.heading = e.heading;
|
||||
|
||||
itemid = e.itemid;
|
||||
charges = e.charges;
|
||||
type = e.type;
|
||||
icon = e.icon;
|
||||
|
||||
id = (uint32)Strings::ToInt(row[0]);
|
||||
data.zone_id = Strings::ToInt(row[1]);
|
||||
data.x = Strings::ToFloat(row[2]);
|
||||
data.y = Strings::ToFloat(row[3]);
|
||||
data.z = Strings::ToFloat(row[4]);
|
||||
data.heading = Strings::ToFloat(row[5]);
|
||||
itemid = (uint32)Strings::ToInt(row[6]);
|
||||
charges = (int16)Strings::ToInt(row[7]);
|
||||
strcpy(data.object_name, row[8]);
|
||||
type = (uint8)Strings::ToInt(row[9]);
|
||||
icon = (uint32)Strings::ToInt(row[10]);
|
||||
data.object_type = type;
|
||||
data.linked_list_addr[0] = 0;
|
||||
data.linked_list_addr[1] = 0;
|
||||
|
||||
data.solidtype = (uint32)Strings::ToInt(row[12]);
|
||||
data.unknown020 = (uint32)Strings::ToInt(row[13]);
|
||||
data.unknown024 = (uint32)Strings::ToInt(row[14]);
|
||||
data.unknown076 = (uint32)Strings::ToInt(row[15]);
|
||||
data.size = Strings::ToFloat(row[16]);
|
||||
data.tilt_x = Strings::ToFloat(row[17]);
|
||||
data.tilt_y = Strings::ToFloat(row[18]);
|
||||
strn0cpy(data.object_name, e.objectname.c_str(), sizeof(data.object_name));
|
||||
|
||||
data.solid_type = e.solid_type;
|
||||
data.incline = e.incline;
|
||||
data.unknown024 = e.unknown24;
|
||||
data.unknown076 = e.unknown76;
|
||||
data.size = e.size;
|
||||
data.tilt_x = e.tilt_x;
|
||||
data.tilt_y = e.tilt_y;
|
||||
data.unknown084 = 0;
|
||||
|
||||
|
||||
@@ -280,9 +274,8 @@ bool Zone::LoadZoneObjects()
|
||||
}
|
||||
|
||||
EQ::ItemInstance *inst = nullptr;
|
||||
// FatherNitwit: this dosent seem to work...
|
||||
// tradeskill containers do not have an itemid of 0... at least what I am seeing
|
||||
if (itemid == 0) {
|
||||
// tradeskill containers do not have an itemid of 0
|
||||
if (!itemid) {
|
||||
// Generic tradeskill container
|
||||
inst = new EQ::ItemInstance(ItemInstWorldContainer);
|
||||
} else {
|
||||
@@ -290,8 +283,7 @@ bool Zone::LoadZoneObjects()
|
||||
inst = database.CreateItem(itemid);
|
||||
}
|
||||
|
||||
// Father Nitwit's fix... not perfect...
|
||||
if (inst == nullptr && type != OT_DROPPEDITEM) {
|
||||
if (!inst && type != ObjectTypes::Temporary) {
|
||||
inst = new EQ::ItemInstance(ItemInstWorldContainer);
|
||||
}
|
||||
|
||||
@@ -301,15 +293,17 @@ bool Zone::LoadZoneObjects()
|
||||
}
|
||||
|
||||
auto object = new Object(id, type, icon, data, inst);
|
||||
object->SetDisplayName(row[19]);
|
||||
object->SetDisplayName(e.display_name.c_str());
|
||||
entity_list.AddObject(object, false);
|
||||
if (type == OT_DROPPEDITEM && itemid != 0)
|
||||
|
||||
if (type == ObjectTypes::Temporary && itemid) {
|
||||
entity_list.RemoveObject(object->GetID());
|
||||
}
|
||||
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] world objects", Strings::Commify(results.RowCount()));
|
||||
LogInfo("Loaded [{}] world objects", Strings::Commify(l.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2912,6 +2912,7 @@ bool ZoneDatabase::LoadBlockedSpells(int64 blocked_spells_count, ZoneSpellsBlock
|
||||
into[i].m_Location = glm::vec3(e.x, e.y, e.z);
|
||||
into[i].m_Difference = glm::vec3(e.x_diff, e.y_diff, e.z_diff);
|
||||
strn0cpy(into[i].message, e.message.c_str(), sizeof(into[i].message));
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+1
-1
@@ -1343,7 +1343,7 @@ bool Client::CanEnterZone(const std::string& zone_short_name, int16 instance_ver
|
||||
}
|
||||
|
||||
if (!z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && Strings::ToBool(z->flag_needed)) {
|
||||
if (Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(z->zoneidnumber)) {
|
||||
if (!GetGM() && !HasZoneFlag(z->zoneidnumber)) {
|
||||
LogInfo(
|
||||
"Character [{}] does not have the flag to be in this zone [{}]!",
|
||||
GetCleanName(),
|
||||
|
||||
Reference in New Issue
Block a user