Compare commits

...

19 Commits

Author SHA1 Message Date
Alex King 0ebc7f9bb6 [Release] 22.43.2 (#4017)
### Bots

* ^mez command spell list fix ([#3998](https://github.com/EQEmu/Server/pull/3998)) @dariusuknuis 2024-01-19

### Code

* Cleanup position methods ([#4015](https://github.com/EQEmu/Server/pull/4015)) @Kinglykrab 2024-01-25

### Commands

* Add `#npcedit set_grid [Grid ID]` to `#npcedit` ([#4004](https://github.com/EQEmu/Server/pull/4004)) @Kinglykrab 2024-01-22

### Crash Fix

* Fix crash when creating Frogloks/Drakkin ([#4016](https://github.com/EQEmu/Server/pull/4016)) @Kinglykrab 2024-01-25
* Reverting PR #3877 ([#3997](https://github.com/EQEmu/Server/pull/3997)) @fryguy503 2024-01-17

### Database

* Drop deprecated item_tick table ([#3977](https://github.com/EQEmu/Server/pull/3977)) @Akkadius 2024-01-14
* Drop item_tick if exists tweak in manifest ([#3985](https://github.com/EQEmu/Server/pull/3985)) @Akkadius 2024-01-15
* Increase max spawngroup name from 50 to 200 ([#3991](https://github.com/EQEmu/Server/pull/3991)) @Akkadius 2024-01-22

### Fixes

* Fix Mercenaries Buffs/Zoning Issues ([#4000](https://github.com/EQEmu/Server/pull/4000)) @Kinglykrab 2024-01-22
* Fix zone database update manifest ([#3972](https://github.com/EQEmu/Server/pull/3972)) @Kinglykrab 2024-01-13
* Fixes to zone idle while empty changes. ([#4006](https://github.com/EQEmu/Server/pull/4006)) @noudess 2024-01-23
* Reversed logic on InLiquid ([#3979](https://github.com/EQEmu/Server/pull/3979)) @fryguy503 2024-01-14

### Instances

* Convert Instance Quest Methods to Repositories ([#4012](https://github.com/EQEmu/Server/pull/4012)) @Kinglykrab 2024-01-25

### Logging

* Force Info category to be always on in file/console logs ([#3990](https://github.com/EQEmu/Server/pull/3990)) @Akkadius 2024-01-22

### Merchants

* Change database structure for merchant slots ([#3974](https://github.com/EQEmu/Server/pull/3974)) @joligario 2024-01-14

### Messages

* Fix disciple message added by previous patch. ([#3986](https://github.com/EQEmu/Server/pull/3986)) @noudess 2024-01-15

### Quest API

* QuestReward should now summon item to the inventory instead of the cursor. ([#3996](https://github.com/EQEmu/Server/pull/3996)) @regneq 2024-01-22

### Repositories

* Add `rank` to reserved words ([#3982](https://github.com/EQEmu/Server/pull/3982)) @Akkadius 2024-01-15
* Fix datetime zero-value save behavior ([#3976](https://github.com/EQEmu/Server/pull/3976)) @Akkadius 2024-01-14

### Spawn2

* Spawn condition value should default spawn_conditions value ([#3980](https://github.com/EQEmu/Server/pull/3980)) @noudess 2024-01-14

### Zoning

* Additional logs for zoning under instance checks ([#3989](https://github.com/EQEmu/Server/pull/3989)) @Akkadius 2024-01-22
2024-01-25 16:30:50 -06:00
Alex King 9ac25338bb [Crash Fix] Fix crash when creating Frogloks/Drakkin (#4016)
* [Crash Fix] Fix crash when creating Frogloks/Drakkin

# Notes
- https://github.com/EQEmu/Server/pull/3920 introduced an issue where we were using `uchar` for `race_selection` and `class_selection` which was not functioning properly within `IsPlayerRace()`.

* Update client.cpp
2024-01-25 06:19:59 -05:00
Alex King e9285fd2ca [Instances] Convert Instance Quest Methods to Repositories (#4012)
* [Instances] Convert Instance Quest Methods to Repositories

# Notes
- Convert `UpdateInstanceTimer()` and `GetInstanceTimerByID()` to repositories.
- Cleanup other instance methods.

* Update questmgr.cpp
2024-01-25 05:50:10 -05:00
Alex King 5b85f89c21 [Cleanup] Cleanup position methods (#4015)
# Notes
- Cleanup logic.
2024-01-24 22:47:24 -06:00
Paul Coene 7fed8fc8c8 [Bug Fix] Fixes to zone idle while empty changes. (#4006) 2024-01-22 19:33:00 -05:00
Alex King 26769f40d9 [Commands] Add #npcedit set_grid [Grid ID] to #npcedit (#4004)
* [Commands] Add #npcedit grid_id to #npcedit

# Notes
- Adds `#npcedit grid_id [Grid ID]` to `#npcedit`.

* set_grid
2024-01-22 17:49:18 -05:00
regneq f6148b9b8d [Quest] QuestReward should now summon item to the inventory instead of the cursor. (#3996)
* [forage rule feature] add a rule to disabled using common_food_ids from the list in forage.cpp.  currently set to enabled.

* [Quest] change QuestReward summonitem to SummonItemToInventory.

* add closing brackets in QuestReward functions.
2024-01-22 17:35:15 -05:00
Chris Miles ca1299bf1d [Database] Increase max spawngroup name from 50 to 200 (#3991) 2024-01-22 17:34:54 -05:00
Chris Miles 3fb24dc0a3 [Logging] Force Info category to be always on in file/console logs (#3990) 2024-01-22 17:34:48 -05:00
Chris Miles dcd7bffa54 [Zoning] Additional logs for zoning under instance checks (#3989) 2024-01-22 17:34:41 -05:00
Alex King 5298abe6bc [Bug Fix] Fix Mercenaries Buffs/Zoning Issues (#4000)
# Notes
- Mercenaries were disappearing on zoning because they were saving to slot `1` and being loaded from slot `0`.
- Mercenaries were not displaying properly in group window because of this as well.
- Mercenary buffs were saving even when they did not have any buffs.
2024-01-22 17:34:28 -05:00
dariusuknuis fbc2b7c152 [Bot] ^mez command spell list fix (#3998)
This change will allow necros to cast mez spells when ^mez command is used.
2024-01-19 16:39:14 -05:00
Paul Coene 86705000b0 Push discpline messages under melee->disciplines (#3987)
* Push discpline messages under melee->disciplines

* Added safe_delete()

* Remove fryguy's new message code and fix existing instead
2024-01-19 08:55:26 -05:00
Fryguy 748e37dbdf [Crash Fix] Reverting PR #3877 (#3997)
Reports of #3877 causing crashes on windows. No reports on Linux, but reverting for safety.
2024-01-17 18:22:11 -05:00
Paul Coene 27256215b8 [Messages] Fix disciple message added by previous patch. (#3986) 2024-01-15 14:01:24 -05:00
Chris Miles 59cbe1a152 [Database] Drop item_tick if exists tweak in manifest (#3985) 2024-01-14 23:14:15 -05:00
Chris Miles 3e50427bb7 [Repositories] Add rank to reserved words (#3982)
* [Repositories] Add `rank` to reserved words

* Update zonedb.cpp

* Guild Ranks

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-01-14 20:58:03 -05:00
Paul Coene 883b3b5826 [Spawn2] Spawn condition value should default spawn_conditions value (#3980)
* [Spawn2] Spawn condition value should default to value in spawn_conditions table

* Formatting changes and {}
2024-01-14 13:50:05 -05:00
Fryguy 135ee6b2b7 [Bug Fix] Reversed logic on InLiquid (#3979)
Thank you @noudness for catching this. Reversed logic on InLiquid check for falling damage.
2024-01-14 11:22:48 -05:00
31 changed files with 479 additions and 314 deletions
+65
View File
@@ -1,3 +1,68 @@
## [22.43.2] - 1/25/2024
### Bots
* ^mez command spell list fix ([#3998](https://github.com/EQEmu/Server/pull/3998)) @dariusuknuis 2024-01-19
### Code
* Cleanup position methods ([#4015](https://github.com/EQEmu/Server/pull/4015)) @Kinglykrab 2024-01-25
### Commands
* Add `#npcedit set_grid [Grid ID]` to `#npcedit` ([#4004](https://github.com/EQEmu/Server/pull/4004)) @Kinglykrab 2024-01-22
### Crash Fix
* Fix crash when creating Frogloks/Drakkin ([#4016](https://github.com/EQEmu/Server/pull/4016)) @Kinglykrab 2024-01-25
* Reverting PR #3877 ([#3997](https://github.com/EQEmu/Server/pull/3997)) @fryguy503 2024-01-17
### Database
* Drop deprecated item_tick table ([#3977](https://github.com/EQEmu/Server/pull/3977)) @Akkadius 2024-01-14
* Drop item_tick if exists tweak in manifest ([#3985](https://github.com/EQEmu/Server/pull/3985)) @Akkadius 2024-01-15
* Increase max spawngroup name from 50 to 200 ([#3991](https://github.com/EQEmu/Server/pull/3991)) @Akkadius 2024-01-22
### Fixes
* Fix Mercenaries Buffs/Zoning Issues ([#4000](https://github.com/EQEmu/Server/pull/4000)) @Kinglykrab 2024-01-22
* Fix zone database update manifest ([#3972](https://github.com/EQEmu/Server/pull/3972)) @Kinglykrab 2024-01-13
* Fixes to zone idle while empty changes. ([#4006](https://github.com/EQEmu/Server/pull/4006)) @noudess 2024-01-23
* Reversed logic on InLiquid ([#3979](https://github.com/EQEmu/Server/pull/3979)) @fryguy503 2024-01-14
### Instances
* Convert Instance Quest Methods to Repositories ([#4012](https://github.com/EQEmu/Server/pull/4012)) @Kinglykrab 2024-01-25
### Logging
* Force Info category to be always on in file/console logs ([#3990](https://github.com/EQEmu/Server/pull/3990)) @Akkadius 2024-01-22
### Merchants
* Change database structure for merchant slots ([#3974](https://github.com/EQEmu/Server/pull/3974)) @joligario 2024-01-14
### Messages
* Fix disciple message added by previous patch. ([#3986](https://github.com/EQEmu/Server/pull/3986)) @noudess 2024-01-15
### Quest API
* QuestReward should now summon item to the inventory instead of the cursor. ([#3996](https://github.com/EQEmu/Server/pull/3996)) @regneq 2024-01-22
### Repositories
* Add `rank` to reserved words ([#3982](https://github.com/EQEmu/Server/pull/3982)) @Akkadius 2024-01-15
* Fix datetime zero-value save behavior ([#3976](https://github.com/EQEmu/Server/pull/3976)) @Akkadius 2024-01-14
### Spawn2
* Spawn condition value should default spawn_conditions value ([#3980](https://github.com/EQEmu/Server/pull/3980)) @noudess 2024-01-14
### Zoning
* Additional logs for zoning under instance checks ([#3989](https://github.com/EQEmu/Server/pull/3989)) @Akkadius 2024-01-22
## [22.43.1] - 1/14/2024
### Repositories
+12 -1
View File
@@ -5229,7 +5229,18 @@ ALTER TABLE `merchantlist_temp`
.condition = "not_empty",
.match = "",
.sql = R"(
DROP TABLE item_tick
DROP TABLE IF EXISTS item_tick
)"
},
ManifestEntry{
.version = 9256,
.description = "2024_01_16_increase_spawngroup_size.sql",
.check = "SHOW COLUMNS FROM `spawngroup` LIKE 'name'",
.condition = "contains",
.match = "varchar(50)",
.sql = R"(
ALTER TABLE `spawngroup`
MODIFY COLUMN `name` varchar(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `id`;
)"
}
// -- template; copy/paste this when you need to create a new entry
+6
View File
@@ -631,6 +631,12 @@ struct ConsentResponse_Struct {
char zonename[32];
};
struct NameApproval_Struct {
char name[64];
uint32 race_id;
uint32 class_id;
};
/*
** Name Generator Struct
** Length: 72 bytes
+2
View File
@@ -701,6 +701,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_file = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_file = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
return this;
}
@@ -21,7 +21,7 @@ public:
struct CharacterLeadershipAbilities {
uint32_t id;
uint16_t slot;
uint16_t rank;
uint16_t rank_;
};
static std::string PrimaryKey()
@@ -34,7 +34,7 @@ public:
return {
"id",
"slot",
"rank",
"`rank`",
};
}
@@ -43,7 +43,7 @@ public:
return {
"id",
"slot",
"rank",
"`rank`",
};
}
@@ -84,9 +84,9 @@ public:
{
CharacterLeadershipAbilities e{};
e.id = 0;
e.slot = 0;
e.rank = 0;
e.id = 0;
e.slot = 0;
e.rank_ = 0;
return e;
}
@@ -123,9 +123,9 @@ public:
if (results.RowCount() == 1) {
CharacterLeadershipAbilities e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot = row[1] ? static_cast<uint16_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot = row[1] ? static_cast<uint16_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank_ = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
return e;
}
@@ -161,7 +161,7 @@ public:
v.push_back(columns[0] + " = " + std::to_string(e.id));
v.push_back(columns[1] + " = " + std::to_string(e.slot));
v.push_back(columns[2] + " = " + std::to_string(e.rank));
v.push_back(columns[2] + " = " + std::to_string(e.rank_));
auto results = db.QueryDatabase(
fmt::format(
@@ -185,7 +185,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
auto results = db.QueryDatabase(
fmt::format(
@@ -217,7 +217,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -251,9 +251,9 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterLeadershipAbilities e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot = row[1] ? static_cast<uint16_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot = row[1] ? static_cast<uint16_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank_ = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -278,9 +278,9 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterLeadershipAbilities e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot = row[1] ? static_cast<uint16_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.slot = row[1] ? static_cast<uint16_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank_ = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -357,7 +357,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
auto results = db.QueryDatabase(
fmt::format(
@@ -382,7 +382,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -21,7 +21,7 @@ public:
struct GuildMembers {
int32_t char_id;
uint32_t guild_id;
uint8_t rank;
uint8_t rank_;
uint8_t tribute_enable;
uint32_t total_tribute;
uint32_t last_tribute;
@@ -41,7 +41,7 @@ public:
return {
"char_id",
"guild_id",
"rank",
"`rank`",
"tribute_enable",
"total_tribute",
"last_tribute",
@@ -57,7 +57,7 @@ public:
return {
"char_id",
"guild_id",
"rank",
"`rank`",
"tribute_enable",
"total_tribute",
"last_tribute",
@@ -107,7 +107,7 @@ public:
e.char_id = 0;
e.guild_id = 0;
e.rank = 0;
e.rank_ = 0;
e.tribute_enable = 0;
e.total_tribute = 0;
e.last_tribute = 0;
@@ -153,7 +153,7 @@ public:
e.char_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.rank_ = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.tribute_enable = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.total_tribute = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.last_tribute = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
@@ -196,7 +196,7 @@ public:
v.push_back(columns[0] + " = " + std::to_string(e.char_id));
v.push_back(columns[1] + " = " + std::to_string(e.guild_id));
v.push_back(columns[2] + " = " + std::to_string(e.rank));
v.push_back(columns[2] + " = " + std::to_string(e.rank_));
v.push_back(columns[3] + " = " + std::to_string(e.tribute_enable));
v.push_back(columns[4] + " = " + std::to_string(e.total_tribute));
v.push_back(columns[5] + " = " + std::to_string(e.last_tribute));
@@ -227,7 +227,7 @@ public:
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.tribute_enable));
v.push_back(std::to_string(e.total_tribute));
v.push_back(std::to_string(e.last_tribute));
@@ -266,7 +266,7 @@ public:
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.tribute_enable));
v.push_back(std::to_string(e.total_tribute));
v.push_back(std::to_string(e.last_tribute));
@@ -309,7 +309,7 @@ public:
e.char_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.rank_ = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.tribute_enable = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.total_tribute = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.last_tribute = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
@@ -343,7 +343,7 @@ public:
e.char_id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.guild_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.rank_ = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.tribute_enable = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.total_tribute = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.last_tribute = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
@@ -427,7 +427,7 @@ public:
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.tribute_enable));
v.push_back(std::to_string(e.total_tribute));
v.push_back(std::to_string(e.last_tribute));
@@ -459,7 +459,7 @@ public:
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.tribute_enable));
v.push_back(std::to_string(e.total_tribute));
v.push_back(std::to_string(e.last_tribute));
@@ -20,7 +20,7 @@ class BaseGuildRanksRepository {
public:
struct GuildRanks {
uint32_t guild_id;
uint8_t rank;
uint8_t rank_;
std::string title;
};
@@ -33,7 +33,7 @@ public:
{
return {
"guild_id",
"rank",
"`rank`",
"title",
};
}
@@ -42,7 +42,7 @@ public:
{
return {
"guild_id",
"rank",
"`rank`",
"title",
};
}
@@ -85,7 +85,7 @@ public:
GuildRanks e{};
e.guild_id = 0;
e.rank = 0;
e.rank_ = 0;
e.title = "";
return e;
@@ -124,7 +124,7 @@ public:
GuildRanks e{};
e.guild_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.rank = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.title = row[2] ? row[2] : "";
return e;
@@ -160,7 +160,7 @@ public:
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.guild_id));
v.push_back(columns[1] + " = " + std::to_string(e.rank));
v.push_back(columns[1] + " = " + std::to_string(e.rank_));
v.push_back(columns[2] + " = '" + Strings::Escape(e.title) + "'");
auto results = db.QueryDatabase(
@@ -184,7 +184,7 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back("'" + Strings::Escape(e.title) + "'");
auto results = db.QueryDatabase(
@@ -216,7 +216,7 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back("'" + Strings::Escape(e.title) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
@@ -252,7 +252,7 @@ public:
GuildRanks e{};
e.guild_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.rank = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.title = row[2] ? row[2] : "";
all_entries.push_back(e);
@@ -279,7 +279,7 @@ public:
GuildRanks e{};
e.guild_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.rank = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.rank_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.title = row[2] ? row[2] : "";
all_entries.push_back(e);
@@ -356,7 +356,7 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back("'" + Strings::Escape(e.title) + "'");
auto results = db.QueryDatabase(
@@ -381,7 +381,7 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.guild_id));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back("'" + Strings::Escape(e.title) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
@@ -227,7 +227,7 @@ public:
int32_t no_block;
int32_t field206;
int32_t spellgroup;
int32_t rank;
int32_t rank_;
int32_t field209;
int32_t field210;
int32_t CastRestriction;
@@ -474,7 +474,7 @@ public:
"no_block",
"field206",
"spellgroup",
"rank",
"`rank`",
"field209",
"field210",
"CastRestriction",
@@ -717,7 +717,7 @@ public:
"no_block",
"field206",
"spellgroup",
"rank",
"`rank`",
"field209",
"field210",
"CastRestriction",
@@ -994,7 +994,7 @@ public:
e.no_block = 0;
e.field206 = -1;
e.spellgroup = 0;
e.rank = 0;
e.rank_ = 0;
e.field209 = 0;
e.field210 = 1;
e.CastRestriction = 0;
@@ -1267,7 +1267,7 @@ public:
e.no_block = row[205] ? static_cast<int32_t>(atoi(row[205])) : 0;
e.field206 = row[206] ? static_cast<int32_t>(atoi(row[206])) : -1;
e.spellgroup = row[207] ? static_cast<int32_t>(atoi(row[207])) : 0;
e.rank = row[208] ? static_cast<int32_t>(atoi(row[208])) : 0;
e.rank_ = row[208] ? static_cast<int32_t>(atoi(row[208])) : 0;
e.field209 = row[209] ? static_cast<int32_t>(atoi(row[209])) : 0;
e.field210 = row[210] ? static_cast<int32_t>(atoi(row[210])) : 1;
e.CastRestriction = row[211] ? static_cast<int32_t>(atoi(row[211])) : 0;
@@ -1537,7 +1537,7 @@ public:
v.push_back(columns[205] + " = " + std::to_string(e.no_block));
v.push_back(columns[206] + " = " + std::to_string(e.field206));
v.push_back(columns[207] + " = " + std::to_string(e.spellgroup));
v.push_back(columns[208] + " = " + std::to_string(e.rank));
v.push_back(columns[208] + " = " + std::to_string(e.rank_));
v.push_back(columns[209] + " = " + std::to_string(e.field209));
v.push_back(columns[210] + " = " + std::to_string(e.field210));
v.push_back(columns[211] + " = " + std::to_string(e.CastRestriction));
@@ -1795,7 +1795,7 @@ public:
v.push_back(std::to_string(e.no_block));
v.push_back(std::to_string(e.field206));
v.push_back(std::to_string(e.spellgroup));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.field209));
v.push_back(std::to_string(e.field210));
v.push_back(std::to_string(e.CastRestriction));
@@ -2061,7 +2061,7 @@ public:
v.push_back(std::to_string(e.no_block));
v.push_back(std::to_string(e.field206));
v.push_back(std::to_string(e.spellgroup));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.field209));
v.push_back(std::to_string(e.field210));
v.push_back(std::to_string(e.CastRestriction));
@@ -2331,7 +2331,7 @@ public:
e.no_block = row[205] ? static_cast<int32_t>(atoi(row[205])) : 0;
e.field206 = row[206] ? static_cast<int32_t>(atoi(row[206])) : -1;
e.spellgroup = row[207] ? static_cast<int32_t>(atoi(row[207])) : 0;
e.rank = row[208] ? static_cast<int32_t>(atoi(row[208])) : 0;
e.rank_ = row[208] ? static_cast<int32_t>(atoi(row[208])) : 0;
e.field209 = row[209] ? static_cast<int32_t>(atoi(row[209])) : 0;
e.field210 = row[210] ? static_cast<int32_t>(atoi(row[210])) : 1;
e.CastRestriction = row[211] ? static_cast<int32_t>(atoi(row[211])) : 0;
@@ -2592,7 +2592,7 @@ public:
e.no_block = row[205] ? static_cast<int32_t>(atoi(row[205])) : 0;
e.field206 = row[206] ? static_cast<int32_t>(atoi(row[206])) : -1;
e.spellgroup = row[207] ? static_cast<int32_t>(atoi(row[207])) : 0;
e.rank = row[208] ? static_cast<int32_t>(atoi(row[208])) : 0;
e.rank_ = row[208] ? static_cast<int32_t>(atoi(row[208])) : 0;
e.field209 = row[209] ? static_cast<int32_t>(atoi(row[209])) : 0;
e.field210 = row[210] ? static_cast<int32_t>(atoi(row[210])) : 1;
e.CastRestriction = row[211] ? static_cast<int32_t>(atoi(row[211])) : 0;
@@ -2903,7 +2903,7 @@ public:
v.push_back(std::to_string(e.no_block));
v.push_back(std::to_string(e.field206));
v.push_back(std::to_string(e.spellgroup));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.field209));
v.push_back(std::to_string(e.field210));
v.push_back(std::to_string(e.CastRestriction));
@@ -3162,7 +3162,7 @@ public:
v.push_back(std::to_string(e.no_block));
v.push_back(std::to_string(e.field206));
v.push_back(std::to_string(e.spellgroup));
v.push_back(std::to_string(e.rank));
v.push_back(std::to_string(e.rank_));
v.push_back(std::to_string(e.field209));
v.push_back(std::to_string(e.field210));
v.push_back(std::to_string(e.CastRestriction));
+33 -6
View File
@@ -45,14 +45,41 @@ public:
// Custom extended repository methods here
static int UpdateDuration(Database& db, int instance_id, uint32_t new_duration)
static int UpdateDuration(Database& db, uint16 instance_id, uint32_t new_duration)
{
auto results = db.QueryDatabase(fmt::format(
"UPDATE {} SET duration = {} WHERE {} = {};",
TableName(), new_duration, PrimaryKey(), instance_id
));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{}` SET `duration` = {} WHERE `{}` = {}",
TableName(),
new_duration,
PrimaryKey(),
instance_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
return results.Success() ? results.RowsAffected() : 0;
}
static uint32 GetRemainingTimeByInstanceID(Database& db, uint16 instance_id)
{
auto results = db.QueryDatabase(
fmt::format(
SQL(
SELECT ((start_time + duration) - UNIX_TIMESTAMP()) AS `remaining` FROM `{}`
WHERE `id` = {}
),
TableName(),
instance_id
)
);
if (!results.Success() || !results.RowCount()) {
return 0;
}
auto row = results.begin();
return Strings::ToUnsignedInt(row[0]);
}
};
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.43.1-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.43.2-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9255
#define CURRENT_BINARY_DATABASE_VERSION 9256
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.43.1",
"version": "22.43.2",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
-1
View File
@@ -398,6 +398,5 @@ void QSDatabase::GeneralQueryReceive(ServerPacket *pack)
LogInfo("[{}]", query.c_str());
}
safe_delete(pack);
safe_delete_array(queryBuffer);
}
@@ -599,6 +599,7 @@ sub get_reserved_cpp_variable_names
"class",
"int",
"key",
"rank",
"range"
);
}
+34 -37
View File
@@ -535,67 +535,64 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app)
return false;
}
auto length = snprintf(char_name, 64, "%s", (char*)app->pBuffer);
auto n = (NameApproval_Struct*) app->pBuffer;
uchar race_selection = app->pBuffer[64];
uchar class_selection = app->pBuffer[68];
strn0cpy(char_name, n->name, sizeof(char_name));
if (!IsPlayerRace(race_selection)) {
const uint32 length = strlen(n->name);
const uint32 race_id = n->race_id;
const uint32 class_id = n->class_id;
if (!IsPlayerRace(race_id)) {
LogInfo("Invalid Race ID.");
return false;
}
if (!EQ::ValueWithin(class_selection, Class::Warrior, Class::Berserker)) {
if (!EQ::ValueWithin(class_id, Class::Warrior, Class::Berserker)) {
LogInfo("Invalid Class ID.");
return false;
}
LogInfo("Name approval request. Name=[{}], race_selection=[{}], class=[{}]", char_name, GetRaceIDName(race_selection), GetClassIDName(class_selection));
EQApplicationPacket *outapp;
outapp = new EQApplicationPacket;
outapp->SetOpcode(OP_ApproveName);
outapp->pBuffer = new uchar[1];
outapp->size = 1;
LogInfo(
"char_name [{}] race_id [{}] class_id [{}]",
char_name,
GetRaceIDName(race_id),
GetClassIDName(class_id)
);
bool valid = true;
/* Name must be between 4 and 15 characters long, packet forged if this is true */
if (length < 4 || length > 15) {
valid = false;
}
/* Name must begin with an upper-case letter, can be sent with some tricking of the client */
else if (islower(char_name[0])) {
valid = false;
}
/* Name must not have any spaces, packet forged if this is true */
else if (strstr(char_name, " ")) {
valid = false;
}
/* I would like to do this later, since it's likely more expensive, but oh well */
else if (!database.CheckNameFilter(char_name)) {
valid = false;
}
else {
/* Name must not not contain any uppercase letters, can be sent with some tricking of the client */
bool is_valid = true;
if (!EQ::ValueWithin(length, 4, 15)) { /* Name must be between 4 and 15 characters long, packet forged if this is true */
is_valid = false;
} else if (islower(char_name[0])) { /* Name must begin with an upper-case letter, can be sent with some tricking of the client */
is_valid = false;
} else if (strstr(char_name, " ")) { /* Name must not have any spaces, packet forged if this is true */
is_valid = false;
} else if (!database.CheckNameFilter(char_name)) { /* I would like to do this later, since it's likely more expensive, but oh well */
is_valid = false;
} else { /* Name must not contain any uppercase letters, can be sent with some tricking of the client */
for (int i = 1; i < length; ++i) {
if (isupper(char_name[i])) {
valid = false;
is_valid = false;
break;
}
}
}
/* Still not invalid, let's see if it's taken */
if (valid) {
valid = database.ReserveName(GetAccountID(), char_name);
if (is_valid) { /* Still not invalid, let's see if it's taken */
is_valid = database.ReserveName(GetAccountID(), char_name);
}
outapp->pBuffer[0] = valid ? 1 : 0;
auto outapp = new EQApplicationPacket(OP_ApproveName, 1);
outapp->pBuffer[0] = is_valid ? 1 : 0;
QueuePacket(outapp);
safe_delete(outapp);
if (!valid)
if (!is_valid) {
memset(char_name, 0, sizeof(char_name));
}
return true;
}
+6 -3
View File
@@ -4435,9 +4435,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
// If an "innate" spell, change to spell type to
// produce a spell message. Send to everyone.
// This fixes issues with npc-procs like 1002 and 918 which
// need to spit out extra spell color.
if (IsValidSpell(spell_id) && skill_used == EQ::skills::SkillTigerClaw) {
// This fixes issues with npc-procs like 1002 and 918 and
// damage based disciplines which need to spit out extra spell color.
if (IsValidSpell(spell_id) &&
(skill_used == EQ::skills::SkillTigerClaw ||
(IsDamageSpell(spell_id) && IsDiscipline(spell_id)))
) {
a->type = DamageTypeSpell;
entity_list.QueueCloseClients(
this, /* Sender */
+1 -1
View File
@@ -281,7 +281,7 @@ public:
entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Animal;
break;
case SE_Mez:
if (spells[spell_id].spell_affect_index != 12)
if (spells[spell_id].effect_id[EFFECTIDTOINDEX(1)] != 31)
break;
entry_prototype = new STBaseEntry(BCEnum::SpT_Mesmerize);
break;
+24 -19
View File
@@ -8113,7 +8113,8 @@ void Client::SendColoredText(uint32 color, std::string message)
}
void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction) {
void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction)
{
auto outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct));
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
@@ -8128,16 +8129,16 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
qr->item_id[0] = itemid;
qr->exp_reward = exp;
if (copper > 0 || silver > 0 || gold > 0 || platinum > 0)
if (copper > 0 || silver > 0 || gold > 0 || platinum > 0) {
AddMoneyToPP(copper, silver, gold, platinum);
}
if (itemid > 0)
SummonItem(itemid, -1, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
if (itemid > 0) {
SummonItemIntoInventory(itemid, -1, 0, 0, 0, 0, 0, 0, false);
}
if (faction)
{
if (target && target->IsNPC() && !target->IsCharmed())
{
if (faction) {
if (target && target->IsNPC() && !target->IsCharmed()) {
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
qr->faction = target->CastToNPC()->GetPrimaryFaction();
@@ -8145,8 +8146,9 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
}
}
if (exp > 0)
if (exp > 0) {
AddEXP(exp);
}
QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
safe_delete(outapp);
@@ -8163,23 +8165,25 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac
// not set in caller because reasons
qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name, tasks won't set this
if (reward.copper > 0 || reward.silver > 0 || reward.gold > 0 || reward.platinum > 0)
if (reward.copper > 0 || reward.silver > 0 || reward.gold > 0 || reward.platinum > 0) {
AddMoneyToPP(reward.copper, reward.silver, reward.gold, reward.platinum);
}
for (int i = 0; i < QUESTREWARD_COUNT; ++i)
if (reward.item_id[i] > 0)
SummonItem(reward.item_id[i], -1, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
for (int i = 0; i < QUESTREWARD_COUNT; ++i) {
if (reward.item_id[i] > 0) {
SummonItemIntoInventory(reward.item_id[i], -1, 0, 0, 0, 0, 0, 0, false);
}
}
// only process if both are valid
// if we don't have a target here, we want to just reward, but if there is a target, need to check charm
if (reward.faction && reward.faction_mod && (target == nullptr || !target->IsCharmed()))
if (reward.faction && reward.faction_mod && (target == nullptr || !target->IsCharmed())) {
RewardFaction(reward.faction, reward.faction_mod);
}
// legacy support
if (faction)
{
if (target && target->IsNPC() && !target->IsCharmed())
{
if (faction) {
if (target && target->IsNPC() && !target->IsCharmed()) {
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
qr->faction = target->CastToNPC()->GetPrimaryFaction();
@@ -8187,8 +8191,9 @@ void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool fac
}
}
if (reward.exp_reward > 0)
if (reward.exp_reward > 0) {
AddEXP(reward.exp_reward);
}
QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
safe_delete(outapp);
+1 -1
View File
@@ -6256,7 +6256,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
if (ed->dmgtype == EQ::constants::EnvironmentalDamage::Falling) {
if (zone->HasWaterMap()) {
auto target_position = glm::vec3(GetX(), GetY(), GetZ());
if (!zone->watermap->InLiquid(target_position)) {
if (zone->watermap->InLiquid(target_position)) {
return;
}
}
+16 -25
View File
@@ -491,42 +491,33 @@ void EntityList::MobProcess()
old_client_count > 0 &&
zone->GetSecondsBeforeIdle() > 0
) {
if (!zone->IsIdle()) {
LogInfo(
"Zone will go into an idle state after [{}] second{}.",
zone->GetSecondsBeforeIdle(),
zone->GetSecondsBeforeIdle() != 1 ? "s" : ""
);
}
LogInfo(
"Zone will go into an idle state after [{}] second{}.",
zone->GetSecondsBeforeIdle(),
zone->GetSecondsBeforeIdle() != 1 ? "s" : ""
);
mob_settle_timer->Start(zone->GetSecondsBeforeIdle() * 1000);
}
old_client_count = numclients;
if (numclients == 0 && mob_settle_timer->Check()) {
if (!zone->IsIdle()) {
LogInfo(
"Zone has gone idle after [{}] second{}.",
zone->GetSecondsBeforeIdle(),
zone->GetSecondsBeforeIdle() != 1 ? "s" : ""
);
zone->SetIsIdle(true);
}
LogInfo(
"Zone has gone idle after [{}] second{}.",
zone->GetSecondsBeforeIdle(),
zone->GetSecondsBeforeIdle() != 1 ? "s" : ""
);
mob_settle_timer->Disable();
}
// Disable settle timer if someone zones into empty zone
if (numclients > 0 || mob_settle_timer->Check()) {
if (zone->IsIdle()) {
LogInfo("Zone is no longer idle.");
zone->SetIsIdle(false);
if (mob_settle_timer->Enabled()) {
LogInfo("Zone is no longer scheduled to go idle.");
mob_settle_timer->Disable();
}
mob_settle_timer->Disable();
}
old_client_count = numclients;
Spawn2* s2 = mob->CastToNPC()->respawn2;
// Perform normal mob processing if any of these are true:
+26
View File
@@ -1645,6 +1645,31 @@ void command_npcedit(Client *c, const Seperator *sep)
);
return;
}
} else if (!strcasecmp(sep->arg[1], "set_grid")) {
if (sep->IsNumber(2)) {
const uint32 grid_id = Strings::ToUnsignedInt(sep->arg[2]);
if (grid_id) {
d = fmt::format(
"{} now has a Grid ID of {} on Spawn Group ID {}.",
npc_id_string,
grid_id,
Strings::Commify(std::to_string(t->GetSpawnGroupId()))
);
auto query = fmt::format(
"UPDATE spawn2 SET pathgrid = {} WHERE spawngroupID = {} AND version = {}",
grid_id,
t->GetSpawnGroupId(),
zone->GetInstanceVersion()
);
content_db.QueryDatabase(query);
} else {
c->Message(Chat::White, "Grid ID must be greater than 0.");
return;
}
} else {
c->Message(Chat::White, "Usage: #npcedit set_grid [Grid ID] - Sets an NPC's Grid ID");
return;
}
} else {
SendNPCEditSubCommands(c);
return;
@@ -1768,4 +1793,5 @@ void SendNPCEditSubCommands(Client *c)
c->Message(Chat::White, "Usage: #npcedit keeps_sold_items [Flag] - Sets an NPC's Keeps Sold Items Flag [0 = False, 1 = True]");
c->Message(Chat::White, "Usage: #npcedit setanimation [Animation ID] - Sets an NPC's Animation on Spawn (Stored in spawn2 table)");
c->Message(Chat::White, "Usage: #npcedit respawntime [Respawn Time] - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)");
c->Message(Chat::White, "Usage: #npcedit set_grid [Grid ID] - Sets an NPC's Grid ID");
}
+1 -1
View File
@@ -6,7 +6,7 @@ void command_petitems(Client *c, const Seperator *sep)
c->Message(Chat::White, "You must have a pet to use this command.");
return;
}
auto pet = c->GetPet()->CastToNPC();
auto loot_list = pet->GetLootList();
if (!loot_list.empty()) {
+27 -30
View File
@@ -5575,20 +5575,17 @@ Merc* Client::GetMerc() {
return (tmp);
}
uint8 Client::GetNumberOfMercenaries() {
uint8 Client::GetNumberOfMercenaries()
{
uint8 count = 0;
uint8 numMercs = 0;
for(int i=0; i<MAXMERCS; i++)
{
if(m_mercinfo[i].mercid != 0)
{
numMercs++;
for (int slot_id = 0; slot_id < MAXMERCS; slot_id++) {
if (m_mercinfo[slot_id].mercid != 0) {
count++;
}
}
Log(Logs::General, Logs::Mercenaries, "GetNumberOfMercenaries Number: %i for %s.", numMercs, GetName());
return numMercs;
return count;
}
void Merc::SetMercData( uint32 template_id ) {
@@ -5738,17 +5735,17 @@ void NPC::LoadMercenaryTypes()
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
if (!results.Success() || !results.RowCount()) {
return;
}
for (auto row = results.begin(); row != results.end(); ++row) {
MercType t;
t.Type = Strings::ToInt(row[0]);
t.ClientVersion = Strings::ToInt(row[1]);
mercTypeList.push_back(t);
for (auto row : results) {
mercTypeList.push_back(
MercType{
.Type = Strings::ToUnsignedInt(row[0]),
.ClientVersion = Strings::ToUnsignedInt(row[1])
}
);
}
}
@@ -5772,21 +5769,21 @@ void NPC::LoadMercenaries()
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
if (!results.Success() || !results.RowCount()) {
return;
}
for (auto row = results.begin(); row != results.end(); ++row) {
MercData t;
t.MercTemplateID = Strings::ToInt(row[0]);
t.MercType = Strings::ToInt(row[1]);
t.MercSubType = Strings::ToInt(row[2]);
t.CostFormula = Strings::ToInt(row[3]);
t.ClientVersion = Strings::ToInt(row[4]);
t.NPCID = Strings::ToInt(row[5]);
mercDataList.push_back(t);
for (auto row : results) {
mercDataList.push_back(
MercData{
.MercTemplateID = Strings::ToUnsignedInt(row[0]),
.MercType = Strings::ToUnsignedInt(row[1]),
.MercSubType = Strings::ToUnsignedInt(row[2]),
.CostFormula = Strings::ToUnsignedInt(row[3]),
.ClientVersion = Strings::ToUnsignedInt(row[4]),
.NPCID = Strings::ToUnsignedInt(row[5])
}
);
}
}
+61 -27
View File
@@ -3,19 +3,38 @@
#include <string>
#include <cmath>
#include "../common/strings.h"
#include "../common/data_verification.h"
static const float position_eps = 0.0001f;
constexpr float position_eps = 0.0001f;
std::string to_string(const glm::vec4 &position) {
return StringFormat("(%.3f, %.3f, %.3f, %.3f)", position.x,position.y,position.z,position.w);
std::string to_string(const glm::vec4 &position)
{
return fmt::format(
"({:.3f}, {:.3f}, {:.3f}, {:.3f})",
position.x,
position.y,
position.z,
position.w
);
}
std::string to_string(const glm::vec3 &position){
return StringFormat("(%.3f, %.3f, %.3f)", position.x,position.y,position.z);
std::string to_string(const glm::vec3 &position)
{
return fmt::format(
"({:.3f}, {:.3f}, {:.3f})",
position.x,
position.y,
position.z
);
}
std::string to_string(const glm::vec2 &position){
return StringFormat("(%.3f, %.3f)", position.x,position.y);
std::string to_string(const glm::vec2 &position)
{
return fmt::format(
"({:.3f}, {:.3f})",
position.x,
position.y
);
}
bool IsOrigin(const glm::vec3 &position) {
@@ -103,14 +122,23 @@ float DistanceSquaredNoZ(const glm::vec4& point1, const glm::vec4& point2) {
* box (3 dimensional) formed from the points minimum and maximum.
*/
bool IsWithinAxisAlignedBox(const glm::vec3 &position, const glm::vec3 &minimum, const glm::vec3 &maximum) {
auto actualMinimum = glm::vec3(std::min(minimum.x, maximum.x), std::min(minimum.y, maximum.y),std::min(minimum.z, maximum.z));
auto actualMaximum = glm::vec3(std::max(minimum.x, maximum.x), std::max(minimum.y, maximum.y),std::max(minimum.z, maximum.z));
auto min = glm::vec3(
std::min(minimum.x, maximum.x),
std::min(minimum.y, maximum.y),
std::min(minimum.z, maximum.z)
);
bool xcheck = position.x >= actualMinimum.x && position.x <= actualMaximum.x;
bool ycheck = position.y >= actualMinimum.y && position.y <= actualMaximum.y;
bool zcheck = position.z >= actualMinimum.z && position.z <= actualMaximum.z;
auto max = glm::vec3(
std::max(minimum.x, maximum.x),
std::max(minimum.y, maximum.y),
std::max(minimum.z, maximum.z)
);
return xcheck && ycheck && zcheck;
const bool x_check = EQ::ValueWithin(position.x, min.x, max.x);
const bool y_check = EQ::ValueWithin(position.y, min.y, max.y);
const bool z_check = EQ::ValueWithin(position.z, min.z, max.z);
return x_check && y_check && z_check;
}
/**
@@ -118,13 +146,13 @@ bool IsWithinAxisAlignedBox(const glm::vec3 &position, const glm::vec3 &minimum,
* box (2 dimensional) formed from the points minimum and maximum.
*/
bool IsWithinAxisAlignedBox(const glm::vec2 &position, const glm::vec2 &minimum, const glm::vec2 &maximum) {
auto actualMinimum = glm::vec2(std::min(minimum.x, maximum.x), std::min(minimum.y, maximum.y));
auto actualMaximum = glm::vec2(std::max(minimum.x, maximum.x), std::max(minimum.y, maximum.y));
auto min = glm::vec2(std::min(minimum.x, maximum.x), std::min(minimum.y, maximum.y));
auto max = glm::vec2(std::max(minimum.x, maximum.x), std::max(minimum.y, maximum.y));
bool xcheck = position.x >= actualMinimum.x && position.x <= actualMaximum.x;
bool ycheck = position.y >= actualMinimum.y && position.y <= actualMaximum.y;
const bool x_check = EQ::ValueWithin(position.x, min.x, max.x);
const bool y_check = EQ::ValueWithin(position.y, min.y, max.y);
return xcheck && ycheck;
return x_check && y_check;
}
/**
@@ -144,10 +172,10 @@ float GetReciprocalHeading(const glm::vec4& point1) {
*/
float GetReciprocalHeading(const float heading)
{
float result = 0;
float result;
// Convert to radians
float h = (heading / 512.0f) * 6.283184f;
const float h = (heading / 512.0f) * 6.283184f;
// Calculate the reciprocal heading in radians
result = h + 3.141592f;
@@ -228,23 +256,29 @@ bool IsPositionWithinSimpleCylinder(const glm::vec4 &p1, const glm::vec4 &cylind
float CalculateHeadingAngleBetweenPositions(float x1, float y1, float x2, float y2)
{
float y_diff = std::abs(y1 - y2);
float x_diff = std::abs(x1 - x2);
if (y_diff < 0.0000009999999974752427)
float y_diff = std::abs(y1 - y2);
if (y_diff < 0.0000009999999974752427) {
y_diff = 0.0000009999999974752427;
}
float angle = atan2(x_diff, y_diff) * 180.0f * 0.3183099014828645f; // angle, nice "pi"
const float angle = atan2(x_diff, y_diff) * 180.0f * 0.3183099014828645f; // angle, nice "pi"
// return the right thing based on relative quadrant
// I'm sure this could be improved for readability, but whatever
if (y1 >= y2) {
if (x2 >= x1)
if (x2 >= x1) {
return (90.0f - angle + 90.0f) * 511.5f * 0.0027777778f;
if (x2 <= x1)
}
if (x2 <= x1) {
return (angle + 180.0f) * 511.5f * 0.0027777778f;
}
}
if (y1 > y2 || x2 > x1)
if (y1 > y2 || x2 > x1) {
return angle * 511.5f * 0.0027777778f;
else
} else {
return (90.0f - angle + 270.0f) * 511.5f * 0.0027777778f;
}
}
+78 -70
View File
@@ -40,6 +40,7 @@
#include "dialogue_window.h"
#include "../common/repositories/tradeskill_recipe_repository.h"
#include "../common/repositories/instance_list_repository.h"
#include <iostream>
#include <limits.h>
@@ -3239,7 +3240,7 @@ std::string QuestManager::getcleannpcnamebyid(uint32 npc_id) {
return res;
}
uint16 QuestManager::CreateInstance(const char *zone_short_name, int16 instance_version, uint32 duration)
uint16 QuestManager::CreateInstance(const std::string& zone_short_name, int16 instance_version, uint32 duration)
{
QuestManagerCurrentQuestVars();
@@ -3275,57 +3276,56 @@ void QuestManager::DestroyInstance(uint16 instance_id)
void QuestManager::UpdateInstanceTimer(uint16 instance_id, uint32 new_duration)
{
std::string query = StringFormat("UPDATE instance_list SET duration = %lu, start_time = UNIX_TIMESTAMP() WHERE id = %lu",
(unsigned long)new_duration, (unsigned long)instance_id);
auto results = database.QueryDatabase(query);
auto e = InstanceListRepository::FindOne(database, instance_id);
if (results.Success()) {
if (!e.id) {
return;
}
e.duration = new_duration;
e.start_time = std::time(nullptr);
const int updated = InstanceListRepository::UpdateOne(database, e);
if (updated) {
auto pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct));
ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*) pack->pBuffer;
ut->instance_id = instance_id;
auto ut = (ServerInstanceUpdateTime_Struct*) pack->pBuffer;
ut->instance_id = instance_id;
ut->new_duration = new_duration;
worldserver.SendPacket(pack);
safe_delete(pack);
}
}
uint32 QuestManager::GetInstanceTimer() {
if (zone && zone->GetInstanceID() > 0 && zone->GetInstanceTimer()) {
uint32 ttime = zone->GetInstanceTimer()->GetRemainingTime();
return ttime;
uint32 QuestManager::GetInstanceTimer()
{
if (zone && zone->GetInstanceID() && zone->GetInstanceTimer()) {
return zone->GetInstanceTimer()->GetRemainingTime();
}
return 0;
}
uint32 QuestManager::GetInstanceTimerByID(uint16 instance_id) {
if (instance_id == 0)
return 0;
std::string query = StringFormat("SELECT ((start_time + duration) - UNIX_TIMESTAMP()) AS `remaining` FROM `instance_list` WHERE `id` = %lu", (unsigned long)instance_id);
auto results = database.QueryDatabase(query);
if (results.Success()) {
auto row = results.begin();
uint32 timer = Strings::ToInt(row[0]);
return timer;
}
return 0;
uint32 QuestManager::GetInstanceTimerByID(uint16 instance_id)
{
return instance_id ? InstanceListRepository::GetRemainingTimeByInstanceID(database, instance_id) : 0;
}
uint16 QuestManager::GetInstanceID(const char *zone, int16 version)
{
QuestManagerCurrentQuestVars();
if (initiator)
{
return database.GetInstanceID(ZoneID(zone), initiator->CharacterID(), version);
}
return 0;
return initiator ? database.GetInstanceID(ZoneID(zone), initiator->CharacterID(), version) : 0;
}
std::vector<uint16> QuestManager::GetInstanceIDs(std::string zone_name, uint32 character_id)
{
if (!character_id) {
QuestManagerCurrentQuestVars();
if (initiator) {
return database.GetInstanceIDs(ZoneID(zone_name), initiator->CharacterID());
}
@@ -3336,33 +3336,37 @@ std::vector<uint16> QuestManager::GetInstanceIDs(std::string zone_name, uint32 c
return database.GetInstanceIDs(ZoneID(zone_name), character_id);
}
uint16 QuestManager::GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id) {
return database.GetInstanceID(ZoneID(zone), char_id, version);
uint16 QuestManager::GetInstanceIDByCharID(
const std::string &zone_short_name,
int16 instance_version,
uint32 character_id
)
{
return database.GetInstanceID(ZoneID(zone_short_name), character_id, instance_version);
}
void QuestManager::AssignToInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if (initiator)
{
if (initiator) {
database.AddClientToInstance(instance_id, initiator->CharacterID());
}
}
void QuestManager::AssignToInstanceByCharID(uint16 instance_id, uint32 char_id) {
database.AddClientToInstance(instance_id, char_id);
void QuestManager::AssignToInstanceByCharID(uint16 instance_id, uint32 character_id)
{
database.AddClientToInstance(instance_id, character_id);
}
void QuestManager::AssignGroupToInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if (initiator)
{
Group *g = initiator->GetGroup();
if (g)
{
uint32 gid = g->GetID();
database.AssignGroupToInstance(gid, instance_id);
if (initiator) {
Group* g = initiator->GetGroup();
if (g) {
database.AssignGroupToInstance(g->GetID(), instance_id);
}
}
}
@@ -3370,13 +3374,11 @@ void QuestManager::AssignGroupToInstance(uint16 instance_id)
void QuestManager::AssignRaidToInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if (initiator)
{
Raid *r = initiator->GetRaid();
if(r)
{
uint32 rid = r->GetID();
database.AssignRaidToInstance(rid, instance_id);
if (initiator) {
Raid* r = initiator->GetRaid();
if (r) {
database.AssignRaidToInstance(r->GetID(), instance_id);
}
}
}
@@ -3384,12 +3386,13 @@ void QuestManager::AssignRaidToInstance(uint16 instance_id)
void QuestManager::RemoveFromInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if (initiator)
{
if (database.RemoveClientFromInstance(instance_id, initiator->CharacterID()))
if (initiator) {
if (database.RemoveClientFromInstance(instance_id, initiator->CharacterID())) {
initiator->Message(Chat::Say, "Removed client from instance.");
else
} else {
initiator->Message(Chat::Say, "Failed to remove client from instance.");
}
}
}
@@ -3404,16 +3407,22 @@ bool QuestManager::CheckInstanceByCharID(uint16 instance_id, uint32 char_id) {
void QuestManager::RemoveAllFromInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if (initiator)
{
if (initiator) {
std::list<uint32> character_ids;
if (database.RemoveClientsFromInstance(instance_id))
if (database.RemoveClientsFromInstance(instance_id)) {
initiator->Message(Chat::Say, "Removed all players from instance.");
else
{
} else {
database.GetCharactersInInstance(instance_id, character_ids);
initiator->Message(Chat::Say, "Failed to remove %i player(s) from instance.", character_ids.size()); // once the expedition system is in, this message it not relevant
initiator->Message(
Chat::Say,
fmt::format(
"Failed to remove {} player{} from instance.",
character_ids.size(),
character_ids.size() != 1 ? "s" : ""
).c_str()
);
}
}
}
@@ -3421,8 +3430,8 @@ void QuestManager::RemoveAllFromInstance(uint16 instance_id)
void QuestManager::MovePCInstance(int zone_id, int instance_id, const glm::vec4& position)
{
QuestManagerCurrentQuestVars();
if(initiator)
{
if (initiator) {
initiator->MovePC(zone_id, instance_id, position.x, position.y, position.z, position.w);
}
}
@@ -3430,10 +3439,10 @@ void QuestManager::MovePCInstance(int zone_id, int instance_id, const glm::vec4&
void QuestManager::FlagInstanceByGroupLeader(uint32 zone, int16 version)
{
QuestManagerCurrentQuestVars();
if(initiator)
{
Group *g = initiator->GetGroup();
if(g){
if (initiator) {
Group* g = initiator->GetGroup();
if (g) {
database.FlagInstanceByGroupLeader(zone, version, initiator->CharacterID(), g->GetID());
}
}
@@ -3442,11 +3451,10 @@ void QuestManager::FlagInstanceByGroupLeader(uint32 zone, int16 version)
void QuestManager::FlagInstanceByRaidLeader(uint32 zone, int16 version)
{
QuestManagerCurrentQuestVars();
if(initiator)
{
Raid *r = initiator->GetRaid();
if(r)
{
if (initiator) {
Raid* r = initiator->GetRaid();
if (r) {
database.FlagInstanceByRaidLeader(zone, version, initiator->CharacterID(), r->GetID());
}
}
+2 -2
View File
@@ -262,7 +262,7 @@ public:
void UpdateSpawnTimer(uint32 id, uint32 newTime);
void MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity = 0);
uint32 MerchantCountItem(uint32 NPCid, uint32 itemid);
uint16 CreateInstance(const char *zone_short_name, int16 instance_version, uint32 duration);
uint16 CreateInstance(const std::string& zone_short_name, int16 instance_version, uint32 duration);
void UpdateInstanceTimer(uint16 instance_id, uint32 new_duration);
void UpdateZoneHeader(std::string type, std::string value);
uint32 GetInstanceTimer();
@@ -270,7 +270,7 @@ public:
void DestroyInstance(uint16 instance_id);
uint16 GetInstanceID(const char *zone, int16 version);
std::vector<uint16> GetInstanceIDs(std::string zone_name, uint32 character_id = 0);
uint16 GetInstanceIDByCharID(const char *zone, int16 version, uint32 char_id);
uint16 GetInstanceIDByCharID(const std::string& zone_short_name, int16 instance_version, uint32 character_id);
void AssignToInstance(uint16 instance_id);
void AssignToInstanceByCharID(uint16 instance_id, uint32 char_id);
void AssignGroupToInstance(uint16 instance_id);
+13 -7
View File
@@ -845,7 +845,7 @@ bool SpawnConditionManager::LoadDBEvent(uint32 event_id, SpawnEvent &event, std:
std::string timeAsString;
EQTime::ToString(&event.next, timeAsString);
LogSpawns("(LoadDBEvent) Loaded [{}] spawn event [{}] on condition [{}] with period [{}], action [{}], argument [{}], strict [{}]. Will trigger at [{}]", event.enabled? "enabled": "disabled", event.id, event.condition_id, event.period, event.action, event.argument, event.strict, timeAsString.c_str());
LogSpawns("(LoadDBEvent) Loaded [{}] spawn event [{}] on condition [{}] with period [{}] action [{}] argument [{}] strict [{}]. Will trigger at [{}]", event.enabled? "enabled": "disabled", event.id, event.condition_id, event.period, event.action, event.argument, event.strict, timeAsString.c_str());
return true;
}
@@ -931,7 +931,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
spawn_events.push_back(event);
LogSpawns(
"(LoadSpawnConditions) Loaded [{}] spawn event [{}] on condition [{}] with period [{}], action [{}], argument [{}], strict [{}]",
"(LoadSpawnConditions) Loaded [{}] spawn event [{}] on condition [{}] with period [{}] action [{}] argument [{}] strict [{}]",
event.enabled ? "enabled" : "disabled",
event.id,
event.condition_id,
@@ -965,9 +965,15 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
cevent.next.year == tod.year)
StrictCheck = true;
//If event is disabled, or we failed the strict check, set initial spawn_condition to 0.
if(!cevent.enabled || !StrictCheck)
SetCondition(zone->GetShortName(), zone->GetInstanceID(),cevent.condition_id,0);
//If event is disabled, or we failed the strict check, set initial spawn_condition to default startup value from spawn_conditions.
if(!cevent.enabled || !StrictCheck) {
SetCondition(
zone->GetShortName(),
zone->GetInstanceID(),
cevent.condition_id,
spawn_conditions[cevent.condition_id].value
);
}
if(!cevent.enabled)
continue;
@@ -1053,7 +1059,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
SpawnCondition &cond = condi->second;
if(cond.value == new_value) {
LogSpawns("Condition update received from world for [{}] with value [{}], which is what we already have", condition_id, new_value);
LogSpawns("Condition update received from world for [{}] with value [{}] which is what we already have", condition_id, new_value);
return;
}
@@ -1080,7 +1086,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
SpawnCondition &cond = condi->second;
if(cond.value == new_value) {
LogSpawns("Local Condition update requested for [{}] with value [{}], which is what we already have", condition_id, new_value);
LogSpawns("Local Condition update requested for [{}] with value [{}] which is what we already have", condition_id, new_value);
return;
}
-4
View File
@@ -3805,10 +3805,6 @@ bool Mob::SpellOnTarget(
LogSpells("Casting spell [{}] on [{}] with effective caster level [{}]", spell_id, spelltar->GetName(), caster_level);
if (IsOfClientBotMerc() && (IsDiscipline(spell_id) || spells[spell_id].is_discipline)) {
entity_list.MessageClose(this, false, 200, 0, fmt::format("{}{}", GetCleanName(), spells[spell_id].cast_on_other).c_str());
}
// Actual cast action - this causes the caster animation and the particles
// around the target
// we do this first, that way we get the particles even if the spell
-10
View File
@@ -3259,13 +3259,3 @@ void Zone::SetSecondsBeforeIdle(uint32 seconds_before_idle)
{
Zone::m_seconds_before_idle = seconds_before_idle;
}
bool Zone::IsIdle() const
{
return m_is_idle;
}
void Zone::SetIsIdle(bool m_is_idle)
{
Zone::m_is_idle = m_is_idle;
}
-3
View File
@@ -105,8 +105,6 @@ public:
AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id);
AA::Rank *GetAlternateAdvancementRank(int rank_id);
bool is_zone_time_localized;
bool IsIdle() const;
void SetIsIdle(bool m_is_idle);
bool IsIdleWhenEmpty() const;
void SetIdleWhenEmpty(bool idle_when_empty);
uint32 GetSecondsBeforeIdle() const;
@@ -443,7 +441,6 @@ private:
uint32 m_last_ucss_update;
bool m_idle_when_empty;
uint32 m_seconds_before_idle;
bool m_is_idle;
GlobalLootManager m_global_loot;
LinkedList<ZoneClientAuth_Struct *> client_auth_list;
+9 -7
View File
@@ -739,7 +739,7 @@ bool ZoneDatabase::LoadCharacterLeadershipAbilities(uint32 character_id, PlayerP
);
for (const auto& e : l) {
pp->leader_abilities.ranks[e.slot] = e.rank;
pp->leader_abilities.ranks[e.slot] = e.rank_;
}
return true;
@@ -1098,9 +1098,9 @@ bool ZoneDatabase::SaveCharacterLeadershipAbilities(uint32 character_id, PlayerP
for (int slot_id = 0; slot_id < MAX_LEADERSHIP_AA_ARRAY; slot_id++) {
if (pp->leader_abilities.ranks[slot_id] > 0) {
e.id = character_id;
e.slot = slot_id;
e.rank = pp->leader_abilities.ranks[slot_id];
e.id = character_id;
e.slot = slot_id;
e.rank_ = pp->leader_abilities.ranks[slot_id];
v.emplace_back(e);
}
@@ -2295,7 +2295,7 @@ bool ZoneDatabase::SaveMercenary(Merc* m)
auto e = MercsRepository::NewEntity();
e.OwnerCharacterID = m->GetMercenaryCharacterID();
e.Slot = c->GetNumberOfMercenaries();
e.Slot = (c->GetNumberOfMercenaries() - 1);
e.Name = m->GetCleanName();
e.TemplateID = m->GetMercenaryTemplateID();
e.SuspendedTime = c->GetMercInfo().SuspendedTime;
@@ -2336,7 +2336,7 @@ bool ZoneDatabase::SaveMercenary(Merc* m)
auto e = MercsRepository::FindOne(*this, m->GetMercenaryID());
e.OwnerCharacterID = m->GetMercenaryCharacterID();
e.Slot = c->GetNumberOfMercenaries();
e.Slot = (c->GetNumberOfMercenaries() - 1);
e.Name = m->GetCleanName();
e.TemplateID = m->GetMercenaryTemplateID();
e.SuspendedTime = c->GetMercInfo().SuspendedTime;
@@ -2416,7 +2416,9 @@ void ZoneDatabase::SaveMercenaryBuffs(Merc* m)
v.emplace_back(e);
}
MercBuffsRepository::InsertMany(*this, v);
if (!v.empty()) {
MercBuffsRepository::InsertMany(*this, v);
}
}
void ZoneDatabase::LoadMercenaryBuffs(Merc* m)
+2
View File
@@ -166,6 +166,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
target_instance_id
).c_str()
);
LogZoning("Client [{}] Invalid zone instance request to zone id [{}]", GetCleanName(), target_zone_id);
SendZoneCancel(zc);
return;
}
@@ -179,6 +180,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
target_zone_id
).c_str()
);
LogZoning("Client [{}] Invalid zone instance request to zone id [{}]", GetCleanName(), target_zone_id);
SendZoneCancel(zc);
return;
}