mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
Compare commits
100 Commits
v22.45.1
...
multiquest
| Author | SHA1 | Date | |
|---|---|---|---|
| caae34ac5e | |||
| 56c7db4cbf | |||
| 043eeced6f | |||
| e9a0c79301 | |||
| dc48c45421 | |||
| d7a8fb8691 | |||
| 3a5381d38a | |||
| e64f03fcc0 | |||
| d77966797e | |||
| 048aad437b | |||
| b2d9de8d96 | |||
| 42bfa4bb2e | |||
| 72ce7c8e91 | |||
| e306c86875 | |||
| 3ae7979a67 | |||
| b638795f9b | |||
| 9e3bf91374 | |||
| cd89926435 | |||
| e19f72f021 | |||
| df1dc5d1e4 | |||
| e11286164f | |||
| b946b800fb | |||
| ab8ac81df6 | |||
| 109940fc0c | |||
| a87496b0cf | |||
| f905ee70e4 | |||
| 52417023f8 | |||
| 20d9417628 | |||
| 4692799677 | |||
| cf7f0f4321 | |||
| 823a5956de | |||
| 6a8bd3c5d6 | |||
| 523ba30d81 | |||
| d7ea290b6b | |||
| 036309ebec | |||
| b400700d81 | |||
| 21cec87ac4 | |||
| abdec39cdd | |||
| d2372de982 | |||
| ea9b7841d4 | |||
| 8826d7b927 | |||
| e4157f0221 | |||
| 66cc947b2a | |||
| 5bfd8f5da2 | |||
| 96830b4a19 | |||
| 4bf60a6522 | |||
| 16cb7364e8 | |||
| f5050ab5dc | |||
| e32cbf19ee | |||
| ee12a7ad2e | |||
| e5bdbc4f1e | |||
| f829a99e6d | |||
| 82aa6a1587 | |||
| 161c13f457 | |||
| b29c26becb | |||
| e48dae2392 | |||
| 4b83a96f64 | |||
| 95cc22ffbb | |||
| 6ca11256c6 | |||
| d94493468c | |||
| 957b4f8821 | |||
| 5013459824 | |||
| 94af2843e3 | |||
| 3bfb148bdc | |||
| 96370e0298 | |||
| fef5108b0d | |||
| 6f883566f6 | |||
| 45b1501c8a | |||
| 7e94f0ac72 | |||
| 2aa19f4cae | |||
| 805829f15d | |||
| 2c2a8cdb63 | |||
| ee3d02bac6 | |||
| b90139bd9a | |||
| e6a3d5e1c5 | |||
| 74f1eac401 | |||
| 1be9b2cdfd | |||
| add0a8dddf | |||
| 8c226054e7 | |||
| b4605f77e3 | |||
| 74a63daf7e | |||
| 8ee7910569 | |||
| b766a79c11 | |||
| 5e3b6d363a | |||
| b2fc59878a | |||
| 4896688ac5 | |||
| 0385ed8526 | |||
| 9974aaff57 | |||
| b6c3e549da | |||
| 70ee95efc0 | |||
| 1d38e473d7 | |||
| 1aa3a4b11a | |||
| 398ecbc8cf | |||
| c4613e1b0f | |||
| 3003a59955 | |||
| 0c582cc4f9 | |||
| 69c42510ca | |||
| 79c8858ec8 | |||
| c3d8d423fe | |||
| 1cbda61891 |
+137
@@ -1,3 +1,140 @@
|
|||||||
|
## [22.48.0] 3/23/2024
|
||||||
|
|
||||||
|
### Bots
|
||||||
|
|
||||||
|
* IsValidTarget Crash Fix ([#4187](https://github.com/EQEmu/Server/pull/4187)) @nytmyr 2024-03-12
|
||||||
|
* Move BotGroupSay to Pet Response ([#4171](https://github.com/EQEmu/Server/pull/4171)) @nytmyr 2024-03-08
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Cleanup Zone Get Methods ([#4169](https://github.com/EQEmu/Server/pull/4169)) @Kinglykrab 2024-03-09
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* An Update to Xtarget to exclude Bot owned Temp/Swarm Pets ([#4172](https://github.com/EQEmu/Server/pull/4172)) @MortimerGreenwald 2024-03-08
|
||||||
|
* Fix #serverrules Command ([#4193](https://github.com/EQEmu/Server/pull/4193)) @Kinglykrab 2024-03-20
|
||||||
|
* Fix Bot Cloning ([#4186](https://github.com/EQEmu/Server/pull/4186)) @Kinglykrab 2024-03-17
|
||||||
|
* Fix Crash in ClientList::GetCLEIP ([#4173](https://github.com/EQEmu/Server/pull/4173)) @Kinglykrab 2024-03-10
|
||||||
|
* Fix Default Value in `rule_values` table ([#4166](https://github.com/EQEmu/Server/pull/4166)) @Kinglykrab 2024-03-07
|
||||||
|
* Fix EVENT_KILLED_MERIT firing before NPC removal ([#4185](https://github.com/EQEmu/Server/pull/4185)) @Kinglykrab 2024-03-17
|
||||||
|
* Fix Empty Groups When Removing Bots ([#4178](https://github.com/EQEmu/Server/pull/4178)) @Kinglykrab 2024-03-14
|
||||||
|
* Fix GetLeaderName() for Groups ([#4184](https://github.com/EQEmu/Server/pull/4184)) @Kinglykrab 2024-03-14
|
||||||
|
* Fix Mob::CalculateDistance(mob) Typo ([#4183](https://github.com/EQEmu/Server/pull/4183)) @Kinglykrab 2024-03-10
|
||||||
|
* Fix Proximity Say ([#4189](https://github.com/EQEmu/Server/pull/4189)) @Kinglykrab 2024-03-15
|
||||||
|
* Fix ScaleNPC() in Perl ([#4196](https://github.com/EQEmu/Server/pull/4196)) @Kinglykrab 2024-03-23
|
||||||
|
* Fix range_percent ([#4197](https://github.com/EQEmu/Server/pull/4197)) @Kinglykrab 2024-03-22
|
||||||
|
* Fix reusing timers ([#4199](https://github.com/EQEmu/Server/pull/4199)) @joligario 2024-03-23
|
||||||
|
|
||||||
|
### Hot Fix
|
||||||
|
|
||||||
|
* Add bool return to fix Client::RemoveAAPoints ([#4176](https://github.com/EQEmu/Server/pull/4176)) @Kinglykrab 2024-03-09
|
||||||
|
|
||||||
|
### Loot
|
||||||
|
|
||||||
|
* Fix issue with nested data being loaded multiple times ([#4192](https://github.com/EQEmu/Server/pull/4192)) @Akkadius 2024-03-23
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
|
||||||
|
* Windows preprocessor define in crash.cpp ([#4191](https://github.com/EQEmu/Server/pull/4191)) @joligario 2024-03-23
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add Buff Support to Perl/Lua ([#4182](https://github.com/EQEmu/Server/pull/4182)) @Kinglykrab 2024-03-14
|
||||||
|
* Add DeleteBot() to Perl/Lua ([#4167](https://github.com/EQEmu/Server/pull/4167)) @nytmyr 2024-03-07
|
||||||
|
* Add GetDeityName() to Perl/Lua ([#4180](https://github.com/EQEmu/Server/pull/4180)) @Kinglykrab 2024-03-14
|
||||||
|
* Add RemoveAAPoints() and AA Loss Event to Perl/Lua ([#4174](https://github.com/EQEmu/Server/pull/4174)) @Kinglykrab 2024-03-09
|
||||||
|
* Add RemoveAlternateCurrencyValue() to Perl/Lua ([#4190](https://github.com/EQEmu/Server/pull/4190)) @Kinglykrab 2024-03-17
|
||||||
|
* Add Restore Methods for Health, Mana, and Endurance to Perl/Lua ([#4179](https://github.com/EQEmu/Server/pull/4179)) @Kinglykrab 2024-03-23
|
||||||
|
* Add Silent Saylink Methods to Perl/Lua ([#4177](https://github.com/EQEmu/Server/pull/4177)) @Kinglykrab 2024-03-14
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Add World:Rules Rule ([#4194](https://github.com/EQEmu/Server/pull/4194)) @Kinglykrab 2024-03-23
|
||||||
|
|
||||||
|
### Tradeskills
|
||||||
|
|
||||||
|
* Implement learning recipes from books ([#4170](https://github.com/EQEmu/Server/pull/4170)) @hgtw 2024-03-23
|
||||||
|
|
||||||
|
## [22.47.0] 3/5/2024
|
||||||
|
|
||||||
|
### Crash Fix
|
||||||
|
|
||||||
|
* Added a guild_mgr check ([#4163](https://github.com/EQEmu/Server/pull/4163)) @neckkola 2024-03-06
|
||||||
|
* Goto Command could crash using Developer Tools ([#4158](https://github.com/EQEmu/Server/pull/4158)) @neckkola 2024-03-04
|
||||||
|
* Groundspawn Memory Corruption ([#4157](https://github.com/EQEmu/Server/pull/4157)) @neckkola 2024-03-04
|
||||||
|
* Update to location of qGlobals initialization ([#4144](https://github.com/EQEmu/Server/pull/4144)) @neckkola 2024-03-02
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
|
||||||
|
* Adds rules to control level requirements for Double Backstab, Assassinate, and Double Bowshot (#4159) ([#29](https://github.com/EQEmu/Server/pull/29)) @catapultam-habeo 2024-03-04
|
||||||
|
* Adjust String-based Rules Length ([#4138](https://github.com/EQEmu/Server/pull/4138)) @Kinglykrab 2024-03-06
|
||||||
|
* Exempt a zone from IP-limit checks. ([#4137](https://github.com/EQEmu/Server/pull/4137)) @catapultam-habeo 2024-03-02
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Add id to the guild_bank table ([#4155](https://github.com/EQEmu/Server/pull/4155)) @neckkola 2024-03-05
|
||||||
|
* Fix Bots/Bot Pets ending up on XTargets ([#4132](https://github.com/EQEmu/Server/pull/4132)) @Kinglykrab 2024-03-02
|
||||||
|
* Fix Character EXP Modifiers default ([#4161](https://github.com/EQEmu/Server/pull/4161)) @Kinglykrab 2024-03-06
|
||||||
|
* Fix Spawns Not Parsing Quest on Zone Bootup ([#4149](https://github.com/EQEmu/Server/pull/4149)) @Kinglykrab 2024-03-05
|
||||||
|
* Fix typo when updating spawn events in spawn condition manager ([#4160](https://github.com/EQEmu/Server/pull/4160)) @joligario 2024-03-05
|
||||||
|
* GetBotNameByID Temporary Reference Warning ([#4145](https://github.com/EQEmu/Server/pull/4145)) @Kinglykrab 2024-03-02
|
||||||
|
* Prevent NPE when creating DZ using ad-hoc version IDs ([#4141](https://github.com/EQEmu/Server/pull/4141)) @catapultam-habeo 2024-03-05
|
||||||
|
* Update FreeGuildID Routine ([#4143](https://github.com/EQEmu/Server/pull/4143)) @neckkola 2024-03-02
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add Bot Special Attacks for Immune Aggro/Damage ([#4108](https://github.com/EQEmu/Server/pull/4108)) @Kinglykrab 2024-03-02
|
||||||
|
* Add GetHeroicStrikethrough() to Perl/Lua ([#4150](https://github.com/EQEmu/Server/pull/4150)) @Kinglykrab 2024-03-03
|
||||||
|
* Add IsAlwaysAggro() to Perl/Lua ([#4152](https://github.com/EQEmu/Server/pull/4152)) @Kinglykrab 2024-03-04
|
||||||
|
* Add IsBoat()/IsControllableBoat() to Perl/Lua ([#4151](https://github.com/EQEmu/Server/pull/4151)) @Kinglykrab 2024-03-03
|
||||||
|
* Add IsDestructibleObject() to Perl/Lua ([#4153](https://github.com/EQEmu/Server/pull/4153)) @Kinglykrab 2024-03-03
|
||||||
|
|
||||||
|
### Zone
|
||||||
|
|
||||||
|
* Zone Routing Improvements ([#4142](https://github.com/EQEmu/Server/pull/4142)) @Akkadius 2024-03-02
|
||||||
|
|
||||||
|
### Zoning
|
||||||
|
|
||||||
|
* Zone routing adjustment ([#4162](https://github.com/EQEmu/Server/pull/4162)) @Akkadius 2024-03-06
|
||||||
|
|
||||||
|
## [22.46.1] 3/2/2024
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Change `UnburyCorpse` to use repository methods ([#4147](https://github.com/EQEmu/Server/pull/4147)) @joligario 2024-03-03
|
||||||
|
|
||||||
|
## [22.46.0] 3/2/2024
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
* Add #fish Command ([#4136](https://github.com/EQEmu/Server/pull/4136)) @Kinglykrab 2024-03-01
|
||||||
|
|
||||||
|
### Crash Fix
|
||||||
|
|
||||||
|
* Raid::UpdateGroupAAs ([#4139](https://github.com/EQEmu/Server/pull/4139)) @neckkola 2024-03-02
|
||||||
|
* Update to location of qGlobals initialization ([#4144](https://github.com/EQEmu/Server/pull/4144)) @neckkola 2024-03-02
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
|
||||||
|
* Exempt a zone from IP-limit checks. ([#4137](https://github.com/EQEmu/Server/pull/4137)) @catapultam-habeo 2024-03-02
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Cleanup NPC Mana Tap Logic ([#4134](https://github.com/EQEmu/Server/pull/4134)) @noudess 2024-03-02
|
||||||
|
* Fix Bots/Bot Pets ending up on XTargets ([#4132](https://github.com/EQEmu/Server/pull/4132)) @Kinglykrab 2024-03-02
|
||||||
|
* Fix issue with NPC Secondary Textures ([#4129](https://github.com/EQEmu/Server/pull/4129)) @Kinglykrab 2024-03-01
|
||||||
|
* GetBotNameByID Temporary Reference Warning ([#4145](https://github.com/EQEmu/Server/pull/4145)) @Kinglykrab 2024-03-02
|
||||||
|
* Update FreeGuildID Routine ([#4143](https://github.com/EQEmu/Server/pull/4143)) @neckkola 2024-03-02
|
||||||
|
* Use std::clamp for Mob::ChangeSize ([#4140](https://github.com/EQEmu/Server/pull/4140)) @joligario 2024-03-02
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add Bot Special Attacks for Immune Aggro/Damage ([#4108](https://github.com/EQEmu/Server/pull/4108)) @Kinglykrab 2024-03-02
|
||||||
|
|
||||||
|
### Zone
|
||||||
|
|
||||||
|
* Zone Routing Improvements ([#4142](https://github.com/EQEmu/Server/pull/4142)) @Akkadius 2024-03-02
|
||||||
|
|
||||||
## [22.45.1] 2/29/2024
|
## [22.45.1] 2/29/2024
|
||||||
|
|
||||||
### Character Creation
|
### Character Creation
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#include "../../common/content/world_content_service.h"
|
#include "../../common/content/world_content_service.h"
|
||||||
#include "../../common/zone_store.h"
|
#include "../../common/zone_store.h"
|
||||||
#include "../../common/path_manager.h"
|
#include "../../common/path_manager.h"
|
||||||
|
#include "../../common/repositories/skill_caps_repository.h"
|
||||||
|
#include "../../common/file.h"
|
||||||
|
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
WorldContentService content_service;
|
WorldContentService content_service;
|
||||||
@@ -166,79 +168,74 @@ void ExportSpells(SharedDatabase *db)
|
|||||||
|
|
||||||
bool SkillUsable(SharedDatabase* db, int skill_id, int class_id)
|
bool SkillUsable(SharedDatabase* db, int skill_id, int class_id)
|
||||||
{
|
{
|
||||||
|
const auto& l = SkillCapsRepository::GetWhere(
|
||||||
bool res = false;
|
*db,
|
||||||
|
fmt::format(
|
||||||
std::string query = StringFormat(
|
"`class_id` = {} AND `skill_id` = {} ORDER BY `cap` DESC LIMIT 1",
|
||||||
"SELECT max(cap) FROM skill_caps WHERE class=%d AND skillID=%d",
|
class_id,
|
||||||
class_id, skill_id
|
skill_id
|
||||||
|
)
|
||||||
);
|
);
|
||||||
auto results = db->QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
return !l.empty();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0) {
|
uint32 GetSkill(SharedDatabase* db, int skill_id, int class_id, int level)
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
if (row[0] && Strings::ToInt(row[0]) > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level)
|
|
||||||
{
|
{
|
||||||
|
const auto& l = SkillCapsRepository::GetWhere(
|
||||||
std::string query = StringFormat(
|
*db,
|
||||||
"SELECT cap FROM skill_caps WHERE class=%d AND skillID=%d AND level=%d",
|
fmt::format(
|
||||||
class_id, skill_id, level
|
"`class_id` = {} AND `skill_id` = {} AND `level` = {}",
|
||||||
|
class_id,
|
||||||
|
skill_id,
|
||||||
|
level
|
||||||
|
)
|
||||||
);
|
);
|
||||||
auto results = db->QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
if (l.empty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0) {
|
auto e = l.front();
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = results.begin();
|
return e.cap;
|
||||||
return Strings::ToInt(row[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportSkillCaps(SharedDatabase* db)
|
void ExportSkillCaps(SharedDatabase* db)
|
||||||
{
|
{
|
||||||
LogInfo("Exporting Skill Caps");
|
LogInfo("Exporting Skill Caps");
|
||||||
|
|
||||||
std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath());
|
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()));
|
||||||
FILE *f = fopen(file.c_str(), "w");
|
if (!file || !file.is_open()) {
|
||||||
if (!f) {
|
|
||||||
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
|
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int cl = 1; cl <= 16; ++cl) {
|
const uint8 skill_cap_max_level = (
|
||||||
for (int skill = 0; skill <= 77; ++skill) {
|
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
||||||
if (SkillUsable(db, skill, cl)) {
|
RuleI(Character, SkillCapMaxLevel) :
|
||||||
int previous_cap = 0;
|
RuleI(Character, MaxLevel)
|
||||||
for (int level = 1; level <= 100; ++level) {
|
);
|
||||||
int cap = GetSkill(db, skill, cl, level);
|
|
||||||
|
for (uint8 class_id = Class::Warrior; class_id <= Class::Berserker; class_id++) {
|
||||||
|
for (uint8 skill_id = EQ::skills::Skill1HBlunt; skill_id <= EQ::skills::Skill2HPiercing; skill_id++) {
|
||||||
|
if (SkillUsable(db, skill_id, class_id)) {
|
||||||
|
uint32 previous_cap = 0;
|
||||||
|
for (uint8 level = 1; level <= skill_cap_max_level; level++) {
|
||||||
|
uint32 cap = GetSkill(db, skill_id, class_id, level);
|
||||||
if (cap < previous_cap) {
|
if (cap < previous_cap) {
|
||||||
cap = previous_cap;
|
cap = previous_cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f, "%d^%d^%d^%d^0\n", cl, skill, level, cap);
|
file << fmt::format("{}^{}^{}^{}^0", class_id, skill_id, level, cap) << std::endl;
|
||||||
|
|
||||||
previous_cap = cap;
|
previous_cap = cap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportBaseData(SharedDatabase *db)
|
void ExportBaseData(SharedDatabase *db)
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ SET(common_sources
|
|||||||
shared_tasks.cpp
|
shared_tasks.cpp
|
||||||
shareddb.cpp
|
shareddb.cpp
|
||||||
skills.cpp
|
skills.cpp
|
||||||
|
skill_caps.cpp
|
||||||
spdat.cpp
|
spdat.cpp
|
||||||
strings.cpp
|
strings.cpp
|
||||||
struct_strategy.cpp
|
struct_strategy.cpp
|
||||||
@@ -606,6 +607,7 @@ SET(common_headers
|
|||||||
shared_tasks.h
|
shared_tasks.h
|
||||||
shareddb.h
|
shareddb.h
|
||||||
skills.h
|
skills.h
|
||||||
|
skill_caps.h
|
||||||
spdat.h
|
spdat.h
|
||||||
strings.h
|
strings.h
|
||||||
struct_strategy.h
|
struct_strategy.h
|
||||||
|
|||||||
@@ -178,12 +178,13 @@ void WorldContentService::ReloadContentFlags()
|
|||||||
LogInfo(
|
LogInfo(
|
||||||
"Loaded content flag [{}] [{}]",
|
"Loaded content flag [{}] [{}]",
|
||||||
f.flag_name,
|
f.flag_name,
|
||||||
(f.enabled ? "Enabled" : "Disabled")
|
(f.enabled ? "enabled" : "disabled")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetContentFlags(set_content_flags);
|
SetContentFlags(set_content_flags);
|
||||||
SetContentZones(ZoneRepository::All(*m_content_database));
|
LoadZones();
|
||||||
|
LoadStaticGlobalZoneInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
Database *WorldContentService::GetDatabase() const
|
Database *WorldContentService::GetDatabase() const
|
||||||
@@ -235,19 +236,6 @@ void WorldContentService::SetContentFlag(const std::string &content_flag_name, b
|
|||||||
ReloadContentFlags();
|
ReloadContentFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetZones sets the zones for the world content service
|
|
||||||
// this is used for zone routing middleware
|
|
||||||
// we pull the zone list from the zone repository and feed from the zone store for now
|
|
||||||
// we're holding a copy in the content service - but we're talking 250kb of data in memory to handle routing of zoning
|
|
||||||
WorldContentService *WorldContentService::SetContentZones(const std::vector<BaseZoneRepository::Zone>& zones)
|
|
||||||
{
|
|
||||||
m_zones = zones;
|
|
||||||
|
|
||||||
LogInfo("Loaded [{}] zones", m_zones.size());
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleZoneRoutingMiddleware is meant to handle content and context aware zone routing
|
// HandleZoneRoutingMiddleware is meant to handle content and context aware zone routing
|
||||||
//
|
//
|
||||||
// example # 1
|
// example # 1
|
||||||
@@ -260,16 +248,57 @@ WorldContentService *WorldContentService::SetContentZones(const std::vector<Base
|
|||||||
// scripts handle all the same way, you don't have to think about instances, the middleware will handle the magic
|
// scripts handle all the same way, you don't have to think about instances, the middleware will handle the magic
|
||||||
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
|
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
|
||||||
// we decide to route the client to the correct version of the zone based on the current server side expansion
|
// we decide to route the client to the correct version of the zone based on the current server side expansion
|
||||||
// example # 2
|
|
||||||
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
|
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
|
||||||
{
|
{
|
||||||
// if we're already in an instance, we don't want to route the player to another instance
|
auto r = FindZone(zc->zoneID, zc->instanceID);
|
||||||
if (zc->instanceID > 0) {
|
if (r.zone_id == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zc->instanceID = r.instance.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadStaticGlobalZoneInstances loads all static global zone instances
|
||||||
|
// these are zones that are never set to expire and are global
|
||||||
|
// these are used commonly in v1/v2/v3 versions of the same zone for expansion routing
|
||||||
|
WorldContentService * WorldContentService::LoadStaticGlobalZoneInstances()
|
||||||
|
{
|
||||||
|
m_zone_instances = InstanceListRepository::GetWhere(*GetDatabase(), fmt::format("never_expires = 1 AND is_global = 1"));
|
||||||
|
|
||||||
|
LogInfo("Loaded [{}] zone_instances", m_zone_instances.size());
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadZones sets the zones for the world content service
|
||||||
|
// this is used for zone routing middleware
|
||||||
|
// we pull the zone list from the zone repository and feed from the zone store for now
|
||||||
|
// we're holding a copy in the content service - but we're talking 250kb of data in memory to handle routing of zoning
|
||||||
|
WorldContentService * WorldContentService::LoadZones()
|
||||||
|
{
|
||||||
|
m_zones = ZoneRepository::All(*GetContentDatabase());
|
||||||
|
|
||||||
|
LogInfo("Loaded [{}] zones", m_zones.size());
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindZone is critical to the zone routing middleware and any logic that needs to route players to the correct zone
|
||||||
|
// era contextual routing, multiple version of zones, etc
|
||||||
|
WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
|
||||||
|
{
|
||||||
|
// if there's an active dynamic instance, we don't need to route
|
||||||
|
if (instance_id > 0) {
|
||||||
|
auto inst = InstanceListRepository::FindOne(*GetDatabase(), instance_id);
|
||||||
|
if (inst.id != 0 && !inst.is_global && !inst.never_expires) {
|
||||||
|
return WorldContentService::FindZoneResult{
|
||||||
|
.zone_id = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &z: m_zones) {
|
for (auto &z: m_zones) {
|
||||||
if (z.zoneidnumber == zc->zoneID) {
|
if (z.zoneidnumber == zone_id) {
|
||||||
auto f = ContentFlags{
|
auto f = ContentFlags{
|
||||||
.min_expansion = z.min_expansion,
|
.min_expansion = z.min_expansion,
|
||||||
.max_expansion = z.max_expansion,
|
.max_expansion = z.max_expansion,
|
||||||
@@ -286,33 +315,45 @@ void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
|
|||||||
z.long_name
|
z.long_name
|
||||||
);
|
);
|
||||||
|
|
||||||
auto instances = InstanceListRepository::GetWhere(
|
// first pass, explicit match on public static global zone instances
|
||||||
*GetDatabase(),
|
for (auto &i: m_zone_instances) {
|
||||||
fmt::format(
|
if (i.zone == zone_id && i.version == z.version) {
|
||||||
"zone = {} AND version = {} AND never_expires = 1 AND is_global = 1",
|
|
||||||
z.zoneidnumber,
|
|
||||||
z.version
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!instances.empty()) {
|
|
||||||
auto instance = instances.front();
|
|
||||||
zc->instanceID = instance.id;
|
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"Routed player to instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
|
"Routed player to instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
|
||||||
instance.id,
|
i.id,
|
||||||
z.short_name,
|
z.short_name,
|
||||||
z.zoneidnumber,
|
z.zoneidnumber,
|
||||||
z.version,
|
z.version,
|
||||||
z.long_name,
|
z.long_name,
|
||||||
instance.notes
|
i.notes
|
||||||
);
|
);
|
||||||
|
|
||||||
break;
|
return WorldContentService::FindZoneResult{
|
||||||
|
.zone_id = static_cast<uint32>(z.zoneidnumber),
|
||||||
|
.instance = i,
|
||||||
|
.zone = z
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Routed player to non-instance zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
|
||||||
|
z.short_name,
|
||||||
|
z.zoneidnumber,
|
||||||
|
z.version,
|
||||||
|
z.long_name,
|
||||||
|
z.note
|
||||||
|
);
|
||||||
|
|
||||||
|
return WorldContentService::FindZoneResult{
|
||||||
|
.zone_id = static_cast<uint32>(z.zoneidnumber),
|
||||||
|
.instance = InstanceListRepository::NewEntity(),
|
||||||
|
.zone = z
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return WorldContentService::FindZoneResult{.zone_id = 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../repositories/content_flags_repository.h"
|
#include "../repositories/content_flags_repository.h"
|
||||||
#include "../repositories/zone_repository.h"
|
#include "../repositories/zone_repository.h"
|
||||||
|
#include "../repositories/instance_list_repository.h"
|
||||||
|
|
||||||
class Database;
|
class Database;
|
||||||
|
|
||||||
@@ -169,7 +170,14 @@ public:
|
|||||||
void SetContentFlag(const std::string &content_flag_name, bool enabled);
|
void SetContentFlag(const std::string &content_flag_name, bool enabled);
|
||||||
|
|
||||||
void HandleZoneRoutingMiddleware(ZoneChange_Struct *zc);
|
void HandleZoneRoutingMiddleware(ZoneChange_Struct *zc);
|
||||||
WorldContentService * SetContentZones(const std::vector<ZoneRepository::Zone>& zones);
|
|
||||||
|
struct FindZoneResult {
|
||||||
|
uint32 zone_id = 0;
|
||||||
|
InstanceListRepository::InstanceList instance;
|
||||||
|
ZoneRepository::Zone zone;
|
||||||
|
};
|
||||||
|
|
||||||
|
FindZoneResult FindZone(uint32 zone_id, uint32 instance_id);
|
||||||
private:
|
private:
|
||||||
int current_expansion{};
|
int current_expansion{};
|
||||||
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
|
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
|
||||||
@@ -180,6 +188,9 @@ private:
|
|||||||
|
|
||||||
// holds a record of the zone table from the database
|
// holds a record of the zone table from the database
|
||||||
std::vector<ZoneRepository::Zone> m_zones = {};
|
std::vector<ZoneRepository::Zone> m_zones = {};
|
||||||
|
WorldContentService *LoadStaticGlobalZoneInstances();
|
||||||
|
std::vector<InstanceListRepository::InstanceList> m_zone_instances;
|
||||||
|
WorldContentService * LoadZones();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern WorldContentService content_service;
|
extern WorldContentService content_service;
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if WINDOWS
|
#ifdef _WINDOWS
|
||||||
#define popen _popen
|
#define popen _popen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+1030
-1304
File diff suppressed because it is too large
Load Diff
+122
-116
@@ -38,8 +38,7 @@
|
|||||||
class MySQLRequestResult;
|
class MySQLRequestResult;
|
||||||
class Client;
|
class Client;
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ {
|
||||||
{
|
|
||||||
class InventoryProfile;
|
class InventoryProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +54,8 @@ struct VarCache_Struct {
|
|||||||
uint32 last_update;
|
uint32 last_update;
|
||||||
VarCache_Struct() : last_update(0) { }
|
VarCache_Struct() : last_update(0) { }
|
||||||
void Add(const std::string& key, const std::string& value) { m_cache[key] = value; }
|
void Add(const std::string& key, const std::string& value) { m_cache[key] = value; }
|
||||||
const std::string *Get(const std::string &key) {
|
const std::string* Get(const std::string& key)
|
||||||
|
{
|
||||||
auto it = m_cache.find(key);
|
auto it = m_cache.find(key);
|
||||||
return (it != m_cache.end() ? &it->second : nullptr);
|
return (it != m_cache.end() ? &it->second : nullptr);
|
||||||
}
|
}
|
||||||
@@ -76,37 +76,33 @@ class PTimerList;
|
|||||||
|
|
||||||
#define SQL(...) #__VA_ARGS__
|
#define SQL(...) #__VA_ARGS__
|
||||||
|
|
||||||
class LogSettings;
|
|
||||||
class Database : public DBcore {
|
class Database : public DBcore {
|
||||||
public:
|
public:
|
||||||
Database();
|
Database();
|
||||||
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
Database(
|
||||||
bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port, std::string connection_label = "default");
|
const std::string& host,
|
||||||
|
const std::string& user,
|
||||||
|
const std::string& password,
|
||||||
|
const std::string& database,
|
||||||
|
uint32 port
|
||||||
|
);
|
||||||
|
bool Connect(
|
||||||
|
const std::string& host,
|
||||||
|
const std::string& user,
|
||||||
|
const std::string& password,
|
||||||
|
const std::string& database,
|
||||||
|
uint32 port,
|
||||||
|
std::string connection_label = "default"
|
||||||
|
);
|
||||||
~Database();
|
~Database();
|
||||||
|
|
||||||
/* Character Creation */
|
/* Character Creation */
|
||||||
|
bool DeleteCharacter(const std::string& name);
|
||||||
bool CreateCharacter(
|
bool MoveCharacterToZone(const std::string& name, uint32 zone_id);
|
||||||
uint32 account_id,
|
|
||||||
char *name,
|
|
||||||
uint16 gender,
|
|
||||||
uint16 race,
|
|
||||||
uint16 class_,
|
|
||||||
uint8 str,
|
|
||||||
uint8 sta,
|
|
||||||
uint8 cha,
|
|
||||||
uint8 dex,
|
|
||||||
uint8 int_,
|
|
||||||
uint8 agi,
|
|
||||||
uint8 wis,
|
|
||||||
uint8 face
|
|
||||||
);
|
|
||||||
bool DeleteCharacter(char *character_name);
|
|
||||||
bool MoveCharacterToZone(const char *charname, uint32 zone_id);
|
|
||||||
bool MoveCharacterToZone(uint32 character_id, uint32 zone_id);
|
bool MoveCharacterToZone(uint32 character_id, uint32 zone_id);
|
||||||
bool ReserveName(uint32 account_id, char *name);
|
bool ReserveName(uint32 account_id, const std::string& name);
|
||||||
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
|
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
|
||||||
bool UpdateName(const char *oldname, const char *newname);
|
bool UpdateName(const std::string& old_name, const std::string& new_name);
|
||||||
bool CopyCharacter(
|
bool CopyCharacter(
|
||||||
const std::string& source_character_name,
|
const std::string& source_character_name,
|
||||||
const std::string& destination_character_name,
|
const std::string& destination_character_name,
|
||||||
@@ -114,32 +110,29 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
/* General Information Queries */
|
/* General Information Queries */
|
||||||
|
bool AddBannedIP(const std::string& banned_ip, const std::string& notes); //Add IP address to the banned_ips table.
|
||||||
|
bool AddToNameFilter(const std::string& name);
|
||||||
|
bool CheckBannedIPs(const std::string& login_ip); //Check incoming connection against banned IP table.
|
||||||
|
bool CheckGMIPs(const std::string& login_ip, uint32 account_id);
|
||||||
|
bool CheckNameFilter(const std::string& name, bool surname = false);
|
||||||
|
bool IsNameUsed(const std::string& name);
|
||||||
|
|
||||||
bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table.
|
uint32 GetAccountIDByChar(const std::string& name, uint32* character_id = 0);
|
||||||
bool AddToNameFilter(std::string name);
|
uint32 GetAccountIDByChar(uint32 character_id);
|
||||||
bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table.
|
uint32 GetAccountIDByName(const std::string& account_name, const std::string& loginserver, int16* status = 0, uint32* lsid = 0);
|
||||||
bool CheckGMIPs(std::string login_ip, uint32 account_id);
|
|
||||||
bool CheckNameFilter(std::string name, bool surname = false);
|
|
||||||
bool CheckUsedName(std::string name);
|
|
||||||
|
|
||||||
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
|
|
||||||
uint32 GetAccountIDByChar(uint32 char_id);
|
|
||||||
uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0);
|
|
||||||
uint32 GetCharacterID(const std::string& name);
|
uint32 GetCharacterID(const std::string& name);
|
||||||
uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id);
|
uint32 GetGuildIDByCharID(uint32 character_id);
|
||||||
uint32 GetGuildIDByCharID(uint32 char_id);
|
uint32 GetGroupIDByCharID(uint32 character_id);
|
||||||
uint32 GetGroupIDByCharID(uint32 char_id);
|
uint32 GetRaidIDByCharID(uint32 character_id);
|
||||||
uint32 GetRaidIDByCharID(uint32 char_id);
|
|
||||||
|
|
||||||
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
|
const std::string GetAccountName(uint32 account_id, uint32* lsaccount_id = 0);
|
||||||
void GetCharName(uint32 char_id, char* name);
|
const std::string GetCharName(uint32 character_id);
|
||||||
std::string GetCharNameByID(uint32 char_id);
|
const std::string GetCharNameByID(uint32 character_id);
|
||||||
std::string GetNPCNameByID(uint32 npc_id);
|
const std::string GetNPCNameByID(uint32 npc_id);
|
||||||
std::string GetCleanNPCNameByID(uint32 npc_id);
|
const std::string GetCleanNPCNameByID(uint32 npc_id);
|
||||||
void LoginIP(uint32 account_id, std::string login_ip);
|
void LoginIP(uint32 account_id, const std::string& login_ip);
|
||||||
|
|
||||||
/* Instancing */
|
/* Instancing */
|
||||||
|
|
||||||
bool AddClientToInstance(uint16 instance_id, uint32 character_id);
|
bool AddClientToInstance(uint16 instance_id, uint32 character_id);
|
||||||
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id);
|
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id);
|
||||||
bool CheckInstanceExists(uint16 instance_id);
|
bool CheckInstanceExists(uint16 instance_id);
|
||||||
@@ -152,117 +145,130 @@ public:
|
|||||||
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id);
|
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id);
|
||||||
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
|
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
|
||||||
|
|
||||||
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
|
uint16 GetInstanceID(uint32 zone, uint32 character_id, int16 version);
|
||||||
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id);
|
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id);
|
||||||
uint8_t GetInstanceVersion(uint16 instance_id);
|
uint8_t GetInstanceVersion(uint16 instance_id);
|
||||||
uint32 GetTimeRemainingInstance(uint16 instance_id, bool& is_perma);
|
uint32 GetTimeRemainingInstance(uint16 instance_id, bool& is_perma);
|
||||||
uint32 GetInstanceZoneID(uint16 instance_id);
|
uint32 GetInstanceZoneID(uint16 instance_id);
|
||||||
|
|
||||||
void AssignGroupToInstance(uint32 gid, uint32 instance_id);
|
void AssignGroupToInstance(uint32 group_id, uint32 instance_id);
|
||||||
void AssignRaidToInstance(uint32 rid, uint32 instance_id);
|
void AssignRaidToInstance(uint32 raid_id, uint32 instance_id);
|
||||||
void DeleteInstance(uint16 instance_id);
|
void DeleteInstance(uint16 instance_id);
|
||||||
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id);
|
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id);
|
||||||
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id);
|
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id);
|
||||||
void GetCharactersInInstance(uint16 instance_id, std::list<uint32>& character_ids);
|
void GetCharactersInInstance(uint16 instance_id, std::list<uint32>& character_ids);
|
||||||
void PurgeExpiredInstances();
|
void PurgeExpiredInstances();
|
||||||
void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
|
void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
|
||||||
void CleanupInstanceCorpses();
|
void CleanupInstanceCorpses();
|
||||||
|
|
||||||
/* Adventure related. */
|
/* Adventure related. */
|
||||||
|
void UpdateAdventureStatsEntry(uint32 character_id, uint8 theme_id, bool is_win = false, bool is_remove = false);
|
||||||
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win = false, bool remove = false);
|
bool GetAdventureStats(uint32 character_id, AdventureStats_Struct* as);
|
||||||
bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
|
|
||||||
|
|
||||||
/* Account Related */
|
/* Account Related */
|
||||||
|
const std::string GetLiveChar(uint32 account_id);
|
||||||
bool DeleteAccount(const char *name, const char* loginserver);
|
|
||||||
bool GetLiveChar(uint32 account_id, char* cname);
|
|
||||||
bool SetAccountStatus(const char* name, int16 status);
|
|
||||||
bool SetAccountStatus(const std::string& account_name, int16 status);
|
bool SetAccountStatus(const std::string& account_name, int16 status);
|
||||||
bool SetLocalPassword(uint32 accid, const char* password);
|
bool SetLocalPassword(uint32 account_id, const std::string& password);
|
||||||
bool UpdateLiveChar(char* charname, uint32 account_id);
|
bool UpdateLiveChar(const std::string& name, uint32 account_id);
|
||||||
|
|
||||||
int16 CheckStatus(uint32 account_id);
|
int16 CheckStatus(uint32 account_id);
|
||||||
|
void SetAccountCRCField(uint32 account_id, const std::string& field_name, uint64 checksum);
|
||||||
|
uint32 CheckLogin(const std::string& name, const std::string& password, const std::string& loginserver, int16* status = 0);
|
||||||
|
uint32 CreateAccount(
|
||||||
|
const std::string& name,
|
||||||
|
const std::string& password,
|
||||||
|
int16 status,
|
||||||
|
const std::string& 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
|
||||||
|
);
|
||||||
|
|
||||||
void SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum);
|
|
||||||
|
|
||||||
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 account_id);
|
uint8 GetAgreementFlag(uint32 account_id);
|
||||||
|
|
||||||
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
|
|
||||||
void SetAgreementFlag(uint32 account_id);
|
void SetAgreementFlag(uint32 account_id);
|
||||||
|
|
||||||
int GetIPExemption(std::string account_ip);
|
int GetIPExemption(const std::string& account_ip);
|
||||||
void SetIPExemption(std::string account_ip, int exemption_amount);
|
void SetIPExemption(const std::string& account_ip, int exemption_amount);
|
||||||
|
|
||||||
int GetInstanceID(uint32 char_id, uint32 zone_id);
|
int GetInstanceID(uint32 character_id, uint32 zone_id);
|
||||||
|
|
||||||
|
|
||||||
/* Groups */
|
/* Groups */
|
||||||
|
std::string GetGroupLeaderForLogin(const std::string& character_name);
|
||||||
std::string GetGroupLeaderForLogin(std::string character_name);
|
char* GetGroupLeadershipInfo(
|
||||||
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
|
uint32 group_id,
|
||||||
|
char* leaderbuf,
|
||||||
uint32 GetGroupID(const char* name);
|
char* maintank = nullptr,
|
||||||
|
char* assist = nullptr,
|
||||||
void ClearGroup(uint32 gid = 0);
|
char* puller = nullptr,
|
||||||
void ClearGroupLeader(uint32 gid = 0);
|
char* marknpc = nullptr,
|
||||||
void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false);
|
char* mentoree = nullptr,
|
||||||
void SetGroupLeaderName(uint32 gid, const char* name);
|
int* mentor_percent = nullptr,
|
||||||
|
GroupLeadershipAA_Struct* GLAA = nullptr
|
||||||
|
);
|
||||||
|
std::string GetGroupLeaderName(uint32 group_id);
|
||||||
|
uint32 GetGroupID(const std::string& name);
|
||||||
|
void ClearGroup(uint32 group_id = 0);
|
||||||
|
void ClearGroupLeader(uint32 group_id = 0);
|
||||||
|
void SetGroupLeaderName(uint32 group_id, const std::string& name);
|
||||||
|
|
||||||
/* Raids */
|
/* Raids */
|
||||||
|
const std::string GetRaidLeaderName(uint32 raid_id);
|
||||||
const char *GetRaidLeaderName(uint32 rid);
|
uint32 GetRaidID(const std::string& name);
|
||||||
|
void ClearRaid(uint32 raid_id = 0);
|
||||||
uint32 GetRaidID(const char* name);
|
void ClearRaidDetails(uint32 raid_id = 0);
|
||||||
|
void ClearRaidLeader(uint32 group_id = std::numeric_limits<uint32>::max(), uint32 raid_id = 0);
|
||||||
void ClearRaid(uint32 rid = 0);
|
void GetGroupLeadershipInfo(
|
||||||
void ClearRaidDetails(uint32 rid = 0);
|
uint32 group_id,
|
||||||
void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0);
|
uint32 raid_id,
|
||||||
void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
|
char* maintank = nullptr,
|
||||||
void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, RaidLeadershipAA_Struct* RLAA = nullptr);
|
char* assist = nullptr,
|
||||||
void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid);
|
char* puller = nullptr,
|
||||||
|
char* marknpc = nullptr,
|
||||||
|
char* mentoree = nullptr,
|
||||||
|
int* mentor_percent = nullptr,
|
||||||
|
GroupLeadershipAA_Struct* GLAA = nullptr
|
||||||
|
);
|
||||||
|
void GetRaidLeadershipInfo(
|
||||||
|
uint32 raid_id,
|
||||||
|
char* maintank = nullptr,
|
||||||
|
char* assist = nullptr,
|
||||||
|
char* puller = nullptr,
|
||||||
|
char* marknpc = nullptr,
|
||||||
|
RaidLeadershipAA_Struct* RLAA = nullptr
|
||||||
|
);
|
||||||
|
void SetRaidGroupLeaderInfo(uint32 group_id, uint32 raid_id);
|
||||||
|
|
||||||
void PurgeAllDeletedDataBuckets();
|
void PurgeAllDeletedDataBuckets();
|
||||||
|
|
||||||
|
|
||||||
/* Database Variables */
|
/* Database Variables */
|
||||||
|
bool GetVariable(const std::string& name, std::string& value);
|
||||||
bool GetVariable(std::string varname, std::string &varvalue);
|
bool SetVariable(const std::string& name, const std::string& value);
|
||||||
bool SetVariable(const std::string& varname, const std::string &varvalue);
|
|
||||||
bool LoadVariables();
|
bool LoadVariables();
|
||||||
|
|
||||||
/* General Queries */
|
|
||||||
|
|
||||||
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0);
|
|
||||||
bool LoadPTimers(uint32 charid, PTimerList &into);
|
|
||||||
|
|
||||||
uint8 GetPEQZone(uint32 zone_id, uint32 version);
|
uint8 GetPEQZone(uint32 zone_id, uint32 version);
|
||||||
uint8 GetMinStatus(uint32 zone_id, uint32 instance_version);
|
uint32 GetServerType();
|
||||||
uint8 GetRaceSkill(uint8 skillid, uint8 in_race);
|
void AddReport(const std::string& who, const std::string& against, const std::string& lines);
|
||||||
uint8 GetServerType();
|
|
||||||
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
|
|
||||||
|
|
||||||
void AddReport(std::string who, std::string against, std::string lines);
|
|
||||||
struct TimeOfDay_Struct LoadTime(time_t& realtime);
|
struct TimeOfDay_Struct LoadTime(time_t& realtime);
|
||||||
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
|
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
|
||||||
void ClearMerchantTemp();
|
void ClearMerchantTemp();
|
||||||
void ClearPTimers(uint32 charid);
|
void ClearPTimers(uint32 character_id);
|
||||||
void SetFirstLogon(uint32 CharID, uint8 firstlogon);
|
void SetFirstLogon(uint32 character_id, uint8 first_logon);
|
||||||
void SetLFG(uint32 CharID, bool LFG);
|
void SetLFG(uint32 character_id, bool is_lfg);
|
||||||
void SetLFP(uint32 CharID, bool LFP);
|
void SetLFP(uint32 character_id, bool is_lfp);
|
||||||
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
|
void SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon);
|
||||||
|
|
||||||
int CountInvSnapshots();
|
int64 CountInvSnapshots();
|
||||||
void ClearInvSnapshots(bool from_now = false);
|
void ClearInvSnapshots(bool from_now = false);
|
||||||
|
|
||||||
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
|
void SourceDatabaseTableFromUrl(const std::string& table_name, const std::string& url);
|
||||||
void SourceSqlFromUrl(std::string url);
|
void SourceSqlFromUrl(const std::string& url);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Mutex Mvarcache;
|
Mutex Mvarcache;
|
||||||
VarCache_Struct varcache;
|
VarCache_Struct varcache;
|
||||||
|
|
||||||
|
|||||||
@@ -5410,6 +5410,65 @@ ADD COLUMN `augment_five` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_fou
|
|||||||
ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`;
|
ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`;
|
||||||
)",
|
)",
|
||||||
.content_schema_update = true
|
.content_schema_update = true
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9265,
|
||||||
|
.description = "2024_03_03_add_id_to_guild_bank.sql",
|
||||||
|
.check = "SHOW COLUMNS FROM `guild_bank` LIKE 'id'",
|
||||||
|
.condition = "empty",
|
||||||
|
.match = "",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `guild_bank`
|
||||||
|
ADD COLUMN `id` INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
|
||||||
|
ADD PRIMARY KEY (`id`);
|
||||||
|
)",
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9266,
|
||||||
|
.description = "2024_03_02_rule_values_rule_value_length.sql",
|
||||||
|
.check = "SHOW COLUMNS FROM `rule_values` LIKE 'rule_value'",
|
||||||
|
.condition = "contains",
|
||||||
|
.match = "varchar(30)",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `rule_values`
|
||||||
|
MODIFY COLUMN `rule_value` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `rule_name`;
|
||||||
|
)"
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9267,
|
||||||
|
.description = "2024_02_18_group_id_bot_id.sql",
|
||||||
|
.check = "SHOW COLUMNS FROM `group_id` LIKE 'bot_id'",
|
||||||
|
.condition = "empty",
|
||||||
|
.match = "",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `group_id`
|
||||||
|
CHANGE COLUMN `groupid` `group_id` int(11) UNSIGNED NOT NULL DEFAULT 0 FIRST,
|
||||||
|
CHANGE COLUMN `charid` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `group_id`,
|
||||||
|
CHANGE COLUMN `ismerc` `merc_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `name`,
|
||||||
|
ADD COLUMN `bot_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `character_id`,
|
||||||
|
MODIFY COLUMN `name` varchar(64) NOT NULL DEFAULT '' AFTER `character_id`,
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
ADD PRIMARY KEY (`group_id`, `character_id`, `bot_id`, `merc_id`) USING BTREE;
|
||||||
|
ALTER TABLE `group_id`
|
||||||
|
MODIFY COLUMN `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `name`;
|
||||||
|
)"
|
||||||
|
},
|
||||||
|
ManifestEntry{
|
||||||
|
.version = 9268,
|
||||||
|
.description = "2024_03_23_skill_caps.sql",
|
||||||
|
.check = "SHOW COLUMNS FROM `skill_caps` LIKE 'skill_id'",
|
||||||
|
.condition = "empty",
|
||||||
|
.match = "",
|
||||||
|
.sql = R"(
|
||||||
|
ALTER TABLE `skill_caps`
|
||||||
|
CHANGE COLUMN `skillID` `skill_id` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 FIRST,
|
||||||
|
CHANGE COLUMN `class` `class_id` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `skill_id`,
|
||||||
|
ADD COLUMN `id` int(3) UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
ADD PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
ADD INDEX `level_skill_cap`(`skill_id`, `class_id`, `level`, `cap`);
|
||||||
|
)",
|
||||||
|
.content_schema_update = true,
|
||||||
}
|
}
|
||||||
// -- template; copy/paste this when you need to create a new entry
|
// -- template; copy/paste this when you need to create a new entry
|
||||||
// ManifestEntry{
|
// ManifestEntry{
|
||||||
|
|||||||
@@ -421,20 +421,25 @@ void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
|
|||||||
auto zone_id = GetInstanceZoneID(instance_id);
|
auto zone_id = GetInstanceZoneID(instance_id);
|
||||||
auto version = GetInstanceVersion(instance_id);
|
auto version = GetInstanceVersion(instance_id);
|
||||||
|
|
||||||
auto l = GroupIdRepository::GetWhere(
|
const auto& l = GroupIdRepository::GetWhere(
|
||||||
*this,
|
*this,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"groupid = {}",
|
"`group_id` = {}",
|
||||||
group_id
|
group_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (l.empty()) {
|
if (l.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& e : l) {
|
for (const auto& e : l) {
|
||||||
if (!GetInstanceID(zone_id, e.charid, version)) {
|
if (!e.character_id) {
|
||||||
AddClientToInstance(instance_id, e.charid);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetInstanceID(zone_id, e.character_id, version)) {
|
||||||
|
AddClientToInstance(instance_id, e.character_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -504,7 +509,7 @@ void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 ch
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id));
|
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id).c_str());
|
||||||
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
|
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
|
||||||
|
|
||||||
if (!raid_leader_instance_id) {
|
if (!raid_leader_instance_id) {
|
||||||
|
|||||||
@@ -698,6 +698,8 @@ const std::map<uint32, std::string>& EQ::constants::GetSpecialAbilityMap()
|
|||||||
{ IMMUNE_OPEN, "Immune to Open" },
|
{ IMMUNE_OPEN, "Immune to Open" },
|
||||||
{ IMMUNE_ASSASSINATE, "Immune to Assassinate" },
|
{ IMMUNE_ASSASSINATE, "Immune to Assassinate" },
|
||||||
{ IMMUNE_HEADSHOT, "Immune to Headshot" },
|
{ IMMUNE_HEADSHOT, "Immune to Headshot" },
|
||||||
|
{ IMMUNE_AGGRO_BOT, "Immune to Bot Aggro" },
|
||||||
|
{ IMMUNE_DAMAGE_BOT, "Immune to Bot Damage" },
|
||||||
};
|
};
|
||||||
|
|
||||||
return special_ability_map;
|
return special_ability_map;
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ namespace EQ
|
|||||||
using RoF2::invslot::SLOT_INVALID;
|
using RoF2::invslot::SLOT_INVALID;
|
||||||
using RoF2::invslot::SLOT_BEGIN;
|
using RoF2::invslot::SLOT_BEGIN;
|
||||||
|
|
||||||
|
using RoF2::invslot::SLOT_QUEST;
|
||||||
|
|
||||||
using Titanium::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
|
using Titanium::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
|
||||||
|
|
||||||
const int16 SLOT_AUGMENT_GENERIC_RETURN = 1001; // clients don't appear to use this method... (internal inventory return value)
|
const int16 SLOT_AUGMENT_GENERIC_RETURN = 1001; // clients don't appear to use this method... (internal inventory return value)
|
||||||
@@ -656,7 +658,9 @@ enum {
|
|||||||
IMMUNE_OPEN = 53,
|
IMMUNE_OPEN = 53,
|
||||||
IMMUNE_ASSASSINATE = 54,
|
IMMUNE_ASSASSINATE = 54,
|
||||||
IMMUNE_HEADSHOT = 55,
|
IMMUNE_HEADSHOT = 55,
|
||||||
MAX_SPECIAL_ATTACK = 56
|
IMMUNE_AGGRO_BOT = 56,
|
||||||
|
IMMUNE_DAMAGE_BOT = 57,
|
||||||
|
MAX_SPECIAL_ATTACK = 58
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ enum CrystalReclaimTypes
|
|||||||
Radiant = 4,
|
Radiant = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace ItemStackSizeConstraint {
|
||||||
|
constexpr int16 Minimum = 1;
|
||||||
|
constexpr int16 Maximum = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ namespace Logs {
|
|||||||
Zoning,
|
Zoning,
|
||||||
EqTime,
|
EqTime,
|
||||||
Corpses,
|
Corpses,
|
||||||
|
XTargets,
|
||||||
MaxCategoryID /* Don't Remove this */
|
MaxCategoryID /* Don't Remove this */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -241,6 +242,7 @@ namespace Logs {
|
|||||||
"Zoning",
|
"Zoning",
|
||||||
"EqTime",
|
"EqTime",
|
||||||
"Corpses",
|
"Corpses",
|
||||||
|
"XTargets"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -834,6 +834,16 @@
|
|||||||
OutF(LogSys, Logs::Detail, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
OutF(LogSys, Logs::Detail, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define LogXTargets(message, ...) do {\
|
||||||
|
if (LogSys.IsLogEnabled(Logs::General, Logs::XTargets))\
|
||||||
|
OutF(LogSys, Logs::General, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogXTargetsDetail(message, ...) do {\
|
||||||
|
if (LogSys.IsLogEnabled(Logs::Detail, Logs::XTargets))\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define Log(debug_level, log_category, message, ...) do {\
|
#define Log(debug_level, log_category, message, ...) do {\
|
||||||
if (LogSys.IsLogEnabled(debug_level, log_category))\
|
if (LogSys.IsLogEnabled(debug_level, log_category))\
|
||||||
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ Zone extensions and features
|
|||||||
#define QUEST_GLOBAL_DIRECTORY "global"
|
#define QUEST_GLOBAL_DIRECTORY "global"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Number of quest items a Quest NPC can hold
|
||||||
|
#define MAX_NPC_QUEST_INVENTORY 24
|
||||||
|
|
||||||
|
|
||||||
//the min ratio at which a mob's speed is reduced
|
//the min ratio at which a mob's speed is reduced
|
||||||
#define FLEE_HP_MINSPEED 22
|
#define FLEE_HP_MINSPEED 22
|
||||||
//number of tics to try to run straight away before looking again
|
//number of tics to try to run straight away before looking again
|
||||||
@@ -111,6 +115,7 @@ Zone extensions and features
|
|||||||
|
|
||||||
#define SKILL_MAX_LEVEL 75
|
#define SKILL_MAX_LEVEL 75
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Zone Numerical configuration
|
Zone Numerical configuration
|
||||||
|
|||||||
+2
-29
@@ -342,39 +342,12 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 BaseGuildManager::_GetFreeGuildID()
|
|
||||||
{
|
|
||||||
GuildsRepository::DeleteWhere(*m_db, "`name` = ''");
|
|
||||||
|
|
||||||
GuildsRepository::Guilds out;
|
|
||||||
out.id = 0;
|
|
||||||
out.leader = 0;
|
|
||||||
out.minstatus = 0;
|
|
||||||
out.tribute = 0;
|
|
||||||
out.name = "";
|
|
||||||
out.motd = "";
|
|
||||||
out.motd_setter = "";
|
|
||||||
out.url = "";
|
|
||||||
out.channel = "";
|
|
||||||
auto last_insert_id = GuildsRepository::InsertOne(*m_db, out);
|
|
||||||
if (last_insert_id.id > 0) {
|
|
||||||
LogGuilds("Located a free guild ID [{}] in the database", last_insert_id.id);
|
|
||||||
return last_insert_id.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogGuilds("Unable to find a free guild ID in the database");
|
|
||||||
return GUILD_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 BaseGuildManager::CreateGuild(std::string name, uint32 leader_char_id)
|
uint32 BaseGuildManager::CreateGuild(std::string name, uint32 leader_char_id)
|
||||||
{
|
{
|
||||||
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
|
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
|
||||||
if (guild_id == GUILD_NONE) {
|
if (guild_id == GUILD_NONE) {
|
||||||
return (GUILD_NONE);
|
return (GUILD_NONE);
|
||||||
}
|
}
|
||||||
//RefreshGuild(guild_id);
|
|
||||||
//SendGuildRefresh(guild_id, true, false, false, false);
|
|
||||||
//SendCharRefresh(GUILD_NONE, guild_id, leader_char_id);
|
|
||||||
|
|
||||||
return guild_id;
|
return guild_id;
|
||||||
}
|
}
|
||||||
@@ -539,8 +512,8 @@ bool BaseGuildManager::SetPublicNote(uint32 charid, std::string public_note)
|
|||||||
|
|
||||||
uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
|
uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
|
||||||
{
|
{
|
||||||
auto new_id = _GetFreeGuildID();
|
auto new_id = GuildsRepository::GetMaxId(*m_db) + 1;
|
||||||
if (new_id == GUILD_NONE) {
|
if (!new_id) {
|
||||||
return GUILD_NONE;
|
return GUILD_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,6 @@ class BaseGuildManager
|
|||||||
|
|
||||||
bool _StoreGuildDB(uint32 guild_id);
|
bool _StoreGuildDB(uint32 guild_id);
|
||||||
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
|
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
|
||||||
uint32 _GetFreeGuildID();
|
|
||||||
GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in);
|
GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in);
|
||||||
};
|
};
|
||||||
#endif /*GUILD_BASE_H_*/
|
#endif /*GUILD_BASE_H_*/
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ struct LootItem {
|
|||||||
uint16 trivial_max_level;
|
uint16 trivial_max_level;
|
||||||
uint16 npc_min_level;
|
uint16 npc_min_level;
|
||||||
uint16 npc_max_level;
|
uint16 npc_max_level;
|
||||||
|
uint8 quest;
|
||||||
|
uint8 pet;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<LootItem*> LootItems;
|
typedef std::list<LootItem*> LootItems;
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ namespace RoF2
|
|||||||
const int16 SLOT_INVALID = IINVALID;
|
const int16 SLOT_INVALID = IINVALID;
|
||||||
const int16 SLOT_BEGIN = INULL;
|
const int16 SLOT_BEGIN = INULL;
|
||||||
|
|
||||||
|
const int16 SLOT_QUEST = 9999;
|
||||||
|
|
||||||
const int16 POSSESSIONS_BEGIN = slotCharm;
|
const int16 POSSESSIONS_BEGIN = slotCharm;
|
||||||
const int16 POSSESSIONS_END = slotCursor;
|
const int16 POSSESSIONS_END = slotCursor;
|
||||||
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
||||||
|
|||||||
@@ -162,6 +162,8 @@ namespace RoF
|
|||||||
const int16 SLOT_INVALID = IINVALID;
|
const int16 SLOT_INVALID = IINVALID;
|
||||||
const int16 SLOT_BEGIN = INULL;
|
const int16 SLOT_BEGIN = INULL;
|
||||||
|
|
||||||
|
const int16 SLOT_QUEST = 9999;
|
||||||
|
|
||||||
const int16 POSSESSIONS_BEGIN = slotCharm;
|
const int16 POSSESSIONS_BEGIN = slotCharm;
|
||||||
const int16 POSSESSIONS_END = slotCursor;
|
const int16 POSSESSIONS_END = slotCursor;
|
||||||
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
||||||
|
|||||||
@@ -152,6 +152,8 @@ namespace SoD
|
|||||||
|
|
||||||
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
||||||
|
|
||||||
|
const int16 SLOT_QUEST = 9999;
|
||||||
|
|
||||||
const int16 POSSESSIONS_BEGIN = slotCharm;
|
const int16 POSSESSIONS_BEGIN = slotCharm;
|
||||||
const int16 POSSESSIONS_END = slotCursor;
|
const int16 POSSESSIONS_END = slotCursor;
|
||||||
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
||||||
|
|||||||
@@ -152,6 +152,8 @@ namespace SoF
|
|||||||
|
|
||||||
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
||||||
|
|
||||||
|
const int16 SLOT_QUEST = 9999;
|
||||||
|
|
||||||
const int16 POSSESSIONS_BEGIN = slotCharm;
|
const int16 POSSESSIONS_BEGIN = slotCharm;
|
||||||
const int16 POSSESSIONS_END = slotCursor;
|
const int16 POSSESSIONS_END = slotCursor;
|
||||||
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ namespace Titanium
|
|||||||
|
|
||||||
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
||||||
|
|
||||||
|
const int16 SLOT_QUEST = 9999;
|
||||||
|
|
||||||
const int16 POSSESSIONS_BEGIN = slotCharm;
|
const int16 POSSESSIONS_BEGIN = slotCharm;
|
||||||
const int16 POSSESSIONS_END = slotCursor;
|
const int16 POSSESSIONS_END = slotCursor;
|
||||||
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
||||||
|
|||||||
@@ -152,6 +152,8 @@ namespace UF
|
|||||||
|
|
||||||
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
const int16 SLOT_TRADESKILL_EXPERIMENT_COMBINE = 1000;
|
||||||
|
|
||||||
|
const int16 SLOT_QUEST = 9999;
|
||||||
|
|
||||||
const int16 POSSESSIONS_BEGIN = slotCharm;
|
const int16 POSSESSIONS_BEGIN = slotCharm;
|
||||||
const int16 POSSESSIONS_END = slotCursor;
|
const int16 POSSESSIONS_END = slotCursor;
|
||||||
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
|
||||||
|
|||||||
+1
-1
@@ -1379,7 +1379,7 @@ uint32 GetPlayerRaceValue(uint16 race_id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 GetPlayerRaceBit(uint16 race_id) {
|
uint16 GetPlayerRaceBit(uint16 race_id) {
|
||||||
switch (race_id) {
|
switch (race_id) {
|
||||||
case HUMAN:
|
case HUMAN:
|
||||||
return PLAYER_RACE_HUMAN_BIT;
|
return PLAYER_RACE_HUMAN_BIT;
|
||||||
|
|||||||
+1
-1
@@ -124,7 +124,7 @@ bool IsPlayerRace(uint16 race_id);
|
|||||||
const std::string GetPlayerRaceAbbreviation(uint16 race_id);
|
const std::string GetPlayerRaceAbbreviation(uint16 race_id);
|
||||||
|
|
||||||
uint32 GetPlayerRaceValue(uint16 race_id);
|
uint32 GetPlayerRaceValue(uint16 race_id);
|
||||||
uint32 GetPlayerRaceBit(uint16 race_id);
|
uint16 GetPlayerRaceBit(uint16 race_id);
|
||||||
|
|
||||||
uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value);
|
uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value);
|
||||||
uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit);
|
uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit);
|
||||||
|
|||||||
@@ -44,7 +44,51 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static int16 GetAccountStatus(Database& db, const uint32 account_id)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `{}` WHERE `{}` = {}",
|
||||||
|
TableName(),
|
||||||
|
PrimaryKey(),
|
||||||
|
account_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!results.Success() || !results.RowCount()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
int16 status = static_cast<int16>(Strings::ToInt(row[0]));
|
||||||
|
int date_diff = 0;
|
||||||
|
|
||||||
|
if (row[1]) {
|
||||||
|
date_diff = Strings::ToInt(row[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (date_diff > 0) {
|
||||||
|
status = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool UpdatePassword(Database& db, const uint32 account_id, const std::string& password)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE `{}` SET `password` = MD5('{}') WHERE `{}` = {}",
|
||||||
|
TableName(),
|
||||||
|
password,
|
||||||
|
PrimaryKey(),
|
||||||
|
account_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return results.Success();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_ACCOUNT_REPOSITORY_H
|
#endif //EQEMU_ACCOUNT_REPOSITORY_H
|
||||||
|
|||||||
@@ -44,7 +44,65 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static void UpdateAdventureStatsEntry(Database& db, uint32 character_id, uint8 theme_id, bool is_win, bool is_remove)
|
||||||
|
{
|
||||||
|
std::string field;
|
||||||
|
|
||||||
|
switch (theme_id) {
|
||||||
|
case LDoNThemes::GUK: {
|
||||||
|
field = "guk_";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LDoNThemes::MIR: {
|
||||||
|
field = "mir_";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LDoNThemes::MMC: {
|
||||||
|
field = "mmc_";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LDoNThemes::RUJ: {
|
||||||
|
field = "ruj_";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LDoNThemes::TAK: {
|
||||||
|
field = "tak_";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field += is_win ? "wins" : "losses";
|
||||||
|
|
||||||
|
auto e = FindOne(db, character_id);
|
||||||
|
|
||||||
|
if (!e.player_id && !is_remove) {
|
||||||
|
const std::string& query = fmt::format(
|
||||||
|
"INSERT INTO `{}` SET `{}` = 1, `{}` = {}",
|
||||||
|
TableName(),
|
||||||
|
field,
|
||||||
|
PrimaryKey(),
|
||||||
|
character_id
|
||||||
|
);
|
||||||
|
|
||||||
|
db.QueryDatabase(query);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& field_operation = is_remove ? "-" : "+";
|
||||||
|
|
||||||
|
const std::string& query = fmt::format(
|
||||||
|
"UPDATE `{}` SET `{}` = {} {} 1 WHERE `{}` = {}",
|
||||||
|
TableName(),
|
||||||
|
field,
|
||||||
|
field,
|
||||||
|
field_operation,
|
||||||
|
PrimaryKey(),
|
||||||
|
character_id
|
||||||
|
);
|
||||||
|
|
||||||
|
db.QueryDatabase(query);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_ADVENTURE_STATS_REPOSITORY_H
|
#endif //EQEMU_ADVENTURE_STATS_REPOSITORY_H
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
int32_t accid;
|
int32_t accid;
|
||||||
std::string ip;
|
std::string ip;
|
||||||
int32_t count;
|
int32_t count;
|
||||||
std::string lastused;
|
time_t lastused;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
"accid",
|
"accid",
|
||||||
"ip",
|
"ip",
|
||||||
"count",
|
"count",
|
||||||
"lastused",
|
"UNIX_TIMESTAMP(lastused)",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ public:
|
|||||||
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||||
e.ip = row[1] ? row[1] : "";
|
e.ip = row[1] ? row[1] : "";
|
||||||
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
|
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
|
||||||
e.lastused = row[3] ? row[3] : std::time(nullptr);
|
e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ public:
|
|||||||
v.push_back(columns[0] + " = " + std::to_string(e.accid));
|
v.push_back(columns[0] + " = " + std::to_string(e.accid));
|
||||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.ip) + "'");
|
v.push_back(columns[1] + " = '" + Strings::Escape(e.ip) + "'");
|
||||||
v.push_back(columns[2] + " = " + std::to_string(e.count));
|
v.push_back(columns[2] + " = " + std::to_string(e.count));
|
||||||
v.push_back(columns[3] + " = '" + Strings::Escape(e.lastused) + "'");
|
v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -192,7 +192,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.accid));
|
v.push_back(std::to_string(e.accid));
|
||||||
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
||||||
v.push_back(std::to_string(e.count));
|
v.push_back(std::to_string(e.count));
|
||||||
v.push_back("'" + Strings::Escape(e.lastused) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -225,7 +225,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.accid));
|
v.push_back(std::to_string(e.accid));
|
||||||
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
||||||
v.push_back(std::to_string(e.count));
|
v.push_back(std::to_string(e.count));
|
||||||
v.push_back("'" + Strings::Escape(e.lastused) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ public:
|
|||||||
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||||
e.ip = row[1] ? row[1] : "";
|
e.ip = row[1] ? row[1] : "";
|
||||||
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
|
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
|
||||||
e.lastused = row[3] ? row[3] : std::time(nullptr);
|
e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -290,7 +290,7 @@ public:
|
|||||||
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||||
e.ip = row[1] ? row[1] : "";
|
e.ip = row[1] ? row[1] : "";
|
||||||
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
|
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
|
||||||
e.lastused = row[3] ? row[3] : std::time(nullptr);
|
e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.accid));
|
v.push_back(std::to_string(e.accid));
|
||||||
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
||||||
v.push_back(std::to_string(e.count));
|
v.push_back(std::to_string(e.count));
|
||||||
v.push_back("'" + Strings::Escape(e.lastused) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -394,7 +394,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.accid));
|
v.push_back(std::to_string(e.accid));
|
||||||
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
v.push_back("'" + Strings::Escape(e.ip) + "'");
|
||||||
v.push_back(std::to_string(e.count));
|
v.push_back(std::to_string(e.count));
|
||||||
v.push_back("'" + Strings::Escape(e.lastused) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,34 +19,37 @@
|
|||||||
class BaseGroupIdRepository {
|
class BaseGroupIdRepository {
|
||||||
public:
|
public:
|
||||||
struct GroupId {
|
struct GroupId {
|
||||||
int32_t groupid;
|
uint32_t group_id;
|
||||||
int32_t charid;
|
|
||||||
std::string name;
|
std::string name;
|
||||||
int8_t ismerc;
|
uint32_t character_id;
|
||||||
|
uint32_t bot_id;
|
||||||
|
uint32_t merc_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
{
|
{
|
||||||
return std::string("groupid");
|
return std::string("group_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> Columns()
|
static std::vector<std::string> Columns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"groupid",
|
"group_id",
|
||||||
"charid",
|
|
||||||
"name",
|
"name",
|
||||||
"ismerc",
|
"character_id",
|
||||||
|
"bot_id",
|
||||||
|
"merc_id",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> SelectColumns()
|
static std::vector<std::string> SelectColumns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"groupid",
|
"group_id",
|
||||||
"charid",
|
|
||||||
"name",
|
"name",
|
||||||
"ismerc",
|
"character_id",
|
||||||
|
"bot_id",
|
||||||
|
"merc_id",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,10 +90,11 @@ public:
|
|||||||
{
|
{
|
||||||
GroupId e{};
|
GroupId e{};
|
||||||
|
|
||||||
e.groupid = 0;
|
e.group_id = 0;
|
||||||
e.charid = 0;
|
|
||||||
e.name = "";
|
e.name = "";
|
||||||
e.ismerc = 0;
|
e.character_id = 0;
|
||||||
|
e.bot_id = 0;
|
||||||
|
e.merc_id = 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -101,7 +105,7 @@ public:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (auto &group_id : group_ids) {
|
for (auto &group_id : group_ids) {
|
||||||
if (group_id.groupid == group_id_id) {
|
if (group_id.group_id == group_id_id) {
|
||||||
return group_id;
|
return group_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,10 +131,11 @@ public:
|
|||||||
if (results.RowCount() == 1) {
|
if (results.RowCount() == 1) {
|
||||||
GroupId e{};
|
GroupId e{};
|
||||||
|
|
||||||
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.name = row[1] ? row[1] : "";
|
||||||
e.name = row[2] ? row[2] : "";
|
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
|
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -164,10 +169,11 @@ public:
|
|||||||
|
|
||||||
auto columns = Columns();
|
auto columns = Columns();
|
||||||
|
|
||||||
v.push_back(columns[0] + " = " + std::to_string(e.groupid));
|
v.push_back(columns[0] + " = " + std::to_string(e.group_id));
|
||||||
v.push_back(columns[1] + " = " + std::to_string(e.charid));
|
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
|
||||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'");
|
v.push_back(columns[2] + " = " + std::to_string(e.character_id));
|
||||||
v.push_back(columns[3] + " = " + std::to_string(e.ismerc));
|
v.push_back(columns[3] + " = " + std::to_string(e.bot_id));
|
||||||
|
v.push_back(columns[4] + " = " + std::to_string(e.merc_id));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -175,7 +181,7 @@ public:
|
|||||||
TableName(),
|
TableName(),
|
||||||
Strings::Implode(", ", v),
|
Strings::Implode(", ", v),
|
||||||
PrimaryKey(),
|
PrimaryKey(),
|
||||||
e.groupid
|
e.group_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -189,10 +195,11 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.groupid));
|
v.push_back(std::to_string(e.group_id));
|
||||||
v.push_back(std::to_string(e.charid));
|
|
||||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
v.push_back(std::to_string(e.ismerc));
|
v.push_back(std::to_string(e.character_id));
|
||||||
|
v.push_back(std::to_string(e.bot_id));
|
||||||
|
v.push_back(std::to_string(e.merc_id));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -203,7 +210,7 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (results.Success()) {
|
if (results.Success()) {
|
||||||
e.groupid = results.LastInsertedID();
|
e.group_id = results.LastInsertedID();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,10 +229,11 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.groupid));
|
v.push_back(std::to_string(e.group_id));
|
||||||
v.push_back(std::to_string(e.charid));
|
|
||||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
v.push_back(std::to_string(e.ismerc));
|
v.push_back(std::to_string(e.character_id));
|
||||||
|
v.push_back(std::to_string(e.bot_id));
|
||||||
|
v.push_back(std::to_string(e.merc_id));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@@ -259,10 +267,11 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
GroupId e{};
|
GroupId e{};
|
||||||
|
|
||||||
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.name = row[1] ? row[1] : "";
|
||||||
e.name = row[2] ? row[2] : "";
|
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
|
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -287,10 +296,11 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
GroupId e{};
|
GroupId e{};
|
||||||
|
|
||||||
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
e.name = row[1] ? row[1] : "";
|
||||||
e.name = row[2] ? row[2] : "";
|
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
|
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
|
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -365,10 +375,11 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.groupid));
|
v.push_back(std::to_string(e.group_id));
|
||||||
v.push_back(std::to_string(e.charid));
|
|
||||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
v.push_back(std::to_string(e.ismerc));
|
v.push_back(std::to_string(e.character_id));
|
||||||
|
v.push_back(std::to_string(e.bot_id));
|
||||||
|
v.push_back(std::to_string(e.merc_id));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -391,10 +402,11 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.groupid));
|
v.push_back(std::to_string(e.group_id));
|
||||||
v.push_back(std::to_string(e.charid));
|
|
||||||
v.push_back("'" + Strings::Escape(e.name) + "'");
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
v.push_back(std::to_string(e.ismerc));
|
v.push_back(std::to_string(e.character_id));
|
||||||
|
v.push_back(std::to_string(e.bot_id));
|
||||||
|
v.push_back(std::to_string(e.merc_id));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
e.gid = 0;
|
e.gid = 0;
|
||||||
e.leadername = "";
|
e.leadername = "";
|
||||||
e.marknpc = "";
|
e.marknpc = "";
|
||||||
e.leadershipaa = 0;
|
e.leadershipaa = "";
|
||||||
e.maintank = "";
|
e.maintank = "";
|
||||||
e.assist = "";
|
e.assist = "";
|
||||||
e.puller = "";
|
e.puller = "";
|
||||||
@@ -150,7 +150,7 @@ public:
|
|||||||
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||||
e.leadername = row[1] ? row[1] : "";
|
e.leadername = row[1] ? row[1] : "";
|
||||||
e.marknpc = row[2] ? row[2] : "";
|
e.marknpc = row[2] ? row[2] : "";
|
||||||
e.leadershipaa = row[3] ? row[3] : 0;
|
e.leadershipaa = row[3] ? row[3] : "";
|
||||||
e.maintank = row[4] ? row[4] : "";
|
e.maintank = row[4] ? row[4] : "";
|
||||||
e.assist = row[5] ? row[5] : "";
|
e.assist = row[5] ? row[5] : "";
|
||||||
e.puller = row[6] ? row[6] : "";
|
e.puller = row[6] ? row[6] : "";
|
||||||
@@ -302,7 +302,7 @@ public:
|
|||||||
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||||
e.leadername = row[1] ? row[1] : "";
|
e.leadername = row[1] ? row[1] : "";
|
||||||
e.marknpc = row[2] ? row[2] : "";
|
e.marknpc = row[2] ? row[2] : "";
|
||||||
e.leadershipaa = row[3] ? row[3] : 0;
|
e.leadershipaa = row[3] ? row[3] : "";
|
||||||
e.maintank = row[4] ? row[4] : "";
|
e.maintank = row[4] ? row[4] : "";
|
||||||
e.assist = row[5] ? row[5] : "";
|
e.assist = row[5] ? row[5] : "";
|
||||||
e.puller = row[6] ? row[6] : "";
|
e.puller = row[6] ? row[6] : "";
|
||||||
@@ -335,7 +335,7 @@ public:
|
|||||||
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
|
||||||
e.leadername = row[1] ? row[1] : "";
|
e.leadername = row[1] ? row[1] : "";
|
||||||
e.marknpc = row[2] ? row[2] : "";
|
e.marknpc = row[2] ? row[2] : "";
|
||||||
e.leadershipaa = row[3] ? row[3] : 0;
|
e.leadershipaa = row[3] ? row[3] : "";
|
||||||
e.maintank = row[4] ? row[4] : "";
|
e.maintank = row[4] ? row[4] : "";
|
||||||
e.assist = row[5] ? row[5] : "";
|
e.assist = row[5] ? row[5] : "";
|
||||||
e.puller = row[6] ? row[6] : "";
|
e.puller = row[6] ? row[6] : "";
|
||||||
|
|||||||
@@ -19,8 +19,9 @@
|
|||||||
class BaseSkillCapsRepository {
|
class BaseSkillCapsRepository {
|
||||||
public:
|
public:
|
||||||
struct SkillCaps {
|
struct SkillCaps {
|
||||||
uint8_t skillID;
|
uint32_t id;
|
||||||
uint8_t class_;
|
uint8_t skill_id;
|
||||||
|
uint8_t class_id;
|
||||||
uint8_t level;
|
uint8_t level;
|
||||||
uint32_t cap;
|
uint32_t cap;
|
||||||
uint8_t class_;
|
uint8_t class_;
|
||||||
@@ -28,14 +29,15 @@ public:
|
|||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
{
|
{
|
||||||
return std::string("skillID");
|
return std::string("id");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> Columns()
|
static std::vector<std::string> Columns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"skillID",
|
"id",
|
||||||
"`class`",
|
"skill_id",
|
||||||
|
"class_id",
|
||||||
"level",
|
"level",
|
||||||
"cap",
|
"cap",
|
||||||
"class_",
|
"class_",
|
||||||
@@ -45,8 +47,9 @@ public:
|
|||||||
static std::vector<std::string> SelectColumns()
|
static std::vector<std::string> SelectColumns()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
"skillID",
|
"id",
|
||||||
"`class`",
|
"skill_id",
|
||||||
|
"class_id",
|
||||||
"level",
|
"level",
|
||||||
"cap",
|
"cap",
|
||||||
"class_",
|
"class_",
|
||||||
@@ -90,8 +93,9 @@ public:
|
|||||||
{
|
{
|
||||||
SkillCaps e{};
|
SkillCaps e{};
|
||||||
|
|
||||||
e.skillID = 0;
|
e.id = 0;
|
||||||
e.class_ = 0;
|
e.skill_id = 0;
|
||||||
|
e.class_id = 0;
|
||||||
e.level = 0;
|
e.level = 0;
|
||||||
e.cap = 0;
|
e.cap = 0;
|
||||||
e.class_ = 0;
|
e.class_ = 0;
|
||||||
@@ -105,7 +109,7 @@ public:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (auto &skill_caps : skill_capss) {
|
for (auto &skill_caps : skill_capss) {
|
||||||
if (skill_caps.skillID == skill_caps_id) {
|
if (skill_caps.id == skill_caps_id) {
|
||||||
return skill_caps;
|
return skill_caps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,11 +135,12 @@ public:
|
|||||||
if (results.RowCount() == 1) {
|
if (results.RowCount() == 1) {
|
||||||
SkillCaps e{};
|
SkillCaps e{};
|
||||||
|
|
||||||
e.skillID = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
|
e.skill_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||||
e.level = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
e.class_id = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.cap = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
e.level = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
e.class_ = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
e.cap = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
|
e.class_ = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -169,11 +174,11 @@ public:
|
|||||||
|
|
||||||
auto columns = Columns();
|
auto columns = Columns();
|
||||||
|
|
||||||
v.push_back(columns[0] + " = " + std::to_string(e.skillID));
|
v.push_back(columns[1] + " = " + std::to_string(e.skill_id));
|
||||||
v.push_back(columns[1] + " = " + std::to_string(e.class_));
|
v.push_back(columns[2] + " = " + std::to_string(e.class_id));
|
||||||
v.push_back(columns[2] + " = " + std::to_string(e.level));
|
v.push_back(columns[3] + " = " + std::to_string(e.level));
|
||||||
v.push_back(columns[3] + " = " + std::to_string(e.cap));
|
v.push_back(columns[4] + " = " + std::to_string(e.cap));
|
||||||
v.push_back(columns[4] + " = " + std::to_string(e.class_));
|
v.push_back(columns[5] + " = " + std::to_string(e.class_));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -181,7 +186,7 @@ public:
|
|||||||
TableName(),
|
TableName(),
|
||||||
Strings::Implode(", ", v),
|
Strings::Implode(", ", v),
|
||||||
PrimaryKey(),
|
PrimaryKey(),
|
||||||
e.skillID
|
e.id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -195,8 +200,9 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.skillID));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.skill_id));
|
||||||
|
v.push_back(std::to_string(e.class_id));
|
||||||
v.push_back(std::to_string(e.level));
|
v.push_back(std::to_string(e.level));
|
||||||
v.push_back(std::to_string(e.cap));
|
v.push_back(std::to_string(e.cap));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.class_));
|
||||||
@@ -210,7 +216,7 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (results.Success()) {
|
if (results.Success()) {
|
||||||
e.skillID = results.LastInsertedID();
|
e.id = results.LastInsertedID();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,8 +235,9 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.skillID));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.skill_id));
|
||||||
|
v.push_back(std::to_string(e.class_id));
|
||||||
v.push_back(std::to_string(e.level));
|
v.push_back(std::to_string(e.level));
|
||||||
v.push_back(std::to_string(e.cap));
|
v.push_back(std::to_string(e.cap));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.class_));
|
||||||
@@ -267,11 +274,12 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
SkillCaps e{};
|
SkillCaps e{};
|
||||||
|
|
||||||
e.skillID = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
|
e.skill_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||||
e.level = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
e.class_id = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.cap = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
e.level = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
e.class_ = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
e.cap = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
|
e.class_ = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -296,11 +304,12 @@ public:
|
|||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
SkillCaps e{};
|
SkillCaps e{};
|
||||||
|
|
||||||
e.skillID = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
|
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||||
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
|
e.skill_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||||
e.level = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
e.class_id = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||||
e.cap = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
e.level = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||||
e.class_ = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
e.cap = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||||
|
e.class_ = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -375,8 +384,9 @@ public:
|
|||||||
{
|
{
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.skillID));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.skill_id));
|
||||||
|
v.push_back(std::to_string(e.class_id));
|
||||||
v.push_back(std::to_string(e.level));
|
v.push_back(std::to_string(e.level));
|
||||||
v.push_back(std::to_string(e.cap));
|
v.push_back(std::to_string(e.cap));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.class_));
|
||||||
@@ -402,8 +412,9 @@ public:
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
|
|
||||||
v.push_back(std::to_string(e.skillID));
|
v.push_back(std::to_string(e.id));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.skill_id));
|
||||||
|
v.push_back(std::to_string(e.class_id));
|
||||||
v.push_back(std::to_string(e.level));
|
v.push_back(std::to_string(e.level));
|
||||||
v.push_back(std::to_string(e.cap));
|
v.push_back(std::to_string(e.cap));
|
||||||
v.push_back(std::to_string(e.class_));
|
v.push_back(std::to_string(e.class_));
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
std::string varname;
|
std::string varname;
|
||||||
std::string value;
|
std::string value;
|
||||||
std::string information;
|
std::string information;
|
||||||
std::string ts;
|
time_t ts;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
"varname",
|
"varname",
|
||||||
"value",
|
"value",
|
||||||
"information",
|
"information",
|
||||||
"ts",
|
"UNIX_TIMESTAMP(ts)",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ public:
|
|||||||
e.varname = row[1] ? row[1] : "";
|
e.varname = row[1] ? row[1] : "";
|
||||||
e.value = row[2] ? row[2] : "";
|
e.value = row[2] ? row[2] : "";
|
||||||
e.information = row[3] ? row[3] : "";
|
e.information = row[3] ? row[3] : "";
|
||||||
e.ts = row[4] ? row[4] : std::time(nullptr);
|
e.ts = strtoll(row[4] ? row[4] : "-1", nullptr, 10);
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ public:
|
|||||||
v.push_back(columns[1] + " = '" + Strings::Escape(e.varname) + "'");
|
v.push_back(columns[1] + " = '" + Strings::Escape(e.varname) + "'");
|
||||||
v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'");
|
v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'");
|
||||||
v.push_back(columns[3] + " = '" + Strings::Escape(e.information) + "'");
|
v.push_back(columns[3] + " = '" + Strings::Escape(e.information) + "'");
|
||||||
v.push_back(columns[4] + " = '" + Strings::Escape(e.ts) + "'");
|
v.push_back(columns[4] + " = FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -198,7 +198,7 @@ public:
|
|||||||
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.information) + "'");
|
v.push_back("'" + Strings::Escape(e.information) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.ts) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -232,7 +232,7 @@ public:
|
|||||||
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.information) + "'");
|
v.push_back("'" + Strings::Escape(e.information) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.ts) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")");
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@@ -270,7 +270,7 @@ public:
|
|||||||
e.varname = row[1] ? row[1] : "";
|
e.varname = row[1] ? row[1] : "";
|
||||||
e.value = row[2] ? row[2] : "";
|
e.value = row[2] ? row[2] : "";
|
||||||
e.information = row[3] ? row[3] : "";
|
e.information = row[3] ? row[3] : "";
|
||||||
e.ts = row[4] ? row[4] : std::time(nullptr);
|
e.ts = strtoll(row[4] ? row[4] : "-1", nullptr, 10);
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -299,7 +299,7 @@ public:
|
|||||||
e.varname = row[1] ? row[1] : "";
|
e.varname = row[1] ? row[1] : "";
|
||||||
e.value = row[2] ? row[2] : "";
|
e.value = row[2] ? row[2] : "";
|
||||||
e.information = row[3] ? row[3] : "";
|
e.information = row[3] ? row[3] : "";
|
||||||
e.ts = row[4] ? row[4] : std::time(nullptr);
|
e.ts = strtoll(row[4] ? row[4] : "-1", nullptr, 10);
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@@ -378,7 +378,7 @@ public:
|
|||||||
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.information) + "'");
|
v.push_back("'" + Strings::Escape(e.information) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.ts) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")");
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -405,7 +405,7 @@ public:
|
|||||||
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
v.push_back("'" + Strings::Escape(e.varname) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.value) + "'");
|
v.push_back("'" + Strings::Escape(e.value) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.information) + "'");
|
v.push_back("'" + Strings::Escape(e.information) + "'");
|
||||||
v.push_back("'" + Strings::Escape(e.ts) + "'");
|
v.push_back("FROM_UNIXTIME(" + (e.ts > 0 ? std::to_string(e.ts) : "null") + ")");
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,24 @@ public:
|
|||||||
return NewEntity();
|
return NewEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// insert with ON DUPLICATE KEY UPDATE to leave rows that exist unchanged
|
||||||
|
static int InsertUpdateMany(Database& db, const std::vector<CharRecipeList>& entries)
|
||||||
|
{
|
||||||
|
std::vector<std::string> values;
|
||||||
|
values.reserve(entries.size());
|
||||||
|
|
||||||
|
for (const auto& e: entries)
|
||||||
|
{
|
||||||
|
values.emplace_back(fmt::format("({},{},{})", e.char_id, e.recipe_id, e.madecount));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(fmt::format(
|
||||||
|
"INSERT INTO {0} (char_id, recipe_id, madecount) VALUES {1} ON DUPLICATE KEY UPDATE {2}={2}",
|
||||||
|
TableName(), fmt::join(values, ","), PrimaryKey()));
|
||||||
|
|
||||||
|
return results.Success() ? results.RowsAffected() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H
|
#endif //EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H
|
||||||
|
|||||||
@@ -213,23 +213,23 @@ public:
|
|||||||
const glm::vec4& position
|
const glm::vec4& position
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto corpse = FindOne(db, corpse_id);
|
||||||
fmt::format(
|
|
||||||
"UPDATE `{}` SET `is_buried` = 0, `zone_id` = {}, `instance_id` = {}, `x` = {:.2f}, `y` = {:.2f}, `z` = {:.2f}, `heading` = {:.2f}, `time_of_death` = {}, `was_at_graveyard` = 0 WHERE `{}` = {}",
|
|
||||||
TableName(),
|
|
||||||
zone_id,
|
|
||||||
instance_id,
|
|
||||||
position.x,
|
|
||||||
position.y,
|
|
||||||
position.z,
|
|
||||||
position.w,
|
|
||||||
std::time(nullptr),
|
|
||||||
PrimaryKey(),
|
|
||||||
corpse_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return results.Success() ? results.RowsAffected() : 0;
|
if (corpse.id == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
corpse.is_buried = 0;
|
||||||
|
corpse.zone_id = zone_id;
|
||||||
|
corpse.instance_id = instance_id;
|
||||||
|
corpse.x = position.x;
|
||||||
|
corpse.y = position.y;
|
||||||
|
corpse.z = position.z;
|
||||||
|
corpse.heading = position.w;
|
||||||
|
corpse.time_of_death = time(nullptr);
|
||||||
|
corpse.was_at_graveyard = 0;
|
||||||
|
|
||||||
|
return UpdateOne(db, corpse);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,11 @@ public:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& m = l.front();
|
||||||
|
|
||||||
return EXPModifier{
|
return EXPModifier{
|
||||||
.aa_modifier = l[0].aa_modifier,
|
.aa_modifier = m.aa_modifier,
|
||||||
.exp_modifier = l[0].exp_modifier
|
.exp_modifier = m.exp_modifier
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static void ClearAllGroups(Database& db)
|
||||||
|
{
|
||||||
|
db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM `{}`",
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_GROUP_ID_REPOSITORY_H
|
#endif //EQEMU_GROUP_ID_REPOSITORY_H
|
||||||
|
|||||||
@@ -44,7 +44,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static void ClearAllGroupLeaders(Database& db)
|
||||||
|
{
|
||||||
|
db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM `{}`",
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_GROUP_LEADERS_REPOSITORY_H
|
#endif //EQEMU_GROUP_LEADERS_REPOSITORY_H
|
||||||
|
|||||||
@@ -191,4 +191,5 @@ public:
|
|||||||
return UpdateOne(db, m);
|
return UpdateOne(db, m);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_GUILD_MEMBERS_REPOSITORY_H
|
#endif //EQEMU_GUILD_MEMBERS_REPOSITORY_H
|
||||||
|
|||||||
@@ -44,7 +44,30 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static int64 CountInventorySnapshots(Database& db)
|
||||||
|
{
|
||||||
|
const std::string& query = "SELECT COUNT(*) FROM (SELECT * FROM `inventory_snapshots` a GROUP BY `charid`, `time_index`) b";
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success() || !results.RowCount()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
const int64 count = Strings::ToBigInt(row[0]);
|
||||||
|
|
||||||
|
if (count > std::numeric_limits<int>::max()) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < 0) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H
|
#endif //EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H
|
||||||
|
|||||||
@@ -66,6 +66,16 @@ public:
|
|||||||
|
|
||||||
return results.Success() ? results.RowsAffected() : 0;
|
return results.Success() ? results.RowsAffected() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ClearAllRaidDetails(Database& db)
|
||||||
|
{
|
||||||
|
db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM `{}`",
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_RAID_DETAILS_REPOSITORY_H
|
#endif //EQEMU_RAID_DETAILS_REPOSITORY_H
|
||||||
|
|||||||
@@ -1,297 +0,0 @@
|
|||||||
#ifndef EQEMU_RAID_LEADERS_REPOSITORY_H
|
|
||||||
#define EQEMU_RAID_LEADERS_REPOSITORY_H
|
|
||||||
|
|
||||||
#include "../database.h"
|
|
||||||
#include "../strings.h"
|
|
||||||
|
|
||||||
class RaidLeadersRepository {
|
|
||||||
public:
|
|
||||||
struct RaidLeaders {
|
|
||||||
int gid;
|
|
||||||
int rid;
|
|
||||||
std::string marknpc;
|
|
||||||
std::string maintank;
|
|
||||||
std::string assist;
|
|
||||||
std::string puller;
|
|
||||||
std::string leadershipaa;
|
|
||||||
std::string mentoree;
|
|
||||||
int mentor_percent;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
|
||||||
{
|
|
||||||
return std::string("");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<std::string> Columns()
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
"gid",
|
|
||||||
"rid",
|
|
||||||
"marknpc",
|
|
||||||
"maintank",
|
|
||||||
"assist",
|
|
||||||
"puller",
|
|
||||||
"leadershipaa",
|
|
||||||
"mentoree",
|
|
||||||
"mentor_percent",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string ColumnsRaw()
|
|
||||||
{
|
|
||||||
return std::string(Strings::Implode(", ", Columns()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string InsertColumnsRaw()
|
|
||||||
{
|
|
||||||
std::vector<std::string> insert_columns;
|
|
||||||
|
|
||||||
for (auto &column : Columns()) {
|
|
||||||
if (column == PrimaryKey()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
insert_columns.push_back(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string(Strings::Implode(", ", insert_columns));
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string TableName()
|
|
||||||
{
|
|
||||||
return std::string("raid_leaders");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string BaseSelect()
|
|
||||||
{
|
|
||||||
return fmt::format(
|
|
||||||
"SELECT {} FROM {}",
|
|
||||||
ColumnsRaw(),
|
|
||||||
TableName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string BaseInsert()
|
|
||||||
{
|
|
||||||
return fmt::format(
|
|
||||||
"INSERT INTO {} ({}) ",
|
|
||||||
TableName(),
|
|
||||||
InsertColumnsRaw()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static RaidLeaders NewEntity()
|
|
||||||
{
|
|
||||||
RaidLeaders entry{};
|
|
||||||
|
|
||||||
entry.gid = 0;
|
|
||||||
entry.rid = 0;
|
|
||||||
entry.marknpc = "";
|
|
||||||
entry.maintank = "";
|
|
||||||
entry.assist = "";
|
|
||||||
entry.puller = "";
|
|
||||||
entry.leadershipaa = 0;
|
|
||||||
entry.mentoree = "";
|
|
||||||
entry.mentor_percent = 0;
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static RaidLeaders GetRaidLeadersEntry(
|
|
||||||
const std::vector<RaidLeaders> &raid_leaderss,
|
|
||||||
int raid_leaders_id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for (auto &raid_leaders : raid_leaderss) {
|
|
||||||
if (raid_leaders. == raid_leaders_id) {
|
|
||||||
return raid_leaders;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
static RaidLeaders FindOne(
|
|
||||||
int raid_leaders_id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto results = database.QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"{} WHERE id = {} LIMIT 1",
|
|
||||||
BaseSelect(),
|
|
||||||
raid_leaders_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
if (results.RowCount() == 1) {
|
|
||||||
RaidLeaders entry{};
|
|
||||||
|
|
||||||
entry.gid = atoi(row[0]);
|
|
||||||
entry.rid = atoi(row[1]);
|
|
||||||
entry.marknpc = row[2];
|
|
||||||
entry.maintank = row[3];
|
|
||||||
entry.assist = row[4];
|
|
||||||
entry.puller = row[5];
|
|
||||||
entry.leadershipaa = row[6];
|
|
||||||
entry.mentoree = row[7];
|
|
||||||
entry.mentor_percent = atoi(row[8]);
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int DeleteOne(
|
|
||||||
int raid_leaders_id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto results = database.QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"DELETE FROM {} WHERE {} = {}",
|
|
||||||
TableName(),
|
|
||||||
PrimaryKey(),
|
|
||||||
raid_leaders_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (results.Success() ? results.RowsAffected() : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int UpdateOne(
|
|
||||||
RaidLeaders raid_leaders_entry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::vector<std::string> update_values;
|
|
||||||
|
|
||||||
auto columns = Columns();
|
|
||||||
|
|
||||||
update_values.push_back(columns[0] + " = " + std::to_string(raid_leaders_entry.gid));
|
|
||||||
update_values.push_back(columns[1] + " = " + std::to_string(raid_leaders_entry.rid));
|
|
||||||
update_values.push_back(columns[2] + " = '" + Strings::Escape(raid_leaders_entry.marknpc) + "'");
|
|
||||||
update_values.push_back(columns[3] + " = '" + Strings::Escape(raid_leaders_entry.maintank) + "'");
|
|
||||||
update_values.push_back(columns[4] + " = '" + Strings::Escape(raid_leaders_entry.assist) + "'");
|
|
||||||
update_values.push_back(columns[5] + " = '" + Strings::Escape(raid_leaders_entry.puller) + "'");
|
|
||||||
update_values.push_back(columns[6] + " = '" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'");
|
|
||||||
update_values.push_back(columns[7] + " = '" + Strings::Escape(raid_leaders_entry.mentoree) + "'");
|
|
||||||
update_values.push_back(columns[8] + " = " + std::to_string(raid_leaders_entry.mentor_percent));
|
|
||||||
|
|
||||||
auto results = database.QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"UPDATE {} SET {} WHERE {} = {}",
|
|
||||||
TableName(),
|
|
||||||
Strings::Implode(", ", update_values),
|
|
||||||
PrimaryKey(),
|
|
||||||
raid_leaders_entry.
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (results.Success() ? results.RowsAffected() : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static RaidLeaders InsertOne(
|
|
||||||
RaidLeaders raid_leaders_entry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::vector<std::string> insert_values;
|
|
||||||
|
|
||||||
insert_values.push_back(std::to_string(raid_leaders_entry.gid));
|
|
||||||
insert_values.push_back(std::to_string(raid_leaders_entry.rid));
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.marknpc) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.maintank) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.assist) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.puller) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.mentoree) + "'");
|
|
||||||
insert_values.push_back(std::to_string(raid_leaders_entry.mentor_percent));
|
|
||||||
|
|
||||||
auto results = database.QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"{} VALUES ({})",
|
|
||||||
BaseInsert(),
|
|
||||||
Strings::Implode(",", insert_values)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (results.Success()) {
|
|
||||||
raid_leaders_entry.id = results.LastInsertedID();
|
|
||||||
return raid_leaders_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
raid_leaders_entry = InstanceListRepository::NewEntity();
|
|
||||||
|
|
||||||
return raid_leaders_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int InsertMany(
|
|
||||||
std::vector<RaidLeaders> raid_leaders_entries
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::vector<std::string> insert_chunks;
|
|
||||||
|
|
||||||
for (auto &raid_leaders_entry: raid_leaders_entries) {
|
|
||||||
std::vector<std::string> insert_values;
|
|
||||||
|
|
||||||
insert_values.push_back(std::to_string(raid_leaders_entry.gid));
|
|
||||||
insert_values.push_back(std::to_string(raid_leaders_entry.rid));
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.marknpc) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.maintank) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.assist) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.puller) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.leadershipaa) + "'");
|
|
||||||
insert_values.push_back("'" + Strings::Escape(raid_leaders_entry.mentoree) + "'");
|
|
||||||
insert_values.push_back(std::to_string(raid_leaders_entry.mentor_percent));
|
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> insert_values;
|
|
||||||
|
|
||||||
auto results = database.QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"{} VALUES {}",
|
|
||||||
BaseInsert(),
|
|
||||||
Strings::Implode(",", insert_chunks)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (results.Success() ? results.RowsAffected() : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<RaidLeaders> All()
|
|
||||||
{
|
|
||||||
std::vector<RaidLeaders> all_entries;
|
|
||||||
|
|
||||||
auto results = database.QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"{}",
|
|
||||||
BaseSelect()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
all_entries.reserve(results.RowCount());
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
RaidLeaders entry{};
|
|
||||||
|
|
||||||
entry.gid = atoi(row[0]);
|
|
||||||
entry.rid = atoi(row[1]);
|
|
||||||
entry.marknpc = row[2];
|
|
||||||
entry.maintank = row[3];
|
|
||||||
entry.assist = row[4];
|
|
||||||
entry.puller = row[5];
|
|
||||||
entry.leadershipaa = row[6];
|
|
||||||
entry.mentoree = row[7];
|
|
||||||
entry.mentor_percent = atoi(row[8]);
|
|
||||||
|
|
||||||
all_entries.push_back(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return all_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //EQEMU_RAID_LEADERS_REPOSITORY_H
|
|
||||||
@@ -98,5 +98,15 @@ public:
|
|||||||
|
|
||||||
return results.Success() ? results.RowsAffected() : 0;
|
return results.Success() ? results.RowsAffected() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ClearAllRaids(Database& db)
|
||||||
|
{
|
||||||
|
db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM `{}`",
|
||||||
|
TableName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif //EQEMU_RAID_MEMBERS_REPOSITORY_H
|
#endif //EQEMU_RAID_MEMBERS_REPOSITORY_H
|
||||||
|
|||||||
+35
-5
@@ -34,8 +34,8 @@ const char *RuleManager::s_categoryNames[_CatCount + 1] = {
|
|||||||
"InvalidCategory"
|
"InvalidCategory"
|
||||||
};
|
};
|
||||||
|
|
||||||
const RuleManager::RuleInfo RuleManager::s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + 1] = {
|
const RuleManager::RuleInfo RuleManager::s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount + 1] = {
|
||||||
/* this is done in three steps so we can reliably get to them by index*/
|
/* this is done in three steps, so we can reliably get to them by index*/
|
||||||
#define RULE_INT(category_name, rule_name, default_value, notes) \
|
#define RULE_INT(category_name, rule_name, default_value, notes) \
|
||||||
{ #category_name ":" #rule_name, Category__##category_name, IntRule, Int__##rule_name, notes },
|
{ #category_name ":" #rule_name, Category__##category_name, IntRule, Int__##rule_name, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
@@ -45,6 +45,9 @@ const RuleManager::RuleInfo RuleManager::s_RuleInfo[IntRuleCount + RealRuleCount
|
|||||||
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
||||||
{ #category_name ":" #rule_name, Category__##category_name, BoolRule, Bool__##rule_name, notes },
|
{ #category_name ":" #rule_name, Category__##category_name, BoolRule, Bool__##rule_name, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
|
#define RULE_STRING(category_name, rule_name, default_value, notes) \
|
||||||
|
{ #category_name ":" #rule_name, Category__##category_name, StringRule, String__##rule_name, notes },
|
||||||
|
#include "ruletypes.h"
|
||||||
{ "Invalid Rule", _CatCount, IntRule }
|
{ "Invalid Rule", _CatCount, IntRule }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +117,9 @@ bool RuleManager::GetRule(const std::string &rule_name, std::string &rule_value)
|
|||||||
case BoolRule:
|
case BoolRule:
|
||||||
rule_value = m_RuleBoolValues[index] ? "true" : "false";
|
rule_value = m_RuleBoolValues[index] ? "true" : "false";
|
||||||
break;
|
break;
|
||||||
|
case StringRule:
|
||||||
|
rule_value = m_RuleStringValues[index];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -152,6 +158,10 @@ bool RuleManager::SetRule(const std::string &rule_name, const std::string &rule_
|
|||||||
m_RuleBoolValues[index] = static_cast<uint32>(Strings::ToBool(rule_value));
|
m_RuleBoolValues[index] = static_cast<uint32>(Strings::ToBool(rule_value));
|
||||||
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
|
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
|
||||||
break;
|
break;
|
||||||
|
case StringRule:
|
||||||
|
m_RuleStringValues[index] = rule_value;
|
||||||
|
LogRules("Set rule [{}] to value [{}]", rule_name, rule_value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (db_save) {
|
if (db_save) {
|
||||||
@@ -215,11 +225,13 @@ std::string RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
|||||||
return s_RuleInfo[index + IntRuleCount].name;
|
return s_RuleInfo[index + IntRuleCount].name;
|
||||||
case BoolRule:
|
case BoolRule:
|
||||||
return s_RuleInfo[index + IntRuleCount + RealRuleCount].name;
|
return s_RuleInfo[index + IntRuleCount + RealRuleCount].name;
|
||||||
|
case StringRule:
|
||||||
|
return s_RuleInfo[index + IntRuleCount + RealRuleCount + StringRuleCount].name;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount].name;
|
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
//assumes index is valid!
|
//assumes index is valid!
|
||||||
@@ -231,11 +243,13 @@ const std::string &RuleManager::_GetRuleNotes(RuleType type, uint16 index) {
|
|||||||
return s_RuleInfo[index + IntRuleCount].notes;
|
return s_RuleInfo[index + IntRuleCount].notes;
|
||||||
case BoolRule:
|
case BoolRule:
|
||||||
return s_RuleInfo[index + IntRuleCount + RealRuleCount].notes;
|
return s_RuleInfo[index + IntRuleCount + RealRuleCount].notes;
|
||||||
|
case StringRule:
|
||||||
|
return s_RuleInfo[index + IntRuleCount + RealRuleCount + StringRuleCount].notes;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount].notes;
|
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount].notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleManager::LoadRules(Database *db, const std::string &rule_set_name, bool reload) {
|
bool RuleManager::LoadRules(Database *db, const std::string &rule_set_name, bool reload) {
|
||||||
@@ -343,6 +357,10 @@ void RuleManager::SaveRules(Database *db, const std::string &rule_set_name) {
|
|||||||
for (i = 0; i < BoolRuleCount; i++) {
|
for (i = 0; i < BoolRuleCount; i++) {
|
||||||
_SaveRule(db, BoolRule, i);
|
_SaveRule(db, BoolRule, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < StringRuleCount; i++) {
|
||||||
|
_SaveRule(db, StringRule, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
|
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
|
||||||
@@ -367,6 +385,9 @@ void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
|
|||||||
case BoolRule:
|
case BoolRule:
|
||||||
rule_value = m_RuleBoolValues[index] ? "true" : "false";
|
rule_value = m_RuleBoolValues[index] ? "true" : "false";
|
||||||
break;
|
break;
|
||||||
|
case StringRule:
|
||||||
|
rule_value = m_RuleStringValues[index];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& rule_notes = _GetRuleNotes(type, index);
|
const auto& rule_notes = _GetRuleNotes(type, index);
|
||||||
@@ -446,6 +467,10 @@ bool RuleManager::UpdateInjectedRules(Database *db, const std::string &rule_set_
|
|||||||
rule_data[r.name].first = fmt::format("{}", m_RuleBoolValues[r.rule_index] ? "true" : "false");
|
rule_data[r.name].first = fmt::format("{}", m_RuleBoolValues[r.rule_index] ? "true" : "false");
|
||||||
rule_data[r.name].second = &r.notes;
|
rule_data[r.name].second = &r.notes;
|
||||||
break;
|
break;
|
||||||
|
case StringRule:
|
||||||
|
rule_data[r.name].first = m_RuleStringValues[r.rule_index];
|
||||||
|
rule_data[r.name].second = &r.notes;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -552,7 +577,7 @@ bool RuleManager::RestoreRuleNotes(Database *db)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount];
|
return s_RuleInfo[IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount];
|
||||||
}(e.rule_name);
|
}(e.rule_name);
|
||||||
|
|
||||||
if (Strings::Contains(rule.name, e.rule_name)) {
|
if (Strings::Contains(rule.name, e.rule_name)) {
|
||||||
@@ -617,3 +642,8 @@ bool RuleManager::GetBoolRule(RuleManager::BoolType t) const
|
|||||||
{
|
{
|
||||||
return m_RuleBoolValues[t] == 1;
|
return m_RuleBoolValues[t] == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string RuleManager::GetStringRule(RuleManager::StringType t) const
|
||||||
|
{
|
||||||
|
return m_RuleStringValues[t];
|
||||||
|
}
|
||||||
|
|||||||
+22
-2
@@ -23,6 +23,7 @@
|
|||||||
* - RuleI(category, rule) -> fetch an integer rule's value
|
* - RuleI(category, rule) -> fetch an integer rule's value
|
||||||
* - RuleR(category, rule) -> fetch a real (float) rule's value
|
* - RuleR(category, rule) -> fetch a real (float) rule's value
|
||||||
* - RuleB(category, rule) -> fetch a boolean/flag rule's value
|
* - RuleB(category, rule) -> fetch a boolean/flag rule's value
|
||||||
|
* - RuleS(category, rule) -> fetch a string rule's value
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -35,6 +36,8 @@
|
|||||||
RuleManager::Instance()->GetRealRule( RuleManager::Real__##rule_name )
|
RuleManager::Instance()->GetRealRule( RuleManager::Real__##rule_name )
|
||||||
#define RuleB(category_name, rule_name) \
|
#define RuleB(category_name, rule_name) \
|
||||||
RuleManager::Instance()->GetBoolRule( RuleManager::Bool__##rule_name )
|
RuleManager::Instance()->GetBoolRule( RuleManager::Bool__##rule_name )
|
||||||
|
#define RuleS(category_name, rule_name) \
|
||||||
|
RuleManager::Instance()->GetStringRule( RuleManager::String__##rule_name )
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -81,6 +84,17 @@ public:
|
|||||||
|
|
||||||
static const int BoolRuleCount = static_cast<int>(_BoolRuleCount);
|
static const int BoolRuleCount = static_cast<int>(_BoolRuleCount);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
#define RULE_STRING(category_name, rule_name, default_value, notes) \
|
||||||
|
String__##rule_name,
|
||||||
|
|
||||||
|
#include "ruletypes.h"
|
||||||
|
|
||||||
|
_StringRuleCount
|
||||||
|
} StringType;
|
||||||
|
|
||||||
|
static const int StringRuleCount = static_cast<int>(_StringRuleCount);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define RULE_CATEGORY(category_name) \
|
#define RULE_CATEGORY(category_name) \
|
||||||
Category__##category_name,
|
Category__##category_name,
|
||||||
@@ -99,22 +113,26 @@ public:
|
|||||||
static const IntType InvalidInt = _IntRuleCount;
|
static const IntType InvalidInt = _IntRuleCount;
|
||||||
static const RealType InvalidReal = _RealRuleCount;
|
static const RealType InvalidReal = _RealRuleCount;
|
||||||
static const BoolType InvalidBool = _BoolRuleCount;
|
static const BoolType InvalidBool = _BoolRuleCount;
|
||||||
|
static const StringType InvalidString = _StringRuleCount;
|
||||||
static const CategoryType InvalidCategory = _CatCount;
|
static const CategoryType InvalidCategory = _CatCount;
|
||||||
|
|
||||||
static const uint32 RulesCount = IntRuleCount + RealRuleCount + BoolRuleCount;
|
static const uint32 RulesCount = IntRuleCount + RealRuleCount + BoolRuleCount + StringRuleCount;
|
||||||
|
|
||||||
//fetch routines, you should generally use the Rule* macros instead of this
|
//fetch routines, you should generally use the Rule* macros instead of this
|
||||||
int GetIntRule(IntType t) const;
|
int GetIntRule(IntType t) const;
|
||||||
float GetRealRule(RealType t) const;
|
float GetRealRule(RealType t) const;
|
||||||
bool GetBoolRule(BoolType t) const;
|
bool GetBoolRule(BoolType t) const;
|
||||||
|
std::string GetStringRule(StringType t) const;
|
||||||
|
|
||||||
//management routines
|
//management routines
|
||||||
static std::string GetRuleName(IntType t) { return s_RuleInfo[static_cast<int>(t)].name; }
|
static std::string GetRuleName(IntType t) { return s_RuleInfo[static_cast<int>(t)].name; }
|
||||||
static std::string GetRuleName(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].name; }
|
static std::string GetRuleName(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].name; }
|
||||||
static std::string GetRuleName(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].name; }
|
static std::string GetRuleName(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].name; }
|
||||||
|
static std::string GetRuleName(StringType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount + StringRuleCount].name; }
|
||||||
static const std::string& GetRuleNotes(IntType t) { return s_RuleInfo[static_cast<int>(t)].notes; }
|
static const std::string& GetRuleNotes(IntType t) { return s_RuleInfo[static_cast<int>(t)].notes; }
|
||||||
static const std::string& GetRuleNotes(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].notes; }
|
static const std::string& GetRuleNotes(RealType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount].notes; }
|
||||||
static const std::string& GetRuleNotes(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].notes; }
|
static const std::string& GetRuleNotes(BoolType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount].notes; }
|
||||||
|
static const std::string& GetRuleNotes(StringType t) { return s_RuleInfo[static_cast<int>(t) + IntRuleCount + RealRuleCount + StringRuleCount].notes; }
|
||||||
static uint32 CountRules() { return RulesCount; }
|
static uint32 CountRules() { return RulesCount; }
|
||||||
static CategoryType FindCategory(const std::string& category_name);
|
static CategoryType FindCategory(const std::string& category_name);
|
||||||
bool ListRules(const std::string& category_name, std::vector<std::string>& l);
|
bool ListRules(const std::string& category_name, std::vector<std::string>& l);
|
||||||
@@ -150,11 +168,13 @@ private:
|
|||||||
int m_RuleIntValues[IntRuleCount];
|
int m_RuleIntValues[IntRuleCount];
|
||||||
float m_RuleRealValues[RealRuleCount];
|
float m_RuleRealValues[RealRuleCount];
|
||||||
uint32 m_RuleBoolValues[BoolRuleCount];
|
uint32 m_RuleBoolValues[BoolRuleCount];
|
||||||
|
std::string m_RuleStringValues[StringRuleCount];
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
IntRule,
|
IntRule,
|
||||||
RealRule,
|
RealRule,
|
||||||
BoolRule
|
BoolRule,
|
||||||
|
StringRule
|
||||||
} RuleType;
|
} RuleType;
|
||||||
|
|
||||||
static bool _FindRule(const std::string& rule_name, RuleType& type_into, uint16& index_into);
|
static bool _FindRule(const std::string& rule_name, RuleType& type_into, uint16& index_into);
|
||||||
|
|||||||
+14
-1
@@ -28,6 +28,9 @@
|
|||||||
#ifndef RULE_BOOL
|
#ifndef RULE_BOOL
|
||||||
#define RULE_BOOL(cat, rule, default_value, notes)
|
#define RULE_BOOL(cat, rule, default_value, notes)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef RULE_STRING
|
||||||
|
#define RULE_STRING(cat, rule, default_value, notes)
|
||||||
|
#endif
|
||||||
#ifndef RULE_CATEGORY_END
|
#ifndef RULE_CATEGORY_END
|
||||||
#define RULE_CATEGORY_END()
|
#define RULE_CATEGORY_END()
|
||||||
#endif
|
#endif
|
||||||
@@ -324,6 +327,9 @@ RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest err
|
|||||||
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_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_BOOL(World, UseItemLinksForKeyRing, false, "Uses item links for Key Ring Listing instead of item name")
|
||||||
RULE_BOOL(World, UseOldShadowKnightClassExport, true, "Disable to have Shadowknight show as Shadow Knight (live-like)")
|
RULE_BOOL(World, UseOldShadowKnightClassExport, true, "Disable to have Shadowknight show as Shadow Knight (live-like)")
|
||||||
|
RULE_STRING(World, IPExemptionZones, "", "Comma-delimited list of zones to exclude from IP-limit checks. Empty string to disable.")
|
||||||
|
RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to have this be used instead of variables table 'motd' value")
|
||||||
|
RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be used instead of variables table 'rules' value, lines are pipe (|) separated, example: A|B|C")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
@@ -349,6 +355,7 @@ RULE_INT(Zone, GlobalLootMultiplier, 1, "Sets Global Loot drop multiplier for da
|
|||||||
RULE_BOOL(Zone, KillProcessOnDynamicShutdown, true, "When process has booted a zone and has hit its zone shut down timer, it will hard kill the process to free memory back to the OS")
|
RULE_BOOL(Zone, KillProcessOnDynamicShutdown, true, "When process has booted a zone and has hit its zone shut down timer, it will hard kill the process to free memory back to the OS")
|
||||||
RULE_INT(Zone, SpawnEventMin, 3, "When strict is set in spawn_events, specifies the max EQ minutes into the trigger hour a spawn_event will fire. Going below 3 may cause the spawn_event to not fire.")
|
RULE_INT(Zone, SpawnEventMin, 3, "When strict is set in spawn_events, specifies the max EQ minutes into the trigger hour a spawn_event will fire. Going below 3 may cause the spawn_event to not fire.")
|
||||||
RULE_INT(Zone, ForageChance, 25, "Chance of foraging from zone table vs global table")
|
RULE_INT(Zone, ForageChance, 25, "Chance of foraging from zone table vs global table")
|
||||||
|
RULE_INT(Zone, FishingChance, 399, "Chance of fishing from zone table vs global table")
|
||||||
RULE_BOOL(Zone, AllowCrossZoneSpellsOnBots, false, "Set to true to allow cross zone spells (cast/remove) to affect bots")
|
RULE_BOOL(Zone, AllowCrossZoneSpellsOnBots, false, "Set to true to allow cross zone spells (cast/remove) to affect bots")
|
||||||
RULE_BOOL(Zone, AllowCrossZoneSpellsOnMercs, false, "Set to true to allow cross zone spells (cast/remove) to affect mercenaries")
|
RULE_BOOL(Zone, AllowCrossZoneSpellsOnMercs, false, "Set to true to allow cross zone spells (cast/remove) to affect mercenaries")
|
||||||
RULE_BOOL(Zone, AllowCrossZoneSpellsOnPets, false, "Set to true to allow cross zone spells (cast/remove) to affect pets")
|
RULE_BOOL(Zone, AllowCrossZoneSpellsOnPets, false, "Set to true to allow cross zone spells (cast/remove) to affect pets")
|
||||||
@@ -444,7 +451,8 @@ RULE_BOOL(Spells, Jun182014HundredHandsRevamp, false, "This should be true for i
|
|||||||
RULE_BOOL(Spells, SwarmPetTargetLock, false, "Use old method of swarm pets target locking till target dies then despawning")
|
RULE_BOOL(Spells, SwarmPetTargetLock, false, "Use old method of swarm pets target locking till target dies then despawning")
|
||||||
RULE_BOOL(Spells, NPC_UseFocusFromSpells, true, "Allow NPC to use most spell derived focus effects")
|
RULE_BOOL(Spells, NPC_UseFocusFromSpells, true, "Allow NPC to use most spell derived focus effects")
|
||||||
RULE_BOOL(Spells, NPC_UseFocusFromItems, false, "Allow NPC to use most item derived focus effects")
|
RULE_BOOL(Spells, NPC_UseFocusFromItems, false, "Allow NPC to use most item derived focus effects")
|
||||||
RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false, "Allows an additive focus effect to be calculated from worn slot")
|
RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false, "Allows an additive focus effect to be calculated from worn slot. Does not apply limits checks. Can only have one additive focus rule be true.")
|
||||||
|
RULE_BOOL(Spells, UseAdditiveFocusFromWornSlotWithLimits, false, "Allows an additive focus effect to be calculated from worn slot. Applies normal limit checks. Can only have one additive focus rule be true.")
|
||||||
RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false, "Ignore Leadership Alternate Abilities level if true")
|
RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false, "Ignore Leadership Alternate Abilities level if true")
|
||||||
RULE_BOOL(Spells, FlatItemExtraSpellAmt, false, "Allow SpellDmg stat to affect all spells, regardless of cast time/cooldown/etc")
|
RULE_BOOL(Spells, FlatItemExtraSpellAmt, false, "Allow SpellDmg stat to affect all spells, regardless of cast time/cooldown/etc")
|
||||||
RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false, "Ignore the 5 level spread on applying SpellDmg")
|
RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false, "Ignore the 5 level spread on applying SpellDmg")
|
||||||
@@ -495,6 +503,7 @@ RULE_BOOL(Spells, EvacClearCharmPet, false, "Enable to have evac in zone clear c
|
|||||||
RULE_BOOL(Spells, ManaTapsRequireNPCMana, false, "Enabling will require target to have mana to tap. Default off as many npc's are caster class with 0 mana and need fixed.")
|
RULE_BOOL(Spells, ManaTapsRequireNPCMana, false, "Enabling will require target to have mana to tap. Default off as many npc's are caster class with 0 mana and need fixed.")
|
||||||
RULE_INT(Spells, HarmTouchCritRatio, 200, "Harmtouch crit bonus, on top of BaseCritRatio")
|
RULE_INT(Spells, HarmTouchCritRatio, 200, "Harmtouch crit bonus, on top of BaseCritRatio")
|
||||||
RULE_BOOL(Spells, UseClassicSpellFocus, false, "Enabling will tell the server to handle random focus damage as classic spell imports lack the limit values.")
|
RULE_BOOL(Spells, UseClassicSpellFocus, false, "Enabling will tell the server to handle random focus damage as classic spell imports lack the limit values.")
|
||||||
|
RULE_BOOL(Spells, ManaTapsOnAnyClass, false, "Enabling this will allow you to cast mana taps on any class, this will bypass ManaTapsRequireNPCMana rule.")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Combat)
|
RULE_CATEGORY(Combat)
|
||||||
@@ -521,6 +530,7 @@ RULE_REAL(Combat, BaseProcChance, 0.035, "Base chance for procs")
|
|||||||
RULE_REAL(Combat, ProcDexDivideBy, 11000, "Divisor for the probability of a proc increased by dexterity")
|
RULE_REAL(Combat, ProcDexDivideBy, 11000, "Divisor for the probability of a proc increased by dexterity")
|
||||||
RULE_INT(Combat, MinRangedAttackDist, 25, "Minimum Distance to use Ranged Attacks")
|
RULE_INT(Combat, MinRangedAttackDist, 25, "Minimum Distance to use Ranged Attacks")
|
||||||
RULE_BOOL(Combat, ArcheryBonusRequiresStationary, true, "does the 2x archery bonus chance require a stationary npc")
|
RULE_BOOL(Combat, ArcheryBonusRequiresStationary, true, "does the 2x archery bonus chance require a stationary npc")
|
||||||
|
RULE_INT(Combat, ArcheryBonusLevelRequirement, 51, "Level requirement when the 2x archery bonus will be enabled. The default is 51.")
|
||||||
RULE_REAL(Combat, ArcheryNPCMultiplier, 1.0, "Value is multiplied by the regular dmg to get the archery dmg")
|
RULE_REAL(Combat, ArcheryNPCMultiplier, 1.0, "Value is multiplied by the regular dmg to get the archery dmg")
|
||||||
RULE_BOOL(Combat, AssistNoTargetSelf, true, "When assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like)")
|
RULE_BOOL(Combat, AssistNoTargetSelf, true, "When assisting a target that does not have a target: true = target self, false = leave target as was before assist (false = live like)")
|
||||||
RULE_INT(Combat, MaxRampageTargets, 3, "Maximum number of people hit with rampage")
|
RULE_INT(Combat, MaxRampageTargets, 3, "Maximum number of people hit with rampage")
|
||||||
@@ -569,10 +579,12 @@ RULE_BOOL(Combat, NPCsUseFrontalStunImmunityClasses, false, "Enable or disable N
|
|||||||
RULE_INT(Combat, FrontalStunImmunityRaces, 512, "Bitmask for Races than have frontal stun immunity, Ogre (512) only by default.")
|
RULE_INT(Combat, FrontalStunImmunityRaces, 512, "Bitmask for Races than have frontal stun immunity, Ogre (512) only by default.")
|
||||||
RULE_BOOL(Combat, NPCsUseFrontalStunImmunityRaces, true, "Enable or disable NPCs using frontal stun immunity Races from Combat:FrontalStunImmunityRaces, true by default.")
|
RULE_BOOL(Combat, NPCsUseFrontalStunImmunityRaces, true, "Enable or disable NPCs using frontal stun immunity Races from Combat:FrontalStunImmunityRaces, true by default.")
|
||||||
RULE_BOOL(Combat, AssassinateOnlyHumanoids, true, "Enable or disable Assassinate only being allowed on Humanoids, true by default.")
|
RULE_BOOL(Combat, AssassinateOnlyHumanoids, true, "Enable or disable Assassinate only being allowed on Humanoids, true by default.")
|
||||||
|
RULE_INT(Combat, AssassinateLevelRequirement, 60, "Level requirement to enable assassinate attempts on backstabs. The default is 60.")
|
||||||
RULE_BOOL(Combat, HeadshotOnlyHumanoids, true, "Enable or disable Headshot only being allowed on Humanoids, true by default.")
|
RULE_BOOL(Combat, HeadshotOnlyHumanoids, true, "Enable or disable Headshot only being allowed on Humanoids, true by default.")
|
||||||
RULE_BOOL(Combat, EnableWarriorShielding, true, "Enable or disable Warrior Shielding Ability (/shield), true by default.")
|
RULE_BOOL(Combat, EnableWarriorShielding, true, "Enable or disable Warrior Shielding Ability (/shield), true by default.")
|
||||||
RULE_BOOL(Combat, BackstabIgnoresElemental, false, "Enable or disable Elemental weapon damage affecting backstab damage, false by default.")
|
RULE_BOOL(Combat, BackstabIgnoresElemental, false, "Enable or disable Elemental weapon damage affecting backstab damage, false by default.")
|
||||||
RULE_BOOL(Combat, BackstabIgnoresBane, false, "Enable or disable Bane weapon damage affecting backstab damage, false by default.")
|
RULE_BOOL(Combat, BackstabIgnoresBane, false, "Enable or disable Bane weapon damage affecting backstab damage, false by default.")
|
||||||
|
RULE_INT(Combat, DoubleBackstabLevelRequirement, 55, "Level requirement to enable double backstab attempts. The default is 55.")
|
||||||
RULE_BOOL(Combat, SummonMeleeRange, true, "Enable or disable summoning of a player when already in melee range of the summoner.")
|
RULE_BOOL(Combat, SummonMeleeRange, true, "Enable or disable summoning of a player when already in melee range of the summoner.")
|
||||||
RULE_BOOL(Combat, WaterMatchRequiredForAutoFireLoS, true, "Enable/Disable the requirement of both the attacker/victim being both in or out of water for AutoFire LoS to pass.")
|
RULE_BOOL(Combat, WaterMatchRequiredForAutoFireLoS, true, "Enable/Disable the requirement of both the attacker/victim being both in or out of water for AutoFire LoS to pass.")
|
||||||
RULE_INT(Combat, ExtraAllowedKickClassesBitmask, 0, "Bitmask for allowing extra classes beyond Warrior, Ranger, Beastlord, and Berserker to kick, No Extra Classes (0) by default")
|
RULE_INT(Combat, ExtraAllowedKickClassesBitmask, 0, "Bitmask for allowing extra classes beyond Warrior, Ranger, Beastlord, and Berserker to kick, No Extra Classes (0) by default")
|
||||||
@@ -950,4 +962,5 @@ RULE_CATEGORY_END()
|
|||||||
#undef RULE_INT
|
#undef RULE_INT
|
||||||
#undef RULE_REAL
|
#undef RULE_REAL
|
||||||
#undef RULE_BOOL
|
#undef RULE_BOOL
|
||||||
|
#undef RULE_STRING
|
||||||
#undef RULE_CATEGORY_END
|
#undef RULE_CATEGORY_END
|
||||||
|
|||||||
+3
-2
@@ -348,7 +348,7 @@ std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
|
|||||||
if (ch != startpos)
|
if (ch != startpos)
|
||||||
{
|
{
|
||||||
std::string str(startpos, ch - startpos);
|
std::string str(startpos, ch - startpos);
|
||||||
new_message += EQ::SayLinkEngine::GenerateQuestSaylink(str, false, str);
|
new_message += Saylink::Create(str);
|
||||||
}
|
}
|
||||||
in_bracket_state = false;
|
in_bracket_state = false;
|
||||||
}
|
}
|
||||||
@@ -422,6 +422,7 @@ std::string Saylink::Create(const std::string &saylink_text, bool silent, const
|
|||||||
return EQ::SayLinkEngine::GenerateQuestSaylink(saylink_text, silent, (link_name.empty() ? saylink_text : link_name));
|
return EQ::SayLinkEngine::GenerateQuestSaylink(saylink_text, silent, (link_name.empty() ? saylink_text : link_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Saylink::Silent(const std::string &saylink_text, const std::string &link_name) {
|
std::string Saylink::Silent(const std::string& saylink_text, const std::string& link_name)
|
||||||
|
{
|
||||||
return EQ::SayLinkEngine::GenerateQuestSaylink(saylink_text, true, (link_name.empty() ? saylink_text : link_name));
|
return EQ::SayLinkEngine::GenerateQuestSaylink(saylink_text, true, (link_name.empty() ? saylink_text : link_name));
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -130,7 +130,7 @@ namespace EQ
|
|||||||
|
|
||||||
class Saylink {
|
class Saylink {
|
||||||
public:
|
public:
|
||||||
static std::string Create(const std::string &saylink_text, bool silent, const std::string &link_name = "");
|
static std::string Create(const std::string &saylink_text, bool silent = false, const std::string &link_name = "");
|
||||||
static std::string Silent(const std::string &saylink_text, const std::string &link_name = "");
|
static std::string Silent(const std::string &saylink_text, const std::string &link_name = "");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,7 @@
|
|||||||
#define ServerOP_ReloadFactions 0x4126
|
#define ServerOP_ReloadFactions 0x4126
|
||||||
#define ServerOP_ReloadLoot 0x4127
|
#define ServerOP_ReloadLoot 0x4127
|
||||||
#define ServerOP_ReloadBaseData 0x4128
|
#define ServerOP_ReloadBaseData 0x4128
|
||||||
|
#define ServerOP_ReloadSkillCaps 0x4129
|
||||||
|
|
||||||
#define ServerOP_CZDialogueWindow 0x4500
|
#define ServerOP_CZDialogueWindow 0x4500
|
||||||
#define ServerOP_CZLDoNUpdate 0x4501
|
#define ServerOP_CZLDoNUpdate 0x4501
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ SharedTaskRequest SharedTask::GetRequestCharacters(Database &db, uint32_t reques
|
|||||||
request.group_type = SharedTaskRequestGroupType::Group;
|
request.group_type = SharedTaskRequestGroupType::Group;
|
||||||
auto characters = CharacterDataRepository::GetWhere(
|
auto characters = CharacterDataRepository::GetWhere(
|
||||||
db, fmt::format(
|
db, fmt::format(
|
||||||
"id IN (select charid from group_id where groupid = (select groupid from group_id where charid = {}))",
|
"id IN (select character_id from group_id where group_id = (select group_id from group_id where character_id = {}))",
|
||||||
requested_character_id
|
requested_character_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
+2
-132
@@ -45,6 +45,7 @@
|
|||||||
#include "repositories/loottable_repository.h"
|
#include "repositories/loottable_repository.h"
|
||||||
#include "repositories/character_item_recast_repository.h"
|
#include "repositories/character_item_recast_repository.h"
|
||||||
#include "repositories/character_corpses_repository.h"
|
#include "repositories/character_corpses_repository.h"
|
||||||
|
#include "repositories/skill_caps_repository.h"
|
||||||
|
|
||||||
namespace ItemField
|
namespace ItemField
|
||||||
{
|
{
|
||||||
@@ -793,8 +794,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cv_conflict) {
|
if (cv_conflict) {
|
||||||
char char_name[64] = "";
|
const std::string& char_name = GetCharName(char_id);
|
||||||
GetCharName(char_id, char_name);
|
|
||||||
LogError("ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
|
LogError("ClientVersion/Expansion conflict during inventory load at zone entry for [{}] (charid: [{}], inver: [{}], gmi: [{}])",
|
||||||
char_name,
|
char_name,
|
||||||
char_id,
|
char_id,
|
||||||
@@ -1626,136 +1626,6 @@ bool SharedDatabase::GetCommandSubSettings(std::vector<CommandSubsettingsReposit
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
|
||||||
skill_caps_mmf.reset(nullptr);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const auto Config = EQEmuConfig::get();
|
|
||||||
EQ::IPCMutex mutex("skill_caps");
|
|
||||||
mutex.Lock();
|
|
||||||
std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("skill_caps"));
|
|
||||||
LogInfo("Loading [{}]", file_name);
|
|
||||||
skill_caps_mmf = std::make_unique<EQ::MemoryMappedFile>(file_name);
|
|
||||||
|
|
||||||
LogInfo("Loaded skill caps via shared memory");
|
|
||||||
|
|
||||||
mutex.Unlock();
|
|
||||||
} catch(std::exception &ex) {
|
|
||||||
LogError("Error loading skill caps: {}", ex.what());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedDatabase::LoadSkillCaps(void *data) {
|
|
||||||
const uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
|
||||||
const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
|
||||||
const uint32 level_count = HARD_LEVEL_CAP + 1;
|
|
||||||
uint16 *skill_caps_table = static_cast<uint16*>(data);
|
|
||||||
|
|
||||||
const std::string query = "SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level";
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
|
||||||
LogError("Error loading skill caps from database: {}", results.ErrorMessage().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& row = results.begin(); row != results.end(); ++row) {
|
|
||||||
const uint8 skillID = Strings::ToUnsignedInt(row[0]);
|
|
||||||
const uint8 class_ = Strings::ToUnsignedInt(row[1]) - 1;
|
|
||||||
const uint8 level = Strings::ToUnsignedInt(row[2]);
|
|
||||||
const uint16 cap = Strings::ToUnsignedInt(row[3]);
|
|
||||||
|
|
||||||
if(skillID >= skill_count || class_ >= class_count || level >= level_count)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const uint32 index = (((class_ * skill_count) + skillID) * level_count) + level;
|
|
||||||
skill_caps_table[index] = cap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 SharedDatabase::GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const
|
|
||||||
{
|
|
||||||
if(!skill_caps_mmf) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Class_ == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel);
|
|
||||||
if(SkillMaxLevel < 1) {
|
|
||||||
SkillMaxLevel = RuleI(Character, MaxLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
|
||||||
const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
|
||||||
const uint32 level_count = HARD_LEVEL_CAP + 1;
|
|
||||||
if(Class_ > class_count || static_cast<uint32>(Skill) > skill_count || Level > level_count) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Level > static_cast<uint8>(SkillMaxLevel)){
|
|
||||||
Level = static_cast<uint8>(SkillMaxLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count) + Level;
|
|
||||||
const uint16 *skill_caps_table = static_cast<uint16*>(skill_caps_mmf->Get());
|
|
||||||
return skill_caps_table[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const
|
|
||||||
{
|
|
||||||
if(!skill_caps_mmf) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Class_ == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel);
|
|
||||||
if (SkillMaxLevel < 1) {
|
|
||||||
SkillMaxLevel = RuleI(Character, MaxLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
|
||||||
const uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
|
||||||
const uint32 level_count = HARD_LEVEL_CAP + 1;
|
|
||||||
if(Class_ > class_count || static_cast<uint32>(Skill) > skill_count || Level > level_count) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 ret = 0;
|
|
||||||
if(Level > static_cast<uint8>(SkillMaxLevel)) {
|
|
||||||
const uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count);
|
|
||||||
const uint16 *skill_caps_table = static_cast<uint16*>(skill_caps_mmf->Get());
|
|
||||||
for(uint8 x = 0; x < Level; x++){
|
|
||||||
if(skill_caps_table[index + x]){
|
|
||||||
ret = x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count);
|
|
||||||
const uint16 *skill_caps_table = static_cast<uint16*>(skill_caps_mmf->Get());
|
|
||||||
for(int x = 0; x < SkillMaxLevel; x++){
|
|
||||||
if(skill_caps_table[index + x]){
|
|
||||||
ret = x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ret > GetSkillCap(Class_, Skill, Level))
|
|
||||||
ret = static_cast<uint8>(GetSkillCap(Class_, Skill, Level));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) {
|
void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) {
|
||||||
const std::string query = StringFormat("SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 "
|
const std::string query = StringFormat("SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 "
|
||||||
"AND `spellid` <= %i", iMaxSpellID);
|
"AND `spellid` <= %i", iMaxSpellID);
|
||||||
|
|||||||
@@ -160,14 +160,6 @@ public:
|
|||||||
uint32 GetSharedItemsCount() { return m_shared_items_count; }
|
uint32 GetSharedItemsCount() { return m_shared_items_count; }
|
||||||
uint32 GetItemsCount();
|
uint32 GetItemsCount();
|
||||||
|
|
||||||
/**
|
|
||||||
* skills
|
|
||||||
*/
|
|
||||||
void LoadSkillCaps(void *data);
|
|
||||||
bool LoadSkillCaps(const std::string &prefix);
|
|
||||||
uint16 GetSkillCap(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const;
|
|
||||||
uint8 GetTrainLevel(uint8 Class_, EQ::skills::SkillType Skill, uint8 Level) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* spells
|
* spells
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#include "skill_caps.h"
|
||||||
|
|
||||||
|
SkillCaps *SkillCaps::SetContentDatabase(Database *db)
|
||||||
|
{
|
||||||
|
m_content_database = db;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkillCapsRepository::SkillCaps SkillCaps::GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
||||||
|
{
|
||||||
|
if (!IsPlayerClass(class_id)) {
|
||||||
|
return SkillCapsRepository::NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &e: m_skill_caps) {
|
||||||
|
if (
|
||||||
|
e.class_id == class_id &&
|
||||||
|
e.level == level &&
|
||||||
|
static_cast<EQ::skills::SkillType>(e.skill_id) == skill_id
|
||||||
|
) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SkillCapsRepository::NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 SkillCaps::GetTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
!IsPlayerClass(class_id) ||
|
||||||
|
class_id > Class::PLAYER_CLASS_COUNT ||
|
||||||
|
static_cast<uint32>(skill_id) > (EQ::skills::HIGHEST_SKILL + 1)
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8 skill_cap_max_level = (
|
||||||
|
RuleI(Character, SkillCapMaxLevel) > 0 ?
|
||||||
|
RuleI(Character, SkillCapMaxLevel) :
|
||||||
|
RuleI(Character, MaxLevel)
|
||||||
|
);
|
||||||
|
|
||||||
|
const uint8 max_level = level > skill_cap_max_level ? level : skill_cap_max_level;
|
||||||
|
|
||||||
|
for (const auto &e: m_skill_caps) {
|
||||||
|
for (uint8 current_level = 1; current_level <= max_level; current_level++) {
|
||||||
|
if (
|
||||||
|
e.class_id == class_id &&
|
||||||
|
static_cast<EQ::skills::SkillType>(e.skill_id) == skill_id &&
|
||||||
|
e.level == current_level
|
||||||
|
) {
|
||||||
|
return current_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkillCaps::LoadSkillCaps()
|
||||||
|
{
|
||||||
|
const auto &l = SkillCapsRepository::All(*m_content_database);
|
||||||
|
|
||||||
|
m_skill_caps.reserve(l.size());
|
||||||
|
|
||||||
|
for (const auto &e: l) {
|
||||||
|
if (
|
||||||
|
e.level < 1 ||
|
||||||
|
!IsPlayerClass(e.class_id) ||
|
||||||
|
static_cast<EQ::skills::SkillType>(e.skill_id) >= EQ::skills::SkillCount
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_skill_caps.emplace_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Loaded [{}] Skill Cap Entr{}",
|
||||||
|
l.size(),
|
||||||
|
l.size() != 1 ? "ies" : "y"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkillCaps::ReloadSkillCaps()
|
||||||
|
{
|
||||||
|
ClearSkillCaps();
|
||||||
|
LoadSkillCaps();
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef CODE_SKILL_CAPS_H
|
||||||
|
#define CODE_SKILL_CAPS_H
|
||||||
|
|
||||||
|
#include "repositories/skill_caps_repository.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "classes.h"
|
||||||
|
#include "skills.h"
|
||||||
|
|
||||||
|
class SkillCaps {
|
||||||
|
public:
|
||||||
|
inline void ClearSkillCaps() { m_skill_caps.clear(); }
|
||||||
|
SkillCapsRepository::SkillCaps GetSkillCap(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
||||||
|
uint8 GetTrainLevel(uint8 class_id, EQ::skills::SkillType skill_id, uint8 level);
|
||||||
|
void LoadSkillCaps();
|
||||||
|
void ReloadSkillCaps();
|
||||||
|
|
||||||
|
SkillCaps *SetContentDatabase(Database *db);
|
||||||
|
private:
|
||||||
|
Database *m_content_database{};
|
||||||
|
std::vector<SkillCapsRepository::SkillCaps> m_skill_caps = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SkillCaps skill_caps;
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CODE_SKILL_CAPS_H
|
||||||
+1
-1
@@ -18,10 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "skills.h"
|
#include "skills.h"
|
||||||
|
#include "classes.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
bool EQ::skills::IsTradeskill(SkillType skill)
|
bool EQ::skills::IsTradeskill(SkillType skill)
|
||||||
{
|
{
|
||||||
switch (skill) {
|
switch (skill) {
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ
|
||||||
{
|
{
|
||||||
namespace skills {
|
namespace skills {
|
||||||
|
|||||||
+1
-1
@@ -1257,7 +1257,7 @@ typedef enum {
|
|||||||
#define SE_Ff_Override_NotFocusable 460 // implemented, @Fc, Allow spell to be focused event if flagged with 'not_focusable' in spell table, base: 1
|
#define SE_Ff_Override_NotFocusable 460 // implemented, @Fc, Allow spell to be focused event if flagged with 'not_focusable' in spell table, base: 1
|
||||||
#define SE_ImprovedDamage2 461 // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct
|
#define SE_ImprovedDamage2 461 // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct
|
||||||
#define SE_FcDamageAmt2 462 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt
|
#define SE_FcDamageAmt2 462 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt
|
||||||
//#define SE_Shield_Target 463 //
|
#define SE_Shield_Target 463 // implemented, Base1 % damage shielded on target
|
||||||
#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round
|
#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round
|
||||||
#define SE_PC_Pet_AE_Rampage 465 // implemented - Base1 % chance to do AE rampage for base2 % of damage each melee round
|
#define SE_PC_Pet_AE_Rampage 465 // implemented - Base1 % chance to do AE rampage for base2 % of damage each melee round
|
||||||
#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit.
|
#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit.
|
||||||
|
|||||||
+2
-2
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// Build variables
|
// Build variables
|
||||||
// these get injected during the build pipeline
|
// these get injected during the build pipeline
|
||||||
#define CURRENT_VERSION "22.45.1-dev" // always append -dev to the current version for custom-builds
|
#define CURRENT_VERSION "22.48.0-dev" // always append -dev to the current version for custom-builds
|
||||||
#define LOGIN_VERSION "0.8.0"
|
#define LOGIN_VERSION "0.8.0"
|
||||||
#define COMPILE_DATE __DATE__
|
#define COMPILE_DATE __DATE__
|
||||||
#define COMPILE_TIME __TIME__
|
#define COMPILE_TIME __TIME__
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9264
|
#define CURRENT_BINARY_DATABASE_VERSION 9268
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9043
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9043
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+234
-900
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eqemu-server",
|
"name": "eqemu-server",
|
||||||
"version": "22.45.1",
|
"version": "22.48.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EQEmu/Server.git"
|
"url": "https://github.com/EQEmu/Server.git"
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Description
|
||||||
|
|
||||||
|
Please include a summary of the changes and the related issue (Why is this change necessary). Please also include relevant motivation and context. List any dependencies that are required for this change.
|
||||||
|
|
||||||
|
Fixes # (issue)
|
||||||
|
|
||||||
|
## Type of change
|
||||||
|
|
||||||
|
Please delete options that are not relevant.
|
||||||
|
|
||||||
|
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||||
|
- [ ] New feature (non-breaking change which adds functionality)
|
||||||
|
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||||
|
- [ ] This change requires a documentation update
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
|
||||||
|
Attach images and describe testing done to validate functionality.
|
||||||
|
|
||||||
|
Clients tested:
|
||||||
|
|
||||||
|
# Checklist
|
||||||
|
|
||||||
|
- [ ] I have tested my changes
|
||||||
|
- [ ] I have performed a self-review of my code. Ensuring variables, functions and methods are named in a human-readable way, comments are added only where naming of variables, functions and methods can't give enough context.
|
||||||
|
- [ ] I have made corresponding changes to the documentation (if applicable, if not delete this line)
|
||||||
|
- [ ] I own the changes of my code and take responsibility for the potential issues that occur
|
||||||
|
- [ ] If my changes make database schema changes, I have tested the changes on a local database (attach image). Updated version.h CURRENT_BINARY_DATABASE_VERSION to the new version. (Delete this if not applicable)
|
||||||
@@ -4,13 +4,11 @@ SET(shared_memory_sources
|
|||||||
items.cpp
|
items.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
spells.cpp
|
spells.cpp
|
||||||
skill_caps.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(shared_memory_headers
|
SET(shared_memory_headers
|
||||||
items.h
|
items.h
|
||||||
spells.h
|
spells.h
|
||||||
skill_caps.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_EXECUTABLE(shared_memory ${shared_memory_sources} ${shared_memory_headers})
|
ADD_EXECUTABLE(shared_memory ${shared_memory_sources} ${shared_memory_headers})
|
||||||
|
|||||||
+1
-17
@@ -28,7 +28,6 @@
|
|||||||
#include "../common/eqemu_exception.h"
|
#include "../common/eqemu_exception.h"
|
||||||
#include "../common/strings.h"
|
#include "../common/strings.h"
|
||||||
#include "items.h"
|
#include "items.h"
|
||||||
#include "skill_caps.h"
|
|
||||||
#include "spells.h"
|
#include "spells.h"
|
||||||
#include "../common/content/world_content_service.h"
|
#include "../common/content/world_content_service.h"
|
||||||
#include "../common/zone_store.h"
|
#include "../common/zone_store.h"
|
||||||
@@ -183,7 +182,6 @@ int main(int argc, char **argv)
|
|||||||
bool load_all = true;
|
bool load_all = true;
|
||||||
bool load_items = false;
|
bool load_items = false;
|
||||||
bool load_loot = false;
|
bool load_loot = false;
|
||||||
bool load_skill_caps = false;
|
|
||||||
bool load_spells = false;
|
bool load_spells = false;
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
@@ -197,11 +195,7 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
if (strcasecmp("skill_caps", argv[i]) == 0) {
|
if (strcasecmp("spells", argv[i]) == 0) {
|
||||||
load_skill_caps = true;
|
|
||||||
load_all = false;
|
|
||||||
}
|
|
||||||
else if (strcasecmp("spells", argv[i]) == 0) {
|
|
||||||
load_spells = true;
|
load_spells = true;
|
||||||
load_all = false;
|
load_all = false;
|
||||||
}
|
}
|
||||||
@@ -236,16 +230,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_all || load_skill_caps) {
|
|
||||||
LogInfo("Loading skill caps");
|
|
||||||
try {
|
|
||||||
LoadSkillCaps(&content_db, hotfix_name);
|
|
||||||
} catch (std::exception &ex) {
|
|
||||||
LogError("{}", ex.what());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (load_all || load_spells) {
|
if (load_all || load_spells) {
|
||||||
LogInfo("Loading spells");
|
LogInfo("Loading spells");
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
||||||
are required to give you total support for your newly bought product;
|
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "skill_caps.h"
|
|
||||||
#include "../common/global_define.h"
|
|
||||||
#include "../common/shareddb.h"
|
|
||||||
#include "../common/ipc_mutex.h"
|
|
||||||
#include "../common/memory_mapped_file.h"
|
|
||||||
#include "../common/eqemu_exception.h"
|
|
||||||
#include "../common/classes.h"
|
|
||||||
#include "../common/features.h"
|
|
||||||
|
|
||||||
void LoadSkillCaps(SharedDatabase *database, const std::string &prefix) {
|
|
||||||
EQ::IPCMutex mutex("skill_caps");
|
|
||||||
mutex.Lock();
|
|
||||||
|
|
||||||
uint32 class_count = Class::PLAYER_CLASS_COUNT;
|
|
||||||
uint32 skill_count = EQ::skills::HIGHEST_SKILL + 1;
|
|
||||||
uint32 level_count = HARD_LEVEL_CAP + 1;
|
|
||||||
uint32 size = (class_count * skill_count * level_count * sizeof(uint16));
|
|
||||||
|
|
||||||
auto Config = EQEmuConfig::get();
|
|
||||||
std::string file_name = Config->SharedMemDir + prefix + std::string("skill_caps");
|
|
||||||
EQ::MemoryMappedFile mmf(file_name, size);
|
|
||||||
mmf.ZeroFile();
|
|
||||||
|
|
||||||
void *ptr = mmf.Get();
|
|
||||||
database->LoadSkillCaps(ptr);
|
|
||||||
mutex.Unlock();
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
||||||
are required to give you total support for your newly bought product;
|
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __EQEMU_SHARED_MEMORY_SKILL_CAPS_H
|
|
||||||
#define __EQEMU_SHARED_MEMORY_SKILL_CAPS_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "../common/eqemu_config.h"
|
|
||||||
|
|
||||||
class SharedDatabase;
|
|
||||||
void LoadSkillCaps(SharedDatabase *database, const std::string &prefix);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ foreach my $table_to_generate (@tables) {
|
|||||||
|
|
||||||
# column names (string)
|
# column names (string)
|
||||||
$column_names_quoted .= sprintf("\t\t\t\"%s\",\n", format_column_name_for_mysql($column_name));
|
$column_names_quoted .= sprintf("\t\t\t\"%s\",\n", format_column_name_for_mysql($column_name));
|
||||||
if ($data_type =~ /datetime/) {
|
if ($data_type =~ /datetime|timestamp/) {
|
||||||
$select_column_names_quoted .= sprintf("\t\t\t\"UNIX_TIMESTAMP(%s)\",\n", format_column_name_for_mysql($column_name));
|
$select_column_names_quoted .= sprintf("\t\t\t\"UNIX_TIMESTAMP(%s)\",\n", format_column_name_for_mysql($column_name));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -293,7 +293,7 @@ foreach my $table_to_generate (@tables) {
|
|||||||
if ($data_type =~ /int|float|double|decimal/) {
|
if ($data_type =~ /int|float|double|decimal/) {
|
||||||
$query_value = sprintf('" + std::to_string(e.%s));', $column_name_formatted);
|
$query_value = sprintf('" + std::to_string(e.%s));', $column_name_formatted);
|
||||||
}
|
}
|
||||||
elsif ($data_type =~ /datetime/) {
|
elsif ($data_type =~ /datetime|timestamp/) {
|
||||||
$query_value = sprintf('FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")");', $column_name_formatted, $column_name_formatted);
|
$query_value = sprintf('FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")");', $column_name_formatted, $column_name_formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +309,7 @@ foreach my $table_to_generate (@tables) {
|
|||||||
if ($data_type =~ /int|float|double|decimal/) {
|
if ($data_type =~ /int|float|double|decimal/) {
|
||||||
$value = sprintf('std::to_string(e.%s)', $column_name_formatted);
|
$value = sprintf('std::to_string(e.%s)', $column_name_formatted);
|
||||||
}
|
}
|
||||||
elsif ($data_type =~ /datetime/) {
|
elsif ($data_type =~ /datetime|timestamp/) {
|
||||||
$value = sprintf('"FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")"', $column_name_formatted, $column_name_formatted);
|
$value = sprintf('"FROM_UNIXTIME(" + (e.%s > 0 ? std::to_string(e.%s) : "null") + ")"', $column_name_formatted, $column_name_formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ foreach my $table_to_generate (@tables) {
|
|||||||
$all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? strtoll(row[%s], nullptr, 10) : %s;\n", $column_name_formatted, $index, $index, $default_value);
|
$all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? strtoll(row[%s], nullptr, 10) : %s;\n", $column_name_formatted, $index, $index, $default_value);
|
||||||
$find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? strtoll(row[%s], nullptr, 10) : %s;\n", $column_name_formatted, $index, $index, $default_value);
|
$find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = row[%s] ? strtoll(row[%s], nullptr, 10) : %s;\n", $column_name_formatted, $index, $index, $default_value);
|
||||||
}
|
}
|
||||||
elsif ($data_type =~ /datetime/) {
|
elsif ($data_type =~ /datetime|timestamp/) {
|
||||||
$all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index);
|
$all_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index);
|
||||||
$find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index);
|
$find_one_entries .= sprintf("\t\t\te.%-${longest_column_length}s = strtoll(row[%s] ? row[%s] : \"-1\", nullptr, 10);\n", $column_name_formatted, $index, $index);
|
||||||
}
|
}
|
||||||
@@ -591,7 +591,7 @@ sub translate_mysql_data_type_to_c
|
|||||||
elsif ($mysql_data_type =~ /double/) {
|
elsif ($mysql_data_type =~ /double/) {
|
||||||
$struct_data_type = 'double';
|
$struct_data_type = 'double';
|
||||||
}
|
}
|
||||||
elsif ($mysql_data_type =~ /datetime/) {
|
elsif ($mysql_data_type =~ /datetime|timestamp/) {
|
||||||
$struct_data_type = 'time_t';
|
$struct_data_type = 'time_t';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+62
-16
@@ -52,6 +52,10 @@
|
|||||||
#include "../common/repositories/player_event_logs_repository.h"
|
#include "../common/repositories/player_event_logs_repository.h"
|
||||||
#include "../common/repositories/inventory_repository.h"
|
#include "../common/repositories/inventory_repository.h"
|
||||||
#include "../common/events/player_event_logs.h"
|
#include "../common/events/player_event_logs.h"
|
||||||
|
#include "../common/content/world_content_service.h"
|
||||||
|
#include "../common/repositories/group_id_repository.h"
|
||||||
|
#include "../common/repositories/character_data_repository.h"
|
||||||
|
#include "../common/skill_caps.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -189,9 +193,10 @@ bool Client::CanTradeFVNoDropItem()
|
|||||||
|
|
||||||
void Client::SendEnterWorld(std::string name)
|
void Client::SendEnterWorld(std::string name)
|
||||||
{
|
{
|
||||||
char char_name[64] = { 0 };
|
std::string live_name {};
|
||||||
if (is_player_zoning && database.GetLiveChar(GetAccountID(), char_name)) {
|
if (is_player_zoning) {
|
||||||
if(database.GetAccountIDByChar(char_name) != GetAccountID()) {
|
live_name = database.GetLiveChar(GetAccountID());
|
||||||
|
if(database.GetAccountIDByChar(live_name) != GetAccountID()) {
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@@ -199,8 +204,8 @@ void Client::SendEnterWorld(std::string name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_EnterWorld, strlen(char_name) + 1);
|
auto outapp = new EQApplicationPacket(OP_EnterWorld, live_name.length() + 1);
|
||||||
memcpy(outapp->pBuffer,char_name,strlen(char_name)+1);
|
memcpy(outapp->pBuffer, live_name.c_str(), live_name.length() + 1);
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
@@ -763,21 +768,50 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||||||
auto ew = (EnterWorld_Struct *) app->pBuffer;
|
auto ew = (EnterWorld_Struct *) app->pBuffer;
|
||||||
strn0cpy(char_name, ew->name, sizeof(char_name));
|
strn0cpy(char_name, ew->name, sizeof(char_name));
|
||||||
|
|
||||||
uint32 temporary_account_id = 0;
|
const auto& l = CharacterDataRepository::GetWhere(
|
||||||
charid = database.GetCharacterInfo(char_name, &temporary_account_id, &zone_id, &instance_id);
|
database,
|
||||||
if (!charid) {
|
fmt::format(
|
||||||
|
"`name` = '{}' LIMIT 1",
|
||||||
|
Strings::Escape(char_name)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (l.empty()) {
|
||||||
LogInfo("Could not get CharInfo for [{}]", char_name);
|
LogInfo("Could not get CharInfo for [{}]", char_name);
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto r = content_service.FindZone(zone_id, instance_id);
|
||||||
|
if (r.zone_id && r.instance.id != instance_id) {
|
||||||
|
LogInfo(
|
||||||
|
"Zone [{}] has been remapped to instance_id [{}] from instance_id [{}] for client [{}]",
|
||||||
|
r.zone.short_name,
|
||||||
|
r.instance.id,
|
||||||
|
instance_id,
|
||||||
|
char_name
|
||||||
|
);
|
||||||
|
instance_id = r.instance.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& e = l.front();
|
||||||
|
|
||||||
// Make sure this account owns this character
|
// Make sure this account owns this character
|
||||||
if (temporary_account_id != account_id) {
|
if (e.account_id != account_id) {
|
||||||
LogInfo("Account [{}] does not own the character named [{}] from account [{}]", account_id, char_name, temporary_account_id);
|
LogInfo(
|
||||||
|
"Account [{}] does not own the character named [{}] from account [{}]",
|
||||||
|
account_id,
|
||||||
|
char_name,
|
||||||
|
e.account_id
|
||||||
|
);
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
charid = e.id;
|
||||||
|
zone_id = e.zone_id;
|
||||||
|
instance_id = e.zone_instance;
|
||||||
|
|
||||||
// This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above)
|
// This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above)
|
||||||
// (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration)
|
// (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration)
|
||||||
if (!is_player_zoning) {
|
if (!is_player_zoning) {
|
||||||
@@ -868,7 +902,14 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!is_player_zoning) {
|
if(!is_player_zoning) {
|
||||||
database.SetGroupID(char_name, 0, charid);
|
GroupIdRepository::DeleteWhere(
|
||||||
|
database,
|
||||||
|
fmt::format(
|
||||||
|
"`character_id` = {} AND `name` = '{}'",
|
||||||
|
charid,
|
||||||
|
Strings::Escape(char_name)
|
||||||
|
)
|
||||||
|
);
|
||||||
database.SetLoginFlags(charid, false, false, 1);
|
database.SetLoginFlags(charid, false, false, 1);
|
||||||
} else {
|
} else {
|
||||||
auto group_id = database.GetGroupID(char_name);
|
auto group_id = database.GetGroupID(char_name);
|
||||||
@@ -887,12 +928,17 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_MOTD);
|
auto outapp = new EQApplicationPacket(OP_MOTD);
|
||||||
std::string motd_message;
|
std::string motd = RuleS(World, MOTD);
|
||||||
if (database.GetVariable("MOTD", motd_message)) {
|
if (!motd.empty()) {
|
||||||
outapp->size = motd_message.length() + 1;
|
outapp->size = motd.length() + 1;
|
||||||
outapp->pBuffer = new uchar[outapp->size];
|
outapp->pBuffer = new uchar[outapp->size];
|
||||||
memset(outapp->pBuffer, 0, outapp->size);
|
memset(outapp->pBuffer, 0, outapp->size);
|
||||||
strcpy((char*)outapp->pBuffer, motd_message.c_str());
|
strcpy((char*) outapp->pBuffer, motd.c_str());
|
||||||
|
} else if (database.GetVariable("MOTD", motd)) {
|
||||||
|
outapp->size = motd.length() + 1;
|
||||||
|
outapp->pBuffer = new uchar[outapp->size];
|
||||||
|
memset(outapp->pBuffer, 0, outapp->size);
|
||||||
|
strcpy((char*) outapp->pBuffer, motd.c_str());
|
||||||
} else { // Null Message of the Day. :)
|
} else { // Null Message of the Day. :)
|
||||||
outapp->size = 1;
|
outapp->size = 1;
|
||||||
outapp->pBuffer = new uchar[outapp->size];
|
outapp->pBuffer = new uchar[outapp->size];
|
||||||
@@ -2089,7 +2135,7 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
|
|||||||
i == EQ::skills::SkillAlcoholTolerance || i == EQ::skills::SkillBindWound)
|
i == EQ::skills::SkillAlcoholTolerance || i == EQ::skills::SkillBindWound)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pp->skills[i] = content_db.GetSkillCap(pp->class_, (EQ::skills::SkillType)i, 1);
|
pp->skills[i] = skill_caps.GetSkillCap(pp->class_, (EQ::skills::SkillType)i, 1).cap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_p
|
|||||||
|
|
||||||
paccountid = database.CreateAccount(
|
paccountid = database.CreateAccount(
|
||||||
loginserver_account_name,
|
loginserver_account_name,
|
||||||
0,
|
std::string(),
|
||||||
default_account_status,
|
default_account_status,
|
||||||
source_loginserver,
|
source_loginserver,
|
||||||
LSID()
|
LSID()
|
||||||
|
|||||||
@@ -94,8 +94,25 @@ void ClientList::GetCLEIP(uint32 in_ip) {
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
iterator.Reset();
|
iterator.Reset();
|
||||||
|
|
||||||
|
const auto& zones = Strings::Split(RuleS(World, IPExemptionZones), ",");
|
||||||
|
|
||||||
while (iterator.MoreElements()) {
|
while (iterator.MoreElements()) {
|
||||||
cle = iterator.GetData();
|
cle = iterator.GetData();
|
||||||
|
|
||||||
|
if (!zones.empty() && cle->zone()) {
|
||||||
|
auto it = std::ranges::find_if(
|
||||||
|
zones,
|
||||||
|
[cle](const auto& z) {
|
||||||
|
return Strings::ToUnsignedInt(z) == cle->zone();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (it != zones.end()) {
|
||||||
|
iterator.Advance();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
cle->GetIP() == in_ip &&
|
cle->GetIP() == in_ip &&
|
||||||
(
|
(
|
||||||
|
|||||||
+1
-2
@@ -57,8 +57,7 @@ struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string &username, const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char account_name[64];
|
const std::string& account_name = database.GetAccountName(ret.account_id);
|
||||||
database.GetAccountName(ret.account_id, account_name);
|
|
||||||
|
|
||||||
ret.account_name = account_name;
|
ret.account_name = account_name;
|
||||||
ret.status = database.CheckStatus(ret.account_id);
|
ret.status = database.CheckStatus(ret.account_id);
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ std::vector<Reload> reload_types = {
|
|||||||
Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"},
|
Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"},
|
||||||
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
|
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
|
||||||
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
|
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
|
||||||
|
Reload{.command = "content_flags", .opcode = ServerOP_ReloadContentFlags, .desc = "Content Flags"},
|
||||||
Reload{.command = "data_buckets_cache", .opcode = ServerOP_ReloadDataBucketsCache, .desc = "Data Buckets Cache"},
|
Reload{.command = "data_buckets_cache", .opcode = ServerOP_ReloadDataBucketsCache, .desc = "Data Buckets Cache"},
|
||||||
Reload{.command = "doors", .opcode = ServerOP_ReloadDoors, .desc = "Doors"},
|
Reload{.command = "doors", .opcode = ServerOP_ReloadDoors, .desc = "Doors"},
|
||||||
Reload{.command = "dztemplates", .opcode = ServerOP_ReloadDzTemplates, .desc = "Dynamic Zone Templates"},
|
Reload{.command = "dztemplates", .opcode = ServerOP_ReloadDzTemplates, .desc = "Dynamic Zone Templates"},
|
||||||
@@ -155,6 +156,7 @@ std::vector<Reload> reload_types = {
|
|||||||
Reload{.command = "opcodes", .opcode = ServerOP_ReloadOpcodes, .desc = "Opcodes"},
|
Reload{.command = "opcodes", .opcode = ServerOP_ReloadOpcodes, .desc = "Opcodes"},
|
||||||
Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"},
|
Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"},
|
||||||
Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"},
|
Reload{.command = "rules", .opcode = ServerOP_ReloadRules, .desc = "Rules"},
|
||||||
|
Reload{.command = "skill_caps", .opcode = ServerOP_ReloadSkillCaps, .desc = "Skill Caps"},
|
||||||
Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"},
|
Reload{.command = "static", .opcode = ServerOP_ReloadStaticZoneData, .desc = "Static Zone Data"},
|
||||||
Reload{.command = "tasks", .opcode = ServerOP_ReloadTasks, .desc = "Tasks"},
|
Reload{.command = "tasks", .opcode = ServerOP_ReloadTasks, .desc = "Tasks"},
|
||||||
Reload{.command = "titles", .opcode = ServerOP_ReloadTitles, .desc = "Titles"},
|
Reload{.command = "titles", .opcode = ServerOP_ReloadTitles, .desc = "Titles"},
|
||||||
|
|||||||
+9
-1
@@ -86,8 +86,9 @@
|
|||||||
#include "world_boot.h"
|
#include "world_boot.h"
|
||||||
#include "../common/path_manager.h"
|
#include "../common/path_manager.h"
|
||||||
#include "../common/events/player_event_logs.h"
|
#include "../common/events/player_event_logs.h"
|
||||||
|
#include "../common/skill_caps.h"
|
||||||
|
|
||||||
|
SkillCaps skill_caps;
|
||||||
ZoneStore zone_store;
|
ZoneStore zone_store;
|
||||||
ClientList client_list;
|
ClientList client_list;
|
||||||
GroupLFPList LFPGroupList;
|
GroupLFPList LFPGroupList;
|
||||||
@@ -188,6 +189,13 @@ int main(int argc, char **argv)
|
|||||||
RegisterConsoleFunctions(console);
|
RegisterConsoleFunctions(console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content_service.SetDatabase(&database)
|
||||||
|
->SetContentDatabase(&content_db)
|
||||||
|
->SetExpansionContext()
|
||||||
|
->ReloadContentFlags();
|
||||||
|
|
||||||
|
skill_caps.SetContentDatabase(&content_db)->LoadSkillCaps();
|
||||||
|
|
||||||
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
||||||
server_connection = std::make_unique<EQ::Net::ServertalkServer>();
|
server_connection = std::make_unique<EQ::Net::ServertalkServer>();
|
||||||
|
|
||||||
|
|||||||
@@ -292,10 +292,6 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
|
|||||||
LogError("Error: Could not load item data. But ignoring");
|
LogError("Error: Could not load item data. But ignoring");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!content_db.LoadSkillCaps(std::string(hotfix_name))) {
|
|
||||||
LogError("Error: Could not load skill cap data. But ignoring");
|
|
||||||
}
|
|
||||||
|
|
||||||
guild_mgr.LoadGuilds();
|
guild_mgr.LoadGuilds();
|
||||||
guild_mgr.LoadTributes();
|
guild_mgr.LoadTributes();
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "../common/patches/patches.h"
|
#include "../common/patches/patches.h"
|
||||||
#include "../zone/data_bucket.h"
|
#include "../zone/data_bucket.h"
|
||||||
#include "../common/repositories/guild_tributes_repository.h"
|
#include "../common/repositories/guild_tributes_repository.h"
|
||||||
|
#include "../common/skill_caps.h"
|
||||||
|
|
||||||
extern ClientList client_list;
|
extern ClientList client_list;
|
||||||
extern GroupLFPList LFPGroupList;
|
extern GroupLFPList LFPGroupList;
|
||||||
@@ -1100,7 +1101,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto smotd = (ServerMotd_Struct*) pack->pBuffer;
|
auto smotd = (ServerMotd_Struct*) pack->pBuffer;
|
||||||
database.SetVariable("MOTD", smotd->motd);
|
RuleManager::Instance()->SetRule("MOTD", smotd->motd, &database, true, true);
|
||||||
zoneserver_list.SendPacket(pack);
|
zoneserver_list.SendPacket(pack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1436,6 +1437,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
zoneserver_list.SendPacket(pack);
|
zoneserver_list.SendPacket(pack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_ReloadSkillCaps: {
|
||||||
|
zoneserver_list.SendPacket(pack);
|
||||||
|
skill_caps.ReloadSkillCaps();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ServerOP_ReloadRules: {
|
case ServerOP_ReloadRules: {
|
||||||
zoneserver_list.SendPacket(pack);
|
zoneserver_list.SendPacket(pack);
|
||||||
RuleManager::Instance()->LoadRules(&database, "default", true);
|
RuleManager::Instance()->LoadRules(&database, "default", true);
|
||||||
@@ -1496,11 +1502,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
LogInfo("Error: Could not load item data. But ignoring");
|
LogInfo("Error: Could not load item data. But ignoring");
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Loading skill caps");
|
|
||||||
if (!content_db.LoadSkillCaps(hotfix_name)) {
|
|
||||||
LogInfo("Error: Could not load skill cap data. But ignoring");
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneserver_list.SendPacket(pack);
|
zoneserver_list.SendPacket(pack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ SET(zone_sources
|
|||||||
loot.cpp
|
loot.cpp
|
||||||
lua_bot.cpp
|
lua_bot.cpp
|
||||||
lua_bit.cpp
|
lua_bit.cpp
|
||||||
|
lua_buff.cpp
|
||||||
lua_corpse.cpp
|
lua_corpse.cpp
|
||||||
lua_client.cpp
|
lua_client.cpp
|
||||||
lua_door.cpp
|
lua_door.cpp
|
||||||
@@ -105,6 +106,7 @@ SET(zone_sources
|
|||||||
pathfinder_null.cpp
|
pathfinder_null.cpp
|
||||||
pathing.cpp
|
pathing.cpp
|
||||||
perl_bot.cpp
|
perl_bot.cpp
|
||||||
|
perl_buff.cpp
|
||||||
perl_client.cpp
|
perl_client.cpp
|
||||||
perl_doors.cpp
|
perl_doors.cpp
|
||||||
perl_entity.cpp
|
perl_entity.cpp
|
||||||
@@ -207,6 +209,7 @@ SET(zone_headers
|
|||||||
horse.h
|
horse.h
|
||||||
lua_bot.h
|
lua_bot.h
|
||||||
lua_bit.h
|
lua_bit.h
|
||||||
|
lua_buff.h
|
||||||
lua_client.h
|
lua_client.h
|
||||||
lua_corpse.h
|
lua_corpse.h
|
||||||
lua_door.h
|
lua_door.h
|
||||||
|
|||||||
+16
-6
@@ -621,28 +621,38 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
|
|||||||
// NPC *npc1, *npc2;
|
// NPC *npc1, *npc2;
|
||||||
int reverse;
|
int reverse;
|
||||||
|
|
||||||
if(!zone->CanDoCombat())
|
if (!zone->CanDoCombat()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// some special cases
|
// some special cases
|
||||||
if(!target)
|
if (!target) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(this == target) // you can attack yourself
|
if (this == target) { // you can attack yourself
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (target->GetSpecialAbility(NO_HARM_FROM_CLIENT)) {
|
if (target->GetSpecialAbility(NO_HARM_FROM_CLIENT)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT) && IsClient())
|
if (IsBot() && target->GetSpecialAbility(IMMUNE_DAMAGE_BOT)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (target->GetSpecialAbility(IMMUNE_DAMAGE_NPC) && IsNPC())
|
if (IsClient() && target->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (target->IsHorse())
|
if (IsNPC() && target->GetSpecialAbility(IMMUNE_DAMAGE_NPC)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target->IsHorse()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// can't damage own pet (applies to everthing)
|
// can't damage own pet (applies to everthing)
|
||||||
Mob *target_owner = target->GetOwner();
|
Mob *target_owner = target->GetOwner();
|
||||||
|
|||||||
@@ -57,9 +57,7 @@ EQ::Net::WebsocketLoginStatus CheckLogin(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char account_name[64];
|
ret.account_name = database.GetAccountName(static_cast<uint32>(ret.account_id));
|
||||||
database.GetAccountName(static_cast<uint32>(ret.account_id), account_name);
|
|
||||||
ret.account_name = account_name;
|
|
||||||
ret.logged_in = true;
|
ret.logged_in = true;
|
||||||
ret.status = database.CheckStatus(ret.account_id);
|
ret.status = database.CheckStatus(ret.account_id);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
+138
-46
@@ -1687,13 +1687,6 @@ bool Mob::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//used by complete heal and #heal
|
|
||||||
void Mob::Heal()
|
|
||||||
{
|
|
||||||
SetMaxHP();
|
|
||||||
SendHPUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special)
|
void Client::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special)
|
||||||
{
|
{
|
||||||
if (dead || IsCorpse())
|
if (dead || IsCorpse())
|
||||||
@@ -2618,12 +2611,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m.member) {
|
if (m.member) {
|
||||||
m.member->RecordKilledNPCEvent(this);
|
|
||||||
|
|
||||||
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) {
|
|
||||||
parse->EventNPC(EVENT_KILLED_MERIT, this, m.member, "killed", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RuleB(NPC, EnableMeritBasedFaction)) {
|
if (RuleB(NPC, EnableMeritBasedFaction)) {
|
||||||
m.member->SetFactionLevel(
|
m.member->SetFactionLevel(
|
||||||
m.member->CharacterID(),
|
m.member->CharacterID(),
|
||||||
@@ -2683,18 +2670,11 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the EVENT_KILLED_MERIT event and update kill tasks
|
/* Update kill tasks for all group members */
|
||||||
* for all group members */
|
|
||||||
for (const auto& m : killer_group->members) {
|
for (const auto& m : killer_group->members) {
|
||||||
if (m && m->IsClient()) {
|
if (m && m->IsClient()) {
|
||||||
Client* c = m->CastToClient();
|
Client* c = m->CastToClient();
|
||||||
|
|
||||||
c->RecordKilledNPCEvent(this);
|
|
||||||
|
|
||||||
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) {
|
|
||||||
parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RuleB(NPC, EnableMeritBasedFaction)) {
|
if (RuleB(NPC, EnableMeritBasedFaction)) {
|
||||||
c->SetFactionLevel(
|
c->SetFactionLevel(
|
||||||
c->CharacterID(),
|
c->CharacterID(),
|
||||||
@@ -2756,13 +2736,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the EVENT_KILLED_MERIT event */
|
|
||||||
give_exp_client->RecordKilledNPCEvent(this);
|
|
||||||
|
|
||||||
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) {
|
|
||||||
parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RuleB(NPC, EnableMeritBasedFaction)) {
|
if (RuleB(NPC, EnableMeritBasedFaction)) {
|
||||||
give_exp_client->SetFactionLevel(
|
give_exp_client->SetFactionLevel(
|
||||||
give_exp_client->CharacterID(),
|
give_exp_client->CharacterID(),
|
||||||
@@ -2843,6 +2816,9 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
|
|
||||||
entity_list.RemoveFromAutoXTargets(this);
|
entity_list.RemoveFromAutoXTargets(this);
|
||||||
|
|
||||||
|
// Here we create the corpse.
|
||||||
|
DeleteInvalidQuestLoot();
|
||||||
|
|
||||||
corpse = new Corpse(
|
corpse = new Corpse(
|
||||||
this,
|
this,
|
||||||
&m_loot_items,
|
&m_loot_items,
|
||||||
@@ -2991,6 +2967,17 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
|
|
||||||
m_combat_record.Stop();
|
m_combat_record.Stop();
|
||||||
|
|
||||||
|
if (give_exp_client && !IsCorpse()) {
|
||||||
|
const auto& v = give_exp_client->GetRaidOrGroupOrSelf(true);
|
||||||
|
for (const auto& m : v) {
|
||||||
|
m->CastToClient()->RecordKilledNPCEvent(this);
|
||||||
|
|
||||||
|
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) {
|
||||||
|
parse->EventNPC(EVENT_KILLED_MERIT, this, m, "killed", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
|
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
|
||||||
const auto& export_string = fmt::format(
|
const auto& export_string = fmt::format(
|
||||||
"{} {} {} {} {} {} {} {} {}",
|
"{} {} {} {} {} {} {} {} {}",
|
||||||
@@ -3091,26 +3078,37 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
TryTriggerOnCastRequirement();
|
TryTriggerOnCastRequirement();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsClient() && !IsAIControlled())
|
if (IsClient() && !IsAIControlled()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO))
|
if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC())
|
if (other->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient())
|
if (other->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsValidSpell(spell_id) && IsNoDetrimentalSpellAggroSpell(spell_id))
|
if (other->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (other == myowner)
|
if (IsValidSpell(spell_id) && IsNoDetrimentalSpellAggroSpell(spell_id)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (other->GetSpecialAbility(IMMUNE_AGGRO_ON))
|
if (other == myowner) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other->GetSpecialAbility(IMMUNE_AGGRO_ON)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(NPC_TUNNELVISION)) {
|
if (GetSpecialAbility(NPC_TUNNELVISION)) {
|
||||||
int tv_mod = GetSpecialAbilityParam(NPC_TUNNELVISION, 0);
|
int tv_mod = GetSpecialAbilityParam(NPC_TUNNELVISION, 0);
|
||||||
@@ -3194,8 +3192,9 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
// owner must get on list, but he's not actually gained any hate yet
|
// owner must get on list, but he's not actually gained any hate yet
|
||||||
if (
|
if (
|
||||||
!owner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!owner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
!(GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && owner->IsClient()) &&
|
!(owner->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
||||||
!(GetSpecialAbility(IMMUNE_AGGRO_NPC) && owner->IsNPC())
|
!(owner->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
||||||
|
!(owner->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
||||||
) {
|
) {
|
||||||
if (owner->IsClient() && !CheckAggro(owner)) {
|
if (owner->IsClient() && !CheckAggro(owner)) {
|
||||||
owner->CastToClient()->AddAutoXTarget(this);
|
owner->CastToClient()->AddAutoXTarget(this);
|
||||||
@@ -3209,8 +3208,9 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
if (
|
if (
|
||||||
!mypet->IsFamiliar() &&
|
!mypet->IsFamiliar() &&
|
||||||
!mypet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!mypet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && IsClient()) &&
|
!(IsBot() && mypet->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
||||||
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && IsNPC())
|
!(IsClient() && mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
||||||
|
!(IsNPC() && mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
||||||
) {
|
) {
|
||||||
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
@@ -3219,8 +3219,9 @@ void Mob::AddToHateList(Mob* other, int64 hate /*= 0*/, int64 damage /*= 0*/, bo
|
|||||||
if (
|
if (
|
||||||
myowner->IsAIControlled() &&
|
myowner->IsAIControlled() &&
|
||||||
!myowner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!myowner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
!(GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && myowner->IsClient()) &&
|
!(myowner->IsBot() && GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
||||||
!(GetSpecialAbility(IMMUNE_AGGRO_NPC) && myowner->IsNPC())
|
!(myowner->IsClient() && GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
||||||
|
!(myowner->IsNPC() && GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
||||||
) {
|
) {
|
||||||
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
@@ -3966,6 +3967,18 @@ bool Mob::CheckDoubleAttack()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks special) {
|
void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks special) {
|
||||||
|
#ifdef LUA_EQEMU
|
||||||
|
int64 lua_ret = 0;
|
||||||
|
bool ignore_default = false;
|
||||||
|
lua_ret = LuaParser::Instance()->CommonDamage(this, attacker, damage, spell_id, static_cast<int>(skill_used), avoidable, buffslot, iBuffTic, static_cast<int>(special), ignore_default);
|
||||||
|
if (lua_ret != 0) {
|
||||||
|
damage = lua_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignore_default) {
|
||||||
|
//return lua_ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// This method is called with skill_used=ABJURE for Damage Shield damage.
|
// This method is called with skill_used=ABJURE for Damage Shield damage.
|
||||||
bool FromDamageShield = (skill_used == EQ::skills::SkillAbjuration);
|
bool FromDamageShield = (skill_used == EQ::skills::SkillAbjuration);
|
||||||
bool ignore_invul = false;
|
bool ignore_invul = false;
|
||||||
@@ -4060,8 +4073,9 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
!pet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!pet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
!pet->IsEngaged() &&
|
!pet->IsEngaged() &&
|
||||||
attacker &&
|
attacker &&
|
||||||
!(pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) &&
|
!(attacker->IsBot() && pet->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
||||||
!(pet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) &&
|
!(attacker->IsClient() && pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
||||||
|
!(attacker->IsNPC() && pet->GetSpecialAbility(IMMUNE_AGGRO_NPC)) &&
|
||||||
attacker != this &&
|
attacker != this &&
|
||||||
!attacker->IsCorpse() &&
|
!attacker->IsCorpse() &&
|
||||||
!pet->IsGHeld() &&
|
!pet->IsGHeld() &&
|
||||||
@@ -4692,6 +4706,19 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
|
|
||||||
void Mob::HealDamage(uint64 amount, Mob* caster, uint16 spell_id)
|
void Mob::HealDamage(uint64 amount, Mob* caster, uint16 spell_id)
|
||||||
{
|
{
|
||||||
|
#ifdef LUA_EQEMU
|
||||||
|
uint64 lua_ret = 0;
|
||||||
|
bool ignore_default = false;
|
||||||
|
|
||||||
|
lua_ret = LuaParser::Instance()->HealDamage(this, caster, amount, spell_id, ignore_default);
|
||||||
|
if (lua_ret != 0) {
|
||||||
|
amount = lua_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignore_default) {
|
||||||
|
//return lua_ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
int64 maxhp = GetMaxHP();
|
int64 maxhp = GetMaxHP();
|
||||||
int64 curhp = GetHP();
|
int64 curhp = GetHP();
|
||||||
uint64 acthealed = 0;
|
uint64 acthealed = 0;
|
||||||
@@ -6194,7 +6221,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
|||||||
if (headshot > 0) {
|
if (headshot > 0) {
|
||||||
hit.damage_done = headshot;
|
hit.damage_done = headshot;
|
||||||
}
|
}
|
||||||
else if (GetClass() == Class::Ranger && GetLevel() > 50) { // no double dmg on headshot
|
else if (GetClass() == Class::Ranger && GetLevel() >= RuleI(Combat, ArcheryBonusLevelRequirement)) { // no double dmg on headshot
|
||||||
if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) {
|
if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) {
|
||||||
hit.damage_done *= 2;
|
hit.damage_done *= 2;
|
||||||
MessageString(Chat::MeleeCrit, BOW_DOUBLE_DAMAGE);
|
MessageString(Chat::MeleeCrit, BOW_DOUBLE_DAMAGE);
|
||||||
@@ -6286,10 +6313,25 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
|||||||
|
|
||||||
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + defender->GetPositionalDmgTakenAmt(this);
|
hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + defender->GetPositionalDmgTakenAmt(this);
|
||||||
|
|
||||||
if (defender->GetShielderID()) {
|
if (defender->GetShielderID() || defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT]) {
|
||||||
|
bool use_shield_ability = true;
|
||||||
|
//If defender is being shielded by an ability AND has a shield spell effect buff use highest mitigation value.
|
||||||
|
if ((defender->GetShieldTargetMitigation() && defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT]) &&
|
||||||
|
(defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] >= defender->GetShieldTargetMitigation())){
|
||||||
|
bool use_shield_ability = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//use targeted /shield ability values
|
||||||
|
if (defender->GetShielderID() && use_shield_ability) {
|
||||||
DoShieldDamageOnShielder(defender, hit.damage_done, hit.skill);
|
DoShieldDamageOnShielder(defender, hit.damage_done, hit.skill);
|
||||||
hit.damage_done -= hit.damage_done * defender->GetShieldTargetMitigation() / 100; //Default shielded takes 50 pct damage
|
hit.damage_done -= hit.damage_done * defender->GetShieldTargetMitigation() / 100; //Default shielded takes 50 pct damage
|
||||||
}
|
}
|
||||||
|
//use spell effect SPA 463 values
|
||||||
|
else if (defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT]){
|
||||||
|
DoShieldDamageOnShielderSpellEffect(defender, hit.damage_done, hit.skill);
|
||||||
|
hit.damage_done -= hit.damage_done * defender->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
||||||
}
|
}
|
||||||
@@ -6331,7 +6373,57 @@ void Mob::DoShieldDamageOnShielder(Mob *shield_target, int64 hit_damage_done, EQ
|
|||||||
|
|
||||||
hit_damage_done -= hit_damage_done * mitigation / 100;
|
hit_damage_done -= hit_damage_done * mitigation / 100;
|
||||||
shielder->Damage(this, hit_damage_done, SPELL_UNKNOWN, skillInUse, true, -1, false, m_specialattacks);
|
shielder->Damage(this, hit_damage_done, SPELL_UNKNOWN, skillInUse, true, -1, false, m_specialattacks);
|
||||||
shielder->CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
|
}
|
||||||
|
|
||||||
|
void Mob::DoShieldDamageOnShielderSpellEffect(Mob* shield_target, int64 hit_damage_done, EQ::skills::SkillType skillInUse)
|
||||||
|
{
|
||||||
|
if (!shield_target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
SPA 463 SE_SHIELD_TARGET
|
||||||
|
|
||||||
|
Live description: "Shields your target, taking a percentage of their damage".
|
||||||
|
Only example spell on live is an NPC who uses it during a raid event "Laurion's Song" expansion. SPA 54492 'Guardian Stance' Described as 100% Melee Shielding
|
||||||
|
|
||||||
|
Example of mechanic. Base value = 70. Caster puts buff on target. Each melee hit Buff Target takes 70% less damage, Buff Caster receives 30% of the melee damage.
|
||||||
|
Added mechanic to cause buff to fade if target or caster are seperated by a distance greater than the casting range of the spell. This allows similiar mechanics
|
||||||
|
to the /shield ability, without a range removal mechanic it would be too easy to abuse if put on a player spell. *can not confirm live does this currently
|
||||||
|
|
||||||
|
Can not be cast on self.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT])
|
||||||
|
{
|
||||||
|
if (shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT] >= 0)
|
||||||
|
{
|
||||||
|
Mob *shielder = entity_list.GetMob(shield_target->buffs[shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]].casterid);
|
||||||
|
if (!shielder) {
|
||||||
|
shield_target->BuffFadeBySlot(shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int shield_spell_id = shield_target->buffs[shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]].spellid;
|
||||||
|
if (!IsValidSpell(shield_spell_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float max_range = spells[shield_spell_id].range;
|
||||||
|
if (spells[shield_spell_id].aoe_range > max_range) {
|
||||||
|
max_range = spells[shield_spell_id].aoe_range;
|
||||||
|
}
|
||||||
|
max_range += 5.0f; //small buffer in case casted at exactly max range.
|
||||||
|
|
||||||
|
if (shield_target->CalculateDistance(shielder->GetX(), shielder->GetY(), shielder->GetZ()) > max_range) {
|
||||||
|
shield_target->BuffFadeBySlot(shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mitigation = 100 - shield_target->spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT];
|
||||||
|
hit_damage_done -= hit_damage_done * mitigation / 100;
|
||||||
|
shielder->Damage(this, hit_damage_done, SPELL_UNKNOWN, skillInUse, true, -1, false, m_specialattacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::CommonBreakInvisibleFromCombat()
|
void Mob::CommonBreakInvisibleFromCombat()
|
||||||
|
|||||||
+24
-1
@@ -2090,7 +2090,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
|||||||
if (focus)
|
if (focus)
|
||||||
{
|
{
|
||||||
if (WornType){
|
if (WornType){
|
||||||
if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) {
|
if (RuleB(Spells, UseAdditiveFocusFromWornSlotWithLimits)) {
|
||||||
|
new_bonus->FocusEffectsWornWithLimits[focus] = spells[spell_id].effect_id[i];
|
||||||
|
}
|
||||||
|
else if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) {
|
||||||
new_bonus->FocusEffectsWorn[focus] += spells[spell_id].base_value[i];
|
new_bonus->FocusEffectsWorn[focus] += spells[spell_id].base_value[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3298,6 +3301,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SE_Shield_Target:
|
||||||
|
{
|
||||||
|
if (new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] < effect_value) {
|
||||||
|
new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] = effect_value;
|
||||||
|
new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT] = buffslot;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SE_TriggerMeleeThreshold:
|
case SE_TriggerMeleeThreshold:
|
||||||
new_bonus->TriggerMeleeThreshold = true;
|
new_bonus->TriggerMeleeThreshold = true;
|
||||||
break;
|
break;
|
||||||
@@ -4989,6 +5001,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
|||||||
case SE_MaxHPChange:
|
case SE_MaxHPChange:
|
||||||
if (negate_spellbonus) { spellbonuses.MaxHPChange = effect_value; }
|
if (negate_spellbonus) { spellbonuses.MaxHPChange = effect_value; }
|
||||||
if (negate_aabonus) { aabonuses.MaxHPChange = effect_value; }
|
if (negate_aabonus) { aabonuses.MaxHPChange = effect_value; }
|
||||||
|
if (negate_aabonus) { aabonuses.MaxHP = effect_value; }
|
||||||
if (negate_itembonus) { itembonuses.MaxHPChange = effect_value; }
|
if (negate_itembonus) { itembonuses.MaxHPChange = effect_value; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -5916,6 +5929,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
|||||||
if (negate_itembonus) { itembonuses.SkillProcSuccess[e] = effect_value; }
|
if (negate_itembonus) { itembonuses.SkillProcSuccess[e] = effect_value; }
|
||||||
if (negate_aabonus) { aabonuses.SkillProcSuccess[e] = effect_value; }
|
if (negate_aabonus) { aabonuses.SkillProcSuccess[e] = effect_value; }
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SE_SkillProcAttempt: {
|
case SE_SkillProcAttempt: {
|
||||||
@@ -5925,6 +5939,15 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
|
|||||||
if (negate_itembonus) { itembonuses.SkillProc[e] = effect_value; }
|
if (negate_itembonus) { itembonuses.SkillProc[e] = effect_value; }
|
||||||
if (negate_aabonus) { aabonuses.SkillProc[e] = effect_value; }
|
if (negate_aabonus) { aabonuses.SkillProc[e] = effect_value; }
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_Shield_Target: {
|
||||||
|
if (negate_spellbonus) {
|
||||||
|
spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] = effect_value;
|
||||||
|
spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT] = effect_value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+126
-68
@@ -27,6 +27,7 @@
|
|||||||
#include "../common/repositories/bot_starting_items_repository.h"
|
#include "../common/repositories/bot_starting_items_repository.h"
|
||||||
#include "../common/data_verification.h"
|
#include "../common/data_verification.h"
|
||||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
#include "../common/skill_caps.h"
|
||||||
|
|
||||||
// This constructor is used during the bot create command
|
// This constructor is used during the bot create command
|
||||||
Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) {
|
Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) {
|
||||||
@@ -1171,7 +1172,7 @@ uint16 Bot::GetPrimarySkillValue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16 Bot::MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const {
|
uint16 Bot::MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const {
|
||||||
return(content_db.GetSkillCap(class_, skillid, level));
|
return skill_caps.GetSkillCap(class_, skillid, level).cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Bot::GetTotalATK() {
|
uint32 Bot::GetTotalATK() {
|
||||||
@@ -2287,7 +2288,7 @@ bool Bot::TryMeditate() {
|
|||||||
if (!IsMoving() && !spellend_timer.Enabled()) {
|
if (!IsMoving() && !spellend_timer.Enabled()) {
|
||||||
if (GetTarget() && AI_EngagedCastCheck()) {
|
if (GetTarget() && AI_EngagedCastCheck()) {
|
||||||
BotMeditate(false);
|
BotMeditate(false);
|
||||||
} else if (GetArchetype() == ARCHETYPE_CASTER) {
|
} else if (GetArchetype() == Archetype::Caster) {
|
||||||
BotMeditate(true);
|
BotMeditate(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2684,16 +2685,19 @@ bool Bot::IsValidTarget(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool valid_target_state = (
|
bool invalid_target_state = false;
|
||||||
HOLDING ||
|
if (HOLDING ||
|
||||||
!tar->IsNPC() ||
|
!tar->IsNPC() ||
|
||||||
tar->IsMezzed() ||
|
tar->IsMezzed() ||
|
||||||
lo_distance > leash_distance ||
|
lo_distance > leash_distance ||
|
||||||
tar_distance > leash_distance
|
tar_distance > leash_distance ||
|
||||||
);
|
(!GetAttackingFlag() && !CheckLosFN(tar) && !leash_owner->CheckLosFN(tar)) ||
|
||||||
const bool valid_target = !GetAttackingFlag() && !CheckLosFN(tar) && !leash_owner->CheckLosFN(tar);
|
!IsAttackAllowed(tar)
|
||||||
|
) {
|
||||||
|
invalid_target_state = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (valid_target_state || valid_target || !IsAttackAllowed(tar)) {
|
if (invalid_target_state) {
|
||||||
// Normally, we wouldn't want to do this without class checks..but, too many issues can arise if we let enchanter animation pets run rampant
|
// Normally, we wouldn't want to do this without class checks..but, too many issues can arise if we let enchanter animation pets run rampant
|
||||||
if (HasPet()) {
|
if (HasPet()) {
|
||||||
GetPet()->RemoveFromHateList(tar);
|
GetPet()->RemoveFromHateList(tar);
|
||||||
@@ -2752,7 +2756,7 @@ Mob* Bot::GetBotTarget(Client* bot_owner)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetArchetype() == ARCHETYPE_CASTER) {
|
if (GetArchetype() == Archetype::Caster) {
|
||||||
BotMeditate(true);
|
BotMeditate(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3340,7 +3344,7 @@ void Bot::LoadAndSpawnAllZonedBots(Client* bot_owner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bot_spawn_limit >= 0 && spawned_bots_count >= bot_spawn_limit) {
|
if (bot_spawn_limit >= 0 && spawned_bots_count >= bot_spawn_limit) {
|
||||||
database.SetGroupID(b->GetCleanName(), 0, b->GetBotID());
|
Group::RemoveFromGroup(b);
|
||||||
g->UpdatePlayer(bot_owner);
|
g->UpdatePlayer(bot_owner);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3352,7 +3356,7 @@ void Bot::LoadAndSpawnAllZonedBots(Client* bot_owner) {
|
|||||||
bot_spawn_limit_class >= 0 &&
|
bot_spawn_limit_class >= 0 &&
|
||||||
spawned_bot_count_class >= bot_spawn_limit_class
|
spawned_bot_count_class >= bot_spawn_limit_class
|
||||||
) {
|
) {
|
||||||
database.SetGroupID(b->GetCleanName(), 0, b->GetBotID());
|
Group::RemoveFromGroup(b);
|
||||||
g->UpdatePlayer(bot_owner);
|
g->UpdatePlayer(bot_owner);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3372,7 +3376,7 @@ void Bot::LoadAndSpawnAllZonedBots(Client* bot_owner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bot_owner->HasGroup()) {
|
if (!bot_owner->HasGroup()) {
|
||||||
database.SetGroupID(b->GetCleanName(), 0, b->GetBotID());
|
Group::RemoveFromGroup(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3629,8 +3633,8 @@ bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) {
|
|||||||
bot->SetFollowID(0);
|
bot->SetFollowID(0);
|
||||||
if (group->DelMember(bot)) {
|
if (group->DelMember(bot)) {
|
||||||
group->DelMemberOOZ(bot->GetName());
|
group->DelMemberOOZ(bot->GetName());
|
||||||
database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID());
|
Group::RemoveFromGroup(bot);
|
||||||
if (group->GroupCount() < 1) {
|
if (group->GroupCount() < 2) {
|
||||||
group->DisbandGroup();
|
group->DisbandGroup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3643,7 +3647,7 @@ bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) {
|
|||||||
group->members[i]->SetFollowID(0);
|
group->members[i]->SetFollowID(0);
|
||||||
}
|
}
|
||||||
group->DisbandGroup();
|
group->DisbandGroup();
|
||||||
database.SetGroupID(bot->GetCleanName(), 0, bot->GetBotID());
|
Group::RemoveFromGroup(bot);
|
||||||
}
|
}
|
||||||
Result = true;
|
Result = true;
|
||||||
}
|
}
|
||||||
@@ -5186,31 +5190,26 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 Bot::CalcMaxMana() {
|
int64 Bot::CalcMaxMana()
|
||||||
switch(GetCasterClass()) {
|
{
|
||||||
case 'I':
|
if (IsIntelligenceCasterClass() || IsWisdomCasterClass()) {
|
||||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
|
max_mana = (
|
||||||
|
GenerateBaseManaPoints() +
|
||||||
|
itembonuses.Mana +
|
||||||
|
spellbonuses.Mana +
|
||||||
|
aabonuses.Mana +
|
||||||
|
GroupLeadershipAAManaEnhancement()
|
||||||
|
);
|
||||||
max_mana += itembonuses.heroic_max_mana;
|
max_mana += itembonuses.heroic_max_mana;
|
||||||
case 'W': {
|
} else {
|
||||||
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
|
|
||||||
max_mana += itembonuses.heroic_max_mana;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'N': {
|
|
||||||
max_mana = 0;
|
max_mana = 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
LogDebug("Invalid Class [{}] in CalcMaxMana", GetCasterClass());
|
|
||||||
max_mana = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_mana > max_mana)
|
if (current_mana > max_mana) {
|
||||||
current_mana = max_mana;
|
current_mana = max_mana;
|
||||||
else if (max_mana < 0)
|
} else if (max_mana < 0) {
|
||||||
max_mana = 0;
|
max_mana = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return max_mana;
|
return max_mana;
|
||||||
}
|
}
|
||||||
@@ -5525,24 +5524,32 @@ bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Bot::GenerateBaseManaPoints() {
|
int32 Bot::GenerateBaseManaPoints()
|
||||||
|
{
|
||||||
int32 bot_mana = 0;
|
int32 bot_mana = 0;
|
||||||
int32 WisInt = 0;
|
int32 WisInt = 0;
|
||||||
int32 MindLesserFactor, MindFactor;
|
int32 MindLesserFactor, MindFactor;
|
||||||
int wisint_mana = 0;
|
int wisint_mana = 0;
|
||||||
int base_mana = 0;
|
int base_mana = 0;
|
||||||
int ConvertedWisInt = 0;
|
int ConvertedWisInt = 0;
|
||||||
switch(GetCasterClass()) {
|
|
||||||
case 'I':
|
if (IsIntelligenceCasterClass()) {
|
||||||
WisInt = INT;
|
WisInt = INT;
|
||||||
if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
|
|
||||||
|
if (
|
||||||
|
GetOwner() &&
|
||||||
|
GetOwner()->CastToClient() &&
|
||||||
|
GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD &&
|
||||||
|
RuleB(Character, SoDClientUseSoDHPManaEnd)
|
||||||
|
) {
|
||||||
if (WisInt > 100) {
|
if (WisInt > 100) {
|
||||||
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
|
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
|
||||||
if (WisInt > 201)
|
if (WisInt > 201) {
|
||||||
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
|
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
ConvertedWisInt = WisInt;
|
ConvertedWisInt = WisInt;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetLevel() < 41) {
|
if (GetLevel() < 41) {
|
||||||
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
|
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
|
||||||
@@ -5554,29 +5561,39 @@ int32 Bot::GenerateBaseManaPoints() {
|
|||||||
wisint_mana = (9 * ConvertedWisInt);
|
wisint_mana = (9 * ConvertedWisInt);
|
||||||
base_mana = (1800 + ((GetLevel() - 80) * 18));
|
base_mana = (1800 + ((GetLevel() - 80) * 18));
|
||||||
}
|
}
|
||||||
|
|
||||||
bot_mana = (base_mana + wisint_mana);
|
bot_mana = (base_mana + wisint_mana);
|
||||||
} else {
|
} else {
|
||||||
if (((WisInt - 199) / 2) > 0)
|
if (((WisInt - 199) / 2) > 0) {
|
||||||
MindLesserFactor = ((WisInt - 199) / 2);
|
MindLesserFactor = ((WisInt - 199) / 2);
|
||||||
else
|
} else {
|
||||||
MindLesserFactor = 0;
|
MindLesserFactor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
MindFactor = WisInt - MindLesserFactor;
|
MindFactor = WisInt - MindLesserFactor;
|
||||||
if (WisInt > 100)
|
if (WisInt > 100) {
|
||||||
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
||||||
else
|
} else {
|
||||||
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 'W':
|
} else if (IsWisdomCasterClass()) {
|
||||||
WisInt = WIS;
|
WisInt = WIS;
|
||||||
if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
|
|
||||||
|
if (
|
||||||
|
GetOwner() &&
|
||||||
|
GetOwner()->CastToClient() &&
|
||||||
|
GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD &&
|
||||||
|
RuleB(Character, SoDClientUseSoDHPManaEnd)
|
||||||
|
) {
|
||||||
if (WisInt > 100) {
|
if (WisInt > 100) {
|
||||||
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
|
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
|
||||||
if (WisInt > 201)
|
if (WisInt > 201) {
|
||||||
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
|
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
ConvertedWisInt = WisInt;
|
ConvertedWisInt = WisInt;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetLevel() < 41) {
|
if (GetLevel() < 41) {
|
||||||
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
|
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
|
||||||
@@ -5588,24 +5605,26 @@ int32 Bot::GenerateBaseManaPoints() {
|
|||||||
wisint_mana = (9 * ConvertedWisInt);
|
wisint_mana = (9 * ConvertedWisInt);
|
||||||
base_mana = (1800 + ((GetLevel() - 80) * 18));
|
base_mana = (1800 + ((GetLevel() - 80) * 18));
|
||||||
}
|
}
|
||||||
|
|
||||||
bot_mana = (base_mana + wisint_mana);
|
bot_mana = (base_mana + wisint_mana);
|
||||||
} else {
|
} else {
|
||||||
if (((WisInt - 199) / 2) > 0)
|
if (((WisInt - 199) / 2) > 0) {
|
||||||
MindLesserFactor = ((WisInt - 199) / 2);
|
MindLesserFactor = ((WisInt - 199) / 2);
|
||||||
else
|
} else {
|
||||||
MindLesserFactor = 0;
|
MindLesserFactor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
MindFactor = (WisInt - MindLesserFactor);
|
MindFactor = (WisInt - MindLesserFactor);
|
||||||
if (WisInt > 100)
|
if (WisInt > 100) {
|
||||||
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
||||||
else
|
} else {
|
||||||
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
bot_mana = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
bot_mana = 0;
|
||||||
|
}
|
||||||
|
|
||||||
max_mana = bot_mana;
|
max_mana = bot_mana;
|
||||||
return bot_mana;
|
return bot_mana;
|
||||||
}
|
}
|
||||||
@@ -6216,11 +6235,10 @@ int64 Bot::CalcMaxHP() {
|
|||||||
uint32 nd = 10000;
|
uint32 nd = 10000;
|
||||||
bot_hp += (GenerateBaseHitPoints() + itembonuses.HP);
|
bot_hp += (GenerateBaseHitPoints() + itembonuses.HP);
|
||||||
bot_hp += itembonuses.heroic_max_hp;
|
bot_hp += itembonuses.heroic_max_hp;
|
||||||
nd += aabonuses.MaxHP;
|
nd += aabonuses.MaxHP + spellbonuses.MaxHPChange + itembonuses.MaxHPChange;
|
||||||
bot_hp = ((float)bot_hp * (float)nd / (float)10000);
|
bot_hp = ((float)bot_hp * (float)nd / (float)10000);
|
||||||
bot_hp += (spellbonuses.HP + aabonuses.HP);
|
bot_hp += (spellbonuses.HP + aabonuses.HP);
|
||||||
bot_hp += GroupLeadershipAAHealthEnhancement();
|
bot_hp += GroupLeadershipAAHealthEnhancement();
|
||||||
bot_hp += (bot_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f));
|
|
||||||
max_hp = bot_hp;
|
max_hp = bot_hp;
|
||||||
if (current_hp > max_hp)
|
if (current_hp > max_hp)
|
||||||
current_hp = max_hp;
|
current_hp = max_hp;
|
||||||
@@ -6582,14 +6600,14 @@ void Bot::ProcessBotGroupInvite(Client* c, std::string const& botName) {
|
|||||||
entity_list.AddGroup(g);
|
entity_list.AddGroup(g);
|
||||||
database.SetGroupLeaderName(g->GetID(), c->GetName());
|
database.SetGroupLeaderName(g->GetID(), c->GetName());
|
||||||
g->SaveGroupLeaderAA();
|
g->SaveGroupLeaderAA();
|
||||||
database.SetGroupID(c->GetName(), g->GetID(), c->CharacterID());
|
g->AddToGroup(c);
|
||||||
database.SetGroupID(invitedBot->GetCleanName(), g->GetID(), invitedBot->GetBotID());
|
g->AddToGroup(invitedBot);
|
||||||
} else {
|
} else {
|
||||||
delete g;
|
delete g;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (AddBotToGroup(invitedBot, c->GetGroup())) {
|
if (AddBotToGroup(invitedBot, c->GetGroup())) {
|
||||||
database.SetGroupID(invitedBot->GetCleanName(), c->GetGroup()->GetID(), invitedBot->GetBotID());
|
c->GetGroup()->AddToGroup(invitedBot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (invitedBot->HasGroup()) {
|
} else if (invitedBot->HasGroup()) {
|
||||||
@@ -6740,7 +6758,7 @@ void Bot::CalcBotStats(bool showtext) {
|
|||||||
SetLevel(GetBotOwner()->GetLevel());
|
SetLevel(GetBotOwner()->GetLevel());
|
||||||
|
|
||||||
for (int sindex = 0; sindex <= EQ::skills::HIGHEST_SKILL; ++sindex) {
|
for (int sindex = 0; sindex <= EQ::skills::HIGHEST_SKILL; ++sindex) {
|
||||||
skills[sindex] = content_db.GetSkillCap(GetClass(), (EQ::skills::SkillType)sindex, GetLevel());
|
skills[sindex] = skill_caps.GetSkillCap(GetClass(), (EQ::skills::SkillType)sindex, GetLevel()).cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
taunt_timer.Start(1000);
|
taunt_timer.Start(1000);
|
||||||
@@ -7646,12 +7664,52 @@ void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) {
|
|||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
vsnprintf(buf, 1000, msg, ap);
|
vsnprintf(buf, 1000, msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (speaker->HasGroup()) {
|
|
||||||
|
if (speaker->IsRaidGrouped()) {
|
||||||
|
Raid* r = entity_list.GetRaidByBotName(speaker->GetName());
|
||||||
|
if (r) {
|
||||||
|
for (const auto& m : r->members) {
|
||||||
|
if (m.member && !m.is_bot) {
|
||||||
|
m.member->FilteredMessageString(
|
||||||
|
speaker,
|
||||||
|
Chat::PetResponse,
|
||||||
|
FilterSocials,
|
||||||
|
GENERIC_SAY,
|
||||||
|
speaker->GetCleanName(),
|
||||||
|
buf
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (speaker->HasGroup()) {
|
||||||
Group* g = speaker->GetGroup();
|
Group* g = speaker->GetGroup();
|
||||||
if (g)
|
if (g) {
|
||||||
g->GroupMessage(speaker->CastToMob(), Language::CommonTongue, Language::MaxValue, buf);
|
for (auto& m : g->members) {
|
||||||
} else
|
if (m && !m->IsBot()) {
|
||||||
speaker->Say("%s", buf);
|
m->FilteredMessageString(
|
||||||
|
speaker,
|
||||||
|
Chat::PetResponse,
|
||||||
|
FilterSocials,
|
||||||
|
GENERIC_SAY,
|
||||||
|
speaker->GetCleanName(),
|
||||||
|
buf
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//speaker->Say("%s", buf);
|
||||||
|
speaker->GetOwner()->FilteredMessageString(
|
||||||
|
speaker,
|
||||||
|
Chat::PetResponse,
|
||||||
|
FilterSocials,
|
||||||
|
GENERIC_SAY,
|
||||||
|
speaker->GetCleanName(),
|
||||||
|
buf
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::UseDiscipline(uint32 spell_id, uint32 target) {
|
bool Bot::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||||
|
|||||||
+5
-32
@@ -184,35 +184,11 @@ bool BotDatabase::QueryNameAvailablity(const std::string& bot_name, bool& availa
|
|||||||
if (
|
if (
|
||||||
bot_name.empty() ||
|
bot_name.empty() ||
|
||||||
bot_name.size() > 60 ||
|
bot_name.size() > 60 ||
|
||||||
!database.CheckUsedName(bot_name)
|
database.IsNameUsed(bot_name)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& bot_data = BotDataRepository::GetWhere(
|
|
||||||
database,
|
|
||||||
fmt::format(
|
|
||||||
"`name` LIKE '{}' LIMIT 1",
|
|
||||||
bot_name
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!bot_data.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& character_data = CharacterDataRepository::GetWhere(
|
|
||||||
database,
|
|
||||||
fmt::format(
|
|
||||||
"`name` LIKE '{}' LIMIT 1",
|
|
||||||
bot_name
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!character_data.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
available_flag = true;
|
available_flag = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1788,6 +1764,7 @@ bool BotDatabase::CreateCloneBotInventory(const uint32 bot_id, const uint32 clon
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& e : l) {
|
for (auto& e : l) {
|
||||||
|
e.inventories_index = 0;
|
||||||
e.bot_id = clone_id;
|
e.bot_id = clone_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1921,18 +1898,14 @@ bool BotDatabase::LoadGroupedBotsByGroupID(const uint32 owner_id, const uint32 g
|
|||||||
const auto& l = GroupIdRepository::GetWhere(
|
const auto& l = GroupIdRepository::GetWhere(
|
||||||
database,
|
database,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"`groupid` = {} AND `name` IN (SELECT `name` FROM `bot_data` WHERE `owner_id` = {})",
|
"`group_id` = {} AND `bot_id` != 0 AND `name` IN (SELECT `name` FROM `bot_data` WHERE `owner_id` = {})",
|
||||||
group_id,
|
group_id,
|
||||||
owner_id
|
owner_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (l.empty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& e : l) {
|
for (const auto& e : l) {
|
||||||
group_list.push_back(e.charid);
|
group_list.emplace_back(e.bot_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -2367,7 +2340,7 @@ const uint8 BotDatabase::GetBotLevelByID(const uint32 bot_id)
|
|||||||
return e.bot_id ? e.level : 0;
|
return e.bot_id ? e.level : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& BotDatabase::GetBotNameByID(const uint32 bot_id)
|
const std::string BotDatabase::GetBotNameByID(const uint32 bot_id)
|
||||||
{
|
{
|
||||||
const auto& e = BotDataRepository::FindOne(database, bot_id);
|
const auto& e = BotDataRepository::FindOne(database, bot_id);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -164,7 +164,7 @@ public:
|
|||||||
const uint8 GetBotGenderByID(const uint32 bot_id);
|
const uint8 GetBotGenderByID(const uint32 bot_id);
|
||||||
std::vector<uint32> GetBotIDsByCharacterID(const uint32 character_id, uint8 class_id = Class::None);
|
std::vector<uint32> GetBotIDsByCharacterID(const uint32 character_id, uint8 class_id = Class::None);
|
||||||
const uint8 GetBotLevelByID(const uint32 bot_id);
|
const uint8 GetBotLevelByID(const uint32 bot_id);
|
||||||
const std::string& GetBotNameByID(const uint32 bot_id);
|
const std::string GetBotNameByID(const uint32 bot_id);
|
||||||
const uint16 GetBotRaceByID(const uint32 bot_id);
|
const uint16 GetBotRaceByID(const uint32 bot_id);
|
||||||
|
|
||||||
class fail {
|
class fail {
|
||||||
|
|||||||
+1
-1
@@ -98,7 +98,7 @@ void Raid::HandleBotGroupDisband(uint32 owner, uint32 gid)
|
|||||||
auto r_group_members = GetRaidGroupMembers(GetGroup(b->GetName()));
|
auto r_group_members = GetRaidGroupMembers(GetGroup(b->GetName()));
|
||||||
auto g = new Group(b);
|
auto g = new Group(b);
|
||||||
entity_list.AddGroup(g);
|
entity_list.AddGroup(g);
|
||||||
database.SetGroupID(b->GetCleanName(), g->GetID(), b->GetBotID());
|
g->AddToGroup(b);
|
||||||
database.SetGroupLeaderName(g->GetID(), b->GetName());
|
database.SetGroupLeaderName(g->GetID(), b->GetName());
|
||||||
|
|
||||||
for (auto m: r_group_members) {
|
for (auto m: r_group_members) {
|
||||||
|
|||||||
@@ -591,7 +591,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
|||||||
//Only check archetype if spell is not a group spell
|
//Only check archetype if spell is not a group spell
|
||||||
//Hybrids get all buffs
|
//Hybrids get all buffs
|
||||||
switch (tar->GetArchetype()) {
|
switch (tar->GetArchetype()) {
|
||||||
case ARCHETYPE_CASTER:
|
case Archetype::Caster:
|
||||||
//TODO: probably more caster specific spell effects in here
|
//TODO: probably more caster specific spell effects in here
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
@@ -606,7 +606,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARCHETYPE_MELEE:
|
case Archetype::Melee:
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) ||
|
IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) ||
|
||||||
@@ -899,7 +899,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
|||||||
|
|
||||||
switch (tar->GetArchetype())
|
switch (tar->GetArchetype())
|
||||||
{
|
{
|
||||||
case ARCHETYPE_CASTER:
|
case Archetype::Caster:
|
||||||
//TODO: probably more caster specific spell effects in here
|
//TODO: probably more caster specific spell effects in here
|
||||||
if (IsEffectInSpell(s.SpellId, SE_AttackSpeed) || IsEffectInSpell(s.SpellId, SE_ATK) ||
|
if (IsEffectInSpell(s.SpellId, SE_AttackSpeed) || IsEffectInSpell(s.SpellId, SE_ATK) ||
|
||||||
IsEffectInSpell(s.SpellId, SE_STR) || IsEffectInSpell(s.SpellId, SE_ReverseDS))
|
IsEffectInSpell(s.SpellId, SE_STR) || IsEffectInSpell(s.SpellId, SE_ReverseDS))
|
||||||
@@ -907,7 +907,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARCHETYPE_MELEE:
|
case Archetype::Melee:
|
||||||
if (IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(s.SpellId, SE_ManaPool) ||
|
if (IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(s.SpellId, SE_ManaPool) ||
|
||||||
IsEffectInSpell(s.SpellId, SE_CastingLevel) || IsEffectInSpell(s.SpellId, SE_ManaRegen_v2) ||
|
IsEffectInSpell(s.SpellId, SE_CastingLevel) || IsEffectInSpell(s.SpellId, SE_ManaRegen_v2) ||
|
||||||
IsEffectInSpell(s.SpellId, SE_CurrentMana))
|
IsEffectInSpell(s.SpellId, SE_CurrentMana))
|
||||||
|
|||||||
+253
-65
@@ -57,6 +57,7 @@ extern volatile bool RunLoops;
|
|||||||
#include "queryserv.h"
|
#include "queryserv.h"
|
||||||
#include "mob_movement_manager.h"
|
#include "mob_movement_manager.h"
|
||||||
#include "cheat_manager.h"
|
#include "cheat_manager.h"
|
||||||
|
#include "lua_parser.h"
|
||||||
|
|
||||||
#include "../common/repositories/character_alternate_abilities_repository.h"
|
#include "../common/repositories/character_alternate_abilities_repository.h"
|
||||||
#include "../common/repositories/account_flags_repository.h"
|
#include "../common/repositories/account_flags_repository.h"
|
||||||
@@ -68,10 +69,12 @@ extern volatile bool RunLoops;
|
|||||||
#include "../common/repositories/discovered_items_repository.h"
|
#include "../common/repositories/discovered_items_repository.h"
|
||||||
#include "../common/repositories/inventory_repository.h"
|
#include "../common/repositories/inventory_repository.h"
|
||||||
#include "../common/repositories/keyring_repository.h"
|
#include "../common/repositories/keyring_repository.h"
|
||||||
|
#include "../common/repositories/tradeskill_recipe_repository.h"
|
||||||
#include "../common/events/player_events.h"
|
#include "../common/events/player_events.h"
|
||||||
#include "../common/events/player_event_logs.h"
|
#include "../common/events/player_event_logs.h"
|
||||||
#include "dialogue_window.h"
|
#include "dialogue_window.h"
|
||||||
#include "../common/zone_store.h"
|
#include "../common/zone_store.h"
|
||||||
|
#include "../common/skill_caps.h"
|
||||||
|
|
||||||
|
|
||||||
extern QueryServ* QServ;
|
extern QueryServ* QServ;
|
||||||
@@ -284,6 +287,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
|||||||
PendingSacrifice = false;
|
PendingSacrifice = false;
|
||||||
controlling_boat_id = 0;
|
controlling_boat_id = 0;
|
||||||
controlled_mob_id = 0;
|
controlled_mob_id = 0;
|
||||||
|
qGlobals = nullptr;
|
||||||
|
|
||||||
if (!RuleB(Character, PerCharacterQglobalMaxLevel) && !RuleB(Character, PerCharacterBucketMaxLevel)) {
|
if (!RuleB(Character, PerCharacterQglobalMaxLevel) && !RuleB(Character, PerCharacterBucketMaxLevel)) {
|
||||||
SetClientMaxLevel(0);
|
SetClientMaxLevel(0);
|
||||||
@@ -311,7 +315,6 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
|||||||
aa_los_them_mob = nullptr;
|
aa_los_them_mob = nullptr;
|
||||||
los_status = false;
|
los_status = false;
|
||||||
los_status_facing = false;
|
los_status_facing = false;
|
||||||
qGlobals = nullptr;
|
|
||||||
HideCorpseMode = HideCorpseNone;
|
HideCorpseMode = HideCorpseNone;
|
||||||
PendingGuildInvitation = false;
|
PendingGuildInvitation = false;
|
||||||
|
|
||||||
@@ -2225,8 +2228,8 @@ void Client::ChangeLastName(std::string last_name) {
|
|||||||
bool Client::ChangeFirstName(const char* in_firstname, const char* gmname)
|
bool Client::ChangeFirstName(const char* in_firstname, const char* gmname)
|
||||||
{
|
{
|
||||||
// check duplicate name
|
// check duplicate name
|
||||||
bool usedname = database.CheckUsedName((const char*) in_firstname);
|
bool used_name = database.IsNameUsed((const char*) in_firstname);
|
||||||
if (!usedname) {
|
if (used_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2294,29 +2297,23 @@ void Client::ReadBook(BookRequest_Struct *book) {
|
|||||||
|
|
||||||
BookText_Struct *out = (BookText_Struct *) outapp->pBuffer;
|
BookText_Struct *out = (BookText_Struct *) outapp->pBuffer;
|
||||||
out->window = book->window;
|
out->window = book->window;
|
||||||
|
|
||||||
|
|
||||||
if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
|
|
||||||
// SoF+ need to look up book type for the output message.
|
|
||||||
const EQ::ItemInstance *inst = nullptr;
|
|
||||||
|
|
||||||
if (book->invslot <= EQ::invbag::GENERAL_BAGS_END)
|
|
||||||
{
|
|
||||||
inst = m_inv[book->invslot];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(inst)
|
|
||||||
out->type = inst->GetItem()->Book;
|
|
||||||
else
|
|
||||||
out->type = book->type;
|
out->type = book->type;
|
||||||
}
|
|
||||||
else {
|
|
||||||
out->type = book->type;
|
|
||||||
}
|
|
||||||
out->invslot = book->invslot;
|
out->invslot = book->invslot;
|
||||||
out->target_id = book->target_id;
|
out->target_id = book->target_id;
|
||||||
out->can_cast = 0; // todo: implement
|
out->can_cast = 0; // todo: implement
|
||||||
out->can_scribe = 0; // todo: implement
|
out->can_scribe = false;
|
||||||
|
|
||||||
|
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && book->invslot <= EQ::invbag::GENERAL_BAGS_END)
|
||||||
|
{
|
||||||
|
const EQ::ItemInstance* inst = m_inv[book->invslot];
|
||||||
|
if (inst && inst->GetItem())
|
||||||
|
{
|
||||||
|
auto recipe = TradeskillRecipeRepository::GetWhere(content_db,
|
||||||
|
fmt::format("learned_by_item_id = {} LIMIT 1", inst->GetItem()->ID));
|
||||||
|
out->type = inst->GetItem()->Book;
|
||||||
|
out->can_scribe = !recipe.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(out->booktext, booktxt2.c_str(), length);
|
memcpy(out->booktext, booktxt2.c_str(), length);
|
||||||
|
|
||||||
@@ -2761,31 +2758,48 @@ void Client::CheckLanguageSkillIncrease(uint8 language_id, uint8 teacher_skill)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::HasSkill(EQ::skills::SkillType skill_id) const {
|
bool Client::HasSkill(EQ::skills::SkillType skill_id) const
|
||||||
return((GetSkill(skill_id) > 0) && CanHaveSkill(skill_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Client::CanHaveSkill(EQ::skills::SkillType skill_id) const {
|
|
||||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == Class::Berserker && skill_id == EQ::skills::Skill1HPiercing)
|
|
||||||
skill_id = EQ::skills::Skill2HPiercing;
|
|
||||||
|
|
||||||
return(content_db.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)) > 0);
|
|
||||||
//if you don't have it by max level, then odds are you never will?
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 Client::MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const {
|
|
||||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == Class::Berserker && skillid == EQ::skills::Skill1HPiercing)
|
|
||||||
skillid = EQ::skills::Skill2HPiercing;
|
|
||||||
|
|
||||||
return(content_db.GetSkillCap(class_, skillid, level));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 Client::SkillTrainLevel(EQ::skills::SkillType skillid, uint16 class_)
|
|
||||||
{
|
{
|
||||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == Class::Berserker && skillid == EQ::skills::Skill1HPiercing)
|
return GetSkill(skill_id) > 0 && CanHaveSkill(skill_id);
|
||||||
skillid = EQ::skills::Skill2HPiercing;
|
}
|
||||||
|
|
||||||
return(content_db.GetTrainLevel(class_, skillid, RuleI(Character, MaxLevel)));
|
bool Client::CanHaveSkill(EQ::skills::SkillType skill_id) const
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
ClientVersion() < EQ::versions::ClientVersion::RoF2 &&
|
||||||
|
class_ == Class::Berserker &&
|
||||||
|
skill_id == EQ::skills::Skill1HPiercing
|
||||||
|
) {
|
||||||
|
skill_id = EQ::skills::Skill2HPiercing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return skill_caps.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)).cap > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 Client::MaxSkill(EQ::skills::SkillType skill_id, uint8 class_id, uint8 level) const
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
ClientVersion() < EQ::versions::ClientVersion::RoF2 &&
|
||||||
|
class_id == Class::Berserker &&
|
||||||
|
skill_id == EQ::skills::Skill1HPiercing
|
||||||
|
) {
|
||||||
|
skill_id = EQ::skills::Skill2HPiercing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return skill_caps.GetSkillCap(class_id, skill_id, level).cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 Client::SkillTrainLevel(EQ::skills::SkillType skill_id, uint8 class_id)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
ClientVersion() < EQ::versions::ClientVersion::RoF2 &&
|
||||||
|
class_id == Class::Berserker &&
|
||||||
|
skill_id == EQ::skills::Skill1HPiercing
|
||||||
|
) {
|
||||||
|
skill_id = EQ::skills::Skill2HPiercing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return skill_caps.GetTrainLevel(class_id, skill_id, RuleI(Character, MaxLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Client::GetMaxSkillAfterSpecializationRules(EQ::skills::SkillType skillid, uint16 maxSkill)
|
uint16 Client::GetMaxSkillAfterSpecializationRules(EQ::skills::SkillType skillid, uint16 maxSkill)
|
||||||
@@ -3791,14 +3805,12 @@ void Client::GetRaidAAs(RaidLeadershipAA_Struct *into) const {
|
|||||||
|
|
||||||
void Client::EnteringMessages(Client* client)
|
void Client::EnteringMessages(Client* client)
|
||||||
{
|
{
|
||||||
std::string rules;
|
std::string rules = RuleS(World, Rules);
|
||||||
if (database.GetVariable("Rules", rules)) {
|
|
||||||
uint8 flag = database.GetAgreementFlag(client->AccountID());
|
if (!rules.empty() || database.GetVariable("Rules", rules)) {
|
||||||
|
const uint8 flag = database.GetAgreementFlag(client->AccountID());
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
auto rules_link = Saylink::Silent(
|
const std::string& rules_link = Saylink::Silent("#serverrules", "rules");
|
||||||
"#serverrules",
|
|
||||||
"rules"
|
|
||||||
);
|
|
||||||
|
|
||||||
client->Message(
|
client->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
@@ -3815,9 +3827,9 @@ void Client::EnteringMessages(Client* client)
|
|||||||
|
|
||||||
void Client::SendRules()
|
void Client::SendRules()
|
||||||
{
|
{
|
||||||
std::string rules;
|
std::string rules = RuleS(World, Rules);
|
||||||
|
|
||||||
if (!database.GetVariable("Rules", rules)) {
|
if (rules.empty() && !database.GetVariable("Rules", rules)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4449,7 +4461,7 @@ bool Client::GroupFollow(Client* inviter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//now we have a group id, can set inviter's id
|
//now we have a group id, can set inviter's id
|
||||||
database.SetGroupID(inviter->GetName(), group->GetID(), inviter->CharacterID(), false);
|
group->AddToGroup(inviter);
|
||||||
database.SetGroupLeaderName(group->GetID(), inviter->GetName());
|
database.SetGroupLeaderName(group->GetID(), inviter->GetName());
|
||||||
group->UpdateGroupAAs();
|
group->UpdateGroupAAs();
|
||||||
|
|
||||||
@@ -6285,7 +6297,17 @@ void Client::SendZonePoints()
|
|||||||
zp->zpe[i].z = data->target_z;
|
zp->zpe[i].z = data->target_z;
|
||||||
zp->zpe[i].heading = data->target_heading;
|
zp->zpe[i].heading = data->target_heading;
|
||||||
zp->zpe[i].zoneid = data->target_zone_id;
|
zp->zpe[i].zoneid = data->target_zone_id;
|
||||||
zp->zpe[i].zoneinstance = data->target_zone_instance;
|
|
||||||
|
// if the target zone is the same as the current zone, use the instance of the current zone
|
||||||
|
// if we don't use the same instance_id that the client was sent, the client will forcefully
|
||||||
|
// issue a zone change request when they should be simply moving to a different point in the same zone
|
||||||
|
// because the client will think the zone point target is different from the current instance
|
||||||
|
auto target_instance = data->target_zone_instance;
|
||||||
|
if (data->target_zone_id == zone->GetZoneID() && data->target_zone_instance == 0) {
|
||||||
|
target_instance = zone->GetInstanceID();
|
||||||
|
}
|
||||||
|
|
||||||
|
zp->zpe[i].zoneinstance = target_instance;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
iterator.Advance();
|
iterator.Advance();
|
||||||
@@ -6610,13 +6632,72 @@ void Client::SendAltCurrencies() {
|
|||||||
|
|
||||||
void Client::SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount)
|
void Client::SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount)
|
||||||
{
|
{
|
||||||
|
if (!zone->DoesAlternateCurrencyExist(currency_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 current_amount = alternate_currency[currency_id];
|
||||||
|
|
||||||
|
const bool is_gain = new_amount > current_amount;
|
||||||
|
|
||||||
|
const uint32 change_amount = is_gain ? (new_amount - current_amount) : (current_amount - new_amount);
|
||||||
|
|
||||||
|
if (!change_amount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
alternate_currency[currency_id] = new_amount;
|
alternate_currency[currency_id] = new_amount;
|
||||||
database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_amount);
|
database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_amount);
|
||||||
SendAlternateCurrencyValue(currency_id);
|
SendAlternateCurrencyValue(currency_id);
|
||||||
|
|
||||||
|
QuestEventID event_id = is_gain ? EVENT_ALT_CURRENCY_GAIN : EVENT_ALT_CURRENCY_LOSS;
|
||||||
|
if (parse->PlayerHasQuestSub(event_id)) {
|
||||||
|
const std::string &export_string = fmt::format(
|
||||||
|
"{} {} {}",
|
||||||
|
currency_id,
|
||||||
|
change_amount,
|
||||||
|
new_amount
|
||||||
|
);
|
||||||
|
|
||||||
|
parse->EventPlayer(event_id, this, export_string, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::RemoveAlternateCurrencyValue(uint32 currency_id, uint32 amount)
|
||||||
|
{
|
||||||
|
if (!amount || !zone->DoesAlternateCurrencyExist(currency_id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 current_amount = alternate_currency[currency_id];
|
||||||
|
if (current_amount < amount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 new_amount = (current_amount - amount);
|
||||||
|
|
||||||
|
alternate_currency[currency_id] = new_amount;
|
||||||
|
|
||||||
|
if (parse->PlayerHasQuestSub(EVENT_ALT_CURRENCY_LOSS)) {
|
||||||
|
const std::string &export_string = fmt::format(
|
||||||
|
"{} {} {}",
|
||||||
|
currency_id,
|
||||||
|
amount,
|
||||||
|
new_amount
|
||||||
|
);
|
||||||
|
|
||||||
|
parse->EventPlayer(EVENT_ALT_CURRENCY_LOSS, this, export_string, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted)
|
int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted)
|
||||||
{
|
{
|
||||||
|
if (!zone->DoesAlternateCurrencyExist(currency_id)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */
|
/* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */
|
||||||
if (is_scripted) {
|
if (is_scripted) {
|
||||||
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
|
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
|
||||||
@@ -6655,7 +6736,6 @@ int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_sc
|
|||||||
SendAlternateCurrencyValue(currency_id);
|
SendAlternateCurrencyValue(currency_id);
|
||||||
|
|
||||||
QuestEventID event_id = amount > 0 ? EVENT_ALT_CURRENCY_GAIN : EVENT_ALT_CURRENCY_LOSS;
|
QuestEventID event_id = amount > 0 ? EVENT_ALT_CURRENCY_GAIN : EVENT_ALT_CURRENCY_LOSS;
|
||||||
|
|
||||||
if (parse->PlayerHasQuestSub(event_id)) {
|
if (parse->PlayerHasQuestSub(event_id)) {
|
||||||
const std::string &export_string = fmt::format(
|
const std::string &export_string = fmt::format(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
@@ -6696,6 +6776,10 @@ void Client::SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null)
|
|||||||
|
|
||||||
uint32 Client::GetAlternateCurrencyValue(uint32 currency_id) const
|
uint32 Client::GetAlternateCurrencyValue(uint32 currency_id) const
|
||||||
{
|
{
|
||||||
|
if (!zone->DoesAlternateCurrencyExist(currency_id)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
auto iter = alternate_currency.find(currency_id);
|
auto iter = alternate_currency.find(currency_id);
|
||||||
|
|
||||||
return iter == alternate_currency.end() ? 0 : (*iter).second;
|
return iter == alternate_currency.end() ? 0 : (*iter).second;
|
||||||
@@ -6765,23 +6849,36 @@ void Client::UpdateClientXTarget(Client *c)
|
|||||||
// IT IS NOT SAFE TO CALL THIS IF IT'S NOT INITIAL AGGRO
|
// IT IS NOT SAFE TO CALL THIS IF IT'S NOT INITIAL AGGRO
|
||||||
void Client::AddAutoXTarget(Mob *m, bool send)
|
void Client::AddAutoXTarget(Mob *m, bool send)
|
||||||
{
|
{
|
||||||
|
if (m->IsBot() || ((m->IsPet() || m->IsTempPet()) && m->IsPetOwnerBot())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_activeautohatermgr->increment_count(m);
|
m_activeautohatermgr->increment_count(m);
|
||||||
|
|
||||||
if (!XTargettingAvailable() || !XTargetAutoAddHaters || IsXTarget(m))
|
if (!XTargettingAvailable() || !XTargetAutoAddHaters || IsXTarget(m)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < GetMaxXTargets(); ++i)
|
for (int i = 0; i < GetMaxXTargets(); ++i) {
|
||||||
{
|
if (XTargets[i].Type == Auto && XTargets[i].ID == 0) {
|
||||||
if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0))
|
|
||||||
{
|
|
||||||
XTargets[i].ID = m->GetID();
|
XTargets[i].ID = m->GetID();
|
||||||
if (send) // if we don't send we're bulk sending updates later on
|
|
||||||
|
if (send) { // if we don't send we're bulk sending updates later on
|
||||||
SendXTargetPacket(i, m);
|
SendXTargetPacket(i, m);
|
||||||
else
|
} else {
|
||||||
XTargets[i].dirty = true;
|
XTargets[i].dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogXTargets(
|
||||||
|
"Adding [{}] to [{}] ({}) XTargets",
|
||||||
|
m->GetCleanName(),
|
||||||
|
GetCleanName(),
|
||||||
|
GetID()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots)
|
void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots)
|
||||||
@@ -6795,10 +6892,18 @@ void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots)
|
|||||||
XTargets[i].dirty = true;
|
XTargets[i].dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto r = GetRaid();
|
auto r = GetRaid();
|
||||||
if (r) {
|
if (r) {
|
||||||
r->UpdateRaidXTargets();
|
r->UpdateRaidXTargets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogXTargets(
|
||||||
|
"Removing [{}] from [{}] ({}) XTargets",
|
||||||
|
m->GetCleanName(),
|
||||||
|
GetCleanName(),
|
||||||
|
GetID()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::UpdateXTargetType(XTargetType Type, Mob *m, const char *Name)
|
void Client::UpdateXTargetType(XTargetType Type, Mob *m, const char *Name)
|
||||||
@@ -9140,6 +9245,7 @@ void Client::ShowDevToolsMenu()
|
|||||||
menu_reload_six += " | " + Saylink::Silent("#reload quest", "Quests");
|
menu_reload_six += " | " + Saylink::Silent("#reload quest", "Quests");
|
||||||
|
|
||||||
menu_reload_seven += Saylink::Silent("#reload rules", "Rules");
|
menu_reload_seven += Saylink::Silent("#reload rules", "Rules");
|
||||||
|
menu_reload_seven += " | " + Saylink::Silent("#reload skill_caps", "Skill Caps");
|
||||||
menu_reload_seven += " | " + Saylink::Silent("#reload static", "Static Zone Data");
|
menu_reload_seven += " | " + Saylink::Silent("#reload static", "Static Zone Data");
|
||||||
menu_reload_seven += " | " + Saylink::Silent("#reload tasks", "Tasks");
|
menu_reload_seven += " | " + Saylink::Silent("#reload tasks", "Tasks");
|
||||||
|
|
||||||
@@ -11267,6 +11373,16 @@ void Client::SendReloadCommandMessages() {
|
|||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
auto skill_caps_link = Saylink::Silent("#reload skill_caps");
|
||||||
|
|
||||||
|
Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} - Reloads Skill Caps globally",
|
||||||
|
skill_caps_link
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
auto static_link = Saylink::Silent("#reload static");
|
auto static_link = Saylink::Silent("#reload static");
|
||||||
|
|
||||||
Message(
|
Message(
|
||||||
@@ -11442,6 +11558,39 @@ void Client::SetLockSavePosition(bool lock_save_position)
|
|||||||
Client::m_lock_save_position = lock_save_position;
|
Client::m_lock_save_position = lock_save_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::SetAAPoints(uint32 points)
|
||||||
|
{
|
||||||
|
const uint32 current_points = m_pp.aapoints;
|
||||||
|
|
||||||
|
m_pp.aapoints = points;
|
||||||
|
|
||||||
|
QuestEventID event_id = points > current_points ? EVENT_AA_GAIN : EVENT_AA_LOSS;
|
||||||
|
const uint32 change = event_id == EVENT_AA_GAIN ? points - current_points : current_points - points;
|
||||||
|
|
||||||
|
if (parse->PlayerHasQuestSub(event_id)) {
|
||||||
|
parse->EventPlayer(event_id, this, std::to_string(change), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendAlternateAdvancementStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::RemoveAAPoints(uint32 points)
|
||||||
|
{
|
||||||
|
if (m_pp.aapoints < points) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pp.aapoints -= points;
|
||||||
|
|
||||||
|
if (parse->PlayerHasQuestSub(EVENT_AA_LOSS)) {
|
||||||
|
parse->EventPlayer(EVENT_AA_LOSS, this, std::to_string(points), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendAlternateAdvancementStats();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Client::AddAAPoints(uint32 points)
|
void Client::AddAAPoints(uint32 points)
|
||||||
{
|
{
|
||||||
m_pp.aapoints += points;
|
m_pp.aapoints += points;
|
||||||
@@ -11499,6 +11648,14 @@ void Client::RegisterBug(BugReport_Struct* r) {
|
|||||||
b.bug_report = r->bug_report;
|
b.bug_report = r->bug_report;
|
||||||
b.system_info = r->system_info;
|
b.system_info = r->system_info;
|
||||||
|
|
||||||
|
#ifdef LUA_EQEMU
|
||||||
|
bool ignore_default = false;
|
||||||
|
LuaParser::Instance()->RegisterBug(this, b, ignore_default);
|
||||||
|
if (ignore_default) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
auto n = BugReportsRepository::InsertOne(database, b);
|
auto n = BugReportsRepository::InsertOne(database, b);
|
||||||
if (!n.id) {
|
if (!n.id) {
|
||||||
Message(Chat::White, "Failed to created your bug report."); // Client sends success message
|
Message(Chat::White, "Failed to created your bug report."); // Client sends success message
|
||||||
@@ -11648,7 +11805,7 @@ void Client::MaxSkills()
|
|||||||
auto current_skill_value = (
|
auto current_skill_value = (
|
||||||
EQ::skills::IsSpecializedSkill(s.first) ?
|
EQ::skills::IsSpecializedSkill(s.first) ?
|
||||||
MAX_SPECIALIZED_SKILL :
|
MAX_SPECIALIZED_SKILL :
|
||||||
content_db.GetSkillCap(GetClass(), s.first, GetLevel())
|
skill_caps.GetSkillCap(GetClass(), s.first, GetLevel()).cap
|
||||||
);
|
);
|
||||||
|
|
||||||
if (GetSkill(s.first) < current_skill_value) {
|
if (GetSkill(s.first) < current_skill_value) {
|
||||||
@@ -12194,3 +12351,34 @@ int Client::GetEXPPercentage()
|
|||||||
|
|
||||||
return static_cast<int>(std::round(scaled * 100.0 / 330.0)); // unscaled pct
|
return static_cast<int>(std::round(scaled * 100.0 / 330.0)); // unscaled pct
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Mob*> Client::GetRaidOrGroupOrSelf(bool clients_only)
|
||||||
|
{
|
||||||
|
std::vector<Mob*> v;
|
||||||
|
|
||||||
|
if (IsRaidGrouped()) {
|
||||||
|
Raid* r = GetRaid();
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
for (const auto& m : r->members) {
|
||||||
|
if (m.member && (!m.is_bot || !clients_only)) {
|
||||||
|
v.emplace_back(m.member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (IsGrouped()) {
|
||||||
|
Group* g = GetGroup();
|
||||||
|
|
||||||
|
if (g) {
|
||||||
|
for (const auto& m : g->members) {
|
||||||
|
if (m && (m->IsClient() || !clients_only)) {
|
||||||
|
v.emplace_back(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v.emplace_back(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|||||||
+10
-5
@@ -272,6 +272,8 @@ public:
|
|||||||
int GetQuiverHaste(int delay);
|
int GetQuiverHaste(int delay);
|
||||||
void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false);
|
void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false);
|
||||||
|
|
||||||
|
std::vector<Mob*> GetRaidOrGroupOrSelf(bool clients_only = false);
|
||||||
|
|
||||||
void AI_Init();
|
void AI_Init();
|
||||||
void AI_Start(uint32 iMoveDelay = 0);
|
void AI_Start(uint32 iMoveDelay = 0);
|
||||||
void AI_Stop();
|
void AI_Stop();
|
||||||
@@ -348,6 +350,7 @@ public:
|
|||||||
int GetRecipeMadeCount(uint32 recipe_id);
|
int GetRecipeMadeCount(uint32 recipe_id);
|
||||||
bool HasRecipeLearned(uint32 recipe_id);
|
bool HasRecipeLearned(uint32 recipe_id);
|
||||||
bool CanIncreaseTradeskill(EQ::skills::SkillType tradeskill);
|
bool CanIncreaseTradeskill(EQ::skills::SkillType tradeskill);
|
||||||
|
void ScribeRecipes(uint32_t item_id) const;
|
||||||
|
|
||||||
bool GetRevoked() const { return revoked; }
|
bool GetRevoked() const { return revoked; }
|
||||||
void SetRevoked(bool rev) { revoked = rev; }
|
void SetRevoked(bool rev) { revoked = rev; }
|
||||||
@@ -812,9 +815,9 @@ public:
|
|||||||
void SetHoTT(uint32 mobid);
|
void SetHoTT(uint32 mobid);
|
||||||
void ShowSkillsWindow();
|
void ShowSkillsWindow();
|
||||||
|
|
||||||
uint16 MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const;
|
uint16 MaxSkill(EQ::skills::SkillType skill_id, uint8 class_id, uint8 level) const;
|
||||||
inline uint16 MaxSkill(EQ::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
|
inline uint16 MaxSkill(EQ::skills::SkillType skill_id) const { return MaxSkill(skill_id, GetClass(), GetLevel()); }
|
||||||
uint8 SkillTrainLevel(EQ::skills::SkillType skillid, uint16 class_);
|
uint8 SkillTrainLevel(EQ::skills::SkillType skill_id, uint8 class_id);
|
||||||
void MaxSkills();
|
void MaxSkills();
|
||||||
|
|
||||||
void SendTradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid);
|
void SendTradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid);
|
||||||
@@ -933,8 +936,9 @@ public:
|
|||||||
void ResetAlternateAdvancementTimers();
|
void ResetAlternateAdvancementTimers();
|
||||||
void ResetOnDeathAlternateAdvancement();
|
void ResetOnDeathAlternateAdvancement();
|
||||||
|
|
||||||
void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); }
|
void SetAAPoints(uint32 points);
|
||||||
void AddAAPoints(uint32 points);
|
void AddAAPoints(uint32 points);
|
||||||
|
bool RemoveAAPoints(uint32 points);
|
||||||
int GetAAPoints() { return m_pp.aapoints; }
|
int GetAAPoints() { return m_pp.aapoints; }
|
||||||
int GetSpentAA() { return m_pp.aapoints_spent; }
|
int GetSpentAA() { return m_pp.aapoints_spent; }
|
||||||
uint32 GetRequiredAAExperience();
|
uint32 GetRequiredAAExperience();
|
||||||
@@ -1090,7 +1094,7 @@ public:
|
|||||||
void SetPEQZoneFlag(uint32 zone_id);
|
void SetPEQZoneFlag(uint32 zone_id);
|
||||||
|
|
||||||
bool CanFish();
|
bool CanFish();
|
||||||
void GoFish();
|
void GoFish(bool guarantee = false, bool use_bait = true);
|
||||||
void ForageItem(bool guarantee = false);
|
void ForageItem(bool guarantee = false);
|
||||||
//Calculate vendor price modifier based on CHA: (reverse==selling)
|
//Calculate vendor price modifier based on CHA: (reverse==selling)
|
||||||
float CalcPriceMod(Mob* other = 0, bool reverse = false);
|
float CalcPriceMod(Mob* other = 0, bool reverse = false);
|
||||||
@@ -1539,6 +1543,7 @@ public:
|
|||||||
void SendAltCurrencies();
|
void SendAltCurrencies();
|
||||||
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
|
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
|
||||||
int AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted = false);
|
int AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted = false);
|
||||||
|
bool RemoveAlternateCurrencyValue(uint32 currency_id, uint32 amount);
|
||||||
void SendAlternateCurrencyValues();
|
void SendAlternateCurrencyValues();
|
||||||
void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true);
|
void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true);
|
||||||
uint32 GetAlternateCurrencyValue(uint32 currency_id) const;
|
uint32 GetAlternateCurrencyValue(uint32 currency_id) const;
|
||||||
|
|||||||
+37
-44
@@ -322,11 +322,12 @@ int64 Client::CalcMaxHP()
|
|||||||
//but the actual effect sent on live causes the client
|
//but the actual effect sent on live causes the client
|
||||||
//to apply it to (basehp + itemhp).. I will oblige to the client's whims over
|
//to apply it to (basehp + itemhp).. I will oblige to the client's whims over
|
||||||
//the aa description
|
//the aa description
|
||||||
nd += aabonuses.MaxHP; //Natural Durability, Physical Enhancement, Planar Durability
|
|
||||||
|
nd += aabonuses.MaxHP + spellbonuses.MaxHPChange + itembonuses.MaxHPChange; //Natural Durability, Physical Enhancement, Planar Durability (MaxHP and MaxHPChange are SPA214)
|
||||||
max_hp = (float)max_hp * (float)nd / (float)10000; //this is to fix the HP-above-495k issue
|
max_hp = (float)max_hp * (float)nd / (float)10000; //this is to fix the HP-above-495k issue
|
||||||
max_hp += spellbonuses.HP + aabonuses.HP;
|
max_hp += spellbonuses.HP + aabonuses.HP;
|
||||||
|
|
||||||
max_hp += GroupLeadershipAAHealthEnhancement();
|
max_hp += GroupLeadershipAAHealthEnhancement();
|
||||||
max_hp += max_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f);
|
|
||||||
if (current_hp > max_hp) {
|
if (current_hp > max_hp) {
|
||||||
current_hp = max_hp;
|
current_hp = max_hp;
|
||||||
}
|
}
|
||||||
@@ -523,28 +524,26 @@ int32 Client::GetRawItemAC()
|
|||||||
|
|
||||||
int64 Client::CalcMaxMana()
|
int64 Client::CalcMaxMana()
|
||||||
{
|
{
|
||||||
switch (GetCasterClass()) {
|
if (IsIntelligenceCasterClass() || IsWisdomCasterClass()) {
|
||||||
case 'I':
|
max_mana = (
|
||||||
case 'W': {
|
CalcBaseMana() +
|
||||||
max_mana = (CalcBaseMana() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
|
itembonuses.Mana +
|
||||||
break;
|
spellbonuses.Mana +
|
||||||
}
|
aabonuses.Mana +
|
||||||
case 'N': {
|
GroupLeadershipAAManaEnhancement()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
max_mana = 0;
|
max_mana = 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
LogSpells("Invalid Class [{}] in CalcMaxMana", GetCasterClass());
|
|
||||||
max_mana = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_mana < 0) {
|
if (max_mana < 0) {
|
||||||
max_mana = 0;
|
max_mana = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_mana > max_mana) {
|
if (current_mana > max_mana) {
|
||||||
current_mana = max_mana;
|
current_mana = max_mana;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mana_perc_cap = spellbonuses.ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
int mana_perc_cap = spellbonuses.ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
||||||
if (mana_perc_cap) {
|
if (mana_perc_cap) {
|
||||||
int curMana_cap = (max_mana * mana_perc_cap) / 100;
|
int curMana_cap = (max_mana * mana_perc_cap) / 100;
|
||||||
@@ -552,6 +551,7 @@ int64 Client::CalcMaxMana()
|
|||||||
current_mana = curMana_cap;
|
current_mana = curMana_cap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogSpells("for [{}] returning [{}]", GetName(), max_mana);
|
LogSpells("for [{}] returning [{}]", GetName(), max_mana);
|
||||||
return max_mana;
|
return max_mana;
|
||||||
}
|
}
|
||||||
@@ -564,11 +564,13 @@ int64 Client::CalcBaseMana()
|
|||||||
int64 base_mana = 0;
|
int64 base_mana = 0;
|
||||||
int wisint_mana = 0;
|
int wisint_mana = 0;
|
||||||
int64 max_m = 0;
|
int64 max_m = 0;
|
||||||
switch (GetCasterClass()) {
|
|
||||||
case 'I':
|
if (IsIntelligenceCasterClass()) {
|
||||||
WisInt = GetINT();
|
WisInt = GetINT();
|
||||||
|
|
||||||
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
|
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
|
||||||
ConvertedWisInt = WisInt;
|
ConvertedWisInt = WisInt;
|
||||||
|
|
||||||
int over200 = WisInt;
|
int over200 = WisInt;
|
||||||
if (WisInt > 100) {
|
if (WisInt > 100) {
|
||||||
if (WisInt > 200) {
|
if (WisInt > 200) {
|
||||||
@@ -576,31 +578,32 @@ int64 Client::CalcBaseMana()
|
|||||||
}
|
}
|
||||||
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
|
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
|
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
|
||||||
if (base_data.level == GetLevel()) {
|
if (base_data.level == GetLevel()) {
|
||||||
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
|
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (((WisInt - 199) / 2) > 0) {
|
if (((WisInt - 199) / 2) > 0) {
|
||||||
MindLesserFactor = (WisInt - 199) / 2;
|
MindLesserFactor = (WisInt - 199) / 2;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
MindLesserFactor = 0;
|
MindLesserFactor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MindFactor = WisInt - MindLesserFactor;
|
MindFactor = WisInt - MindLesserFactor;
|
||||||
|
|
||||||
if (WisInt > 100) {
|
if (WisInt > 100) {
|
||||||
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
} else if (IsWisdomCasterClass()) {
|
||||||
case 'W':
|
|
||||||
WisInt = GetWIS();
|
WisInt = GetWIS();
|
||||||
|
|
||||||
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
|
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
|
||||||
ConvertedWisInt = WisInt;
|
ConvertedWisInt = WisInt;
|
||||||
|
|
||||||
int over200 = WisInt;
|
int over200 = WisInt;
|
||||||
if (WisInt > 100) {
|
if (WisInt > 100) {
|
||||||
if (WisInt > 200) {
|
if (WisInt > 200) {
|
||||||
@@ -608,40 +611,30 @@ int64 Client::CalcBaseMana()
|
|||||||
}
|
}
|
||||||
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
|
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
|
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
|
||||||
if (base_data.level == GetLevel()) {
|
if (base_data.level == GetLevel()) {
|
||||||
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
|
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (((WisInt - 199) / 2) > 0) {
|
if (((WisInt - 199) / 2) > 0) {
|
||||||
MindLesserFactor = (WisInt - 199) / 2;
|
MindLesserFactor = (WisInt - 199) / 2;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
MindLesserFactor = 0;
|
MindLesserFactor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MindFactor = WisInt - MindLesserFactor;
|
MindFactor = WisInt - MindLesserFactor;
|
||||||
|
|
||||||
if (WisInt > 100) {
|
if (WisInt > 100) {
|
||||||
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
case 'N': {
|
|
||||||
max_m = 0;
|
max_m = 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default: {
|
|
||||||
LogDebug("Invalid Class [{}] in CalcMaxMana", GetCasterClass());
|
|
||||||
max_m = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if EQDEBUG >= 11
|
|
||||||
LogDebug("Client::CalcBaseMana() called for [{}] - returning [{}]", GetName(), max_m);
|
|
||||||
#endif
|
|
||||||
return max_m;
|
return max_m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-9
@@ -1530,8 +1530,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
} //else, somebody from our group is already here...
|
} //else, somebody from our group is already here...
|
||||||
|
|
||||||
if (!group)
|
if (!group) { //cannot re-establish group, kill it
|
||||||
database.SetGroupID(GetName(), 0, CharacterID(), false); //cannot re-establish group, kill it
|
Group::RemoveFromGroup(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else { //no group id
|
else { //no group id
|
||||||
@@ -4168,10 +4169,11 @@ void Client::Handle_OP_BookButton(const EQApplicationPacket* app)
|
|||||||
BookButton_Struct* book = reinterpret_cast<BookButton_Struct*>(app->pBuffer);
|
BookButton_Struct* book = reinterpret_cast<BookButton_Struct*>(app->pBuffer);
|
||||||
|
|
||||||
const EQ::ItemInstance* const inst = GetInv().GetItem(book->invslot);
|
const EQ::ItemInstance* const inst = GetInv().GetItem(book->invslot);
|
||||||
if (inst && inst->GetItem()->Book)
|
if (inst && inst->GetItem())
|
||||||
{
|
{
|
||||||
// todo: if scribe book learn recipes and delete book from inventory
|
// todo: cast spell button (unknown if anything on live uses this)
|
||||||
// todo: if cast book use its spell on target and delete book from inventory (unless reusable?)
|
ScribeRecipes(inst->GetItem()->ID);
|
||||||
|
DeleteItemInInventory(book->invslot, 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket outapp(OP_FinishWindow, 0);
|
EQApplicationPacket outapp(OP_FinishWindow, 0);
|
||||||
@@ -5595,9 +5597,20 @@ void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prevent the client from creating more than they have.
|
// Prevent the client from creating more than they have.
|
||||||
const uint32 amount = EQ::ClampUpper(quantity, current_quantity);
|
uint32 amount = EQ::ClampUpper(quantity, current_quantity);
|
||||||
const uint32 item_id = is_radiant ? RuleI(Zone, RadiantCrystalItemID) : RuleI(Zone, EbonCrystalItemID);
|
const uint32 item_id = is_radiant ? RuleI(Zone, RadiantCrystalItemID) : RuleI(Zone, EbonCrystalItemID);
|
||||||
|
|
||||||
|
const auto item = database.GetItem(item_id);
|
||||||
|
// Prevent pulling more than max stack size or 1,000 (if stackable), whichever is lesser
|
||||||
|
const uint32 max_reclaim_amount = EQ::Clamp(
|
||||||
|
item && item->Stackable ? item->StackSize : ItemStackSizeConstraint::Minimum,
|
||||||
|
ItemStackSizeConstraint::Minimum,
|
||||||
|
ItemStackSizeConstraint::Maximum
|
||||||
|
);
|
||||||
|
if (amount > max_reclaim_amount) {
|
||||||
|
amount = max_reclaim_amount;
|
||||||
|
}
|
||||||
|
|
||||||
const bool success = SummonItem(item_id, amount);
|
const bool success = SummonItem(item_id, amount);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return;
|
return;
|
||||||
@@ -6862,7 +6875,7 @@ void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app)
|
|||||||
Client *c = entity_list.GetClientByName(gmn->oldname);
|
Client *c = entity_list.GetClientByName(gmn->oldname);
|
||||||
LogInfo("GM([{}]) changeing players name. Old:[{}] New:[{}]", GetName(), gmn->oldname, gmn->newname);
|
LogInfo("GM([{}]) changeing players name. Old:[{}] New:[{}]", GetName(), gmn->oldname, gmn->newname);
|
||||||
|
|
||||||
const bool used_name = database.CheckUsedName(gmn->newname);
|
const bool used_name = database.IsNameUsed(gmn->newname);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
Message(Chat::Red, fmt::format("{} not found for name change. Operation failed!", gmn->oldname).c_str());
|
Message(Chat::Red, fmt::format("{} not found for name change. Operation failed!", gmn->oldname).c_str());
|
||||||
return;
|
return;
|
||||||
@@ -6873,7 +6886,7 @@ void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!used_name) {
|
if (used_name) {
|
||||||
Message(Chat::Red, fmt::format("{} is already in use. Operation failed!", gmn->newname).c_str());
|
Message(Chat::Red, fmt::format("{} is already in use. Operation failed!", gmn->newname).c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -7177,7 +7190,7 @@ void Client::Handle_OP_GroupCancelInvite(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
if (!GetMerc())
|
if (!GetMerc())
|
||||||
{
|
{
|
||||||
database.SetGroupID(GetName(), 0, CharacterID(), false);
|
Group::RemoveFromGroup(this);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1064,9 +1064,9 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
|
|||||||
);
|
);
|
||||||
SpellOnTarget(resurrection_sickness_spell_id, this);
|
SpellOnTarget(resurrection_sickness_spell_id, this);
|
||||||
} else if (SpellID == SPELL_DIVINE_REZ) {
|
} else if (SpellID == SPELL_DIVINE_REZ) {
|
||||||
SetHP(GetMaxHP());
|
RestoreHealth();
|
||||||
SetMana(GetMaxMana());
|
RestoreMana();
|
||||||
SetEndurance(GetMaxEndurance());
|
RestoreEndurance();
|
||||||
} else {
|
} else {
|
||||||
SetHP(GetMaxHP() / 20);
|
SetHP(GetMaxHP() / 20);
|
||||||
SetMana(GetMaxMana() / 20);
|
SetMana(GetMaxMana() / 20);
|
||||||
@@ -2177,9 +2177,9 @@ void Client::HandleRespawnFromHover(uint32 Option)
|
|||||||
FastQueuePacket(&outapp);
|
FastQueuePacket(&outapp);
|
||||||
|
|
||||||
CalcBonuses();
|
CalcBonuses();
|
||||||
SetHP(GetMaxHP());
|
RestoreHealth();
|
||||||
SetMana(GetMaxMana());
|
RestoreMana();
|
||||||
SetEndurance(GetMaxEndurance());
|
RestoreEndurance();
|
||||||
|
|
||||||
m_Position.x = chosen->x;
|
m_Position.x = chosen->x;
|
||||||
m_Position.y = chosen->y;
|
m_Position.y = chosen->y;
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ int command_init(void)
|
|||||||
command_add("feature", "Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) ||
|
command_add("feature", "Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) ||
|
||||||
command_add("size", "Change your targets size (alias of #feature size)", AccountStatus::QuestTroupe, command_feature) ||
|
command_add("size", "Change your targets size (alias of #feature size)", AccountStatus::QuestTroupe, command_feature) ||
|
||||||
command_add("find", "Search command used to find various things", AccountStatus::Guide, command_find) ||
|
command_add("find", "Search command used to find various things", AccountStatus::Guide, command_find) ||
|
||||||
|
command_add("fish", "Fish for an item", AccountStatus::QuestTroupe, command_fish) ||
|
||||||
command_add("fixmob", "[race|gender|texture|helm|face|hair|haircolor|beard|beardcolor|heritage|tattoo|detail] [next|prev] - Manipulate appearance of your target", AccountStatus::QuestTroupe, command_fixmob) ||
|
command_add("fixmob", "[race|gender|texture|helm|face|hair|haircolor|beard|beardcolor|heritage|tattoo|detail] [next|prev] - Manipulate appearance of your target", AccountStatus::QuestTroupe, command_fixmob) ||
|
||||||
command_add("flagedit", "Edit zone flags on your target. Use #flagedit help for more info.", AccountStatus::GMAdmin, command_flagedit) ||
|
command_add("flagedit", "Edit zone flags on your target. Use #flagedit help for more info.", AccountStatus::GMAdmin, command_flagedit) ||
|
||||||
command_add("forage", "Forage an item", AccountStatus::QuestTroupe, command_forage) ||
|
command_add("forage", "Forage an item", AccountStatus::QuestTroupe, command_forage) ||
|
||||||
@@ -207,6 +208,7 @@ int command_init(void)
|
|||||||
command_add("scribespells", "[Max level] [Min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_scribespells) ||
|
command_add("scribespells", "[Max level] [Min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_scribespells) ||
|
||||||
command_add("sendzonespawns", "Refresh spawn list for all clients in zone", AccountStatus::GMLeadAdmin, command_sendzonespawns) ||
|
command_add("sendzonespawns", "Refresh spawn list for all clients in zone", AccountStatus::GMLeadAdmin, command_sendzonespawns) ||
|
||||||
command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", AccountStatus::Player, command_sensetrap) ||
|
command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", AccountStatus::Player, command_sensetrap) ||
|
||||||
|
command_add("serverrules", "Show server rules", AccountStatus::Player, command_serverrules) ||
|
||||||
command_add("set", "Set command used to set various things", AccountStatus::Guide, command_set) ||
|
command_add("set", "Set command used to set various things", AccountStatus::Guide, command_set) ||
|
||||||
command_add("show", "Show command used to show various things", AccountStatus::Guide, command_show) ||
|
command_add("show", "Show command used to show various things", AccountStatus::Guide, command_show) ||
|
||||||
command_add("shutdown", "Shut this zone process down", AccountStatus::GMLeadAdmin, command_shutdown) ||
|
command_add("shutdown", "Shut this zone process down", AccountStatus::GMLeadAdmin, command_shutdown) ||
|
||||||
@@ -823,6 +825,7 @@ void command_bot(Client *c, const Seperator *sep)
|
|||||||
#include "gm_commands/faction.cpp"
|
#include "gm_commands/faction.cpp"
|
||||||
#include "gm_commands/feature.cpp"
|
#include "gm_commands/feature.cpp"
|
||||||
#include "gm_commands/find.cpp"
|
#include "gm_commands/find.cpp"
|
||||||
|
#include "gm_commands/fish.cpp"
|
||||||
#include "gm_commands/fixmob.cpp"
|
#include "gm_commands/fixmob.cpp"
|
||||||
#include "gm_commands/flagedit.cpp"
|
#include "gm_commands/flagedit.cpp"
|
||||||
#include "gm_commands/forage.cpp"
|
#include "gm_commands/forage.cpp"
|
||||||
@@ -895,6 +898,7 @@ void command_bot(Client *c, const Seperator *sep)
|
|||||||
#include "gm_commands/scribespells.cpp"
|
#include "gm_commands/scribespells.cpp"
|
||||||
#include "gm_commands/sendzonespawns.cpp"
|
#include "gm_commands/sendzonespawns.cpp"
|
||||||
#include "gm_commands/sensetrap.cpp"
|
#include "gm_commands/sensetrap.cpp"
|
||||||
|
#include "gm_commands/serverrules.cpp"
|
||||||
#include "gm_commands/set.cpp"
|
#include "gm_commands/set.cpp"
|
||||||
#include "gm_commands/show.cpp"
|
#include "gm_commands/show.cpp"
|
||||||
#include "gm_commands/shutdown.cpp"
|
#include "gm_commands/shutdown.cpp"
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ void command_faction(Client *c, const Seperator *sep);
|
|||||||
void command_faction_association(Client *c, const Seperator *sep);
|
void command_faction_association(Client *c, const Seperator *sep);
|
||||||
void command_feature(Client *c, const Seperator *sep);
|
void command_feature(Client *c, const Seperator *sep);
|
||||||
void command_find(Client *c, const Seperator *sep);
|
void command_find(Client *c, const Seperator *sep);
|
||||||
|
void command_fish(Client* c, const Seperator* sep);
|
||||||
void command_fixmob(Client *c, const Seperator *sep);
|
void command_fixmob(Client *c, const Seperator *sep);
|
||||||
void command_flagedit(Client *c, const Seperator *sep);
|
void command_flagedit(Client *c, const Seperator *sep);
|
||||||
void command_forage(Client* c, const Seperator* sep);
|
void command_forage(Client* c, const Seperator* sep);
|
||||||
|
|||||||
+14
-7
@@ -19,9 +19,11 @@
|
|||||||
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
|
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
|
||||||
#define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS
|
#define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS
|
||||||
|
|
||||||
#define ARCHETYPE_HYBRID 1
|
namespace Archetype {
|
||||||
#define ARCHETYPE_CASTER 2
|
constexpr uint8 Hybrid = 1;
|
||||||
#define ARCHETYPE_MELEE 3
|
constexpr uint8 Caster = 2;
|
||||||
|
constexpr uint8 Melee = 3;
|
||||||
|
};
|
||||||
|
|
||||||
#define CON_GREEN 2
|
#define CON_GREEN 2
|
||||||
#define CON_LIGHTBLUE 18
|
#define CON_LIGHTBLUE 18
|
||||||
@@ -285,7 +287,7 @@ struct StatBonuses {
|
|||||||
int32 AC;
|
int32 AC;
|
||||||
int64 HP;
|
int64 HP;
|
||||||
int64 HPRegen;
|
int64 HPRegen;
|
||||||
int64 MaxHP;
|
int64 MaxHP; //same bonus as MaxHPChange when applied to spells and item bonuses
|
||||||
int64 ManaRegen;
|
int64 ManaRegen;
|
||||||
int64 EnduranceRegen;
|
int64 EnduranceRegen;
|
||||||
int64 Mana;
|
int64 Mana;
|
||||||
@@ -411,7 +413,7 @@ struct StatBonuses {
|
|||||||
int32 MeleeLifetap; //i
|
int32 MeleeLifetap; //i
|
||||||
int32 Vampirism; //i
|
int32 Vampirism; //i
|
||||||
int32 HealRate; // Spell effect that influences effectiveness of heals
|
int32 HealRate; // Spell effect that influences effectiveness of heals
|
||||||
int32 MaxHPChange; // Spell Effect
|
int32 MaxHPChange; // percent change in hit points (aabonuses use variable MaxHP)
|
||||||
int16 SkillDmgTaken[EQ::skills::HIGHEST_SKILL + 2]; // All Skills + -1
|
int16 SkillDmgTaken[EQ::skills::HIGHEST_SKILL + 2]; // All Skills + -1
|
||||||
int32 HealAmt; // Item Effect
|
int32 HealAmt; // Item Effect
|
||||||
int32 SpellDmg; // Item Effect
|
int32 SpellDmg; // Item Effect
|
||||||
@@ -443,7 +445,8 @@ struct StatBonuses {
|
|||||||
int32 SongRange; // increases range of beneficial bard songs
|
int32 SongRange; // increases range of beneficial bard songs
|
||||||
uint32 HPToManaConvert; // Uses HP to cast spells at specific conversion
|
uint32 HPToManaConvert; // Uses HP to cast spells at specific conversion
|
||||||
int32 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
|
int32 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
|
||||||
int16 FocusEffectsWorn[HIGHEST_FOCUS+1]; // Optional to allow focus effects to be applied additively from worn slot
|
int16 FocusEffectsWorn[HIGHEST_FOCUS+1]; // Optional to allow focus effects to be applied additively from worn slot, limits do not apply
|
||||||
|
int32 FocusEffectsWornWithLimits[HIGHEST_FOCUS + 1];// Optional to allow focus effects to be applied additively from worn slot, limits apply
|
||||||
bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses)
|
bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses)
|
||||||
int32 SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 2]; // Adds skill specific damage
|
int32 SkillDamageAmount2[EQ::skills::HIGHEST_SKILL + 2]; // Adds skill specific damage
|
||||||
uint32 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit
|
uint32 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit
|
||||||
@@ -509,6 +512,7 @@ struct StatBonuses {
|
|||||||
uint8 invisibility; // invisibility level
|
uint8 invisibility; // invisibility level
|
||||||
uint8 invisibility_verse_undead; // IVU level
|
uint8 invisibility_verse_undead; // IVU level
|
||||||
uint8 invisibility_verse_animal; // IVA level
|
uint8 invisibility_verse_animal; // IVA level
|
||||||
|
int32 ShieldTargetSpa[2]; // [0] base = % mitigation amount, [1] buff slot
|
||||||
|
|
||||||
// AAs
|
// AAs
|
||||||
int32 TrapCircumvention; // reduce chance to trigger a trap.
|
int32 TrapCircumvention; // reduce chance to trigger a trap.
|
||||||
@@ -654,6 +658,8 @@ namespace SBIndex {
|
|||||||
constexpr uint16 COMBAT_PROC_SPELL_ID = 1; // SPA
|
constexpr uint16 COMBAT_PROC_SPELL_ID = 1; // SPA
|
||||||
constexpr uint16 COMBAT_PROC_RATE_MOD = 2; // SPA
|
constexpr uint16 COMBAT_PROC_RATE_MOD = 2; // SPA
|
||||||
constexpr uint16 COMBAT_PROC_REUSE_TIMER = 3; // SPA
|
constexpr uint16 COMBAT_PROC_REUSE_TIMER = 3; // SPA
|
||||||
|
constexpr uint16 SHIELD_TARGET_MITIGATION_PERCENT = 0; // SPA 463
|
||||||
|
constexpr uint16 SHIELD_TARGET_BUFFSLOT = 1; // SPA 463
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -826,7 +832,8 @@ struct ExtraAttackOptions {
|
|||||||
armor_pen_percent(0.0f), armor_pen_flat(0),
|
armor_pen_percent(0.0f), armor_pen_flat(0),
|
||||||
crit_percent(1.0f), crit_flat(0.0f),
|
crit_percent(1.0f), crit_flat(0.0f),
|
||||||
hate_percent(1.0f), hate_flat(0), hit_chance(0),
|
hate_percent(1.0f), hate_flat(0), hit_chance(0),
|
||||||
melee_damage_bonus_flat(0), skilldmgtaken_bonus_flat(0)
|
melee_damage_bonus_flat(0), skilldmgtaken_bonus_flat(0),
|
||||||
|
range_percent(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
float damage_percent;
|
float damage_percent;
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
|||||||
if (responses.size() > 1) {
|
if (responses.size() > 1) {
|
||||||
for (auto &r: responses) {
|
for (auto &r: responses) {
|
||||||
bracket_responses.emplace_back(
|
bracket_responses.emplace_back(
|
||||||
fmt::format("[{}]", Saylink::Create(r, false))
|
fmt::format("[{}]", Saylink::Create(r))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,15 @@ Doors::Doors(const DoorsRepository::Doors &door) :
|
|||||||
m_door_param = door.door_param;
|
m_door_param = door.door_param;
|
||||||
m_size = door.size;
|
m_size = door.size;
|
||||||
m_invert_state = door.invert_state;
|
m_invert_state = door.invert_state;
|
||||||
|
|
||||||
|
// if the target zone is the same as the current zone, use the instance of the current zone
|
||||||
|
// if we don't use the same instance_id that the client was sent, the client will forcefully
|
||||||
|
// issue a zone change request when they should be simply moving to a different point in the same zone
|
||||||
|
// because the client will think the zone point target is different from the current instance
|
||||||
|
if (door.dest_zone == zone->GetShortName() && m_destination_instance_id == 0) {
|
||||||
|
m_destination_instance_id = zone->GetInstanceID();
|
||||||
|
}
|
||||||
|
|
||||||
m_destination_instance_id = door.dest_instance;
|
m_destination_instance_id = door.dest_instance;
|
||||||
m_is_ldon_door = door.is_ldon_door;
|
m_is_ldon_door = door.is_ldon_door;
|
||||||
m_dz_switch_id = door.dz_switch_id;
|
m_dz_switch_id = door.dz_switch_id;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ void perl_register_doors();
|
|||||||
void perl_register_expedition();
|
void perl_register_expedition();
|
||||||
void perl_register_expedition_lock_messages();
|
void perl_register_expedition_lock_messages();
|
||||||
void perl_register_bot();
|
void perl_register_bot();
|
||||||
|
void perl_register_buff();
|
||||||
#endif // EMBPERL_XS_CLASSES
|
#endif // EMBPERL_XS_CLASSES
|
||||||
#endif // EMBPERL_XS
|
#endif // EMBPERL_XS
|
||||||
|
|
||||||
@@ -200,6 +201,8 @@ const char* QuestEventSubroutines[_LargestEventID] = {
|
|||||||
"EVENT_ENTITY_VARIABLE_DELETE",
|
"EVENT_ENTITY_VARIABLE_DELETE",
|
||||||
"EVENT_ENTITY_VARIABLE_SET",
|
"EVENT_ENTITY_VARIABLE_SET",
|
||||||
"EVENT_ENTITY_VARIABLE_UPDATE",
|
"EVENT_ENTITY_VARIABLE_UPDATE",
|
||||||
|
"EVENT_AA_LOSS",
|
||||||
|
"EVENT_SPELL_BLOCKED",
|
||||||
|
|
||||||
// Add new events before these or Lua crashes
|
// Add new events before these or Lua crashes
|
||||||
"EVENT_SPELL_EFFECT_BOT",
|
"EVENT_SPELL_EFFECT_BOT",
|
||||||
@@ -1174,6 +1177,7 @@ void PerlembParser::MapFunctions()
|
|||||||
perl_register_expedition();
|
perl_register_expedition();
|
||||||
perl_register_expedition_lock_messages();
|
perl_register_expedition_lock_messages();
|
||||||
perl_register_bot();
|
perl_register_bot();
|
||||||
|
perl_register_buff();
|
||||||
#endif // EMBPERL_XS_CLASSES
|
#endif // EMBPERL_XS_CLASSES
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1934,6 +1938,25 @@ void PerlembParser::ExportEventVariables(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EVENT_SPELL_BLOCKED: {
|
||||||
|
Seperator sep(data);
|
||||||
|
const uint32 blocking_spell_id = Strings::ToUnsignedInt(sep.arg[0]);
|
||||||
|
const uint32 cast_spell_id = Strings::ToUnsignedInt(sep.arg[1]);
|
||||||
|
|
||||||
|
ExportVar(package_name.c_str(), "blocking_spell_id", blocking_spell_id);
|
||||||
|
ExportVar(package_name.c_str(), "cast_spell_id", cast_spell_id);
|
||||||
|
|
||||||
|
if (IsValidSpell(blocking_spell_id)) {
|
||||||
|
ExportVar(package_name.c_str(), "blocking_spell", "Spell", (void*) &spells[blocking_spell_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsValidSpell(cast_spell_id)) {
|
||||||
|
ExportVar(package_name.c_str(), "cast_spell", "Spell", (void*) &spells[cast_spell_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//tradeskill events
|
//tradeskill events
|
||||||
case EVENT_COMBINE_SUCCESS:
|
case EVENT_COMBINE_SUCCESS:
|
||||||
case EVENT_COMBINE_FAILURE: {
|
case EVENT_COMBINE_FAILURE: {
|
||||||
@@ -2273,6 +2296,11 @@ void PerlembParser::ExportEventVariables(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EVENT_AA_LOSS: {
|
||||||
|
ExportVar(package_name.c_str(), "aa_lost", data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case EVENT_AA_EXP_GAIN: {
|
case EVENT_AA_EXP_GAIN: {
|
||||||
ExportVar(package_name.c_str(), "aa_exp_gained", data);
|
ExportVar(package_name.c_str(), "aa_exp_gained", data);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+45
-18
@@ -380,12 +380,12 @@ void Perl__settimer(std::string timer_name, uint32 seconds)
|
|||||||
|
|
||||||
void Perl__settimer(std::string timer_name, uint32 seconds, Mob* m)
|
void Perl__settimer(std::string timer_name, uint32 seconds, Mob* m)
|
||||||
{
|
{
|
||||||
quest_manager.settimer(timer_name, seconds);
|
quest_manager.settimer(timer_name, seconds, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__settimer(std::string timer_name, uint32 seconds, EQ::ItemInstance* inst)
|
void Perl__settimer(std::string timer_name, uint32 seconds, EQ::ItemInstance* inst)
|
||||||
{
|
{
|
||||||
quest_manager.settimer(timer_name, seconds);
|
quest_manager.settimerMS(timer_name, seconds * 1000, inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__settimerMS(std::string timer_name, uint32 milliseconds)
|
void Perl__settimerMS(std::string timer_name, uint32 milliseconds)
|
||||||
@@ -1579,9 +1579,7 @@ std::string Perl__GetCharactersInInstance(uint16 instance_id)
|
|||||||
char_id_string = fmt::format("{} player(s) in instance: ", character_ids.size());
|
char_id_string = fmt::format("{} player(s) in instance: ", character_ids.size());
|
||||||
auto iter = character_ids.begin();
|
auto iter = character_ids.begin();
|
||||||
while (iter != character_ids.end()) {
|
while (iter != character_ids.end()) {
|
||||||
char char_name[64];
|
char_id_string += database.GetCharName(*iter);
|
||||||
database.GetCharName(*iter, char_name);
|
|
||||||
char_id_string += char_name;
|
|
||||||
char_id_string += "(";
|
char_id_string += "(";
|
||||||
char_id_string += itoa(*iter);
|
char_id_string += itoa(*iter);
|
||||||
char_id_string += ")";
|
char_id_string += ")";
|
||||||
@@ -1654,20 +1652,19 @@ void Perl__FlagInstanceByRaidLeader(uint32 zone, uint16 version)
|
|||||||
quest_manager.FlagInstanceByRaidLeader(zone, version);
|
quest_manager.FlagInstanceByRaidLeader(zone, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Perl__saylink(const char* text)
|
std::string Perl__saylink(std::string text)
|
||||||
{
|
{
|
||||||
// const cast is safe since, target api doesn't modify it
|
return Saylink::Create(text);
|
||||||
return quest_manager.saylink(const_cast<char*>(text), false, text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Perl__saylink(const char* text, bool silent)
|
std::string Perl__saylink(std::string text, bool silent)
|
||||||
{
|
{
|
||||||
return quest_manager.saylink(const_cast<char*>(text), silent, text);
|
return Saylink::Create(text, silent);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Perl__saylink(const char* text, bool silent, const char* link_name)
|
std::string Perl__saylink(std::string text, bool silent, std::string link_name)
|
||||||
{
|
{
|
||||||
return quest_manager.saylink(const_cast<char*>(text), silent, link_name);
|
return Saylink::Create(text, silent, link_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Perl__getcharnamebyid(uint32 char_id)
|
std::string Perl__getcharnamebyid(uint32 char_id)
|
||||||
@@ -5833,6 +5830,31 @@ uint16 Perl__GetBotRaceByID(uint32 bot_id)
|
|||||||
return database.botdb.GetBotRaceByID(bot_id);
|
return database.botdb.GetBotRaceByID(bot_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Perl__silent_saylink(std::string text)
|
||||||
|
{
|
||||||
|
return Saylink::Silent(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Perl__silent_saylink(std::string text, std::string link_name)
|
||||||
|
{
|
||||||
|
return Saylink::Silent(text, link_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 Perl__get_class_bitmask(uint8 class_id)
|
||||||
|
{
|
||||||
|
return GetPlayerClassBit(class_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Perl__get_deity_bitmask(uint16 deity_id)
|
||||||
|
{
|
||||||
|
return static_cast<uint32>(EQ::deity::GetDeityBitmask(static_cast<EQ::deity::DeityType>(deity_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 Perl__get_race_bitmask(uint16 race_id)
|
||||||
|
{
|
||||||
|
return GetPlayerRaceBit(race_id);
|
||||||
|
}
|
||||||
|
|
||||||
void perl_register_quest()
|
void perl_register_quest()
|
||||||
{
|
{
|
||||||
perl::interpreter perl(PERL_GET_THX);
|
perl::interpreter perl(PERL_GET_THX);
|
||||||
@@ -6479,9 +6501,11 @@ void perl_register_quest()
|
|||||||
package.add("getconsiderlevelname", &Perl__getconsiderlevelname);
|
package.add("getconsiderlevelname", &Perl__getconsiderlevelname);
|
||||||
package.add("gethexcolorcode", &Perl__gethexcolorcode);
|
package.add("gethexcolorcode", &Perl__gethexcolorcode);
|
||||||
package.add("getcurrencyid", &Perl__getcurrencyid);
|
package.add("getcurrencyid", &Perl__getcurrencyid);
|
||||||
|
package.add("get_class_bitmask", &Perl__get_class_bitmask);
|
||||||
package.add("get_data", &Perl__get_data);
|
package.add("get_data", &Perl__get_data);
|
||||||
package.add("get_data_expires", &Perl__get_data_expires);
|
package.add("get_data_expires", &Perl__get_data_expires);
|
||||||
package.add("get_data_remaining", &Perl__get_data_remaining);
|
package.add("get_data_remaining", &Perl__get_data_remaining);
|
||||||
|
package.add("get_deity_bitmask", &Perl__get_deity_bitmask);
|
||||||
package.add("get_dz_task_id", &Perl__get_dz_task_id);
|
package.add("get_dz_task_id", &Perl__get_dz_task_id);
|
||||||
package.add("getexpmodifierbycharid", (double(*)(uint32, uint32))&Perl__getexpmodifierbycharid);
|
package.add("getexpmodifierbycharid", (double(*)(uint32, uint32))&Perl__getexpmodifierbycharid);
|
||||||
package.add("getexpmodifierbycharid", (double(*)(uint32, uint32, int16))&Perl__getexpmodifierbycharid);
|
package.add("getexpmodifierbycharid", (double(*)(uint32, uint32, int16))&Perl__getexpmodifierbycharid);
|
||||||
@@ -6514,6 +6538,7 @@ void perl_register_quest()
|
|||||||
package.add("getgroupidbycharid", &Perl__getgroupidbycharid);
|
package.add("getgroupidbycharid", &Perl__getgroupidbycharid);
|
||||||
package.add("getinventoryslotname", &Perl__getinventoryslotname);
|
package.add("getinventoryslotname", &Perl__getinventoryslotname);
|
||||||
package.add("getraididbycharid", &Perl__getraididbycharid);
|
package.add("getraididbycharid", &Perl__getraididbycharid);
|
||||||
|
package.add("get_race_bitmask", &Perl__get_race_bitmask);
|
||||||
package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs);
|
package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs);
|
||||||
package.add("get_recipe_container_item_ids", &Perl__GetRecipeContainerItemIDs);
|
package.add("get_recipe_container_item_ids", &Perl__GetRecipeContainerItemIDs);
|
||||||
package.add("get_recipe_fail_item_ids", &Perl__GetRecipeFailItemIDs);
|
package.add("get_recipe_fail_item_ids", &Perl__GetRecipeFailItemIDs);
|
||||||
@@ -6644,9 +6669,9 @@ void perl_register_quest()
|
|||||||
package.add("say", (void(*)(const char*, uint8, int))&Perl__say);
|
package.add("say", (void(*)(const char*, uint8, int))&Perl__say);
|
||||||
package.add("say", (void(*)(const char*, uint8, int, int))&Perl__say);
|
package.add("say", (void(*)(const char*, uint8, int, int))&Perl__say);
|
||||||
package.add("say", (void(*)(const char*, uint8, int, int, int))&Perl__say);
|
package.add("say", (void(*)(const char*, uint8, int, int, int))&Perl__say);
|
||||||
package.add("saylink", (std::string(*)(const char*))&Perl__saylink);
|
package.add("saylink", (std::string(*)(std::string))&Perl__saylink);
|
||||||
package.add("saylink", (std::string(*)(const char*, bool))&Perl__saylink);
|
package.add("saylink", (std::string(*)(std::string, bool))&Perl__saylink);
|
||||||
package.add("saylink", (std::string(*)(const char*, bool, const char*))&Perl__saylink);
|
package.add("saylink", (std::string(*)(std::string, bool, std::string))&Perl__saylink);
|
||||||
package.add("scribespells", (int(*)(int))&Perl__scribespells);
|
package.add("scribespells", (int(*)(int))&Perl__scribespells);
|
||||||
package.add("scribespells", (int(*)(int, int))&Perl__scribespells);
|
package.add("scribespells", (int(*)(int, int))&Perl__scribespells);
|
||||||
package.add("secondstotime", &Perl__secondstotime);
|
package.add("secondstotime", &Perl__secondstotime);
|
||||||
@@ -6684,9 +6709,9 @@ void perl_register_quest()
|
|||||||
package.add("settarget", &Perl__settarget);
|
package.add("settarget", &Perl__settarget);
|
||||||
package.add("settime", (void(*)(int, int))&Perl__settime);
|
package.add("settime", (void(*)(int, int))&Perl__settime);
|
||||||
package.add("settime", (void(*)(int, int, bool))&Perl__settime);
|
package.add("settime", (void(*)(int, int, bool))&Perl__settime);
|
||||||
package.add("settimer", (void(*)(std::string, uint32))&Perl__settimer),
|
package.add("settimer", (void(*)(std::string, uint32))&Perl__settimer);
|
||||||
package.add("settimer", (void(*)(std::string, uint32, EQ::ItemInstance*))&Perl__settimer),
|
package.add("settimer", (void(*)(std::string, uint32, EQ::ItemInstance*))&Perl__settimer);
|
||||||
package.add("settimer", (void(*)(std::string, uint32, Mob*))&Perl__settimer),
|
package.add("settimer", (void(*)(std::string, uint32, Mob*))&Perl__settimer);
|
||||||
package.add("settimerMS", (void(*)(std::string, uint32))&Perl__settimerMS);
|
package.add("settimerMS", (void(*)(std::string, uint32))&Perl__settimerMS);
|
||||||
package.add("settimerMS", (void(*)(std::string, uint32, EQ::ItemInstance*))&Perl__settimerMS);
|
package.add("settimerMS", (void(*)(std::string, uint32, EQ::ItemInstance*))&Perl__settimerMS);
|
||||||
package.add("settimerMS", (void(*)(std::string, uint32, Mob*))&Perl__settimerMS);
|
package.add("settimerMS", (void(*)(std::string, uint32, Mob*))&Perl__settimerMS);
|
||||||
@@ -6698,6 +6723,8 @@ void perl_register_quest()
|
|||||||
package.add("signal", (void(*)(int, int))&Perl__signal);
|
package.add("signal", (void(*)(int, int))&Perl__signal);
|
||||||
package.add("signalwith", (void(*)(int, int))&Perl__signalwith);
|
package.add("signalwith", (void(*)(int, int))&Perl__signalwith);
|
||||||
package.add("signalwith", (void(*)(int, int, int))&Perl__signalwith);
|
package.add("signalwith", (void(*)(int, int, int))&Perl__signalwith);
|
||||||
|
package.add("silent_saylink", (std::string(*)(std::string))&Perl__silent_saylink);
|
||||||
|
package.add("silent_saylink", (std::string(*)(std::string, std::string))&Perl__silent_saylink);
|
||||||
package.add("snow", &Perl__snow);
|
package.add("snow", &Perl__snow);
|
||||||
package.add("spawn", &Perl__spawn);
|
package.add("spawn", &Perl__spawn);
|
||||||
package.add("spawn2", &Perl__spawn2);
|
package.add("spawn2", &Perl__spawn2);
|
||||||
|
|||||||
+14
-5
@@ -2152,7 +2152,7 @@ Group *EntityList::GetGroupByLeaderName(const char *leader)
|
|||||||
iterator = group_list.begin();
|
iterator = group_list.begin();
|
||||||
|
|
||||||
while (iterator != group_list.end()) {
|
while (iterator != group_list.end()) {
|
||||||
if (!strcmp((*iterator)->GetLeaderName(), leader))
|
if (!strcmp((*iterator)->GetLeaderName().c_str(), leader))
|
||||||
return *iterator;
|
return *iterator;
|
||||||
++iterator;
|
++iterator;
|
||||||
}
|
}
|
||||||
@@ -2675,6 +2675,10 @@ void EntityList::RemoveAllMobs()
|
|||||||
{
|
{
|
||||||
auto it = mob_list.begin();
|
auto it = mob_list.begin();
|
||||||
while (it != mob_list.end()) {
|
while (it != mob_list.end()) {
|
||||||
|
if (!it->second) {
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
safe_delete(it->second);
|
safe_delete(it->second);
|
||||||
free_ids.push(it->first);
|
free_ids.push(it->first);
|
||||||
it = mob_list.erase(it);
|
it = mob_list.erase(it);
|
||||||
@@ -2812,6 +2816,9 @@ bool EntityList::RemoveMob(uint16 delete_id)
|
|||||||
|
|
||||||
auto it = mob_list.find(delete_id);
|
auto it = mob_list.find(delete_id);
|
||||||
if (it != mob_list.end()) {
|
if (it != mob_list.end()) {
|
||||||
|
if (!it->second) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (npc_list.count(delete_id)) {
|
if (npc_list.count(delete_id)) {
|
||||||
entity_list.RemoveNPC(delete_id);
|
entity_list.RemoveNPC(delete_id);
|
||||||
}
|
}
|
||||||
@@ -4379,8 +4386,9 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
|
|||||||
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
|
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
|
||||||
if (
|
if (
|
||||||
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
!(n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) &&
|
!(other->IsBot() && n->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
||||||
!(n->GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC())
|
!(other->IsClient() && n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
||||||
|
!(other->IsNPC() && n->GetSpecialAbility(IMMUNE_AGGRO_NPC))
|
||||||
) {
|
) {
|
||||||
n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
@@ -4405,8 +4413,9 @@ void EntityList::AddTempPetsToHateListOnOwnerDamage(Mob *owner, Mob* attacker, i
|
|||||||
attacker != n &&
|
attacker != n &&
|
||||||
!n->IsEngaged() &&
|
!n->IsEngaged() &&
|
||||||
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
|
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
!(n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) &&
|
!(attacker->IsBot() && n->GetSpecialAbility(IMMUNE_AGGRO_BOT)) &&
|
||||||
!(n->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) &&
|
!(attacker->IsClient() && n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT)) &&
|
||||||
|
!(attacker->IsNPC() && n->GetSpecialAbility(IMMUNE_AGGRO_NPC)) &&
|
||||||
!attacker->IsTrap() &&
|
!attacker->IsTrap() &&
|
||||||
!attacker->IsCorpse()
|
!attacker->IsCorpse()
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -142,6 +142,8 @@ typedef enum {
|
|||||||
EVENT_ENTITY_VARIABLE_DELETE,
|
EVENT_ENTITY_VARIABLE_DELETE,
|
||||||
EVENT_ENTITY_VARIABLE_SET,
|
EVENT_ENTITY_VARIABLE_SET,
|
||||||
EVENT_ENTITY_VARIABLE_UPDATE,
|
EVENT_ENTITY_VARIABLE_UPDATE,
|
||||||
|
EVENT_AA_LOSS,
|
||||||
|
EVENT_SPELL_BLOCKED,
|
||||||
|
|
||||||
// Add new events before these or Lua crashes
|
// Add new events before these or Lua crashes
|
||||||
EVENT_SPELL_EFFECT_BOT,
|
EVENT_SPELL_EFFECT_BOT,
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ bool ExpeditionRequest::CanGroupRequest(Group* group)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Group::GetLeaderName() is broken if group formed across zones, ask database instead
|
// Group::GetLeaderName() is broken if group formed across zones, ask database instead
|
||||||
m_leader_name = m_leader ? m_leader->GetName() : GetGroupLeaderName(group->GetID()); // group->GetLeaderName();
|
m_leader_name = m_leader ? m_leader->GetName() : group->GetLeaderName();
|
||||||
m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name);
|
m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name);
|
||||||
|
|
||||||
std::vector<std::string> member_names;
|
std::vector<std::string> member_names;
|
||||||
@@ -148,13 +148,6 @@ bool ExpeditionRequest::CanGroupRequest(Group* group)
|
|||||||
return CanMembersJoin(member_names);
|
return CanMembersJoin(member_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ExpeditionRequest::GetGroupLeaderName(uint32_t group_id)
|
|
||||||
{
|
|
||||||
char leader_name_buffer[64] = { 0 };
|
|
||||||
database.GetGroupLeadershipInfo(group_id, leader_name_buffer);
|
|
||||||
return std::string(leader_name_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ExpeditionRequest::CanMembersJoin(const std::vector<std::string>& member_names)
|
bool ExpeditionRequest::CanMembersJoin(const std::vector<std::string>& member_names)
|
||||||
{
|
{
|
||||||
if (member_names.empty())
|
if (member_names.empty())
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user