mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-18 07:38:22 +00:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ddafd9ed8 | |||
| 5488e9bf22 | |||
| 6db6d7dca9 | |||
| 066b762e73 | |||
| cd85a8524a | |||
| 4490a53ba0 | |||
| 00eb462d47 | |||
| 2df7d19f97 | |||
| 48c6db3a9c | |||
| cce368d94c | |||
| 84b8bdd2b4 | |||
| fc8ace91cb | |||
| 2d6c9f881a | |||
| 9b72c07a54 | |||
| 9d5d13fbd0 | |||
| bc3e9e8fba | |||
| d9cfc3a858 | |||
| 51dc62dfb1 | |||
| e52e4d5b3f | |||
| 0c3149a6e5 | |||
| 611122833d | |||
| b83373491e | |||
| dfa349492c | |||
| c08200188f | |||
| 41d9a15c74 | |||
| 2ed4effbe3 | |||
| 6ec09f300a | |||
| 079f612730 | |||
| 2c971fb2de | |||
| 20e9a8b2d2 | |||
| 8fa6a0b496 | |||
| d6e1c3f187 | |||
| 70a4b6a2b1 | |||
| 7923d7bc6c | |||
| 6007ba454c | |||
| d4a78f4799 | |||
| 0ada53aa96 | |||
| 7803170d6b | |||
| 20778ad7d9 | |||
| 44d63c47d9 | |||
| b288202c96 | |||
| a724e92638 | |||
| 0ea825e9a4 | |||
| 2ca50b339d | |||
| 164fe31fa8 | |||
| f3de3e8c31 | |||
| 1227f35382 | |||
| c0769a9c29 | |||
| 2dd0e51936 | |||
| fd787af53a | |||
| aa39ac8023 | |||
| 397096996c | |||
| f8de9b9167 | |||
| 9d48cbcd29 | |||
| eb5eb0ca30 | |||
| bc4bebb4a9 | |||
| 05f09b56e6 | |||
| 411fe3d95d | |||
| c1e984dfc1 | |||
| a5d9a8596a | |||
| 7e23d798d5 | |||
| 47ab8910a3 | |||
| 259add68f5 | |||
| d2f5dc43a6 | |||
| 99d2e3a8b1 | |||
| 122fe398b4 | |||
| 43c4b13978 | |||
| a3a707adae | |||
| c4da9766a4 | |||
| a8eb2832ce | |||
| 076aab50e8 | |||
| 1e8889a9fc | |||
| 7c3481daf9 | |||
| b93dec357f | |||
| 2f4af4f0c2 | |||
| a0f2a8a743 | |||
| 4c7016bd7b | |||
| 6c18cd0bee | |||
| 87e63e1e36 | |||
| a771882cff | |||
| b3f6a8c55f | |||
| 605502cd9d | |||
| 4712ca471b | |||
| 836c3d6596 | |||
| 53169ae217 |
+146
@@ -1,3 +1,149 @@
|
|||||||
|
## [22.40.0] - 1/7/2024
|
||||||
|
|
||||||
|
### Account
|
||||||
|
|
||||||
|
* Convert Get/Update Account Karma to Repositories ([#3858](https://github.com/EQEmu/Server/pull/3858)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert UpdateGMStatus to Repositories ([#3859](https://github.com/EQEmu/Server/pull/3859)) @Kinglykrab 2024-01-07
|
||||||
|
|
||||||
|
### Bots
|
||||||
|
|
||||||
|
* Resist Spell Fix ([#3840](https://github.com/EQEmu/Server/pull/3840)) @dariusuknuis 2024-01-07
|
||||||
|
|
||||||
|
### Bugfix
|
||||||
|
|
||||||
|
* Negative Aggro Fix ([#3866](https://github.com/EQEmu/Server/pull/3866)) @fryguy503 2024-01-07
|
||||||
|
|
||||||
|
### Character
|
||||||
|
|
||||||
|
* Convert Clear/Delete/Get/Update of Character Item Recast to Repositories ([#3857](https://github.com/EQEmu/Server/pull/3857)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Delete/Load/Remove/Save of Character AA to Repositories ([#3849](https://github.com/EQEmu/Server/pull/3849)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Delete/Load/Save of Character Bandolier to Repositories ([#3845](https://github.com/EQEmu/Server/pull/3845)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Delete/Load/Save of Character Disciplines to Repositories ([#3850](https://github.com/EQEmu/Server/pull/3850)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Delete/Load/Save of Character Leadership Abilities to Repositories ([#3847](https://github.com/EQEmu/Server/pull/3847)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Delete/Load/Save of Character Material to Repositories ([#3846](https://github.com/EQEmu/Server/pull/3846)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Delete/Load/Save of Character Spells to Repositories ([#3842](https://github.com/EQEmu/Server/pull/3842)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Delete/Save of Character Memmed Spells to Repositories ([#3841](https://github.com/EQEmu/Server/pull/3841)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Load/Save of Character Bind to Repositories ([#3851](https://github.com/EQEmu/Server/pull/3851)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Load/Save of Character Buffs to Repositories ([#3855](https://github.com/EQEmu/Server/pull/3855)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Load/Save of Character Currency to Repositories ([#3848](https://github.com/EQEmu/Server/pull/3848)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Load/Save of Character Data to Repositories ([#3839](https://github.com/EQEmu/Server/pull/3839)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Load/Save of Character Potion Belt to Repositories ([#3844](https://github.com/EQEmu/Server/pull/3844)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Load/Save of Character Skills to Repositories ([#3843](https://github.com/EQEmu/Server/pull/3843)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert Load/Update of Character Alternate Currencies to Repositories ([#3856](https://github.com/EQEmu/Server/pull/3856)) @Kinglykrab 2024-01-07
|
||||||
|
* Convert NoRentExpired to Repositories ([#3860](https://github.com/EQEmu/Server/pull/3860)) @Kinglykrab 2024-01-07
|
||||||
|
|
||||||
|
### Characters
|
||||||
|
|
||||||
|
* Convert Load/Save of Character Auras to Repositories ([#3854](https://github.com/EQEmu/Server/pull/3854)) @Kinglykrab 2024-01-07
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Remove bot-based saylink method ([#3852](https://github.com/EQEmu/Server/pull/3852)) @Kinglykrab 2024-01-07
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
* Add #clearxtargets Command ([#3833](https://github.com/EQEmu/Server/pull/3833)) @Kinglykrab 2024-01-07
|
||||||
|
* Add scoped buckets and editing to #databuckets ([#3826](https://github.com/EQEmu/Server/pull/3826)) @Kinglykrab 2024-01-07
|
||||||
|
* Cleanup #appearance Command ([#3827](https://github.com/EQEmu/Server/pull/3827)) @Kinglykrab 2024-01-07
|
||||||
|
* Cleanup #fixmob Command ([#3828](https://github.com/EQEmu/Server/pull/3828)) @Kinglykrab 2024-01-07
|
||||||
|
* Cleanup #petname Command ([#3829](https://github.com/EQEmu/Server/pull/3829)) @Kinglykrab 2024-01-07
|
||||||
|
* Cleanup #shutdown Command ([#3830](https://github.com/EQEmu/Server/pull/3830)) @Kinglykrab 2024-01-07
|
||||||
|
* Remove #zopp Command ([#3831](https://github.com/EQEmu/Server/pull/3831)) @Kinglykrab 2024-01-07
|
||||||
|
|
||||||
|
### Crash
|
||||||
|
|
||||||
|
* Fix crash where Raid invite could be accepted after forming group with the Raid invitor. ([#3837](https://github.com/EQEmu/Server/pull/3837)) @Aeadoin 2024-01-06
|
||||||
|
|
||||||
|
### Feature
|
||||||
|
|
||||||
|
* Break Trader if moved ([#3862](https://github.com/EQEmu/Server/pull/3862)) @fryguy503 2024-01-07
|
||||||
|
* Formula Addition (40+ Harm Touch) ([#3870](https://github.com/EQEmu/Server/pull/3870)) @fryguy503 2024-01-07
|
||||||
|
* Legacy Fizzle Code ([#3868](https://github.com/EQEmu/Server/pull/3868)) @fryguy503 2024-01-07
|
||||||
|
* Legacy Manaburn Rule ([#3872](https://github.com/EQEmu/Server/pull/3872)) @fryguy503 2024-01-07
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Add locations where melee can be bound outside of a city. ([#3887](https://github.com/EQEmu/Server/pull/3887)) @fryguy503 2024-01-07
|
||||||
|
* Amplification should not benefit from instrument mods ([#3898](https://github.com/EQEmu/Server/pull/3898)) @fryguy503 2024-01-07
|
||||||
|
* Bard Caster Level Fixes ([#3883](https://github.com/EQEmu/Server/pull/3883)) @fryguy503 2024-01-07
|
||||||
|
* Buff Sync ([#3896](https://github.com/EQEmu/Server/pull/3896)) @fryguy503 2024-01-07
|
||||||
|
* Cancel Magic SE fix ([#3890](https://github.com/EQEmu/Server/pull/3890)) @fryguy503 2024-01-07
|
||||||
|
* Class Trainers dont steal your money! ([#3864](https://github.com/EQEmu/Server/pull/3864)) @fryguy503 2024-01-07
|
||||||
|
* Clear Ramp when Clearing hate ([#3892](https://github.com/EQEmu/Server/pull/3892)) @fryguy503 2024-01-07
|
||||||
|
* DI/Death Pact Fix ([#3867](https://github.com/EQEmu/Server/pull/3867)) @fryguy503 2024-01-07
|
||||||
|
* Depop Charm Pet and Detach Debuffs on Evacuate ([#3888](https://github.com/EQEmu/Server/pull/3888)) @fryguy503 2024-01-07
|
||||||
|
* Dire Charm Reset ([#3875](https://github.com/EQEmu/Server/pull/3875)) @fryguy503 2024-01-07
|
||||||
|
* Disciplines Getting Focuses Fix ([#3884](https://github.com/EQEmu/Server/pull/3884)) @fryguy503 2024-01-07
|
||||||
|
* Fix issue with 9th/10th inventory slot ([#3835](https://github.com/EQEmu/Server/pull/3835)) @Kinglykrab 2024-01-03
|
||||||
|
* Fix typo on ZoneDatabase::LoadPetInfo ([#3871](https://github.com/EQEmu/Server/pull/3871)) @Kinglykrab 2024-01-07
|
||||||
|
* Harm Touch Unholy Disc Type ([#3874](https://github.com/EQEmu/Server/pull/3874)) @fryguy503 2024-01-07
|
||||||
|
* Prevent QS Crashes ([#3877](https://github.com/EQEmu/Server/pull/3877)) @fryguy503 2024-01-07
|
||||||
|
* Rez Effects Stacking ([#3882](https://github.com/EQEmu/Server/pull/3882)) @fryguy503 2024-01-07
|
||||||
|
* Rez in zone clear aggro ([#3895](https://github.com/EQEmu/Server/pull/3895)) @fryguy503 2024-01-07
|
||||||
|
* Rune Invis Break ([#3893](https://github.com/EQEmu/Server/pull/3893)) @fryguy503 2024-01-07
|
||||||
|
* Snare and DOT Stacking ([#3897](https://github.com/EQEmu/Server/pull/3897)) @fryguy503 2024-01-07
|
||||||
|
* Swim Skillup and Underwater Fall Damage Fix ([#3885](https://github.com/EQEmu/Server/pull/3885)) @fryguy503 2024-01-07
|
||||||
|
* Swimming Rules Adjustment and Racial ([#3889](https://github.com/EQEmu/Server/pull/3889)) @fryguy503 2024-01-07
|
||||||
|
* Target Locked Pet Taunt ([#3894](https://github.com/EQEmu/Server/pull/3894)) @fryguy503 2024-01-07
|
||||||
|
* Vampiric Embrace Fixes ([#3873](https://github.com/EQEmu/Server/pull/3873)) @fryguy503 2024-01-07
|
||||||
|
|
||||||
|
### Languages
|
||||||
|
|
||||||
|
* Cleanup language constants, use repositories ([#3838](https://github.com/EQEmu/Server/pull/3838)) @Kinglykrab 2024-01-07
|
||||||
|
|
||||||
|
### Pets
|
||||||
|
|
||||||
|
* Convert Load/Save of Pet Info to Repositories ([#3853](https://github.com/EQEmu/Server/pull/3853)) @Kinglykrab 2024-01-07
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* Casting Charm on over level = Aggro ([#3886](https://github.com/EQEmu/Server/pull/3886)) @fryguy503 2024-01-07
|
||||||
|
* Classic Invite Requires Target ([#3878](https://github.com/EQEmu/Server/pull/3878)) @fryguy503 2024-01-07
|
||||||
|
* Evac Aggro Wipe ([#3880](https://github.com/EQEmu/Server/pull/3880)) @fryguy503 2024-01-07
|
||||||
|
* Mounts will wear off on zone ([#3865](https://github.com/EQEmu/Server/pull/3865)) @fryguy503 2024-01-07
|
||||||
|
* PC Push and NPCtoNPC Push ([#3879](https://github.com/EQEmu/Server/pull/3879)) @fryguy503 2024-01-07
|
||||||
|
* RequireMnemonicRetention for Spells 9-12 Rule ([#3876](https://github.com/EQEmu/Server/pull/3876)) @fryguy503 2024-01-07
|
||||||
|
* Resist Softcap rules ([#3863](https://github.com/EQEmu/Server/pull/3863)) @fryguy503 2024-01-07
|
||||||
|
* Restrict Finishing Blow to only Fleeing NPC's. ([#3869](https://github.com/EQEmu/Server/pull/3869)) @fryguy503 2024-01-07
|
||||||
|
* Undead Aggro ([#3881](https://github.com/EQEmu/Server/pull/3881)) @fryguy503 2024-01-07
|
||||||
|
|
||||||
|
### Tuning
|
||||||
|
|
||||||
|
* FD and Sneak break when cast on adjustments. ([#3861](https://github.com/EQEmu/Server/pull/3861)) @fryguy503 2024-01-07
|
||||||
|
|
||||||
|
### UCS
|
||||||
|
|
||||||
|
* Consolidate configuration block ([#3768](https://github.com/EQEmu/Server/pull/3768)) @Akkadius 2024-01-07
|
||||||
|
|
||||||
|
## [22.39.1] - 12/31/2023
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
* Appearance not appearence ([#3819](https://github.com/EQEmu/Server/pull/3819)) @Kinglykrab 2023-12-30
|
||||||
|
* Delete errmsg.h in common and zone ([#3821](https://github.com/EQEmu/Server/pull/3821)) @Kinglykrab 2023-12-30
|
||||||
|
* Gender constants cleanup ([#3817](https://github.com/EQEmu/Server/pull/3817)) @Kinglykrab 2023-12-30
|
||||||
|
* Remove MakeSpawnUpdateNoDelta from mob.cpp/mob.h ([#3816](https://github.com/EQEmu/Server/pull/3816)) @Kinglykrab 2023-12-31
|
||||||
|
* Remove SendStunAppearance from mob.cpp/mob.h ([#3818](https://github.com/EQEmu/Server/pull/3818)) @Kinglykrab 2023-12-31
|
||||||
|
* Remove unused PlotPosition methods from mob.cpp/mob.h ([#3820](https://github.com/EQEmu/Server/pull/3820)) @Kinglykrab 2023-12-31
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
|
* Database update improvements, content db and terminal checks ([#3814](https://github.com/EQEmu/Server/pull/3814)) @Akkadius 2023-12-31
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Client:SetBucket Overload Incorrectly Named ([#3825](https://github.com/EQEmu/Server/pull/3825)) @fryguy503 2023-12-30
|
||||||
|
* Fix crash in Client::Handle_OP_GMGoto ([#3832](https://github.com/EQEmu/Server/pull/3832)) @Kinglykrab 2023-12-31
|
||||||
|
|
||||||
|
### Quest API
|
||||||
|
|
||||||
|
* Add HasItemOnCorpse() to Perl/Lua ([#3824](https://github.com/EQEmu/Server/pull/3824)) @Kinglykrab 2023-12-31
|
||||||
|
* Fix issue with death events. ([#3823](https://github.com/EQEmu/Server/pull/3823)) @Kinglykrab 2023-12-31
|
||||||
|
|
||||||
|
### Repositories
|
||||||
|
|
||||||
|
* Protected extended repositories from being overwritten if exists ([#3815](https://github.com/EQEmu/Server/pull/3815)) @Akkadius 2023-12-31
|
||||||
|
|
||||||
## [22.39.0] - 12/27/2023
|
## [22.39.0] - 12/27/2023
|
||||||
|
|
||||||
### Character
|
### Character
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ SET(common_sources
|
|||||||
crc32.cpp
|
crc32.cpp
|
||||||
database/database_dump_service.cpp
|
database/database_dump_service.cpp
|
||||||
database.cpp
|
database.cpp
|
||||||
database_conversions.cpp
|
|
||||||
database_instances.cpp
|
database_instances.cpp
|
||||||
database/database_update_manifest.cpp
|
database/database_update_manifest.cpp
|
||||||
database/database_update_manifest_bots.cpp
|
database/database_update_manifest_bots.cpp
|
||||||
@@ -541,7 +540,6 @@ SET(common_headers
|
|||||||
events/player_event_logs.h
|
events/player_event_logs.h
|
||||||
events/player_event_discord_formatter.h
|
events/player_event_discord_formatter.h
|
||||||
events/player_events.h
|
events/player_events.h
|
||||||
errmsg.h
|
|
||||||
event_sub.h
|
event_sub.h
|
||||||
expedition_lockout_timer.h
|
expedition_lockout_timer.h
|
||||||
extprofile.h
|
extprofile.h
|
||||||
@@ -563,7 +561,6 @@ SET(common_headers
|
|||||||
item_fieldlist.h
|
item_fieldlist.h
|
||||||
item_instance.h
|
item_instance.h
|
||||||
json_config.h
|
json_config.h
|
||||||
languages.h
|
|
||||||
light_source.h
|
light_source.h
|
||||||
linked_list.h
|
linked_list.h
|
||||||
loottable.h
|
loottable.h
|
||||||
|
|||||||
@@ -226,11 +226,6 @@ public:
|
|||||||
|
|
||||||
void PurgeAllDeletedDataBuckets();
|
void PurgeAllDeletedDataBuckets();
|
||||||
|
|
||||||
/* Database Conversions 'database_conversions.cpp' */
|
|
||||||
|
|
||||||
bool CheckDatabaseConversions();
|
|
||||||
bool CheckDatabaseConvertCorpseDeblob();
|
|
||||||
bool CheckDatabaseConvertPPDeblob();
|
|
||||||
|
|
||||||
/* Database Variables */
|
/* Database Variables */
|
||||||
|
|
||||||
|
|||||||
@@ -76,9 +76,9 @@ void DatabaseUpdate::CheckDbUpdates()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DatabaseUpdate::GetQueryResult(std::string query)
|
std::string DatabaseUpdate::GetQueryResult(const ManifestEntry& e)
|
||||||
{
|
{
|
||||||
auto results = m_database->QueryDatabase(query);
|
auto results = (e.content_schema_update ? m_content_database : m_database)->QueryDatabase(e.check);
|
||||||
|
|
||||||
std::vector<std::string> result_lines = {};
|
std::vector<std::string> result_lines = {};
|
||||||
|
|
||||||
@@ -121,6 +121,16 @@ bool DatabaseUpdate::ShouldRunMigration(ManifestEntry &e, std::string query_resu
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if we are running in a terminal
|
||||||
|
bool is_atty()
|
||||||
|
{
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
return ::_isatty(_fileno(stdin));
|
||||||
|
#else
|
||||||
|
return isatty(fileno(stdin));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// return true if we ran updates
|
// return true if we ran updates
|
||||||
bool DatabaseUpdate::UpdateManifest(
|
bool DatabaseUpdate::UpdateManifest(
|
||||||
std::vector<ManifestEntry> entries,
|
std::vector<ManifestEntry> entries,
|
||||||
@@ -136,7 +146,7 @@ bool DatabaseUpdate::UpdateManifest(
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
if (e.version == version) {
|
if (e.version == version) {
|
||||||
bool has_migration = true;
|
bool has_migration = true;
|
||||||
std::string r = GetQueryResult(e.check);
|
std::string r = GetQueryResult(e);
|
||||||
if (ShouldRunMigration(e, r)) {
|
if (ShouldRunMigration(e, r)) {
|
||||||
has_migration = false;
|
has_migration = false;
|
||||||
missing_migrations.emplace_back(e.version);
|
missing_migrations.emplace_back(e.version);
|
||||||
@@ -179,7 +189,7 @@ bool DatabaseUpdate::UpdateManifest(
|
|||||||
if (e.version == m) {
|
if (e.version == m) {
|
||||||
bool errored_migration = false;
|
bool errored_migration = false;
|
||||||
|
|
||||||
auto r = m_database->QueryDatabaseMulti(e.sql);
|
auto r = (e.content_schema_update ? m_content_database : m_database)->QueryDatabaseMulti(e.sql);
|
||||||
|
|
||||||
// ignore empty query result "errors"
|
// ignore empty query result "errors"
|
||||||
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
|
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
|
||||||
@@ -187,31 +197,38 @@ bool DatabaseUpdate::UpdateManifest(
|
|||||||
errored_migration = true;
|
errored_migration = true;
|
||||||
|
|
||||||
LogInfo("Required database update failed. This could be a problem");
|
LogInfo("Required database update failed. This could be a problem");
|
||||||
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
|
|
||||||
|
|
||||||
// user input
|
// if terminal attached then prompt for skip
|
||||||
std::string input;
|
if (is_atty()) {
|
||||||
bool gave_input = false;
|
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
|
||||||
time_t start_time = time(nullptr);
|
|
||||||
time_t wait_time_seconds = 60;
|
|
||||||
|
|
||||||
// spawn a concurrent thread that waits for input from std::cin
|
// user input
|
||||||
std::thread t1(
|
std::string input;
|
||||||
[&]() {
|
bool gave_input = false;
|
||||||
std::cin >> input;
|
time_t start_time = time(nullptr);
|
||||||
gave_input = true;
|
time_t wait_time_seconds = 60;
|
||||||
|
|
||||||
|
// spawn a concurrent thread that waits for input from std::cin
|
||||||
|
std::thread t1(
|
||||||
|
[&]() {
|
||||||
|
std::cin >> input;
|
||||||
|
gave_input = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
t1.detach();
|
||||||
|
|
||||||
|
// check the inputReceived flag once every 50ms for 10 seconds
|
||||||
|
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
);
|
|
||||||
t1.detach();
|
|
||||||
|
|
||||||
// check the inputReceived flag once every 50ms for 10 seconds
|
// prompt for user skip
|
||||||
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
|
if (Strings::Trim(input) == "y") {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
errored_migration = false;
|
||||||
}
|
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
||||||
|
}
|
||||||
// prompt for user skip
|
} else {
|
||||||
if (Strings::Trim(input) == "y") {
|
errored_migration = true;
|
||||||
errored_migration = false;
|
|
||||||
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,6 +264,13 @@ DatabaseUpdate *DatabaseUpdate::SetDatabase(Database *db)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DatabaseUpdate *DatabaseUpdate::SetContentDatabase(Database *db)
|
||||||
|
{
|
||||||
|
m_content_database = db;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||||
{
|
{
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ struct ManifestEntry {
|
|||||||
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
||||||
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
||||||
std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
||||||
|
bool content_schema_update{}; // if true, this migration is a content schema update and should be ran against the content database
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DatabaseVersion {
|
struct DatabaseVersion {
|
||||||
@@ -22,14 +23,16 @@ public:
|
|||||||
DatabaseVersion GetDatabaseVersions();
|
DatabaseVersion GetDatabaseVersions();
|
||||||
DatabaseVersion GetBinaryDatabaseVersions();
|
DatabaseVersion GetBinaryDatabaseVersions();
|
||||||
void CheckDbUpdates();
|
void CheckDbUpdates();
|
||||||
std::string GetQueryResult(std::string query);
|
std::string GetQueryResult(const ManifestEntry& e);
|
||||||
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
|
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
|
||||||
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
|
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
|
||||||
|
|
||||||
DatabaseUpdate *SetDatabase(Database *db);
|
DatabaseUpdate *SetDatabase(Database *db);
|
||||||
|
DatabaseUpdate *SetContentDatabase(Database *db);
|
||||||
bool HasPendingUpdates();
|
bool HasPendingUpdates();
|
||||||
private:
|
private:
|
||||||
Database *m_database;
|
Database *m_database;
|
||||||
|
Database *m_content_database;
|
||||||
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
||||||
void InjectBotsVersionColumn();
|
void InjectBotsVersionColumn();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5016,7 +5016,7 @@ CREATE TABLE `spawn2_disabled` (
|
|||||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
||||||
INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE enabled = 0;
|
INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE enabled = 0;
|
||||||
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
||||||
)"
|
)",
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9242,
|
.version = 9242,
|
||||||
@@ -5028,7 +5028,8 @@ ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
|||||||
ALTER TABLE `spawnentry`
|
ALTER TABLE `spawnentry`
|
||||||
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
|
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
|
||||||
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
|
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9243,
|
.version = 9243,
|
||||||
@@ -5082,7 +5083,8 @@ INSERT INTO
|
|||||||
|
|
||||||
DROP TABLE `starting_items`;
|
DROP TABLE `starting_items`;
|
||||||
RENAME TABLE `starting_items_new` TO `starting_items`;
|
RENAME TABLE `starting_items_new` TO `starting_items`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9244,
|
.version = 9244,
|
||||||
@@ -5092,7 +5094,8 @@ RENAME TABLE `starting_items_new` TO `starting_items`;
|
|||||||
.match = "0000-00-00 00:00:00",
|
.match = "0000-00-00 00:00:00",
|
||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9245,
|
.version = 9245,
|
||||||
@@ -5104,7 +5107,8 @@ ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
|||||||
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
|
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
|
||||||
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
|
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
|
||||||
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
|
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9246,
|
.version = 9246,
|
||||||
@@ -5133,7 +5137,8 @@ CHANGE COLUMN `slot` `inventory_slot` mediumint(9) NOT NULL DEFAULT -1 AFTER `st
|
|||||||
|
|
||||||
ALTER TABLE `starting_items`
|
ALTER TABLE `starting_items`
|
||||||
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
|
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9248,
|
.version = 9248,
|
||||||
@@ -5143,7 +5148,8 @@ CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_
|
|||||||
.match = "",
|
.match = "",
|
||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9249,
|
.version = 9249,
|
||||||
@@ -5154,7 +5160,8 @@ ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
|||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `tasks`
|
ALTER TABLE `tasks`
|
||||||
ADD COLUMN `enabled` smallint NULL DEFAULT 1 AFTER `faction_amount`
|
ADD COLUMN `enabled` smallint NULL DEFAULT 1 AFTER `faction_amount`
|
||||||
)"
|
)",
|
||||||
|
.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
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
#include "../common/global_define.h"
|
|
||||||
#include "../common/rulesys.h"
|
|
||||||
#include "../common/strings.h"
|
|
||||||
|
|
||||||
#include "database.h"
|
|
||||||
#include "database/database_update.h"
|
|
||||||
|
|
||||||
|
|
||||||
// Disgrace: for windows compile
|
|
||||||
#ifdef _WINDOWS
|
|
||||||
#include <windows.h>
|
|
||||||
#define snprintf _snprintf
|
|
||||||
#define strncasecmp _strnicmp
|
|
||||||
#define strcasecmp _stricmp
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "unix.h"
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma pack(1)
|
|
||||||
|
|
||||||
DatabaseUpdate database_update;
|
|
||||||
|
|
||||||
bool Database::CheckDatabaseConversions()
|
|
||||||
{
|
|
||||||
auto *r = RuleManager::Instance();
|
|
||||||
r->LoadRules(this, "default", false);
|
|
||||||
if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) {
|
|
||||||
LogInfo("Bot tables found but rule not enabled, enabling");
|
|
||||||
r->SetRule("Bots:Enabled", "true", this, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
database_update.SetDatabase(this)->CheckDbUpdates();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "dbcore.h"
|
#include "dbcore.h"
|
||||||
|
|
||||||
#include <errmsg.h>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mysqld_error.h>
|
#include <mysqld_error.h>
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#define CR_SERVER_GONE_ERROR 2006
|
||||||
|
#define CR_SERVER_LOST 2013
|
||||||
|
|
||||||
class DBcore {
|
class DBcore {
|
||||||
public:
|
public:
|
||||||
enum eStatus {
|
enum eStatus {
|
||||||
|
|||||||
+92
-34
@@ -22,7 +22,6 @@
|
|||||||
#include "data_verification.h"
|
#include "data_verification.h"
|
||||||
#include "eqemu_logsys.h"
|
#include "eqemu_logsys.h"
|
||||||
#include "eqemu_logsys_log_aliases.h"
|
#include "eqemu_logsys_log_aliases.h"
|
||||||
#include "languages.h"
|
|
||||||
#include "rulesys.h"
|
#include "rulesys.h"
|
||||||
|
|
||||||
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
|
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
|
||||||
@@ -159,45 +158,45 @@ int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<int, std::string>& EQ::constants::GetLanguageMap()
|
const std::map<uint8, std::string>& EQ::constants::GetLanguageMap()
|
||||||
{
|
{
|
||||||
static const std::map<int, std::string> language_map = {
|
static const std::map<uint8, std::string> language_map = {
|
||||||
{ LANG_COMMON_TONGUE, "Common Tongue" },
|
{ Language::CommonTongue, "Common Tongue" },
|
||||||
{ LANG_BARBARIAN, "Barbarian" },
|
{ Language::Barbarian, "Barbarian" },
|
||||||
{ LANG_ERUDIAN, "Erudian" },
|
{ Language::Erudian, "Erudian" },
|
||||||
{ LANG_ELVISH, "Elvish" },
|
{ Language::Elvish, "Elvish" },
|
||||||
{ LANG_DARK_ELVISH, "Dark Elvish" },
|
{ Language::DarkElvish, "Dark Elvish" },
|
||||||
{ LANG_DWARVISH, "Dwarvish" },
|
{ Language::Dwarvish, "Dwarvish" },
|
||||||
{ LANG_TROLL, "Troll" },
|
{ Language::Troll, "Troll" },
|
||||||
{ LANG_OGRE, "Ogre" },
|
{ Language::Ogre, "Ogre" },
|
||||||
{ LANG_GNOMISH, "Gnomish" },
|
{ Language::Gnomish, "Gnomish" },
|
||||||
{ LANG_HALFLING, "Halfling" },
|
{ Language::Halfling, "Halfling" },
|
||||||
{ LANG_THIEVES_CANT, "Thieves Cant" },
|
{ Language::ThievesCant, "Thieves Cant" },
|
||||||
{ LANG_OLD_ERUDIAN, "Old Erudian" },
|
{ Language::OldErudian, "Old Erudian" },
|
||||||
{ LANG_ELDER_ELVISH, "Elder Elvish" },
|
{ Language::ElderElvish, "Elder Elvish" },
|
||||||
{ LANG_FROGLOK, "Froglok" },
|
{ Language::Froglok, "Froglok" },
|
||||||
{ LANG_GOBLIN, "Goblin" },
|
{ Language::Goblin, "Goblin" },
|
||||||
{ LANG_GNOLL, "Gnoll" },
|
{ Language::Gnoll, "Gnoll" },
|
||||||
{ LANG_COMBINE_TONGUE, "Combine Tongue" },
|
{ Language::CombineTongue, "Combine Tongue" },
|
||||||
{ LANG_ELDER_TEIRDAL, "Elder Teirdal" },
|
{ Language::ElderTeirDal, "Elder Teir'Dal" },
|
||||||
{ LANG_LIZARDMAN, "Lizardman" },
|
{ Language::Lizardman, "Lizardman" },
|
||||||
{ LANG_ORCISH, "Orcish" },
|
{ Language::Orcish, "Orcish" },
|
||||||
{ LANG_FAERIE, "Faerie" },
|
{ Language::Faerie, "Faerie" },
|
||||||
{ LANG_DRAGON, "Dragon" },
|
{ Language::Dragon, "Dragon" },
|
||||||
{ LANG_ELDER_DRAGON, "Elder Dragon" },
|
{ Language::ElderDragon, "Elder Dragon" },
|
||||||
{ LANG_DARK_SPEECH, "Dark Speech" },
|
{ Language::DarkSpeech, "Dark Speech" },
|
||||||
{ LANG_VAH_SHIR, "Vah Shir" },
|
{ Language::VahShir, "Vah Shir" },
|
||||||
{ LANG_ALARAN, "Alaran" },
|
{ Language::Alaran, "Alaran" },
|
||||||
{ LANG_HADAL, "Hadal" },
|
{ Language::Hadal, "Hadal" },
|
||||||
{ LANG_UNKNOWN, "Unknown" }
|
{ Language::Unknown27, "Unknown" }
|
||||||
};
|
};
|
||||||
|
|
||||||
return language_map;
|
return language_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EQ::constants::GetLanguageName(int language_id)
|
std::string EQ::constants::GetLanguageName(uint8 language_id)
|
||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
if (!EQ::ValueWithin(language_id, Language::CommonTongue, Language::Unknown27)) {
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +508,6 @@ std::string EQ::constants::GetObjectTypeName(int object_type)
|
|||||||
{
|
{
|
||||||
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
|
||||||
return std::string();
|
return std::string();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
|
||||||
@@ -580,3 +578,63 @@ std::string EQ::constants::GetEmoteTypeName(uint8 emote_type)
|
|||||||
|
|
||||||
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
|
return EQ::constants::GetEmoteTypeMap().find(emote_type)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::map<uint32, std::string>& EQ::constants::GetAppearanceTypeMap()
|
||||||
|
{
|
||||||
|
static const std::map<uint32, std::string> appearance_type_map = {
|
||||||
|
{ AppearanceType::Die, "Die" },
|
||||||
|
{ AppearanceType::WhoLevel, "Who Level" },
|
||||||
|
{ AppearanceType::MaxHealth, "Max Health" },
|
||||||
|
{ AppearanceType::Invisibility, "Invisibility" },
|
||||||
|
{ AppearanceType::PVP, "PVP" },
|
||||||
|
{ AppearanceType::Light, "Light" },
|
||||||
|
{ AppearanceType::Animation, "Animation" },
|
||||||
|
{ AppearanceType::Sneak, "Sneak" },
|
||||||
|
{ AppearanceType::SpawnID, "Spawn ID" },
|
||||||
|
{ AppearanceType::Health, "Health" },
|
||||||
|
{ AppearanceType::Linkdead, "Linkdead" },
|
||||||
|
{ AppearanceType::FlyMode, "Fly Mode" },
|
||||||
|
{ AppearanceType::GM, "GM" },
|
||||||
|
{ AppearanceType::Anonymous, "Anonymous" },
|
||||||
|
{ AppearanceType::GuildID, "Guild ID" },
|
||||||
|
{ AppearanceType::GuildRank, "Guild Rank" },
|
||||||
|
{ AppearanceType::AFK, "AFK" },
|
||||||
|
{ AppearanceType::Pet, "Pet" },
|
||||||
|
{ AppearanceType::Summoned, "Summoned" },
|
||||||
|
{ AppearanceType::Split, "Split" },
|
||||||
|
{ AppearanceType::Size, "Size" },
|
||||||
|
{ AppearanceType::SetType, "Set Type" },
|
||||||
|
{ AppearanceType::NPCName, "NPCName" },
|
||||||
|
{ AppearanceType::AARank, "AARank" },
|
||||||
|
{ AppearanceType::CancelSneakHide, "Cancel Sneak Hide" },
|
||||||
|
{ AppearanceType::AreaHealthRegen, "Area Health Regeneration" },
|
||||||
|
{ AppearanceType::AreaManaRegen, "Area Mana Regeneration" },
|
||||||
|
{ AppearanceType::AreaEnduranceRegen, "Area Endurance Regeneration" },
|
||||||
|
{ AppearanceType::FreezeBeneficialBuffs, "Freeze Beneficial Buffs" },
|
||||||
|
{ AppearanceType::NPCTintIndex, "NPC Tint Index" },
|
||||||
|
{ AppearanceType::GroupAutoConsent, "Group Auto Consent" },
|
||||||
|
{ AppearanceType::RaidAutoConsent, "Raid Auto Consent" },
|
||||||
|
{ AppearanceType::GuildAutoConsent, "Guild Auto Consent" },
|
||||||
|
{ AppearanceType::ShowHelm, "Show Helm" },
|
||||||
|
{ AppearanceType::DamageState, "Damage State" },
|
||||||
|
{ AppearanceType::EQPlayers, "EQ Players" },
|
||||||
|
{ AppearanceType::FindBits, "Find Bits" },
|
||||||
|
{ AppearanceType::TextureType, "Texture Type" },
|
||||||
|
{ AppearanceType::FacePick, "Face Pick" },
|
||||||
|
{ AppearanceType::AntiCheat, "Anti Cheat" },
|
||||||
|
{ AppearanceType::GuildShow, "Guild Show" },
|
||||||
|
{ AppearanceType::OfflineMode, "Offline Mode" }
|
||||||
|
};
|
||||||
|
|
||||||
|
return appearance_type_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EQ::constants::GetAppearanceTypeName(uint32 appearance_type)
|
||||||
|
{
|
||||||
|
const auto& a = EQ::constants::GetAppearanceTypeMap().find(appearance_type);
|
||||||
|
if (a != EQ::constants::GetAppearanceTypeMap().end()) {
|
||||||
|
return a->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|||||||
@@ -358,8 +358,8 @@ namespace EQ
|
|||||||
const char *GetStanceName(StanceType stance_type);
|
const char *GetStanceName(StanceType stance_type);
|
||||||
int ConvertStanceTypeToIndex(StanceType stance_type);
|
int ConvertStanceTypeToIndex(StanceType stance_type);
|
||||||
|
|
||||||
extern const std::map<int, std::string>& GetLanguageMap();
|
extern const std::map<uint8, std::string>& GetLanguageMap();
|
||||||
std::string GetLanguageName(int language_id);
|
std::string GetLanguageName(uint8 language_id);
|
||||||
|
|
||||||
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
|
extern const std::map<uint32, std::string>& GetLDoNThemeMap();
|
||||||
std::string GetLDoNThemeName(uint32 theme_id);
|
std::string GetLDoNThemeName(uint32 theme_id);
|
||||||
@@ -397,6 +397,9 @@ namespace EQ
|
|||||||
extern const std::map<uint8, std::string>& GetEmoteTypeMap();
|
extern const std::map<uint8, std::string>& GetEmoteTypeMap();
|
||||||
std::string GetEmoteTypeName(uint8 emote_type);
|
std::string GetEmoteTypeName(uint8 emote_type);
|
||||||
|
|
||||||
|
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
|
||||||
|
std::string GetAppearanceTypeName(uint32 animation_type);
|
||||||
|
|
||||||
const int STANCE_TYPE_FIRST = stancePassive;
|
const int STANCE_TYPE_FIRST = stancePassive;
|
||||||
const int STANCE_TYPE_LAST = stanceBurnAE;
|
const int STANCE_TYPE_LAST = stanceBurnAE;
|
||||||
const int STANCE_TYPE_COUNT = stanceBurnAE;
|
const int STANCE_TYPE_COUNT = stanceBurnAE;
|
||||||
|
|||||||
+99
-54
@@ -23,61 +23,59 @@
|
|||||||
#include "skills.h"
|
#include "skills.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
namespace AppearanceType {
|
||||||
|
constexpr uint32 Die = 0; // Causes the client to keel over and zone to bind point (default action)
|
||||||
|
constexpr uint32 WhoLevel = 1; // Level that shows up on /who
|
||||||
|
constexpr uint32 MaxHealth = 2;
|
||||||
|
constexpr uint32 Invisibility = 3; // 0 = Visible, 1 = Invisible
|
||||||
|
constexpr uint32 PVP = 4; // 0 = Non-PVP, 1 = PVP
|
||||||
|
constexpr uint32 Light = 5; // Light type emitted by player (lightstone, shiny shield)
|
||||||
|
constexpr uint32 Animation = 14; // 100 = Standing, 102 = Freeze, 105 = Looting, 110 = Sitting, 111 = Crouching, 115 = Lying
|
||||||
|
constexpr uint32 Sneak = 15; // 0 = Normal, 1 = Sneaking
|
||||||
|
constexpr uint32 SpawnID = 16; // Server -> Client, sets player spawn ID
|
||||||
|
constexpr uint32 Health = 17; // Client->Server, my HP has changed (like regen tic)
|
||||||
|
constexpr uint32 Linkdead = 18; // 0 = Normal, 1 = Linkdead
|
||||||
|
constexpr uint32 FlyMode = 19; // 0 = Off, 1 = Flying, 2 = Levitating, 3 = Water, 4 = Floating, 5 = Levitating while Running
|
||||||
|
constexpr uint32 GM = 20; // 0 = Non-GM, 1 = GM
|
||||||
|
constexpr uint32 Anonymous = 21; // 0 = Non-Anonymous, 1 = Anonymous, 2 = Roleplaying
|
||||||
|
constexpr uint32 GuildID = 22;
|
||||||
|
constexpr uint32 GuildRank = 23;
|
||||||
|
constexpr uint32 AFK = 24; // 0 = Non-AFK, 1 = AFK
|
||||||
|
constexpr uint32 Pet = 25; // Parameter is Entity ID of owner, or 0 for when charm breaks
|
||||||
|
constexpr uint32 Summoned = 27;
|
||||||
|
constexpr uint32 Split = 28; // 0 = No Split, 1 = Auto Split
|
||||||
|
constexpr uint32 Size = 29; // Spawn's Size
|
||||||
|
constexpr uint32 SetType = 30; // 0 = PC, 1 = NPC, 2 = Corpse
|
||||||
|
constexpr uint32 NPCName = 31; // Change PC name color to NPC name color
|
||||||
|
constexpr uint32 AARank = 32; // AA Rank Title ID, title in /who?
|
||||||
|
constexpr uint32 CancelSneakHide = 33; // Turns off Hide and Sneak
|
||||||
|
constexpr uint32 AreaHealthRegen = 35; // Guild Hall Regeneration Pool sets to value * 0.001
|
||||||
|
constexpr uint32 AreaManaRegen = 36; // Guild Hall Regeneration Pool sets to value * 0.001
|
||||||
|
constexpr uint32 AreaEnduranceRegen = 37; // Guild Hall Regeneration Pool sets to value * 0.001
|
||||||
|
constexpr uint32 FreezeBeneficialBuffs = 38; // Freezes beneficial buff timers for PCs
|
||||||
|
constexpr uint32 NPCTintIndex = 39;
|
||||||
|
constexpr uint32 GroupAutoConsent = 40; // Auto Consent Group
|
||||||
|
constexpr uint32 RaidAutoConsent = 41; // Auto Consent Raid
|
||||||
|
constexpr uint32 GuildAutoConsent = 42; // Auto Consent Guild
|
||||||
|
constexpr uint32 ShowHelm = 43; // 0 = Hide, 1 = Show
|
||||||
|
constexpr uint32 DamageState = 44; // The damage state of a destructible object (0 through 10) plays sound IDs, most only have 2 or 4 states though
|
||||||
|
constexpr uint32 EQPlayers = 45; // EQ Players Update
|
||||||
|
constexpr uint32 FindBits = 46; // Set Find Bits?
|
||||||
|
constexpr uint32 TextureType = 48; // Texture Type?
|
||||||
|
constexpr uint32 FacePick = 49; // Turns off face pick window?
|
||||||
|
constexpr uint32 AntiCheat = 51; // Sent by the client randomly telling the server how long since last action has occurred
|
||||||
|
constexpr uint32 GuildShow = 52;
|
||||||
|
constexpr uint32 OfflineMode = 53; // Offline Mode
|
||||||
|
}
|
||||||
|
|
||||||
//SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2)
|
namespace Animation {
|
||||||
#define AT_Die 0 // this causes the client to keel over and zone to bind point (default action)
|
constexpr uint32 Standing = 100;
|
||||||
#define AT_WhoLevel 1 // the level that shows up on /who
|
constexpr uint32 Freeze = 102;
|
||||||
#define AT_HPMax 2 // idk
|
constexpr uint32 Looting = 105;
|
||||||
#define AT_Invis 3 // 0 = visible, 1 = invisible
|
constexpr uint32 Sitting = 110;
|
||||||
#define AT_PVP 4 // 0 = blue, 1 = pvp (red)
|
constexpr uint32 Crouching = 111;
|
||||||
#define AT_Light 5 // light type emitted by player (lightstone, shiny shield)
|
constexpr uint32 Lying = 115;
|
||||||
#define AT_Anim 14 // 100=standing, 110=sitting, 111=ducking, 115=feigned, 105=looting
|
}
|
||||||
#define AT_Sneak 15 // 0 = normal, 1 = sneaking
|
|
||||||
#define AT_SpawnID 16 // server to client, sets player spawn id
|
|
||||||
#define AT_HP 17 // Client->Server, my HP has changed (like regen tic)
|
|
||||||
#define AT_Linkdead 18 // 0 = normal, 1 = linkdead
|
|
||||||
#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate max 5, see GravityBehavior enum
|
|
||||||
#define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM
|
|
||||||
#define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay
|
|
||||||
#define AT_GuildID 22
|
|
||||||
#define AT_GuildRank 23 // 0=member, 1=officer, 2=leader
|
|
||||||
#define AT_AFK 24 // 0 = normal, 1 = afk
|
|
||||||
#define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks
|
|
||||||
#define AT_Summoned 27 // Unsure
|
|
||||||
#define AT_Split 28 // 0 = normal, 1 = autosplit on (not showing in SoF+) (client-to-server only)
|
|
||||||
#define AT_Size 29 // spawn's size (present: SoF, absent: RoF2)
|
|
||||||
#define AT_SetType 30 // 0 = PC, 1 = NPC, 2 <= = corpse
|
|
||||||
#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name, Trader on RoF2?
|
|
||||||
#define AT_AARank 32 // AA Rank Title ID thingy, does is this the title in /who?
|
|
||||||
#define AT_CancelSneakHide 33 // Turns off Hide and Sneak
|
|
||||||
//#define AT_34 34 // unknown (present: SoF, absent: RoF2)
|
|
||||||
#define AT_AreaHPRegen 35 // guild hall regen pool sets to value * 0.001
|
|
||||||
#define AT_AreaManaRegen 36 // guild hall regen pool sets to value * 0.001
|
|
||||||
#define AT_AreaEndRegen 37 // guild hall regen pool sets to value * 0.001
|
|
||||||
#define AT_FreezeBuffs 38 // Freezes beneficial buff timers
|
|
||||||
#define AT_NpcTintIndex 39 // not 100% sure
|
|
||||||
#define AT_GroupConsent 40 // auto consent group
|
|
||||||
#define AT_RaidConsent 41 // auto consent raid
|
|
||||||
#define AT_GuildConsent 42 // auto consent guild
|
|
||||||
#define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic
|
|
||||||
#define AT_DamageState 44 // The damage state of a destructible object (0 through 10) plays soundids most only have 2 or 4 states though
|
|
||||||
#define AT_EQPlayers 45 // /eqplayersupdate
|
|
||||||
#define AT_FindBits 46 // set FindBits, whatever those are!
|
|
||||||
#define AT_TextureType 48 // TextureType
|
|
||||||
#define AT_FacePick 49 // Turns off face pick window? maybe ...
|
|
||||||
#define AT_AntiCheat 51 // sent by the client randomly telling the server how long since last action has occured
|
|
||||||
#define AT_GuildShow 52 // this is what MQ2 call sit, not sure
|
|
||||||
#define AT_Offline 53 // Offline mode
|
|
||||||
|
|
||||||
//#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2)
|
|
||||||
|
|
||||||
// animations for AT_Anim
|
|
||||||
#define ANIM_FREEZE 102
|
|
||||||
#define ANIM_STAND 0x64
|
|
||||||
#define ANIM_SIT 0x6e
|
|
||||||
#define ANIM_CROUCH 0x6f
|
|
||||||
#define ANIM_DEATH 0x73
|
|
||||||
#define ANIM_LOOT 0x69
|
|
||||||
|
|
||||||
constexpr int16 RECAST_TYPE_UNLINKED_ITEM = -1;
|
constexpr int16 RECAST_TYPE_UNLINKED_ITEM = -1;
|
||||||
|
|
||||||
@@ -686,6 +684,53 @@ namespace Zones {
|
|||||||
constexpr uint16 APPRENTICE = 999; // Designer Apprentice
|
constexpr uint16 APPRENTICE = 999; // Designer Apprentice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Language {
|
||||||
|
constexpr uint8 CommonTongue = 0;
|
||||||
|
constexpr uint8 Barbarian = 1;
|
||||||
|
constexpr uint8 Erudian = 2;
|
||||||
|
constexpr uint8 Elvish = 3;
|
||||||
|
constexpr uint8 DarkElvish = 4;
|
||||||
|
constexpr uint8 Dwarvish = 5;
|
||||||
|
constexpr uint8 Troll = 6;
|
||||||
|
constexpr uint8 Ogre = 7;
|
||||||
|
constexpr uint8 Gnomish = 8;
|
||||||
|
constexpr uint8 Halfling = 9;
|
||||||
|
constexpr uint8 ThievesCant = 10;
|
||||||
|
constexpr uint8 OldErudian = 11;
|
||||||
|
constexpr uint8 ElderElvish = 12;
|
||||||
|
constexpr uint8 Froglok = 13;
|
||||||
|
constexpr uint8 Goblin = 14;
|
||||||
|
constexpr uint8 Gnoll = 15;
|
||||||
|
constexpr uint8 CombineTongue = 16;
|
||||||
|
constexpr uint8 ElderTeirDal = 17;
|
||||||
|
constexpr uint8 Lizardman = 18;
|
||||||
|
constexpr uint8 Orcish = 19;
|
||||||
|
constexpr uint8 Faerie = 20;
|
||||||
|
constexpr uint8 Dragon = 21;
|
||||||
|
constexpr uint8 ElderDragon = 22;
|
||||||
|
constexpr uint8 DarkSpeech = 23;
|
||||||
|
constexpr uint8 VahShir = 24;
|
||||||
|
constexpr uint8 Alaran = 25;
|
||||||
|
constexpr uint8 Hadal = 26;
|
||||||
|
constexpr uint8 Unknown27 = 27;
|
||||||
|
|
||||||
|
constexpr uint8 MaxValue = 100;
|
||||||
|
}
|
||||||
|
namespace PetInfoType {
|
||||||
|
constexpr int Current = 0;
|
||||||
|
constexpr int Suspended = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace BuffEffectType {
|
||||||
|
constexpr uint8 None = 0;
|
||||||
|
constexpr uint8 Buff = 2;
|
||||||
|
constexpr uint8 InverseBuff = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace AlternateCurrencyMode {
|
||||||
|
constexpr uint32 Update = 7;
|
||||||
|
constexpr uint32 Populate = 8;
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FilterNone = 0,
|
FilterNone = 0,
|
||||||
|
|||||||
@@ -5134,8 +5134,6 @@ struct GroupMakeLeader_Struct
|
|||||||
//ex for a blank crowns window you would send:
|
//ex for a blank crowns window you would send:
|
||||||
//999999|1|999999|0
|
//999999|1|999999|0
|
||||||
//any items come after in much the same way adventure merchant items do except there is no theme included
|
//any items come after in much the same way adventure merchant items do except there is no theme included
|
||||||
#define ALT_CURRENCY_OP_POPULATE 8
|
|
||||||
#define ALT_CURRENCY_OP_UPDATE 7
|
|
||||||
|
|
||||||
//Server -> Client
|
//Server -> Client
|
||||||
//Populates the initial Alternate Currency Window
|
//Populates the initial Alternate Currency Window
|
||||||
|
|||||||
+110
-15
@@ -20,9 +20,12 @@
|
|||||||
#include "eqemu_config.h"
|
#include "eqemu_config.h"
|
||||||
#include "misc_functions.h"
|
#include "misc_functions.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
|
#include "eqemu_logsys.h"
|
||||||
|
#include "json/json.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
|
std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
|
||||||
EQEmuConfig *EQEmuConfig::_config = nullptr;
|
EQEmuConfig *EQEmuConfig::_config = nullptr;
|
||||||
@@ -111,13 +114,12 @@ void EQEmuConfig::parse_config()
|
|||||||
DisableConfigChecks = true;
|
DisableConfigChecks = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* UCS
|
|
||||||
*/
|
CheckUcsConfigConversion();
|
||||||
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
|
|
||||||
ChatPort = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "7778").asString());
|
m_ucs_host = _root["server"]["ucs"].get("host", "eqchat.eqemulator.net").asString();
|
||||||
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
|
m_ucs_port = Strings::ToUnsignedInt(_root["server"]["ucs"].get("port", "7778").asString());
|
||||||
MailPort = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "7778").asString());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database
|
* Database
|
||||||
@@ -246,16 +248,16 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
|||||||
return (WorldHTTPEnabled ? "true" : "false");
|
return (WorldHTTPEnabled ? "true" : "false");
|
||||||
}
|
}
|
||||||
if (var_name == "ChatHost") {
|
if (var_name == "ChatHost") {
|
||||||
return (ChatHost);
|
return (m_ucs_host);
|
||||||
}
|
}
|
||||||
if (var_name == "ChatPort") {
|
if (var_name == "ChatPort") {
|
||||||
return (itoa(ChatPort));
|
return (itoa(m_ucs_port));
|
||||||
}
|
}
|
||||||
if (var_name == "MailHost") {
|
if (var_name == "MailHost") {
|
||||||
return (MailHost);
|
return (m_ucs_host);
|
||||||
}
|
}
|
||||||
if (var_name == "MailPort") {
|
if (var_name == "MailPort") {
|
||||||
return (itoa(MailPort));
|
return (itoa(m_ucs_port));
|
||||||
}
|
}
|
||||||
if (var_name == "DatabaseHost") {
|
if (var_name == "DatabaseHost") {
|
||||||
return (DatabaseHost);
|
return (DatabaseHost);
|
||||||
@@ -362,10 +364,8 @@ void EQEmuConfig::Dump() const
|
|||||||
std::cout << "WorldHTTPPort = " << WorldHTTPPort << std::endl;
|
std::cout << "WorldHTTPPort = " << WorldHTTPPort << std::endl;
|
||||||
std::cout << "WorldHTTPMimeFile = " << WorldHTTPMimeFile << std::endl;
|
std::cout << "WorldHTTPMimeFile = " << WorldHTTPMimeFile << std::endl;
|
||||||
std::cout << "WorldHTTPEnabled = " << WorldHTTPEnabled << std::endl;
|
std::cout << "WorldHTTPEnabled = " << WorldHTTPEnabled << std::endl;
|
||||||
std::cout << "ChatHost = " << ChatHost << std::endl;
|
std::cout << "UCSHost = " << m_ucs_host << std::endl;
|
||||||
std::cout << "ChatPort = " << ChatPort << std::endl;
|
std::cout << "UCSPort = " << m_ucs_port << std::endl;
|
||||||
std::cout << "MailHost = " << MailHost << std::endl;
|
|
||||||
std::cout << "MailPort = " << MailPort << std::endl;
|
|
||||||
std::cout << "DatabaseHost = " << DatabaseHost << std::endl;
|
std::cout << "DatabaseHost = " << DatabaseHost << std::endl;
|
||||||
std::cout << "DatabaseUsername = " << DatabaseUsername << std::endl;
|
std::cout << "DatabaseUsername = " << DatabaseUsername << std::endl;
|
||||||
std::cout << "DatabasePassword = " << DatabasePassword << std::endl;
|
std::cout << "DatabasePassword = " << DatabasePassword << std::endl;
|
||||||
@@ -392,3 +392,98 @@ void EQEmuConfig::Dump() const
|
|||||||
std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl;
|
std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl;
|
||||||
// std::cout << "DynamicCount = " << DynamicCount << std::endl;
|
// std::cout << "DynamicCount = " << DynamicCount << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &EQEmuConfig::GetUCSHost() const
|
||||||
|
{
|
||||||
|
return m_ucs_host;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 EQEmuConfig::GetUCSPort() const
|
||||||
|
{
|
||||||
|
return m_ucs_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQEmuConfig::CheckUcsConfigConversion()
|
||||||
|
{
|
||||||
|
std::string chat_host = _root["server"]["chatserver"].get("host", "").asString();
|
||||||
|
uint32 chat_port = Strings::ToUnsignedInt(_root["server"]["chatserver"].get("port", "0").asString());
|
||||||
|
std::string mail_host = _root["server"]["mailserver"].get("host", "").asString();
|
||||||
|
uint32 mail_port = Strings::ToUnsignedInt(_root["server"]["mailserver"].get("port", "0").asString());
|
||||||
|
std::string ucs_host = _root["server"]["ucs"].get("host", "").asString();
|
||||||
|
|
||||||
|
// automatic ucs legacy configuration migration
|
||||||
|
// if old configuration values are set, let's backup the existing configuration
|
||||||
|
// and migrate to to use the new fields and write the new config
|
||||||
|
if ((!chat_host.empty() || !mail_host.empty()) && ucs_host.empty()) {
|
||||||
|
LogInfo("Migrating old [eqemu_config] UCS configuration to new configuration");
|
||||||
|
|
||||||
|
std::string config_file_path = std::filesystem::path{
|
||||||
|
path.GetServerPath() + "/eqemu_config.json"
|
||||||
|
}.string();
|
||||||
|
|
||||||
|
std::string config_file_bak_path = std::filesystem::path{
|
||||||
|
path.GetServerPath() + "/eqemu_config.ucs-migrate-json.bak"
|
||||||
|
}.string();
|
||||||
|
|
||||||
|
// copy eqemu_config.json to eqemu_config.json.bak
|
||||||
|
std::ifstream src(config_file_path, std::ios::binary);
|
||||||
|
std::ofstream dst(config_file_bak_path, std::ios::binary);
|
||||||
|
dst << src.rdbuf();
|
||||||
|
src.close();
|
||||||
|
|
||||||
|
LogInfo("Old configuration backed up to [{}]", config_file_bak_path);
|
||||||
|
|
||||||
|
// read eqemu_config.json, transplant new fields and write to eqemu_config.json
|
||||||
|
Json::Value root;
|
||||||
|
Json::Reader reader;
|
||||||
|
std::ifstream file(config_file_path);
|
||||||
|
if (!reader.parse(file, root)) {
|
||||||
|
LogError("Failed to parse configuration file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// get old fields
|
||||||
|
std::string host = !chat_host.empty() ? chat_host : mail_host;
|
||||||
|
if (host.empty()) {
|
||||||
|
host = "eqchat.eqemulator.net";
|
||||||
|
}
|
||||||
|
std::string port = chat_port > 0 ? std::to_string(chat_port) : std::to_string(mail_port);
|
||||||
|
if (port.empty()) {
|
||||||
|
port = "7778";
|
||||||
|
}
|
||||||
|
|
||||||
|
// set new fields
|
||||||
|
root["server"]["ucs"]["host"] = host;
|
||||||
|
root["server"]["ucs"]["port"] = port;
|
||||||
|
|
||||||
|
// unset old fields
|
||||||
|
root["server"].removeMember("chatserver");
|
||||||
|
root["server"].removeMember("mailserver");
|
||||||
|
|
||||||
|
// get Json::Value raw string
|
||||||
|
std::string config = root.toStyledString();
|
||||||
|
|
||||||
|
// format using more modern json library
|
||||||
|
nlohmann::json data = nlohmann::json::parse(config);
|
||||||
|
|
||||||
|
// write to file
|
||||||
|
std::ofstream o(config_file_path);
|
||||||
|
o << std::setw(1) << data << std::endl;
|
||||||
|
o.close();
|
||||||
|
|
||||||
|
// write new config
|
||||||
|
LogInfo("New configuration written to [{}]", config_file_path);
|
||||||
|
LogInfo("Migration complete, please review the new configuration file");
|
||||||
|
|
||||||
|
// reload config internally
|
||||||
|
try {
|
||||||
|
std::ifstream fconfig(config_file_path, std::ifstream::binary);
|
||||||
|
fconfig >> _config->_root;
|
||||||
|
_config->parse_config();
|
||||||
|
}
|
||||||
|
catch (std::exception &) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,14 +62,6 @@ class EQEmuConfig
|
|||||||
std::string SharedKey;
|
std::string SharedKey;
|
||||||
bool DisableConfigChecks;
|
bool DisableConfigChecks;
|
||||||
|
|
||||||
// From <chatserver/>
|
|
||||||
std::string ChatHost;
|
|
||||||
uint16 ChatPort;
|
|
||||||
|
|
||||||
// From <mailserver/>
|
|
||||||
std::string MailHost;
|
|
||||||
uint16 MailPort;
|
|
||||||
|
|
||||||
// From <database/>
|
// From <database/>
|
||||||
std::string DatabaseHost;
|
std::string DatabaseHost;
|
||||||
std::string DatabaseUsername;
|
std::string DatabaseUsername;
|
||||||
@@ -122,12 +114,18 @@ class EQEmuConfig
|
|||||||
|
|
||||||
bool auto_database_updates;
|
bool auto_database_updates;
|
||||||
|
|
||||||
|
const std::string &GetUCSHost() const;
|
||||||
|
uint16 GetUCSPort() const;
|
||||||
|
|
||||||
// uint16 DynamicCount;
|
// uint16 DynamicCount;
|
||||||
|
|
||||||
// map<string,uint16> StaticZones;
|
// map<string,uint16> StaticZones;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
std::string m_ucs_host;
|
||||||
|
uint16 m_ucs_port;
|
||||||
|
|
||||||
static EQEmuConfig *_config;
|
static EQEmuConfig *_config;
|
||||||
Json::Value _root;
|
Json::Value _root;
|
||||||
static std::string ConfigFile;
|
static std::string ConfigFile;
|
||||||
@@ -186,6 +184,7 @@ class EQEmuConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
|
void CheckUcsConfigConversion();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with this library; if not, write to the Free
|
|
||||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
||||||
MA 02111-1307, USA */
|
|
||||||
|
|
||||||
/* Error messages for mysql clients */
|
|
||||||
/* error messages for the demon is in share/language/errmsg.sys */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void init_client_errs(void);
|
|
||||||
extern const char *client_errors[]; /* Error messages */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CR_MIN_ERROR 2000 /* For easier client code */
|
|
||||||
#define CR_MAX_ERROR 2999
|
|
||||||
#if defined(OS2) && defined( MYSQL_SERVER)
|
|
||||||
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
|
|
||||||
#else
|
|
||||||
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
|
|
||||||
#endif
|
|
||||||
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
|
|
||||||
|
|
||||||
#define CR_UNKNOWN_ERROR 2000
|
|
||||||
#define CR_SOCKET_CREATE_ERROR 2001
|
|
||||||
#define CR_CONNECTION_ERROR 2002
|
|
||||||
#define CR_CONN_HOST_ERROR 2003
|
|
||||||
#define CR_IPSOCK_ERROR 2004
|
|
||||||
#define CR_UNKNOWN_HOST 2005
|
|
||||||
#define CR_SERVER_GONE_ERROR 2006
|
|
||||||
#define CR_VERSION_ERROR 2007
|
|
||||||
#define CR_OUT_OF_MEMORY 2008
|
|
||||||
#define CR_WRONG_HOST_INFO 2009
|
|
||||||
#define CR_LOCALHOST_CONNECTION 2010
|
|
||||||
#define CR_TCP_CONNECTION 2011
|
|
||||||
#define CR_SERVER_HANDSHAKE_ERR 2012
|
|
||||||
#define CR_SERVER_LOST 2013
|
|
||||||
#define CR_COMMANDS_OUT_OF_SYNC 2014
|
|
||||||
#define CR_NAMEDPIPE_CONNECTION 2015
|
|
||||||
#define CR_NAMEDPIPEWAIT_ERROR 2016
|
|
||||||
#define CR_NAMEDPIPEOPEN_ERROR 2017
|
|
||||||
#define CR_NAMEDPIPESETSTATE_ERROR 2018
|
|
||||||
#define CR_CANT_READ_CHARSET 2019
|
|
||||||
#define CR_NET_PACKET_TOO_LARGE 2020
|
|
||||||
@@ -801,7 +801,7 @@ int16 EQ::InventoryProfile::HasItemByLoreGroup(uint32 loregroup, uint8 where)
|
|||||||
// Returns slot_id when there's one available, else SLOT_INVALID
|
// Returns slot_id when there's one available, else SLOT_INVALID
|
||||||
int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
|
int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
|
||||||
{
|
{
|
||||||
const int16 last_bag_slot = RuleI(World, ExpansionSettings) & EQ::expansions::bitHoT ? EQ::invslot::slotGeneral10 : EQ::invslot::slotGeneral8;
|
const int16 last_bag_slot = (RuleI(World, ExpansionSettings) == -1 || RuleI(World, ExpansionSettings) & EQ::expansions::bitHoT) ? EQ::invslot::slotGeneral10 : EQ::invslot::slotGeneral8;
|
||||||
|
|
||||||
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { // Check basic inventory
|
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { // Check basic inventory
|
||||||
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
|
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.org)
|
|
||||||
|
|
||||||
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 LANGUAGES_H
|
|
||||||
#define LANGUAGES_H
|
|
||||||
#include "../common/types.h"
|
|
||||||
|
|
||||||
#define LANG_COMMON_TONGUE 0
|
|
||||||
#define LANG_BARBARIAN 1
|
|
||||||
#define LANG_ERUDIAN 2
|
|
||||||
#define LANG_ELVISH 3
|
|
||||||
#define LANG_DARK_ELVISH 4
|
|
||||||
#define LANG_DWARVISH 5
|
|
||||||
#define LANG_TROLL 6
|
|
||||||
#define LANG_OGRE 7
|
|
||||||
#define LANG_GNOMISH 8
|
|
||||||
#define LANG_HALFLING 9
|
|
||||||
#define LANG_THIEVES_CANT 10
|
|
||||||
#define LANG_OLD_ERUDIAN 11
|
|
||||||
#define LANG_ELDER_ELVISH 12
|
|
||||||
#define LANG_FROGLOK 13
|
|
||||||
#define LANG_GOBLIN 14
|
|
||||||
#define LANG_GNOLL 15
|
|
||||||
#define LANG_COMBINE_TONGUE 16
|
|
||||||
#define LANG_ELDER_TEIRDAL 17
|
|
||||||
#define LANG_LIZARDMAN 18
|
|
||||||
#define LANG_ORCISH 19
|
|
||||||
#define LANG_FAERIE 20
|
|
||||||
#define LANG_DRAGON 21
|
|
||||||
#define LANG_ELDER_DRAGON 22
|
|
||||||
#define LANG_DARK_SPEECH 23
|
|
||||||
#define LANG_VAH_SHIR 24
|
|
||||||
#define LANG_ALARAN 25
|
|
||||||
#define LANG_HADAL 26
|
|
||||||
#define LANG_UNKNOWN 27
|
|
||||||
|
|
||||||
#define MAX_LANGUAGE_SKILL 100
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ namespace RoF
|
|||||||
unsigned char *emu_buffer = in->pBuffer;
|
unsigned char *emu_buffer = in->pBuffer;
|
||||||
uint32 opcode = *((uint32*)emu_buffer);
|
uint32 opcode = *((uint32*)emu_buffer);
|
||||||
|
|
||||||
if (opcode == 8) {
|
if (opcode == AlternateCurrencyMode::Populate) {
|
||||||
AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer;
|
AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer;
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(
|
auto outapp = new EQApplicationPacket(
|
||||||
@@ -3165,7 +3165,7 @@ namespace RoF
|
|||||||
|
|
||||||
SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer;
|
SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer;
|
||||||
|
|
||||||
if (sas->type != AT_Size)
|
if (sas->type != AppearanceType::Size)
|
||||||
{
|
{
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
dest->FastQueuePacket(&in, ack_req);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ namespace RoF2
|
|||||||
unsigned char *emu_buffer = in->pBuffer;
|
unsigned char *emu_buffer = in->pBuffer;
|
||||||
uint32 opcode = *((uint32*)emu_buffer);
|
uint32 opcode = *((uint32*)emu_buffer);
|
||||||
|
|
||||||
if (opcode == 8) {
|
if (opcode == AlternateCurrencyMode::Populate) {
|
||||||
AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer;
|
AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer;
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(
|
auto outapp = new EQApplicationPacket(
|
||||||
@@ -3218,7 +3218,7 @@ namespace RoF2
|
|||||||
|
|
||||||
SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer;
|
SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer;
|
||||||
|
|
||||||
if (sas->type != AT_Size)
|
if (sas->type != AppearanceType::Size)
|
||||||
{
|
{
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
dest->FastQueuePacket(&in, ack_req);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ namespace UF
|
|||||||
unsigned char *emu_buffer = in->pBuffer;
|
unsigned char *emu_buffer = in->pBuffer;
|
||||||
uint32 opcode = *((uint32*)emu_buffer);
|
uint32 opcode = *((uint32*)emu_buffer);
|
||||||
|
|
||||||
if (opcode == 8) {
|
if (opcode == AlternateCurrencyMode::Populate) {
|
||||||
AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer;
|
AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer;
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(
|
auto outapp = new EQApplicationPacket(
|
||||||
@@ -2339,7 +2339,7 @@ namespace UF
|
|||||||
|
|
||||||
SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer;
|
SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer;
|
||||||
|
|
||||||
if (sas->type != AT_Size)
|
if (sas->type != AppearanceType::Size)
|
||||||
{
|
{
|
||||||
dest->FastQueuePacket(&in, ack_req);
|
dest->FastQueuePacket(&in, ack_req);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ enum : int { //values for pTimerType
|
|||||||
pTimerBeggingPickPocket = 27,
|
pTimerBeggingPickPocket = 27,
|
||||||
pTimerLinkedSpellReuseStart = 28,
|
pTimerLinkedSpellReuseStart = 28,
|
||||||
pTimerLinkedSpellReuseEnd = 48,
|
pTimerLinkedSpellReuseEnd = 48,
|
||||||
|
pTimerClearXTarget = 50,
|
||||||
|
|
||||||
pTimerShieldAbility = 86,
|
pTimerShieldAbility = 86,
|
||||||
|
|
||||||
|
|||||||
+36
-36
@@ -1598,7 +1598,7 @@ float GetRaceGenderDefaultHeight(int race, int gender)
|
|||||||
return 6.0f;
|
return 6.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gender == FEMALE) {
|
if (gender == Gender::Female) {
|
||||||
return female_height[race];
|
return female_height[race];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1606,38 +1606,38 @@ float GetRaceGenderDefaultHeight(int race, int gender)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PlayerAppearance prep
|
// PlayerAppearance prep
|
||||||
#define HUMAN_MALE ((HUMAN << 8) | MALE)
|
#define HUMAN_MALE ((HUMAN << 8) | Gender::Male)
|
||||||
#define HUMAN_FEMALE ((HUMAN << 8) | FEMALE)
|
#define HUMAN_FEMALE ((HUMAN << 8) | Gender::Female)
|
||||||
#define BARBARIAN_MALE ((BARBARIAN << 8) | MALE)
|
#define BARBARIAN_MALE ((BARBARIAN << 8) | Gender::Male)
|
||||||
#define BARBARIAN_FEMALE ((BARBARIAN << 8) | FEMALE)
|
#define BARBARIAN_FEMALE ((BARBARIAN << 8) | Gender::Female)
|
||||||
#define ERUDITE_MALE ((ERUDITE << 8) | MALE)
|
#define ERUDITE_MALE ((ERUDITE << 8) | Gender::Male)
|
||||||
#define ERUDITE_FEMALE ((ERUDITE << 8) | FEMALE)
|
#define ERUDITE_FEMALE ((ERUDITE << 8) | Gender::Female)
|
||||||
#define WOOD_ELF_MALE ((WOOD_ELF << 8) | MALE)
|
#define WOOD_ELF_MALE ((WOOD_ELF << 8) | Gender::Male)
|
||||||
#define WOOD_ELF_FEMALE ((WOOD_ELF << 8) | FEMALE)
|
#define WOOD_ELF_FEMALE ((WOOD_ELF << 8) | Gender::Female)
|
||||||
#define HIGH_ELF_MALE ((HIGH_ELF << 8) | MALE)
|
#define HIGH_ELF_MALE ((HIGH_ELF << 8) | Gender::Male)
|
||||||
#define HIGH_ELF_FEMALE ((HIGH_ELF << 8) | FEMALE)
|
#define HIGH_ELF_FEMALE ((HIGH_ELF << 8) | Gender::Female)
|
||||||
#define DARK_ELF_MALE ((DARK_ELF << 8) | MALE)
|
#define DARK_ELF_MALE ((DARK_ELF << 8) | Gender::Male)
|
||||||
#define DARK_ELF_FEMALE ((DARK_ELF << 8) | FEMALE)
|
#define DARK_ELF_FEMALE ((DARK_ELF << 8) | Gender::Female)
|
||||||
#define HALF_ELF_MALE ((HALF_ELF << 8) | MALE)
|
#define HALF_ELF_MALE ((HALF_ELF << 8) | Gender::Male)
|
||||||
#define HALF_ELF_FEMALE ((HALF_ELF << 8) | FEMALE)
|
#define HALF_ELF_FEMALE ((HALF_ELF << 8) | Gender::Female)
|
||||||
#define DWARF_MALE ((DWARF << 8) | MALE)
|
#define DWARF_MALE ((DWARF << 8) | Gender::Male)
|
||||||
#define DWARF_FEMALE ((DWARF << 8) | FEMALE)
|
#define DWARF_FEMALE ((DWARF << 8) | Gender::Female)
|
||||||
#define TROLL_MALE ((TROLL << 8) | MALE)
|
#define TROLL_MALE ((TROLL << 8) | Gender::Male)
|
||||||
#define TROLL_FEMALE ((TROLL << 8) | FEMALE)
|
#define TROLL_FEMALE ((TROLL << 8) | Gender::Female)
|
||||||
#define OGRE_MALE ((OGRE << 8) | MALE)
|
#define OGRE_MALE ((OGRE << 8) | Gender::Male)
|
||||||
#define OGRE_FEMALE ((OGRE << 8) | FEMALE)
|
#define OGRE_FEMALE ((OGRE << 8) | Gender::Female)
|
||||||
#define HALFLING_MALE ((HALFLING << 8) | MALE)
|
#define HALFLING_MALE ((HALFLING << 8) | Gender::Male)
|
||||||
#define HALFLING_FEMALE ((HALFLING << 8) | FEMALE)
|
#define HALFLING_FEMALE ((HALFLING << 8) | Gender::Female)
|
||||||
#define GNOME_MALE ((GNOME << 8) | MALE)
|
#define GNOME_MALE ((GNOME << 8) | Gender::Male)
|
||||||
#define GNOME_FEMALE ((GNOME << 8) | FEMALE)
|
#define GNOME_FEMALE ((GNOME << 8) | Gender::Female)
|
||||||
#define IKSAR_MALE ((IKSAR << 8) | MALE)
|
#define IKSAR_MALE ((IKSAR << 8) | Gender::Male)
|
||||||
#define IKSAR_FEMALE ((IKSAR << 8) | FEMALE)
|
#define IKSAR_FEMALE ((IKSAR << 8) | Gender::Female)
|
||||||
#define VAHSHIR_MALE ((VAHSHIR << 8) | MALE)
|
#define VAHSHIR_MALE ((VAHSHIR << 8) | Gender::Male)
|
||||||
#define VAHSHIR_FEMALE ((VAHSHIR << 8) | FEMALE)
|
#define VAHSHIR_FEMALE ((VAHSHIR << 8) | Gender::Female)
|
||||||
#define FROGLOK_MALE ((FROGLOK << 8) | MALE)
|
#define FROGLOK_MALE ((FROGLOK << 8) | Gender::Male)
|
||||||
#define FROGLOK_FEMALE ((FROGLOK << 8) | FEMALE)
|
#define FROGLOK_FEMALE ((FROGLOK << 8) | Gender::Female)
|
||||||
#define DRAKKIN_MALE ((DRAKKIN << 8) | MALE)
|
#define DRAKKIN_MALE ((DRAKKIN << 8) | Gender::Male)
|
||||||
#define DRAKKIN_FEMALE ((DRAKKIN << 8) | FEMALE)
|
#define DRAKKIN_FEMALE ((DRAKKIN << 8) | Gender::Female)
|
||||||
|
|
||||||
#define BINDRG(r, g) (((int)r << 8) | g)
|
#define BINDRG(r, g) (((int)r << 8) | g)
|
||||||
|
|
||||||
@@ -2238,11 +2238,11 @@ bool PlayerAppearance::IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_v
|
|||||||
|
|
||||||
const char* GetGenderName(uint32 gender_id) {
|
const char* GetGenderName(uint32 gender_id) {
|
||||||
const char* gender_name = "Unknown";
|
const char* gender_name = "Unknown";
|
||||||
if (gender_id == MALE) {
|
if (gender_id == Gender::Male) {
|
||||||
gender_name = "Male";
|
gender_name = "Male";
|
||||||
} else if (gender_id == FEMALE) {
|
} else if (gender_id == Gender::Female) {
|
||||||
gender_name = "Female";
|
gender_name = "Female";
|
||||||
} else if (gender_id == NEUTER) {
|
} else if (gender_id == Gender::Neuter) {
|
||||||
gender_name = "Neuter";
|
gender_name = "Neuter";
|
||||||
}
|
}
|
||||||
return gender_name;
|
return gender_name;
|
||||||
|
|||||||
+5
-3
@@ -21,9 +21,11 @@
|
|||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#define MALE 0
|
namespace Gender {
|
||||||
#define FEMALE 1
|
constexpr uint8 Male = 0;
|
||||||
#define NEUTER 2
|
constexpr uint8 Female = 1;
|
||||||
|
constexpr uint8 Neuter = 2;
|
||||||
|
}
|
||||||
|
|
||||||
//theres a big list straight from the client below.
|
//theres a big list straight from the client below.
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_ACCOUNT_REPOSITORY_H
|
#ifndef EQEMU_BASE_ACCOUNT_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseAccountRepository {
|
class BaseAccountRepository {
|
||||||
public:
|
public:
|
||||||
struct Account {
|
struct Account {
|
||||||
@@ -196,8 +197,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
account_id
|
account_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -547,6 +549,108 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const Account &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.charname) + "'");
|
||||||
|
v.push_back(std::to_string(e.sharedplat));
|
||||||
|
v.push_back("'" + Strings::Escape(e.password) + "'");
|
||||||
|
v.push_back(std::to_string(e.status));
|
||||||
|
v.push_back("'" + Strings::Escape(e.ls_id) + "'");
|
||||||
|
v.push_back(std::to_string(e.lsaccount_id));
|
||||||
|
v.push_back(std::to_string(e.gmspeed));
|
||||||
|
v.push_back(std::to_string(e.invulnerable));
|
||||||
|
v.push_back(std::to_string(e.flymode));
|
||||||
|
v.push_back(std::to_string(e.ignore_tells));
|
||||||
|
v.push_back(std::to_string(e.revoked));
|
||||||
|
v.push_back(std::to_string(e.karma));
|
||||||
|
v.push_back("'" + Strings::Escape(e.minilogin_ip) + "'");
|
||||||
|
v.push_back(std::to_string(e.hideme));
|
||||||
|
v.push_back(std::to_string(e.rulesflag));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")");
|
||||||
|
v.push_back(std::to_string(e.time_creation));
|
||||||
|
v.push_back("'" + Strings::Escape(e.ban_reason) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.suspend_reason) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.crc_eqgame) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.crc_skillcaps) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.crc_basedata) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<Account> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.charname) + "'");
|
||||||
|
v.push_back(std::to_string(e.sharedplat));
|
||||||
|
v.push_back("'" + Strings::Escape(e.password) + "'");
|
||||||
|
v.push_back(std::to_string(e.status));
|
||||||
|
v.push_back("'" + Strings::Escape(e.ls_id) + "'");
|
||||||
|
v.push_back(std::to_string(e.lsaccount_id));
|
||||||
|
v.push_back(std::to_string(e.gmspeed));
|
||||||
|
v.push_back(std::to_string(e.invulnerable));
|
||||||
|
v.push_back(std::to_string(e.flymode));
|
||||||
|
v.push_back(std::to_string(e.ignore_tells));
|
||||||
|
v.push_back(std::to_string(e.revoked));
|
||||||
|
v.push_back(std::to_string(e.karma));
|
||||||
|
v.push_back("'" + Strings::Escape(e.minilogin_ip) + "'");
|
||||||
|
v.push_back(std::to_string(e.hideme));
|
||||||
|
v.push_back(std::to_string(e.rulesflag));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")");
|
||||||
|
v.push_back(std::to_string(e.time_creation));
|
||||||
|
v.push_back("'" + Strings::Escape(e.ban_reason) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.suspend_reason) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.crc_eqgame) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.crc_skillcaps) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.crc_basedata) + "'");
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_ACCOUNT_REPOSITORY_H
|
#endif //EQEMU_BASE_ACCOUNT_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterAltCurrencyRepository {
|
class BaseCharacterAltCurrencyRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterAltCurrency {
|
struct CharacterAltCurrency {
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_alt_currency_id
|
character_alt_currency_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -338,6 +340,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterAltCurrency &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.currency_id));
|
||||||
|
v.push_back(std::to_string(e.amount));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterAltCurrency> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.currency_id));
|
||||||
|
v.push_back(std::to_string(e.amount));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterAlternateAbilitiesRepository {
|
class BaseCharacterAlternateAbilitiesRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterAlternateAbilities {
|
struct CharacterAlternateAbilities {
|
||||||
@@ -116,8 +117,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_alternate_abilities_id
|
character_alternate_abilities_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -348,6 +350,68 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterAlternateAbilities &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.aa_id));
|
||||||
|
v.push_back(std::to_string(e.aa_value));
|
||||||
|
v.push_back(std::to_string(e.charges));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterAlternateAbilities> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.aa_id));
|
||||||
|
v.push_back(std::to_string(e.aa_value));
|
||||||
|
v.push_back(std::to_string(e.charges));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterAurasRepository {
|
class BaseCharacterAurasRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterAuras {
|
struct CharacterAuras {
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_auras_id
|
character_auras_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -338,6 +340,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterAuras &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterAuras> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterBandolierRepository {
|
class BaseCharacterBandolierRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterBandolier {
|
struct CharacterBandolier {
|
||||||
@@ -124,8 +125,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_bandolier_id
|
character_bandolier_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -368,6 +370,72 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterBandolier &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.bandolier_id));
|
||||||
|
v.push_back(std::to_string(e.bandolier_slot));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.bandolier_name) + "'");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterBandolier> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.bandolier_id));
|
||||||
|
v.push_back(std::to_string(e.bandolier_slot));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.icon));
|
||||||
|
v.push_back("'" + Strings::Escape(e.bandolier_name) + "'");
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterBindRepository {
|
class BaseCharacterBindRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterBind {
|
struct CharacterBind {
|
||||||
@@ -132,8 +133,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_bind_id
|
character_bind_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -387,6 +389,76 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterBind &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.zone_id));
|
||||||
|
v.push_back(std::to_string(e.instance_id));
|
||||||
|
v.push_back(std::to_string(e.x));
|
||||||
|
v.push_back(std::to_string(e.y));
|
||||||
|
v.push_back(std::to_string(e.z));
|
||||||
|
v.push_back(std::to_string(e.heading));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterBind> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.zone_id));
|
||||||
|
v.push_back(std::to_string(e.instance_id));
|
||||||
|
v.push_back(std::to_string(e.x));
|
||||||
|
v.push_back(std::to_string(e.y));
|
||||||
|
v.push_back(std::to_string(e.z));
|
||||||
|
v.push_back(std::to_string(e.heading));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterBuffsRepository {
|
class BaseCharacterBuffsRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterBuffs {
|
struct CharacterBuffs {
|
||||||
@@ -168,8 +169,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_buffs_id
|
character_buffs_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -478,6 +480,94 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterBuffs &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.character_id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
v.push_back(std::to_string(e.caster_level));
|
||||||
|
v.push_back("'" + Strings::Escape(e.caster_name) + "'");
|
||||||
|
v.push_back(std::to_string(e.ticsremaining));
|
||||||
|
v.push_back(std::to_string(e.counters));
|
||||||
|
v.push_back(std::to_string(e.numhits));
|
||||||
|
v.push_back(std::to_string(e.melee_rune));
|
||||||
|
v.push_back(std::to_string(e.magic_rune));
|
||||||
|
v.push_back(std::to_string(e.persistent));
|
||||||
|
v.push_back(std::to_string(e.dot_rune));
|
||||||
|
v.push_back(std::to_string(e.caston_x));
|
||||||
|
v.push_back(std::to_string(e.caston_y));
|
||||||
|
v.push_back(std::to_string(e.caston_z));
|
||||||
|
v.push_back(std::to_string(e.ExtraDIChance));
|
||||||
|
v.push_back(std::to_string(e.instrument_mod));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterBuffs> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.character_id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
v.push_back(std::to_string(e.caster_level));
|
||||||
|
v.push_back("'" + Strings::Escape(e.caster_name) + "'");
|
||||||
|
v.push_back(std::to_string(e.ticsremaining));
|
||||||
|
v.push_back(std::to_string(e.counters));
|
||||||
|
v.push_back(std::to_string(e.numhits));
|
||||||
|
v.push_back(std::to_string(e.melee_rune));
|
||||||
|
v.push_back(std::to_string(e.magic_rune));
|
||||||
|
v.push_back(std::to_string(e.persistent));
|
||||||
|
v.push_back(std::to_string(e.dot_rune));
|
||||||
|
v.push_back(std::to_string(e.caston_x));
|
||||||
|
v.push_back(std::to_string(e.caston_y));
|
||||||
|
v.push_back(std::to_string(e.caston_z));
|
||||||
|
v.push_back(std::to_string(e.ExtraDIChance));
|
||||||
|
v.push_back(std::to_string(e.instrument_mod));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterCurrencyRepository {
|
class BaseCharacterCurrencyRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterCurrency {
|
struct CharacterCurrency {
|
||||||
@@ -168,8 +169,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_currency_id
|
character_currency_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -478,6 +480,94 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterCurrency &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.platinum));
|
||||||
|
v.push_back(std::to_string(e.gold));
|
||||||
|
v.push_back(std::to_string(e.silver));
|
||||||
|
v.push_back(std::to_string(e.copper));
|
||||||
|
v.push_back(std::to_string(e.platinum_bank));
|
||||||
|
v.push_back(std::to_string(e.gold_bank));
|
||||||
|
v.push_back(std::to_string(e.silver_bank));
|
||||||
|
v.push_back(std::to_string(e.copper_bank));
|
||||||
|
v.push_back(std::to_string(e.platinum_cursor));
|
||||||
|
v.push_back(std::to_string(e.gold_cursor));
|
||||||
|
v.push_back(std::to_string(e.silver_cursor));
|
||||||
|
v.push_back(std::to_string(e.copper_cursor));
|
||||||
|
v.push_back(std::to_string(e.radiant_crystals));
|
||||||
|
v.push_back(std::to_string(e.career_radiant_crystals));
|
||||||
|
v.push_back(std::to_string(e.ebon_crystals));
|
||||||
|
v.push_back(std::to_string(e.career_ebon_crystals));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterCurrency> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.platinum));
|
||||||
|
v.push_back(std::to_string(e.gold));
|
||||||
|
v.push_back(std::to_string(e.silver));
|
||||||
|
v.push_back(std::to_string(e.copper));
|
||||||
|
v.push_back(std::to_string(e.platinum_bank));
|
||||||
|
v.push_back(std::to_string(e.gold_bank));
|
||||||
|
v.push_back(std::to_string(e.silver_bank));
|
||||||
|
v.push_back(std::to_string(e.copper_bank));
|
||||||
|
v.push_back(std::to_string(e.platinum_cursor));
|
||||||
|
v.push_back(std::to_string(e.gold_cursor));
|
||||||
|
v.push_back(std::to_string(e.silver_cursor));
|
||||||
|
v.push_back(std::to_string(e.copper_cursor));
|
||||||
|
v.push_back(std::to_string(e.radiant_crystals));
|
||||||
|
v.push_back(std::to_string(e.career_radiant_crystals));
|
||||||
|
v.push_back(std::to_string(e.ebon_crystals));
|
||||||
|
v.push_back(std::to_string(e.career_ebon_crystals));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H
|
||||||
@@ -1339,6 +1339,266 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterData &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.account_id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.last_name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.title) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.suffix) + "'");
|
||||||
|
v.push_back(std::to_string(e.zone_id));
|
||||||
|
v.push_back(std::to_string(e.zone_instance));
|
||||||
|
v.push_back(std::to_string(e.y));
|
||||||
|
v.push_back(std::to_string(e.x));
|
||||||
|
v.push_back(std::to_string(e.z));
|
||||||
|
v.push_back(std::to_string(e.heading));
|
||||||
|
v.push_back(std::to_string(e.gender));
|
||||||
|
v.push_back(std::to_string(e.race));
|
||||||
|
v.push_back(std::to_string(e.class_));
|
||||||
|
v.push_back(std::to_string(e.level));
|
||||||
|
v.push_back(std::to_string(e.deity));
|
||||||
|
v.push_back(std::to_string(e.birthday));
|
||||||
|
v.push_back(std::to_string(e.last_login));
|
||||||
|
v.push_back(std::to_string(e.time_played));
|
||||||
|
v.push_back(std::to_string(e.level2));
|
||||||
|
v.push_back(std::to_string(e.anon));
|
||||||
|
v.push_back(std::to_string(e.gm));
|
||||||
|
v.push_back(std::to_string(e.face));
|
||||||
|
v.push_back(std::to_string(e.hair_color));
|
||||||
|
v.push_back(std::to_string(e.hair_style));
|
||||||
|
v.push_back(std::to_string(e.beard));
|
||||||
|
v.push_back(std::to_string(e.beard_color));
|
||||||
|
v.push_back(std::to_string(e.eye_color_1));
|
||||||
|
v.push_back(std::to_string(e.eye_color_2));
|
||||||
|
v.push_back(std::to_string(e.drakkin_heritage));
|
||||||
|
v.push_back(std::to_string(e.drakkin_tattoo));
|
||||||
|
v.push_back(std::to_string(e.drakkin_details));
|
||||||
|
v.push_back(std::to_string(e.ability_time_seconds));
|
||||||
|
v.push_back(std::to_string(e.ability_number));
|
||||||
|
v.push_back(std::to_string(e.ability_time_minutes));
|
||||||
|
v.push_back(std::to_string(e.ability_time_hours));
|
||||||
|
v.push_back(std::to_string(e.exp));
|
||||||
|
v.push_back(std::to_string(e.exp_enabled));
|
||||||
|
v.push_back(std::to_string(e.aa_points_spent));
|
||||||
|
v.push_back(std::to_string(e.aa_exp));
|
||||||
|
v.push_back(std::to_string(e.aa_points));
|
||||||
|
v.push_back(std::to_string(e.group_leadership_exp));
|
||||||
|
v.push_back(std::to_string(e.raid_leadership_exp));
|
||||||
|
v.push_back(std::to_string(e.group_leadership_points));
|
||||||
|
v.push_back(std::to_string(e.raid_leadership_points));
|
||||||
|
v.push_back(std::to_string(e.points));
|
||||||
|
v.push_back(std::to_string(e.cur_hp));
|
||||||
|
v.push_back(std::to_string(e.mana));
|
||||||
|
v.push_back(std::to_string(e.endurance));
|
||||||
|
v.push_back(std::to_string(e.intoxication));
|
||||||
|
v.push_back(std::to_string(e.str));
|
||||||
|
v.push_back(std::to_string(e.sta));
|
||||||
|
v.push_back(std::to_string(e.cha));
|
||||||
|
v.push_back(std::to_string(e.dex));
|
||||||
|
v.push_back(std::to_string(e.int_));
|
||||||
|
v.push_back(std::to_string(e.agi));
|
||||||
|
v.push_back(std::to_string(e.wis));
|
||||||
|
v.push_back(std::to_string(e.zone_change_count));
|
||||||
|
v.push_back(std::to_string(e.toxicity));
|
||||||
|
v.push_back(std::to_string(e.hunger_level));
|
||||||
|
v.push_back(std::to_string(e.thirst_level));
|
||||||
|
v.push_back(std::to_string(e.ability_up));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_guk));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_mir));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_mmc));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_ruj));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_tak));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_available));
|
||||||
|
v.push_back(std::to_string(e.tribute_time_remaining));
|
||||||
|
v.push_back(std::to_string(e.career_tribute_points));
|
||||||
|
v.push_back(std::to_string(e.tribute_points));
|
||||||
|
v.push_back(std::to_string(e.tribute_active));
|
||||||
|
v.push_back(std::to_string(e.pvp_status));
|
||||||
|
v.push_back(std::to_string(e.pvp_kills));
|
||||||
|
v.push_back(std::to_string(e.pvp_deaths));
|
||||||
|
v.push_back(std::to_string(e.pvp_current_points));
|
||||||
|
v.push_back(std::to_string(e.pvp_career_points));
|
||||||
|
v.push_back(std::to_string(e.pvp_best_kill_streak));
|
||||||
|
v.push_back(std::to_string(e.pvp_worst_death_streak));
|
||||||
|
v.push_back(std::to_string(e.pvp_current_kill_streak));
|
||||||
|
v.push_back(std::to_string(e.pvp2));
|
||||||
|
v.push_back(std::to_string(e.pvp_type));
|
||||||
|
v.push_back(std::to_string(e.show_helm));
|
||||||
|
v.push_back(std::to_string(e.group_auto_consent));
|
||||||
|
v.push_back(std::to_string(e.raid_auto_consent));
|
||||||
|
v.push_back(std::to_string(e.guild_auto_consent));
|
||||||
|
v.push_back(std::to_string(e.leadership_exp_on));
|
||||||
|
v.push_back(std::to_string(e.RestTimer));
|
||||||
|
v.push_back(std::to_string(e.air_remaining));
|
||||||
|
v.push_back(std::to_string(e.autosplit_enabled));
|
||||||
|
v.push_back(std::to_string(e.lfp));
|
||||||
|
v.push_back(std::to_string(e.lfg));
|
||||||
|
v.push_back("'" + Strings::Escape(e.mailkey) + "'");
|
||||||
|
v.push_back(std::to_string(e.xtargets));
|
||||||
|
v.push_back(std::to_string(e.firstlogon));
|
||||||
|
v.push_back(std::to_string(e.e_aa_effects));
|
||||||
|
v.push_back(std::to_string(e.e_percent_to_aa));
|
||||||
|
v.push_back(std::to_string(e.e_expended_aa_spent));
|
||||||
|
v.push_back(std::to_string(e.aa_points_spent_old));
|
||||||
|
v.push_back(std::to_string(e.aa_points_old));
|
||||||
|
v.push_back(std::to_string(e.e_last_invsnapshot));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterData> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.account_id));
|
||||||
|
v.push_back("'" + Strings::Escape(e.name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.last_name) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.title) + "'");
|
||||||
|
v.push_back("'" + Strings::Escape(e.suffix) + "'");
|
||||||
|
v.push_back(std::to_string(e.zone_id));
|
||||||
|
v.push_back(std::to_string(e.zone_instance));
|
||||||
|
v.push_back(std::to_string(e.y));
|
||||||
|
v.push_back(std::to_string(e.x));
|
||||||
|
v.push_back(std::to_string(e.z));
|
||||||
|
v.push_back(std::to_string(e.heading));
|
||||||
|
v.push_back(std::to_string(e.gender));
|
||||||
|
v.push_back(std::to_string(e.race));
|
||||||
|
v.push_back(std::to_string(e.class_));
|
||||||
|
v.push_back(std::to_string(e.level));
|
||||||
|
v.push_back(std::to_string(e.deity));
|
||||||
|
v.push_back(std::to_string(e.birthday));
|
||||||
|
v.push_back(std::to_string(e.last_login));
|
||||||
|
v.push_back(std::to_string(e.time_played));
|
||||||
|
v.push_back(std::to_string(e.level2));
|
||||||
|
v.push_back(std::to_string(e.anon));
|
||||||
|
v.push_back(std::to_string(e.gm));
|
||||||
|
v.push_back(std::to_string(e.face));
|
||||||
|
v.push_back(std::to_string(e.hair_color));
|
||||||
|
v.push_back(std::to_string(e.hair_style));
|
||||||
|
v.push_back(std::to_string(e.beard));
|
||||||
|
v.push_back(std::to_string(e.beard_color));
|
||||||
|
v.push_back(std::to_string(e.eye_color_1));
|
||||||
|
v.push_back(std::to_string(e.eye_color_2));
|
||||||
|
v.push_back(std::to_string(e.drakkin_heritage));
|
||||||
|
v.push_back(std::to_string(e.drakkin_tattoo));
|
||||||
|
v.push_back(std::to_string(e.drakkin_details));
|
||||||
|
v.push_back(std::to_string(e.ability_time_seconds));
|
||||||
|
v.push_back(std::to_string(e.ability_number));
|
||||||
|
v.push_back(std::to_string(e.ability_time_minutes));
|
||||||
|
v.push_back(std::to_string(e.ability_time_hours));
|
||||||
|
v.push_back(std::to_string(e.exp));
|
||||||
|
v.push_back(std::to_string(e.exp_enabled));
|
||||||
|
v.push_back(std::to_string(e.aa_points_spent));
|
||||||
|
v.push_back(std::to_string(e.aa_exp));
|
||||||
|
v.push_back(std::to_string(e.aa_points));
|
||||||
|
v.push_back(std::to_string(e.group_leadership_exp));
|
||||||
|
v.push_back(std::to_string(e.raid_leadership_exp));
|
||||||
|
v.push_back(std::to_string(e.group_leadership_points));
|
||||||
|
v.push_back(std::to_string(e.raid_leadership_points));
|
||||||
|
v.push_back(std::to_string(e.points));
|
||||||
|
v.push_back(std::to_string(e.cur_hp));
|
||||||
|
v.push_back(std::to_string(e.mana));
|
||||||
|
v.push_back(std::to_string(e.endurance));
|
||||||
|
v.push_back(std::to_string(e.intoxication));
|
||||||
|
v.push_back(std::to_string(e.str));
|
||||||
|
v.push_back(std::to_string(e.sta));
|
||||||
|
v.push_back(std::to_string(e.cha));
|
||||||
|
v.push_back(std::to_string(e.dex));
|
||||||
|
v.push_back(std::to_string(e.int_));
|
||||||
|
v.push_back(std::to_string(e.agi));
|
||||||
|
v.push_back(std::to_string(e.wis));
|
||||||
|
v.push_back(std::to_string(e.zone_change_count));
|
||||||
|
v.push_back(std::to_string(e.toxicity));
|
||||||
|
v.push_back(std::to_string(e.hunger_level));
|
||||||
|
v.push_back(std::to_string(e.thirst_level));
|
||||||
|
v.push_back(std::to_string(e.ability_up));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_guk));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_mir));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_mmc));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_ruj));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_tak));
|
||||||
|
v.push_back(std::to_string(e.ldon_points_available));
|
||||||
|
v.push_back(std::to_string(e.tribute_time_remaining));
|
||||||
|
v.push_back(std::to_string(e.career_tribute_points));
|
||||||
|
v.push_back(std::to_string(e.tribute_points));
|
||||||
|
v.push_back(std::to_string(e.tribute_active));
|
||||||
|
v.push_back(std::to_string(e.pvp_status));
|
||||||
|
v.push_back(std::to_string(e.pvp_kills));
|
||||||
|
v.push_back(std::to_string(e.pvp_deaths));
|
||||||
|
v.push_back(std::to_string(e.pvp_current_points));
|
||||||
|
v.push_back(std::to_string(e.pvp_career_points));
|
||||||
|
v.push_back(std::to_string(e.pvp_best_kill_streak));
|
||||||
|
v.push_back(std::to_string(e.pvp_worst_death_streak));
|
||||||
|
v.push_back(std::to_string(e.pvp_current_kill_streak));
|
||||||
|
v.push_back(std::to_string(e.pvp2));
|
||||||
|
v.push_back(std::to_string(e.pvp_type));
|
||||||
|
v.push_back(std::to_string(e.show_helm));
|
||||||
|
v.push_back(std::to_string(e.group_auto_consent));
|
||||||
|
v.push_back(std::to_string(e.raid_auto_consent));
|
||||||
|
v.push_back(std::to_string(e.guild_auto_consent));
|
||||||
|
v.push_back(std::to_string(e.leadership_exp_on));
|
||||||
|
v.push_back(std::to_string(e.RestTimer));
|
||||||
|
v.push_back(std::to_string(e.air_remaining));
|
||||||
|
v.push_back(std::to_string(e.autosplit_enabled));
|
||||||
|
v.push_back(std::to_string(e.lfp));
|
||||||
|
v.push_back(std::to_string(e.lfg));
|
||||||
|
v.push_back("'" + Strings::Escape(e.mailkey) + "'");
|
||||||
|
v.push_back(std::to_string(e.xtargets));
|
||||||
|
v.push_back(std::to_string(e.firstlogon));
|
||||||
|
v.push_back(std::to_string(e.e_aa_effects));
|
||||||
|
v.push_back(std::to_string(e.e_percent_to_aa));
|
||||||
|
v.push_back(std::to_string(e.e_expended_aa_spent));
|
||||||
|
v.push_back(std::to_string(e.aa_points_spent_old));
|
||||||
|
v.push_back(std::to_string(e.aa_points_old));
|
||||||
|
v.push_back(std::to_string(e.e_last_invsnapshot));
|
||||||
|
v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterDisciplinesRepository {
|
class BaseCharacterDisciplinesRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterDisciplines {
|
struct CharacterDisciplines {
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_disciplines_id
|
character_disciplines_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -338,6 +340,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterDisciplines &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.disc_id));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterDisciplines> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.disc_id));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H
|
||||||
@@ -16,11 +16,12 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterItemRecastRepository {
|
class BaseCharacterItemRecastRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterItemRecast {
|
struct CharacterItemRecast {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint16_t recast_type;
|
uint32_t recast_type;
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_item_recast_id
|
character_item_recast_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -123,7 +125,7 @@ public:
|
|||||||
CharacterItemRecast e{};
|
CharacterItemRecast e{};
|
||||||
|
|
||||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||||
e.recast_type = static_cast<uint16_t>(strtoul(row[1], nullptr, 10));
|
e.recast_type = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||||
e.timestamp = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
e.timestamp = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
@@ -251,7 +253,7 @@ public:
|
|||||||
CharacterItemRecast e{};
|
CharacterItemRecast e{};
|
||||||
|
|
||||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||||
e.recast_type = static_cast<uint16_t>(strtoul(row[1], nullptr, 10));
|
e.recast_type = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||||
e.timestamp = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
e.timestamp = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
@@ -278,7 +280,7 @@ public:
|
|||||||
CharacterItemRecast e{};
|
CharacterItemRecast e{};
|
||||||
|
|
||||||
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||||
e.recast_type = static_cast<uint16_t>(strtoul(row[1], nullptr, 10));
|
e.recast_type = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||||
e.timestamp = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
e.timestamp = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
@@ -338,6 +340,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterItemRecast &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.recast_type));
|
||||||
|
v.push_back(std::to_string(e.timestamp));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterItemRecast> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.recast_type));
|
||||||
|
v.push_back(std::to_string(e.timestamp));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterLeadershipAbilitiesRepository {
|
class BaseCharacterLeadershipAbilitiesRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterLeadershipAbilities {
|
struct CharacterLeadershipAbilities {
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_leadership_abilities_id
|
character_leadership_abilities_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -338,6 +340,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterLeadershipAbilities &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.rank));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterLeadershipAbilities> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.rank));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterMaterialRepository {
|
class BaseCharacterMaterialRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterMaterial {
|
struct CharacterMaterial {
|
||||||
@@ -128,8 +129,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_material_id
|
character_material_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -377,6 +379,74 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterMaterial &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.blue));
|
||||||
|
v.push_back(std::to_string(e.green));
|
||||||
|
v.push_back(std::to_string(e.red));
|
||||||
|
v.push_back(std::to_string(e.use_tint));
|
||||||
|
v.push_back(std::to_string(e.color));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterMaterial> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.blue));
|
||||||
|
v.push_back(std::to_string(e.green));
|
||||||
|
v.push_back(std::to_string(e.red));
|
||||||
|
v.push_back(std::to_string(e.use_tint));
|
||||||
|
v.push_back(std::to_string(e.color));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterMemmedSpellsRepository {
|
class BaseCharacterMemmedSpellsRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterMemmedSpells {
|
struct CharacterMemmedSpells {
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_memmed_spells_id
|
character_memmed_spells_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -338,6 +340,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterMemmedSpells &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterMemmedSpells> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterPetBuffsRepository {
|
class BaseCharacterPetBuffsRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterPetBuffs {
|
struct CharacterPetBuffs {
|
||||||
@@ -144,8 +145,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_pet_buffs_id
|
character_pet_buffs_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -418,6 +420,82 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterPetBuffs &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.pet));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
v.push_back(std::to_string(e.caster_level));
|
||||||
|
v.push_back("'" + Strings::Escape(e.castername) + "'");
|
||||||
|
v.push_back(std::to_string(e.ticsremaining));
|
||||||
|
v.push_back(std::to_string(e.counters));
|
||||||
|
v.push_back(std::to_string(e.numhits));
|
||||||
|
v.push_back(std::to_string(e.rune));
|
||||||
|
v.push_back(std::to_string(e.instrument_mod));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterPetBuffs> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.pet));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
v.push_back(std::to_string(e.caster_level));
|
||||||
|
v.push_back("'" + Strings::Escape(e.castername) + "'");
|
||||||
|
v.push_back(std::to_string(e.ticsremaining));
|
||||||
|
v.push_back(std::to_string(e.counters));
|
||||||
|
v.push_back(std::to_string(e.numhits));
|
||||||
|
v.push_back(std::to_string(e.rune));
|
||||||
|
v.push_back(std::to_string(e.instrument_mod));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterPetInfoRepository {
|
class BaseCharacterPetInfoRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterPetInfo {
|
struct CharacterPetInfo {
|
||||||
@@ -136,8 +137,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_pet_info_id
|
character_pet_info_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -398,6 +400,78 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterPetInfo &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.pet));
|
||||||
|
v.push_back("'" + Strings::Escape(e.petname) + "'");
|
||||||
|
v.push_back(std::to_string(e.petpower));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
v.push_back(std::to_string(e.hp));
|
||||||
|
v.push_back(std::to_string(e.mana));
|
||||||
|
v.push_back(std::to_string(e.size));
|
||||||
|
v.push_back(std::to_string(e.taunting));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterPetInfo> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.pet));
|
||||||
|
v.push_back("'" + Strings::Escape(e.petname) + "'");
|
||||||
|
v.push_back(std::to_string(e.petpower));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
v.push_back(std::to_string(e.hp));
|
||||||
|
v.push_back(std::to_string(e.mana));
|
||||||
|
v.push_back(std::to_string(e.size));
|
||||||
|
v.push_back(std::to_string(e.taunting));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterPetInventoryRepository {
|
class BaseCharacterPetInventoryRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterPetInventory {
|
struct CharacterPetInventory {
|
||||||
@@ -116,8 +117,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_pet_inventory_id
|
character_pet_inventory_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -348,6 +350,68 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterPetInventory &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.pet));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterPetInventory> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.char_id));
|
||||||
|
v.push_back(std::to_string(e.pet));
|
||||||
|
v.push_back(std::to_string(e.slot));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterPotionbeltRepository {
|
class BaseCharacterPotionbeltRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterPotionbelt {
|
struct CharacterPotionbelt {
|
||||||
@@ -116,8 +117,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_potionbelt_id
|
character_potionbelt_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -348,6 +350,68 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterPotionbelt &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.potion_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.icon));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterPotionbelt> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.potion_id));
|
||||||
|
v.push_back(std::to_string(e.item_id));
|
||||||
|
v.push_back(std::to_string(e.icon));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterSkillsRepository {
|
class BaseCharacterSkillsRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterSkills {
|
struct CharacterSkills {
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_skills_id
|
character_skills_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -337,6 +339,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterSkills &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.skill_id));
|
||||||
|
v.push_back(std::to_string(e.value));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterSkills> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.skill_id));
|
||||||
|
v.push_back(std::to_string(e.value));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Any modifications to base repositories are to be made by the generator only
|
* Any modifications to base repositories are to be made by the generator only
|
||||||
*
|
*
|
||||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
* @docs https://docs.eqemu.io/developer/repositories
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H
|
#ifndef EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "../../strings.h"
|
#include "../../strings.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
class BaseCharacterSpellsRepository {
|
class BaseCharacterSpellsRepository {
|
||||||
public:
|
public:
|
||||||
struct CharacterSpells {
|
struct CharacterSpells {
|
||||||
@@ -112,8 +113,9 @@ public:
|
|||||||
{
|
{
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} WHERE id = {} LIMIT 1",
|
"{} WHERE {} = {} LIMIT 1",
|
||||||
BaseSelect(),
|
BaseSelect(),
|
||||||
|
PrimaryKey(),
|
||||||
character_spells_id
|
character_spells_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -337,6 +339,66 @@ public:
|
|||||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string BaseReplace()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"REPLACE INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceOne(
|
||||||
|
Database& db,
|
||||||
|
const CharacterSpells &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReplaceMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<CharacterSpells> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
v.push_back(std::to_string(e.slot_id));
|
||||||
|
v.push_back(std::to_string(e.spell_id));
|
||||||
|
|
||||||
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES {}",
|
||||||
|
BaseReplace(),
|
||||||
|
Strings::Implode(",", insert_chunks)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H
|
#endif //EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H
|
||||||
|
|||||||
@@ -46,6 +46,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Custom extended repository methods here
|
// Custom extended repository methods here
|
||||||
|
static uint32 GetSecondsSinceLastLogin(Database &db, const std::string& name)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"SELECT (UNIX_TIMESTAMP(NOW()) - last_login) FROM {} WHERE name = '{}'",
|
||||||
|
TableName(),
|
||||||
|
Strings::Escape(name)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!results.RowCount() || !results.Success()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
|
||||||
|
return Strings::ToUnsignedInt(row[0]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_CHARACTER_DATA_REPOSITORY_H
|
#endif //EQEMU_CHARACTER_DATA_REPOSITORY_H
|
||||||
|
|||||||
@@ -216,6 +216,9 @@ RULE_BOOL(Character, EnableRaidMemberEXPModifier, true, "Enable or disable the r
|
|||||||
RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses")
|
RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses")
|
||||||
RULE_BOOL(Character, ItemExtraSkillDamageCalcAsPercent, false, "If enabled, apply Item Extra Skill Damage as Percentage-based modifiers")
|
RULE_BOOL(Character, ItemExtraSkillDamageCalcAsPercent, false, "If enabled, apply Item Extra Skill Damage as Percentage-based modifiers")
|
||||||
RULE_BOOL(Character, UseForageCommonFood, true, "If enabled, use the common foods specified in the code.")
|
RULE_BOOL(Character, UseForageCommonFood, true, "If enabled, use the common foods specified in the code.")
|
||||||
|
RULE_INT(Character, ClearXTargetDelay, 10, "Seconds between uses of the #clearxtargets command (Set to 0 to disable)")
|
||||||
|
RULE_BOOL(Character, PreventMountsFromZoning, false, "Enable to prevent mounts from zoning - Prior to December 15, 2004 this is enabled.")
|
||||||
|
RULE_BOOL(Character, GroupInvitesRequireTarget, false, "Enable to require players to have invitee on target (Disables /invite name) - Classic Style")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Mercs)
|
RULE_CATEGORY(Mercs)
|
||||||
@@ -430,6 +433,10 @@ RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false, "Ignore Leadership Alternate Ab
|
|||||||
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")
|
||||||
RULE_BOOL(Spells, ItemExtraSpellAmtCalcAsPercent, false, "Apply the Item stats Spell Dmg and Heal Amount as Percentage-based modifiers instead of flat additions")
|
RULE_BOOL(Spells, ItemExtraSpellAmtCalcAsPercent, false, "Apply the Item stats Spell Dmg and Heal Amount as Percentage-based modifiers instead of flat additions")
|
||||||
|
RULE_REAL(Spells, BreakFeignDeathWhenCastOn, 2.0, "Percentage that Feign Death will break when you resist a spell")
|
||||||
|
RULE_REAL(Spells, BreakSneakWhenCastOn, 2.0, "Percentage that Sneak will break when you resist a spell")
|
||||||
|
RULE_BOOL(Spells, EnableResistSoftCap, false, "Enabled resist softcap and can be adjusted by rule, SpellResistSoftCap")
|
||||||
|
RULE_INT(Spells, SpellResistSoftCap, 255, "Softcap for spell resists.")
|
||||||
RULE_BOOL(Spells, AllowItemTGB, false, "Target group buff (/tgb) doesn't work with items on live, custom servers want it though")
|
RULE_BOOL(Spells, AllowItemTGB, false, "Target group buff (/tgb) doesn't work with items on live, custom servers want it though")
|
||||||
RULE_BOOL(Spells, NPCInnateProcOverride, true, "NPC innate procs override the target type to single target")
|
RULE_BOOL(Spells, NPCInnateProcOverride, true, "NPC innate procs override the target type to single target")
|
||||||
RULE_BOOL(Spells, OldRainTargets, false, "Use old incorrectly implemented maximum targets for rains")
|
RULE_BOOL(Spells, OldRainTargets, false, "Use old incorrectly implemented maximum targets for rains")
|
||||||
@@ -462,6 +469,12 @@ RULE_INT(Spells, DefensiveProcPenaltyLevelGap, 6, "Defensive Proc Penalty Level
|
|||||||
RULE_REAL(Spells, DefensiveProcPenaltyLevelGapModifier, 10.0f, "Defensive Proc Penalty Level Gap Modifier where procs start losing their proc rate at defined % after RuleI(Spells, DefensiveProcLevelGap) level difference")
|
RULE_REAL(Spells, DefensiveProcPenaltyLevelGapModifier, 10.0f, "Defensive Proc Penalty Level Gap Modifier where procs start losing their proc rate at defined % after RuleI(Spells, DefensiveProcLevelGap) level difference")
|
||||||
RULE_BOOL(Spells, DOTBonusDamageSplitOverDuration, true, "Disable to have Damage Over Time total bonus damage added to each tick instead of divided across duration")
|
RULE_BOOL(Spells, DOTBonusDamageSplitOverDuration, true, "Disable to have Damage Over Time total bonus damage added to each tick instead of divided across duration")
|
||||||
RULE_BOOL(Spells, HOTBonusHealingSplitOverDuration, true, "Disable to have Heal Over Time total bonus healing added to each tick instead of divided across duration")
|
RULE_BOOL(Spells, HOTBonusHealingSplitOverDuration, true, "Disable to have Heal Over Time total bonus healing added to each tick instead of divided across duration")
|
||||||
|
RULE_BOOL(Spells, UseLegacyFizzleCode, false, "Enable will turn on the legacy fizzle code which is far stricter and more accurate to 2001/2002 testing.")
|
||||||
|
RULE_BOOL(Spells, LegacyManaburn, false, "Enable to have the legacy manaburn system from 2003 and earlier.")
|
||||||
|
RULE_BOOL(Spells, EvacClearAggroInSameZone, false, "Enable to clear aggro on clients when evacing in same zone.")
|
||||||
|
RULE_BOOL(Spells, CharmAggroOverLevel, false, "Enabling this rule will cause Charm casts over level to show resisted and cause aggro. Early EQ style.")
|
||||||
|
RULE_BOOL(Spells, RequireMnemonicRetention, true, "Enabling will require spell slots 9-12 to have the appropriate Mnemonic Retention AA learned.")
|
||||||
|
RULE_BOOL(Spells, EvacClearCharmPet, false, "Enable to have evac in zone clear charm from charm pets and detach buffs.")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Combat)
|
RULE_CATEGORY(Combat)
|
||||||
@@ -508,6 +521,9 @@ RULE_BOOL(Combat, OneProcPerWeapon, true, "If enabled, One proc per weapon per r
|
|||||||
RULE_BOOL(Combat, ProjectileDmgOnImpact, true, "If enabled, projectiles (i.e. arrows) will hit on impact, instead of instantly")
|
RULE_BOOL(Combat, ProjectileDmgOnImpact, true, "If enabled, projectiles (i.e. arrows) will hit on impact, instead of instantly")
|
||||||
RULE_BOOL(Combat, MeleePush, true, "Enable melee push")
|
RULE_BOOL(Combat, MeleePush, true, "Enable melee push")
|
||||||
RULE_INT(Combat, MeleePushChance, 50, "NPC chance the target will be pushed. Made up, 100 actually isn't that bad")
|
RULE_INT(Combat, MeleePushChance, 50, "NPC chance the target will be pushed. Made up, 100 actually isn't that bad")
|
||||||
|
RULE_REAL(Combat, MeleePushForceClientPercent, 0.00, "Percent to add or remove from push for players")
|
||||||
|
RULE_REAL(Combat, MeleePushForcePetPercent, 0.00, "Percent to add or remove from push for pets")
|
||||||
|
RULE_BOOL(Combat, NPCtoNPCPush, false, "Disabled prevents NPC to NPC pushing per the 2013+ patch.")
|
||||||
RULE_BOOL(Combat, UseLiveCombatRounds, true, "Turn this false if you don't want to worry about fixing up combat rounds for NPCs")
|
RULE_BOOL(Combat, UseLiveCombatRounds, true, "Turn this false if you don't want to worry about fixing up combat rounds for NPCs")
|
||||||
RULE_INT(Combat, NPCAssistCap, 5, "Maximum number of NPC that will assist another NPC at once")
|
RULE_INT(Combat, NPCAssistCap, 5, "Maximum number of NPC that will assist another NPC at once")
|
||||||
RULE_INT(Combat, NPCAssistCapTimer, 6000, "Time a NPC will take to clear assist aggro cap space (milliseconds)")
|
RULE_INT(Combat, NPCAssistCapTimer, 6000, "Time a NPC will take to clear assist aggro cap space (milliseconds)")
|
||||||
@@ -538,6 +554,7 @@ RULE_BOOL(Combat, SummonMeleeRange, true, "Enable or disable summoning of a play
|
|||||||
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")
|
||||||
RULE_INT(Combat, MaxProcs, 4, "Adjustable maximum number of procs per round, the hard cap is MAX_PROCS (11). Requires mob repop or client zone when changed")
|
RULE_INT(Combat, MaxProcs, 4, "Adjustable maximum number of procs per round, the hard cap is MAX_PROCS (11). Requires mob repop or client zone when changed")
|
||||||
|
RULE_BOOL(Combat, FinishingBlowOnlyWhenFleeing, false, "Enable to only allow Finishing Blow when fleeing (Original Style Finishing Blow)")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(NPC)
|
RULE_CATEGORY(NPC)
|
||||||
@@ -593,6 +610,7 @@ RULE_INT(Aggro, ClientAggroCheckIdleInterval, 6000, "Interval in which clients a
|
|||||||
RULE_REAL(Aggro, PetAttackRange, 40000.0, "Maximum squared range /pet attack works at default is 200")
|
RULE_REAL(Aggro, PetAttackRange, 40000.0, "Maximum squared range /pet attack works at default is 200")
|
||||||
RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true, "If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level")
|
RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true, "If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level")
|
||||||
RULE_BOOL(Aggro, AggroPlayerPets, false, "If enabled, NPCs will aggro player pets")
|
RULE_BOOL(Aggro, AggroPlayerPets, false, "If enabled, NPCs will aggro player pets")
|
||||||
|
RULE_BOOL(Aggro, UndeadAlwaysAggro, true, "should undead always aggro?")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(TaskSystem)
|
RULE_CATEGORY(TaskSystem)
|
||||||
|
|||||||
+34
-18
@@ -44,6 +44,7 @@
|
|||||||
#include "repositories/starting_items_repository.h"
|
#include "repositories/starting_items_repository.h"
|
||||||
#include "path_manager.h"
|
#include "path_manager.h"
|
||||||
#include "repositories/loottable_repository.h"
|
#include "repositories/loottable_repository.h"
|
||||||
|
#include "repositories/character_item_recast_repository.h"
|
||||||
|
|
||||||
namespace ItemField
|
namespace ItemField
|
||||||
{
|
{
|
||||||
@@ -882,34 +883,49 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryPr
|
|||||||
std::map<uint32, uint32> SharedDatabase::GetItemRecastTimestamps(uint32 char_id)
|
std::map<uint32, uint32> SharedDatabase::GetItemRecastTimestamps(uint32 char_id)
|
||||||
{
|
{
|
||||||
std::map<uint32, uint32> timers;
|
std::map<uint32, uint32> timers;
|
||||||
const std::string query = StringFormat("SELECT recast_type,timestamp FROM character_item_recast WHERE id=%u", char_id);
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success() || results.RowCount() == 0)
|
|
||||||
return timers;
|
|
||||||
|
|
||||||
for (auto& row = results.begin(); row != results.end(); ++row)
|
const auto& l = CharacterItemRecastRepository::GetWhere(
|
||||||
timers[Strings::ToUnsignedInt(row[0])] = Strings::ToUnsignedInt(row[1]);
|
*this,
|
||||||
return timers; // RVO or move assigned
|
fmt::format(
|
||||||
|
"`id` = {}",
|
||||||
|
char_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (l.empty()) {
|
||||||
|
return timers;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& e : l) {
|
||||||
|
timers[e.recast_type] = e.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timers;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 SharedDatabase::GetItemRecastTimestamp(uint32 char_id, uint32 recast_type)
|
uint32 SharedDatabase::GetItemRecastTimestamp(uint32 char_id, uint32 recast_type)
|
||||||
{
|
{
|
||||||
const std::string query = StringFormat("SELECT timestamp FROM character_item_recast WHERE id=%u AND recast_type=%u",
|
const auto& l = CharacterItemRecastRepository::GetWhere(
|
||||||
char_id, recast_type);
|
*this,
|
||||||
auto results = QueryDatabase(query);
|
fmt::format(
|
||||||
if (!results.Success() || results.RowCount() == 0)
|
"`id` = {} AND `recast_type` = {}",
|
||||||
return 0;
|
char_id,
|
||||||
|
recast_type
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
auto& row = results.begin();
|
return l.empty() ? 0 : l[0].timestamp;
|
||||||
return Strings::ToUnsignedInt(row[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedDatabase::ClearOldRecastTimestamps(uint32 char_id)
|
void SharedDatabase::ClearOldRecastTimestamps(uint32 char_id)
|
||||||
{
|
{
|
||||||
// This actually isn't strictly live-like. Live your recast timestamps are forever
|
CharacterItemRecastRepository::DeleteWhere(
|
||||||
const std::string query =
|
*this,
|
||||||
StringFormat("DELETE FROM character_item_recast WHERE id = %u and timestamp < UNIX_TIMESTAMP()", char_id);
|
fmt::format(
|
||||||
QueryDatabase(query);
|
"`id` = {} AND `timestamp` < UNIX_TIMESTAMP()",
|
||||||
|
char_id
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id)
|
void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id)
|
||||||
|
|||||||
@@ -202,6 +202,19 @@
|
|||||||
#define SPELL_GUIDE_LEVITATION 39852
|
#define SPELL_GUIDE_LEVITATION 39852
|
||||||
#define SPELL_GUIDE_SPELL_HASTE 39853
|
#define SPELL_GUIDE_SPELL_HASTE 39853
|
||||||
#define SPELL_GUIDE_HASTE 39854
|
#define SPELL_GUIDE_HASTE 39854
|
||||||
|
#define SPELL_VAMPIRIC_EMBRACE 821
|
||||||
|
#define SPELL_VAMPIRIC_EMBRACE_OF_SHADOW 822
|
||||||
|
#define SPELL_BATTLE_CRY 5027
|
||||||
|
#define SPELL_WAR_CRY 5028
|
||||||
|
#define SPELL_BATTLE_CRY_OF_DRAVEL 5029
|
||||||
|
#define SPELL_WAR_CRY_OF_DRAVEL 5030
|
||||||
|
#define SPELL_BATTLE_CRY_OF_THE_MASTRUQ 5031
|
||||||
|
#define SPELL_ANCIENT_CRY_OF_CHAOS 5032
|
||||||
|
#define SPELL_BLOODTHIRST 8476
|
||||||
|
#define SPELL_AMPLIFICATION 2603
|
||||||
|
|
||||||
|
// discipline IDs.
|
||||||
|
#define DISC_UNHOLY_AURA 4520
|
||||||
|
|
||||||
//spellgroup ids
|
//spellgroup ids
|
||||||
#define SPELLGROUP_FRENZIED_BURNOUT 2754
|
#define SPELLGROUP_FRENZIED_BURNOUT 2754
|
||||||
|
|||||||
+3
-1
@@ -359,9 +359,11 @@ namespace Tasks {
|
|||||||
if (activity_states[i].activity_state != ActivityCompleted)
|
if (activity_states[i].activity_state != ActivityCompleted)
|
||||||
{
|
{
|
||||||
completed_ids[i] = false;
|
completed_ids[i] = false;
|
||||||
current_step = std::min(current_step, el.step);
|
|
||||||
|
// step system advances to next step if only optionals active
|
||||||
if (!el.optional)
|
if (!el.optional)
|
||||||
{
|
{
|
||||||
|
current_step = std::min(current_step, el.step);
|
||||||
result.is_task_complete = false;
|
result.is_task_complete = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// Build variables
|
// Build variables
|
||||||
// these get injected during the build pipeline
|
// these get injected during the build pipeline
|
||||||
#define CURRENT_VERSION "22.39.0-dev" // always append -dev to the current version for custom-builds
|
#define CURRENT_VERSION "22.40.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__
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eqemu-server",
|
"name": "eqemu-server",
|
||||||
"version": "22.39.0",
|
"version": "22.40.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EQEmu/Server.git"
|
"url": "https://github.com/EQEmu/Server.git"
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errmsg.h>
|
|
||||||
#include <mysqld_error.h>
|
#include <mysqld_error.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -399,5 +398,6 @@ void QSDatabase::GeneralQueryReceive(ServerPacket *pack)
|
|||||||
LogInfo("[{}]", query.c_str());
|
LogInfo("[{}]", query.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
safe_delete(pack);
|
||||||
safe_delete_array(queryBuffer);
|
safe_delete_array(queryBuffer);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-8
@@ -463,15 +463,17 @@ void TaskStateTest::TestOptionalSteps()
|
|||||||
// activity_id | step | state
|
// activity_id | step | state
|
||||||
// 0 | 0 | complete
|
// 0 | 0 | complete
|
||||||
// 1 | 1 | hidden | optional (active)
|
// 1 | 1 | hidden | optional (active)
|
||||||
// 2 | 2 | hidden | optional
|
// 2 | 2 | hidden | optional (active)
|
||||||
// 3 | 2 | hidden
|
// 3 | 2 | hidden (active)
|
||||||
|
|
||||||
auto res = Tasks::GetActiveElements(data, state, activity_count);
|
auto res = Tasks::GetActiveElements(data, state, activity_count);
|
||||||
|
|
||||||
// since optional is on its own step it's effectively non-optional to open next step
|
// steps that only contain optionals should not need to be completed to open next step
|
||||||
TEST_ASSERT(res.is_task_complete == false);
|
TEST_ASSERT(res.is_task_complete == false);
|
||||||
TEST_ASSERT(res.active.size() == 1);
|
TEST_ASSERT(res.active.size() == 3);
|
||||||
TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end());
|
TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end());
|
||||||
|
TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end());
|
||||||
|
TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 3) != res.active.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -530,9 +532,9 @@ void TaskStateTest::TestOptionalLastSteps()
|
|||||||
auto state = GetMockWorldState(activity_count);
|
auto state = GetMockWorldState(activity_count);
|
||||||
data[0].step = 0;
|
data[0].step = 0;
|
||||||
data[1].optional = true;
|
data[1].optional = true;
|
||||||
data[1].step = 2;
|
data[1].step = 1;
|
||||||
data[2].optional = true;
|
data[2].optional = true;
|
||||||
data[2].step = 3;
|
data[2].step = 2;
|
||||||
|
|
||||||
{
|
{
|
||||||
// activity_id | step | state
|
// activity_id | step | state
|
||||||
@@ -553,13 +555,15 @@ void TaskStateTest::TestOptionalLastSteps()
|
|||||||
// activity_id | step | state
|
// activity_id | step | state
|
||||||
// 0 | 0 | complete
|
// 0 | 0 | complete
|
||||||
// 1 | 1 | hidden | optional (active)
|
// 1 | 1 | hidden | optional (active)
|
||||||
// 2 | 2 | hidden | optional
|
// 2 | 2 | hidden | optional (active)
|
||||||
|
|
||||||
|
// step with only an optional should not prevent next step being active
|
||||||
auto res = Tasks::GetActiveElements(data, state, activity_count);
|
auto res = Tasks::GetActiveElements(data, state, activity_count);
|
||||||
|
|
||||||
TEST_ASSERT(res.is_task_complete == true);
|
TEST_ASSERT(res.is_task_complete == true);
|
||||||
TEST_ASSERT(res.active.size() == 1);
|
TEST_ASSERT(res.active.size() == 2);
|
||||||
TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end());
|
TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 1) != res.active.end());
|
||||||
|
TEST_ASSERT(std::find(res.active.begin(), res.active.end(), 2) != res.active.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errmsg.h>
|
|
||||||
#include <mysqld_error.h>
|
#include <mysqld_error.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|||||||
+1
-7
@@ -164,13 +164,7 @@ int main() {
|
|||||||
|
|
||||||
database.ExpireMail();
|
database.ExpireMail();
|
||||||
|
|
||||||
if(Config->ChatPort != Config->MailPort)
|
g_Clientlist = new Clientlist(Config->GetUCSPort());
|
||||||
{
|
|
||||||
LogInfo("MailPort and CharPort must be the same in eqemu_config.json for UCS");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Clientlist = new Clientlist(Config->ChatPort);
|
|
||||||
|
|
||||||
ChannelList = new ChatChannelList();
|
ChannelList = new ChatChannelList();
|
||||||
|
|
||||||
|
|||||||
@@ -513,6 +513,13 @@ foreach my $table_to_generate (@tables) {
|
|||||||
#############################################
|
#############################################
|
||||||
if ($repository_generation_option eq "all" || $repository_generation_option eq "extended") {
|
if ($repository_generation_option eq "all" || $repository_generation_option eq "extended") {
|
||||||
my $generated_repository = './common/repositories/' . $table_to_generate . '_repository.h';
|
my $generated_repository = './common/repositories/' . $table_to_generate . '_repository.h';
|
||||||
|
|
||||||
|
# check if file exists firsts
|
||||||
|
if (-e $generated_repository) {
|
||||||
|
print "File [$generated_repository] already exists! Can't overwrite extended once created!\n";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
my $cmake_generated_reference = $generated_repository;
|
my $cmake_generated_reference = $generated_repository;
|
||||||
$cmake_generated_reference =~ s/.\/common\///g;
|
$cmake_generated_reference =~ s/.\/common\///g;
|
||||||
$generated_repository_files .= $cmake_generated_reference . "\n";
|
$generated_repository_files .= $cmake_generated_reference . "\n";
|
||||||
|
|||||||
@@ -9,5 +9,7 @@ void WorldserverCLI::DatabaseUpdates(int argc, char **argv, argh::parser &cmd, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
DatabaseUpdate update;
|
DatabaseUpdate update;
|
||||||
update.SetDatabase(&database)->CheckDbUpdates();
|
update.SetDatabase(&database)
|
||||||
|
->SetContentDatabase(&content_db)
|
||||||
|
->CheckDbUpdates();
|
||||||
}
|
}
|
||||||
|
|||||||
+85
-95
@@ -28,7 +28,6 @@
|
|||||||
#include "../common/inventory_profile.h"
|
#include "../common/inventory_profile.h"
|
||||||
#include "../common/races.h"
|
#include "../common/races.h"
|
||||||
#include "../common/classes.h"
|
#include "../common/classes.h"
|
||||||
#include "../common/languages.h"
|
|
||||||
#include "../common/skills.h"
|
#include "../common/skills.h"
|
||||||
#include "../common/extprofile.h"
|
#include "../common/extprofile.h"
|
||||||
#include "../common/strings.h"
|
#include "../common/strings.h"
|
||||||
@@ -945,8 +944,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer = fmt::format("{},{},{}.{},{}{:08X}",
|
buffer = fmt::format("{},{},{}.{},{}{:08X}",
|
||||||
config->ChatHost,
|
config->GetUCSHost(),
|
||||||
config->ChatPort,
|
config->GetUCSPort(),
|
||||||
config->ShortName,
|
config->ShortName,
|
||||||
GetCharName(),
|
GetCharName(),
|
||||||
static_cast<char>(connection_type),
|
static_cast<char>(connection_type),
|
||||||
@@ -971,8 +970,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer = fmt::format("{},{},{}.{},{}{:08X}",
|
buffer = fmt::format("{},{},{}.{},{}{:08X}",
|
||||||
config->MailHost,
|
config->GetUCSHost(),
|
||||||
config->MailPort,
|
config->GetUCSPort(),
|
||||||
config->ShortName,
|
config->ShortName,
|
||||||
GetCharName(),
|
GetCharName(),
|
||||||
static_cast<char>(connection_type),
|
static_cast<char>(connection_type),
|
||||||
@@ -1692,15 +1691,16 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
|||||||
pp.hunger_level = 6000;
|
pp.hunger_level = 6000;
|
||||||
pp.thirst_level = 6000;
|
pp.thirst_level = 6000;
|
||||||
|
|
||||||
|
/* Set default skills for everybody */
|
||||||
|
pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue);
|
||||||
|
pp.skills[EQ::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue);
|
||||||
|
|
||||||
/* Set Racial and Class specific language and skills */
|
/* Set Racial and Class specific language and skills */
|
||||||
SetRacialLanguages(&pp);
|
SetRacialLanguages(&pp);
|
||||||
SetRaceStartingSkills(&pp);
|
SetRaceStartingSkills(&pp);
|
||||||
SetClassStartingSkills(&pp);
|
SetClassStartingSkills(&pp);
|
||||||
SetClassLanguages(&pp);
|
SetClassLanguages(&pp);
|
||||||
|
|
||||||
pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue);
|
|
||||||
pp.skills[EQ::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue);
|
|
||||||
|
|
||||||
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
|
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
|
||||||
|
|
||||||
memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE));
|
memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE));
|
||||||
@@ -2144,7 +2144,9 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp )
|
|||||||
}
|
}
|
||||||
case FROGLOK:
|
case FROGLOK:
|
||||||
{
|
{
|
||||||
pp->skills[EQ::skills::SkillSwimming] = 125;
|
if (RuleI(Skills, SwimmingStartValue) < 125) {
|
||||||
|
pp->skills[EQ::skills::SkillSwimming] = 125;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GNOME:
|
case GNOME:
|
||||||
@@ -2161,7 +2163,9 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp )
|
|||||||
case IKSAR:
|
case IKSAR:
|
||||||
{
|
{
|
||||||
pp->skills[EQ::skills::SkillForage] = 50;
|
pp->skills[EQ::skills::SkillForage] = 50;
|
||||||
pp->skills[EQ::skills::SkillSwimming] = 100;
|
if (RuleI(Skills, SwimmingStartValue) < 100) {
|
||||||
|
pp->skills[EQ::skills::SkillSwimming] = 100;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WOOD_ELF:
|
case WOOD_ELF:
|
||||||
@@ -2181,115 +2185,101 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp )
|
|||||||
|
|
||||||
void Client::SetRacialLanguages( PlayerProfile_Struct *pp )
|
void Client::SetRacialLanguages( PlayerProfile_Struct *pp )
|
||||||
{
|
{
|
||||||
switch( pp->race )
|
switch (pp->race) {
|
||||||
{
|
case Race::Human: {
|
||||||
case BARBARIAN:
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
{
|
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
|
||||||
pp->languages[LANG_BARBARIAN] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DARK_ELF:
|
case Race::Barbarian: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::Barbarian] = Language::MaxValue;
|
||||||
pp->languages[LANG_DARK_ELVISH] = 100;
|
|
||||||
pp->languages[LANG_DARK_SPEECH] = 100;
|
|
||||||
pp->languages[LANG_ELDER_ELVISH] = 100;
|
|
||||||
pp->languages[LANG_ELVISH] = 25;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DWARF:
|
case Race::Erudite: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::Erudian] = Language::MaxValue;
|
||||||
pp->languages[LANG_DWARVISH] = 100;
|
|
||||||
pp->languages[LANG_GNOMISH] = 25;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ERUDITE:
|
case Race::WoodElf: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::Elvish] = Language::MaxValue;
|
||||||
pp->languages[LANG_ERUDIAN] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FROGLOK:
|
case Race::HighElf: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::DarkElvish] = 25;
|
||||||
pp->languages[LANG_FROGLOK] = 100;
|
pp->languages[Language::ElderElvish] = 25;
|
||||||
pp->languages[LANG_TROLL] = 25;
|
pp->languages[Language::Elvish] = Language::MaxValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GNOME:
|
case Race::DarkElf: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::DarkElvish] = Language::MaxValue;
|
||||||
pp->languages[LANG_DWARVISH] = 25;
|
pp->languages[Language::DarkSpeech] = Language::MaxValue;
|
||||||
pp->languages[LANG_GNOMISH] = 100;
|
pp->languages[Language::ElderElvish] = Language::MaxValue;
|
||||||
|
pp->languages[Language::Elvish] = 25;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HALF_ELF:
|
case Race::HalfElf: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::Elvish] = Language::MaxValue;
|
||||||
pp->languages[LANG_ELVISH] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HALFLING:
|
case Race::Dwarf: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::Dwarvish] = Language::MaxValue;
|
||||||
pp->languages[LANG_HALFLING] = 100;
|
pp->languages[Language::Gnomish] = 25;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIGH_ELF:
|
case Race::Troll: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = RuleI(Character, TrollCommonTongue);
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::DarkSpeech] = Language::MaxValue;
|
||||||
pp->languages[LANG_DARK_ELVISH] = 25;
|
pp->languages[Language::Troll] = Language::MaxValue;
|
||||||
pp->languages[LANG_ELDER_ELVISH] = 25;
|
|
||||||
pp->languages[LANG_ELVISH] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HUMAN:
|
case Race::Ogre: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = RuleI(Character, OgreCommonTongue);
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::DarkSpeech] = Language::MaxValue;
|
||||||
|
pp->languages[Language::Ogre] = Language::MaxValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IKSAR:
|
case Race::Halfling: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = RuleI(Character, IksarCommonTongue);
|
pp->languages[Language::Halfling] = Language::MaxValue;
|
||||||
pp->languages[LANG_DARK_SPEECH] = 100;
|
|
||||||
pp->languages[LANG_LIZARDMAN] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OGRE:
|
case Race::Gnome: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = RuleI(Character, OgreCommonTongue);
|
pp->languages[Language::Dwarvish] = 25;
|
||||||
pp->languages[LANG_DARK_SPEECH] = 100;
|
pp->languages[Language::Gnomish] = Language::MaxValue;
|
||||||
pp->languages[LANG_OGRE] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TROLL:
|
case Race::Iksar: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = RuleI(Character, IksarCommonTongue);
|
||||||
pp->languages[LANG_COMMON_TONGUE] = RuleI(Character, TrollCommonTongue);
|
pp->languages[Language::DarkSpeech] = Language::MaxValue;
|
||||||
pp->languages[LANG_DARK_SPEECH] = 100;
|
pp->languages[Language::Lizardman] = Language::MaxValue;
|
||||||
pp->languages[LANG_TROLL] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WOOD_ELF:
|
case Race::VahShir: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::CombineTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_ELVISH] = 100;
|
pp->languages[Language::Erudian] = 25;
|
||||||
|
pp->languages[Language::VahShir] = Language::MaxValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VAHSHIR:
|
case Race::Froglok: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::Froglok] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMBINE_TONGUE] = 100;
|
pp->languages[Language::Troll] = 25;
|
||||||
pp->languages[LANG_ERUDIAN] = 25;
|
|
||||||
pp->languages[LANG_VAH_SHIR] = 100;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DRAKKIN:
|
case Race::Drakkin: {
|
||||||
{
|
pp->languages[Language::CommonTongue] = Language::MaxValue;
|
||||||
pp->languages[LANG_COMMON_TONGUE] = 100;
|
pp->languages[Language::ElderDragon] = Language::MaxValue;
|
||||||
pp->languages[LANG_ELDER_DRAGON] = 100;
|
pp->languages[Language::Dragon] = Language::MaxValue;
|
||||||
pp->languages[LANG_DRAGON] = 100;
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2298,12 +2288,12 @@ void Client::SetRacialLanguages( PlayerProfile_Struct *pp )
|
|||||||
void Client::SetClassLanguages(PlayerProfile_Struct *pp)
|
void Client::SetClassLanguages(PlayerProfile_Struct *pp)
|
||||||
{
|
{
|
||||||
// we only need to handle one class, but custom server might want to do more
|
// we only need to handle one class, but custom server might want to do more
|
||||||
switch(pp->class_) {
|
switch (pp->class_) {
|
||||||
case Class::Rogue:
|
case Class::Rogue:
|
||||||
pp->languages[LANG_THIEVES_CANT] = 100;
|
pp->languages[Language::ThievesCant] = Language::MaxValue;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-10
@@ -26,6 +26,7 @@
|
|||||||
#include "../common/ip_util.h"
|
#include "../common/ip_util.h"
|
||||||
#include "../common/zone_store.h"
|
#include "../common/zone_store.h"
|
||||||
#include "../common/path_manager.h"
|
#include "../common/path_manager.h"
|
||||||
|
#include "../common/database/database_update.h"
|
||||||
|
|
||||||
extern ZSList zoneserver_list;
|
extern ZSList zoneserver_list;
|
||||||
extern WorldConfig Config;
|
extern WorldConfig Config;
|
||||||
@@ -293,7 +294,18 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
|
|||||||
const auto c = EQEmuConfig::get();
|
const auto c = EQEmuConfig::get();
|
||||||
if (c->auto_database_updates) {
|
if (c->auto_database_updates) {
|
||||||
LogInfo("Checking Database Conversions");
|
LogInfo("Checking Database Conversions");
|
||||||
database.CheckDatabaseConversions();
|
|
||||||
|
auto *r = RuleManager::Instance();
|
||||||
|
r->LoadRules(&database, "default", false);
|
||||||
|
if (!RuleB(Bots, Enabled) && database.DoesTableExist("bot_data")) {
|
||||||
|
LogInfo("Bot tables found but rule not enabled, enabling");
|
||||||
|
r->SetRule("Bots:Enabled", "true", &database, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseUpdate update{};
|
||||||
|
update.SetDatabase(&database)
|
||||||
|
->SetContentDatabase(&content_db)
|
||||||
|
->CheckDbUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RuleB(Logging, WorldGMSayLogging)) {
|
if (RuleB(Logging, WorldGMSayLogging)) {
|
||||||
@@ -622,8 +634,7 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
|||||||
|
|
||||||
// ucs (public)
|
// ucs (public)
|
||||||
if (
|
if (
|
||||||
(!config_address.empty() && c->MailHost != config_address) ||
|
(!config_address.empty() && c->GetUCSHost() != config_address)
|
||||||
(!config_address.empty() && c->ChatHost != config_address)
|
|
||||||
) {
|
) {
|
||||||
LogWarning("# UCS Address Mailhost (Configuration)");
|
LogWarning("# UCS Address Mailhost (Configuration)");
|
||||||
LogWarning("");
|
LogWarning("");
|
||||||
@@ -635,14 +646,9 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
|
|||||||
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]");
|
LogWarning("Docs [https://docs.eqemu.io/server/installation/configure-your-eqemu_config/#mailserver]");
|
||||||
LogWarning("");
|
LogWarning("");
|
||||||
LogWarning(
|
LogWarning(
|
||||||
"[server.world.address] value [{}] [server.chatserver.host] [{}]",
|
"[server.world.address] value [{}] [server.ucs.host] [{}]",
|
||||||
config_address,
|
config_address,
|
||||||
c->ChatHost
|
c->GetUCSHost()
|
||||||
);
|
|
||||||
LogWarning(
|
|
||||||
"[server.world.address] value [{}] [server.mailserver.host] [{}]",
|
|
||||||
config_address,
|
|
||||||
c->MailHost
|
|
||||||
);
|
);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,6 @@ SET(zone_headers
|
|||||||
embperl.h
|
embperl.h
|
||||||
encounter.h
|
encounter.h
|
||||||
entity.h
|
entity.h
|
||||||
errmsg.h
|
|
||||||
event_codes.h
|
event_codes.h
|
||||||
expedition.h
|
expedition.h
|
||||||
expedition_database.h
|
expedition_database.h
|
||||||
|
|||||||
+111
-99
@@ -39,6 +39,8 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
|
|||||||
|
|
||||||
#include "bot.h"
|
#include "bot.h"
|
||||||
|
|
||||||
|
#include "../common/repositories/character_alternate_abilities_repository.h"
|
||||||
|
|
||||||
extern WorldServer worldserver;
|
extern WorldServer worldserver;
|
||||||
extern QueryServ* QServ;
|
extern QueryServ* QServ;
|
||||||
|
|
||||||
@@ -510,38 +512,41 @@ void Mob::WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *tar, uint32 d
|
|||||||
delete made_npc;
|
delete made_npc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ResetAA() {
|
void Client::ResetAA()
|
||||||
|
{
|
||||||
SendClearAA();
|
SendClearAA();
|
||||||
RefundAA();
|
RefundAA();
|
||||||
|
|
||||||
memset(&m_pp.aa_array[0], 0, sizeof(AA_Array) * MAX_PP_AA_ARRAY);
|
memset(&m_pp.aa_array[0], 0, sizeof(AA_Array) * MAX_PP_AA_ARRAY);
|
||||||
|
|
||||||
int i = 0;
|
int slot_id = 0;
|
||||||
for(auto &rank_value : aa_ranks) {
|
|
||||||
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value.first, rank_value.second.first);
|
|
||||||
auto ability = ability_rank.first;
|
|
||||||
auto rank = ability_rank.second;
|
|
||||||
|
|
||||||
if(!rank) {
|
for (auto& rank_value: aa_ranks) {
|
||||||
|
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value.first, rank_value.second.first);
|
||||||
|
auto ability = ability_rank.first;
|
||||||
|
auto rank = ability_rank.second;
|
||||||
|
|
||||||
|
if (!rank) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pp.aa_array[i].AA = rank_value.first;
|
m_pp.aa_array[slot_id].AA = rank_value.first;
|
||||||
m_pp.aa_array[i].value = rank_value.second.first;
|
m_pp.aa_array[slot_id].value = rank_value.second.first;
|
||||||
m_pp.aa_array[i].charges = rank_value.second.second;
|
m_pp.aa_array[slot_id].charges = rank_value.second.second;
|
||||||
++i;
|
++slot_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < _maxLeaderAA; ++i)
|
for (int slot_id = 0; slot_id < _maxLeaderAA; ++slot_id) {
|
||||||
m_pp.leader_abilities.ranks[i] = 0;
|
m_pp.leader_abilities.ranks[slot_id] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
m_pp.group_leadership_points = 0;
|
m_pp.group_leadership_points = 0;
|
||||||
m_pp.raid_leadership_points = 0;
|
m_pp.raid_leadership_points = 0;
|
||||||
m_pp.group_leadership_exp = 0;
|
m_pp.group_leadership_exp = 0;
|
||||||
m_pp.raid_leadership_exp = 0;
|
m_pp.raid_leadership_exp = 0;
|
||||||
|
|
||||||
database.DeleteCharacterAAs(CharacterID());
|
database.DeleteCharacterAAs(CharacterID());
|
||||||
database.DeleteCharacterLeadershipAAs(CharacterID());
|
database.DeleteCharacterLeadershipAbilities(CharacterID());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendClearAA()
|
void Client::SendClearAA()
|
||||||
@@ -833,31 +838,31 @@ void Client::RefundAA() {
|
|||||||
int refunded = 0;
|
int refunded = 0;
|
||||||
|
|
||||||
auto rank_value = aa_ranks.begin();
|
auto rank_value = aa_ranks.begin();
|
||||||
while(rank_value != aa_ranks.end()) {
|
while (rank_value != aa_ranks.end()) {
|
||||||
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value->first, rank_value->second.first);
|
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value->first, rank_value->second.first);
|
||||||
auto ability = ability_rank.first;
|
auto ability = ability_rank.first;
|
||||||
auto rank = ability_rank.second;
|
auto rank = ability_rank.second;
|
||||||
|
|
||||||
if(!ability) {
|
if (!ability) {
|
||||||
++rank_value;
|
++rank_value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ability->charges > 0 && rank_value->second.second < 1) {
|
if (ability->charges > 0 && rank_value->second.second < 1) {
|
||||||
++rank_value;
|
++rank_value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ability->grant_only) {
|
if (ability->grant_only) {
|
||||||
++rank_value;
|
++rank_value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
refunded += rank->total_cost;
|
refunded += rank->total_cost;
|
||||||
rank_value = aa_ranks.erase(rank_value);
|
rank_value = aa_ranks.erase(rank_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(refunded > 0) {
|
if (refunded > 0) {
|
||||||
m_pp.aapoints += refunded;
|
m_pp.aapoints += refunded;
|
||||||
SaveAA();
|
SaveAA();
|
||||||
Save();
|
Save();
|
||||||
@@ -1438,40 +1443,42 @@ void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) {
|
|||||||
|
|
||||||
bool ZoneDatabase::LoadAlternateAdvancement(Client *c) {
|
bool ZoneDatabase::LoadAlternateAdvancement(Client *c) {
|
||||||
c->ClearAAs();
|
c->ClearAAs();
|
||||||
std::string query = StringFormat(
|
|
||||||
"SELECT "
|
|
||||||
"aa_id, "
|
|
||||||
"aa_value, "
|
|
||||||
"charges "
|
|
||||||
"FROM "
|
|
||||||
"`character_alternate_abilities` "
|
|
||||||
"WHERE `id` = %u", c->CharacterID());
|
|
||||||
MySQLRequestResult results = database.QueryDatabase(query);
|
|
||||||
|
|
||||||
int i = 0;
|
const auto& l = CharacterAlternateAbilitiesRepository::GetWhere(
|
||||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
database,
|
||||||
uint32 aa = Strings::ToUnsignedInt(row[0]);
|
fmt::format(
|
||||||
uint32 value = Strings::ToUnsignedInt(row[1]);
|
"`id` = {}",
|
||||||
uint32 charges = Strings::ToUnsignedInt(row[2]);
|
c->CharacterID()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
auto rank = zone->GetAlternateAdvancementRank(aa);
|
uint32 slot_id = 0;
|
||||||
if(!rank) {
|
|
||||||
|
for (const auto& e : l) {
|
||||||
|
const uint16 aa_id = e.aa_id;
|
||||||
|
const uint16 aa_value = e.aa_value;
|
||||||
|
const uint16 charges = e.charges;
|
||||||
|
|
||||||
|
auto rank = zone->GetAlternateAdvancementRank(aa_id);
|
||||||
|
if (!rank) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ability = rank->base_ability;
|
auto ability = rank->base_ability;
|
||||||
if(!ability) {
|
if (!ability) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rank = ability->GetRankByPointsSpent(value);
|
rank = ability->GetRankByPointsSpent(aa_value);
|
||||||
|
|
||||||
if(c->CanUseAlternateAdvancementRank(rank)) {
|
if (c->CanUseAlternateAdvancementRank(rank)) {
|
||||||
c->GetPP().aa_array[i].AA = aa;
|
c->GetPP().aa_array[slot_id].AA = aa_id;
|
||||||
c->GetPP().aa_array[i].value = value;
|
c->GetPP().aa_array[slot_id].value = aa_value;
|
||||||
c->GetPP().aa_array[i].charges = charges;
|
c->GetPP().aa_array[slot_id].charges = charges;
|
||||||
c->SetAA(aa, value, charges);
|
|
||||||
i++;
|
c->SetAA(aa_id, aa_value, charges);
|
||||||
|
|
||||||
|
slot_id++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1556,56 +1563,61 @@ uint32 Mob::GetAAByAAID(uint32 aa_id, uint32 *charges) const {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) {
|
bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges)
|
||||||
if(zone) {
|
{
|
||||||
AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id);
|
if (zone) {
|
||||||
|
auto a = zone->GetAlternateAdvancementAbilityByRank(rank_id);
|
||||||
|
|
||||||
if(!ability) {
|
if (!a) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(new_value > ability->GetMaxLevel(this)) {
|
if(new_value > a->GetMaxLevel(this)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aa_ranks[ability->id] = std::make_pair(new_value, charges);
|
aa_ranks[a->id] = std::make_pair(new_value, charges);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
|
bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank)
|
||||||
|
{
|
||||||
if (!rank) {
|
if (!rank) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AA::Ability *ability = rank->base_ability;
|
const auto a = rank->base_ability;
|
||||||
|
|
||||||
if(!ability)
|
if (!a) {
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!(ability->classes & (1 << GetClass()))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Passive and Active Shroud AAs
|
if (!(a->classes & (1 << GetClass()))) {
|
||||||
// For now we skip them
|
return false;
|
||||||
if(ability->category == 3 || ability->category == 4) {
|
}
|
||||||
|
|
||||||
|
// Passive and Active Shroud AAs, skip for now
|
||||||
|
if (
|
||||||
|
a->category == AACategory::ShroudPassive ||
|
||||||
|
a->category == AACategory::ShroudActive
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//the one titanium hack i will allow
|
//the one titanium hack i will allow
|
||||||
//just to make sure we dont crash the client with newer aas
|
//just to make sure we dont crash the client with newer aas
|
||||||
//we'll exclude any expendable ones
|
//we'll exclude any expendable ones
|
||||||
if(IsClient() && CastToClient()->ClientVersionBit() & EQ::versions::maskTitaniumAndEarlier) {
|
if (IsClient() && CastToClient()->ClientVersionBit() & EQ::versions::maskTitaniumAndEarlier) {
|
||||||
if(ability->charges > 0) {
|
if (a->charges > 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int expansion = RuleI(Expansion, CurrentExpansion);
|
const int expansion = RuleI(Expansion, CurrentExpansion);
|
||||||
bool use_expansion_aa = RuleB(Expansion, UseCurrentExpansionAAOnly);
|
const bool use_expansion_aa = RuleB(Expansion, UseCurrentExpansionAAOnly);
|
||||||
if (use_expansion_aa && expansion >= 0) {
|
if (use_expansion_aa && expansion >= 0) {
|
||||||
if (rank->expansion > expansion) {
|
if (rank->expansion > expansion) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1617,36 +1629,35 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
|
|||||||
if (rank->expansion && !(CastToClient()->GetPP().expansions & (1 << (rank->expansion - 1)))) {
|
if (rank->expansion && !(CastToClient()->GetPP().expansions & (1 << (rank->expansion - 1)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else if (IsBot()) {
|
||||||
else if (IsBot()) {
|
|
||||||
if (rank->expansion && !(CastToBot()->GetExpansionBitmask() & (1 << (rank->expansion - 1)))) {
|
if (rank->expansion && !(CastToBot()->GetExpansionBitmask() & (1 << (rank->expansion - 1)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (rank->expansion && !(RuleI(World, ExpansionSettings) & (1 << (rank->expansion - 1)))) {
|
if (rank->expansion && !(RuleI(World, ExpansionSettings) & (1 << (rank->expansion - 1)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto race = GetPlayerRaceValue(GetBaseRace());
|
auto race = GetPlayerRaceValue(GetBaseRace());
|
||||||
race = race > 16 ? 1 : race;
|
|
||||||
if(!(ability->races & (1 << (race - 1)))) {
|
race = race > PLAYER_RACE_COUNT ? Race::Human : race;
|
||||||
|
|
||||||
|
if (!(a->races & (1 << (race - 1)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto deity = GetDeityBit();
|
const auto deity = GetDeityBit();
|
||||||
if(!(ability->deities & deity)) {
|
if (!(a->deities & deity)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsClient() && CastToClient()->Admin() < ability->status) {
|
if (IsClient() && CastToClient()->Admin() < a->status) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetBaseRace() == 522) {
|
if (GetBaseRace() == Race::Drakkin) {
|
||||||
//drakkin_heritage
|
if (!(a->drakkin_heritage & (1 << GetDrakkinHeritage()))) {
|
||||||
if(!(ability->drakkin_heritage & (1 << GetDrakkinHeritage()))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1654,13 +1665,15 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, bool check_grant) {
|
bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, bool check_grant)
|
||||||
AA::Ability *ability = rank->base_ability;
|
{
|
||||||
|
auto a = rank->base_ability;
|
||||||
|
|
||||||
if(!ability)
|
if (!a) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!CanUseAlternateAdvancementRank(rank)) {
|
if (!CanUseAlternateAdvancementRank(rank)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1668,54 +1681,53 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//You can't purchase grant only AAs they can only be assigned
|
// You cannot purchase grant only AAs they can only be assigned
|
||||||
if(check_grant && ability->grant_only) {
|
if (check_grant && a->grant_only) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check level req
|
if (rank->level_req > GetLevel()) {
|
||||||
if(rank->level_req > GetLevel()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 current_charges = 0;
|
uint32 current_charges = 0;
|
||||||
auto points = GetAA(rank->id, ¤t_charges);
|
const uint32 points = GetAA(rank->id, ¤t_charges);
|
||||||
|
|
||||||
//check that we are on previous rank already (if exists)
|
//check that we are on previous rank already (if exists)
|
||||||
//grant ignores the req to own the previous rank.
|
//grant ignores the req to own the previous rank.
|
||||||
if(check_grant && rank->prev) {
|
if (check_grant && rank->prev) {
|
||||||
if(points != rank->prev->current_value) {
|
if (points != rank->prev->current_value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//check that we aren't already on this rank or one ahead of us
|
//check that we aren't already on this rank or one ahead of us
|
||||||
if(points >= rank->current_value) {
|
if (points >= rank->current_value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if expendable only let us purchase if we have no charges already
|
//if expendable only let us purchase if we have no charges already
|
||||||
//not quite sure on how this functions client side atm
|
//not quite sure on how this functions client side atm
|
||||||
//I intend to look into it later to make sure the behavior is right
|
//I intend to look into it later to make sure the behavior is right
|
||||||
if(ability->charges > 0 && current_charges > 0) {
|
if (a->charges > 0 && current_charges > 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check prereqs
|
//check prereqs
|
||||||
for(auto &prereq : rank->prereqs) {
|
for (auto &prereq: rank->prereqs) {
|
||||||
AA::Ability *prereq_ability = zone->GetAlternateAdvancementAbility(prereq.first);
|
AA::Ability *prereq_ability = zone->GetAlternateAdvancementAbility(prereq.first);
|
||||||
|
|
||||||
if(prereq_ability) {
|
if (prereq_ability) {
|
||||||
auto ranks = GetAA(prereq_ability->first_rank_id);
|
auto ranks = GetAA(prereq_ability->first_rank_id);
|
||||||
if(ranks < prereq.second) {
|
if (ranks < prereq.second) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//check price, if client
|
//check price, if client
|
||||||
if(check_price && IsClient()) {
|
if (check_price && IsClient()) {
|
||||||
if(rank->cost > CastToClient()->GetAAPoints()) {
|
if (rank->cost > CastToClient()->GetAAPoints()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1525,6 +1525,19 @@ enum { //values of AA_Action.action
|
|||||||
aaActionBuy = 3
|
aaActionBuy = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace AACategory {
|
||||||
|
constexpr int None = -1;
|
||||||
|
constexpr int Passive = 1;
|
||||||
|
constexpr int Progression = 2;
|
||||||
|
constexpr int ShroudPassive = 3;
|
||||||
|
constexpr int ShroudActive = 4;
|
||||||
|
constexpr int VeteranReward = 5;
|
||||||
|
constexpr int Tradeskill = 6;
|
||||||
|
constexpr int Expendable = 7;
|
||||||
|
constexpr int RacialInnate = 8;
|
||||||
|
constexpr int EverQuest = 9;
|
||||||
|
}
|
||||||
|
|
||||||
class Timer;
|
class Timer;
|
||||||
class Mob;
|
class Mob;
|
||||||
class SwarmPet {
|
class SwarmPet {
|
||||||
|
|||||||
+2
-1
@@ -524,7 +524,8 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
GetINT() <= RuleI(Aggro, IntAggroThreshold) ||
|
(RuleB(Aggro, UndeadAlwaysAggro) && GetBodyType() == BT_Undead) ||
|
||||||
|
(GetINT() <= RuleI(Aggro, IntAggroThreshold)) ||
|
||||||
AlwaysAggro() ||
|
AlwaysAggro() ||
|
||||||
(
|
(
|
||||||
mob->IsClient() &&
|
mob->IsClient() &&
|
||||||
|
|||||||
+123
-90
@@ -2119,6 +2119,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoveFromHateList(other);
|
RemoveFromHateList(other);
|
||||||
|
RemoveFromRampageList(other);
|
||||||
LogCombat("I am not allowed to attack [{}]", other->GetName());
|
LogCombat("I am not allowed to attack [{}]", other->GetName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2705,68 +2706,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
|
|
||||||
Corpse* corpse = nullptr;
|
Corpse* corpse = nullptr;
|
||||||
|
|
||||||
// Parse quests even if we're killed by an NPC
|
const uint16 entity_id = GetID();
|
||||||
if (oos) {
|
|
||||||
if (IsNPC()) {
|
|
||||||
auto emote_id = GetEmoteID();
|
|
||||||
if (emote_id) {
|
|
||||||
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid, killer_mob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oos->IsNPC()) {
|
|
||||||
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
|
|
||||||
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto emote_id = oos->GetEmoteID();
|
|
||||||
if (emote_id) {
|
|
||||||
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id, this);
|
|
||||||
}
|
|
||||||
if (killer_mob) {
|
|
||||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (killer_mob && killer_mob->IsBot()) {
|
|
||||||
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
|
|
||||||
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_combat_record.Stop();
|
|
||||||
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
|
|
||||||
const auto& export_string = fmt::format(
|
|
||||||
"{} {} {} {}",
|
|
||||||
killer_mob ? killer_mob->GetID() : 0,
|
|
||||||
damage,
|
|
||||||
spell,
|
|
||||||
static_cast<int>(attack_skill)
|
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<std::any> args = { corpse };
|
|
||||||
|
|
||||||
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
|
||||||
|
|
||||||
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
|
|
||||||
const auto& export_string = fmt::format(
|
|
||||||
"{} {} {} {}",
|
|
||||||
killer_mob ? killer_mob->GetID() : 0,
|
|
||||||
damage,
|
|
||||||
spell,
|
|
||||||
static_cast<int>(attack_skill)
|
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<std::any> args = { corpse, this };
|
|
||||||
|
|
||||||
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
|
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
|
||||||
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
|
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
|
||||||
@@ -2877,6 +2817,39 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
entity_list.RemoveFromXTargets(this);
|
entity_list.RemoveFromXTargets(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse quests even if we're killed by an NPC
|
||||||
|
if (oos) {
|
||||||
|
if (IsNPC()) {
|
||||||
|
auto emote_id = GetEmoteID();
|
||||||
|
if (emote_id) {
|
||||||
|
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid, killer_mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oos->IsNPC()) {
|
||||||
|
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
|
||||||
|
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto emote_id = oos->GetEmoteID();
|
||||||
|
if (emote_id) {
|
||||||
|
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id, this);
|
||||||
|
}
|
||||||
|
if (killer_mob) {
|
||||||
|
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (killer_mob && killer_mob->IsBot()) {
|
||||||
|
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
|
||||||
|
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||||
|
}
|
||||||
|
|
||||||
WipeHateList();
|
WipeHateList();
|
||||||
p_depop = true;
|
p_depop = true;
|
||||||
|
|
||||||
@@ -2885,6 +2858,39 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
|
|
||||||
entity_list.UpdateFindableNPCState(this, true);
|
entity_list.UpdateFindableNPCState(this, true);
|
||||||
|
|
||||||
|
m_combat_record.Stop();
|
||||||
|
|
||||||
|
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
|
||||||
|
const auto& export_string = fmt::format(
|
||||||
|
"{} {} {} {} {}",
|
||||||
|
killer_mob ? killer_mob->GetID() : 0,
|
||||||
|
damage,
|
||||||
|
spell,
|
||||||
|
static_cast<int>(attack_skill),
|
||||||
|
entity_id
|
||||||
|
);
|
||||||
|
|
||||||
|
std::vector<std::any> args = { corpse };
|
||||||
|
|
||||||
|
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone controller process EVENT_DEATH_ZONE (Death events)
|
||||||
|
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
|
||||||
|
const auto& export_string = fmt::format(
|
||||||
|
"{} {} {} {} {}",
|
||||||
|
killer_mob ? killer_mob->GetID() : 0,
|
||||||
|
damage,
|
||||||
|
spell,
|
||||||
|
static_cast<int>(attack_skill),
|
||||||
|
entity_id
|
||||||
|
);
|
||||||
|
|
||||||
|
std::vector<std::any> args = { corpse, this };
|
||||||
|
|
||||||
|
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3805,6 +3811,8 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
|
|
||||||
if (damage > 0) {
|
if (damage > 0) {
|
||||||
//if there is some damage being done and theres an attacker involved
|
//if there is some damage being done and theres an attacker involved
|
||||||
|
int previous_hp_ratio = GetHPRatio();
|
||||||
|
|
||||||
if (attacker) {
|
if (attacker) {
|
||||||
// if spell is lifetap add hp to the caster
|
// if spell is lifetap add hp to the caster
|
||||||
if (IsValidSpell(spell_id) && IsLifetapSpell(spell_id)) {
|
if (IsValidSpell(spell_id) && IsLifetapSpell(spell_id)) {
|
||||||
@@ -3909,13 +3917,13 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker);
|
TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsClient() && CastToClient()->sneaking) {
|
if (IsClient()) {
|
||||||
CastToClient()->sneaking = false;
|
CommonBreakInvisible();
|
||||||
SendAppearancePacket(AT_Sneak, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attacker && attacker->IsClient() && attacker->CastToClient()->sneaking) {
|
if (attacker && attacker->IsClient() && attacker->CastToClient()->sneaking) {
|
||||||
attacker->CastToClient()->sneaking = false;
|
attacker->CastToClient()->sneaking = false;
|
||||||
attacker->SendAppearancePacket(AT_Sneak, 0);
|
attacker->SendAppearancePacket(AppearanceType::Sneak, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//final damage has been determined.
|
//final damage has been determined.
|
||||||
@@ -4030,8 +4038,9 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (GetHPRatio() < 16)
|
if (GetHPRatio() < 16 && previous_hp_ratio >= 16) {
|
||||||
TryDeathSave();
|
TryDeathSave();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TryTriggerOnCastRequirement();
|
TryTriggerOnCastRequirement();
|
||||||
@@ -4179,8 +4188,9 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
//send an HP update if we are hurt
|
//send an HP update if we are hurt
|
||||||
if (GetHP() < GetMaxHP())
|
if (GetHP() < GetMaxHP()) {
|
||||||
SendHPUpdate(); // the OP_Damage actually updates the client in these cases, so we skip the HP update for them
|
SendHPUpdate(); // the OP_Damage actually updates the client in these cases, so we skip the HP update for them
|
||||||
|
}
|
||||||
} //end `if damage was done`
|
} //end `if damage was done`
|
||||||
|
|
||||||
//send damage packet...
|
//send damage packet...
|
||||||
@@ -4188,32 +4198,48 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
|
|||||||
auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
|
auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
|
||||||
CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer;
|
CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer;
|
||||||
a->target = GetID();
|
a->target = GetID();
|
||||||
if (attacker == nullptr)
|
|
||||||
|
if (!attacker) {
|
||||||
a->source = 0;
|
a->source = 0;
|
||||||
else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe())
|
} else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe()) {
|
||||||
a->source = 0;
|
a->source = 0;
|
||||||
else
|
} else {
|
||||||
a->source = attacker->GetID();
|
a->source = attacker->GetID();
|
||||||
|
}
|
||||||
|
|
||||||
a->type = (EQ::ValueWithin(skill_used, EQ::skills::Skill1HBlunt, EQ::skills::Skill2HPiercing)) ?
|
a->type = (EQ::ValueWithin(skill_used, EQ::skills::Skill1HBlunt, EQ::skills::Skill2HPiercing)) ?
|
||||||
SkillDamageTypes[skill_used] : SkillDamageTypes[EQ::skills::SkillHandtoHand]; // was 0x1c
|
SkillDamageTypes[skill_used] : SkillDamageTypes[EQ::skills::SkillHandtoHand]; // was 0x1c
|
||||||
a->damage = damage;
|
a->damage = damage;
|
||||||
a->spellid = spell_id;
|
a->spellid = spell_id;
|
||||||
if (special == eSpecialAttacks::AERampage)
|
|
||||||
|
if (special == eSpecialAttacks::AERampage) {
|
||||||
a->special = 1;
|
a->special = 1;
|
||||||
else if (special == eSpecialAttacks::Rampage)
|
} else if (special == eSpecialAttacks::Rampage) {
|
||||||
a->special = 2;
|
a->special = 2;
|
||||||
else
|
} else {
|
||||||
a->special = 0;
|
a->special = 0;
|
||||||
|
}
|
||||||
|
|
||||||
a->hit_heading = attacker ? attacker->GetHeading() : 0.0f;
|
a->hit_heading = attacker ? attacker->GetHeading() : 0.0f;
|
||||||
if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() &&
|
if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() &&
|
||||||
(IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) {
|
(IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) {
|
||||||
a->force = EQ::skills::GetSkillMeleePushForce(skill_used);
|
a->force = EQ::skills::GetSkillMeleePushForce(skill_used);
|
||||||
|
|
||||||
|
if (RuleR(Combat, MeleePushForceClientPercent) && IsClient()) {
|
||||||
|
a->force += a->force * RuleR(Combat, MeleePushForceClientPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RuleR(Combat, MeleePushForcePetPercent) && IsPet()) {
|
||||||
|
a->force += a->force * RuleR(Combat, MeleePushForcePetPercent);
|
||||||
|
}
|
||||||
|
|
||||||
if (IsNPC()) {
|
if (IsNPC()) {
|
||||||
if (attacker && attacker->IsNPC()) {
|
if (!RuleB(Combat, NPCtoNPCPush) && attacker && attacker->IsNPC()) {
|
||||||
a->force = 0.0f; // 2013 change that disabled NPC vs NPC push
|
a->force = 0.0f; // 2013 change that disabled NPC vs NPC push
|
||||||
} else {
|
} else {
|
||||||
a->force *= 0.10f; // force against NPCs is divided by 10 I guess? ex bash is 0.3, parsed 0.03 against an NPC
|
a->force *= 0.10f; // force against NPCs is divided by 10 I guess? ex bash is 0.3, parsed 0.03 against an NPC
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ForcedMovement == 0 && a->force != 0.0f && position_update_melee_push_timer.Check()) {
|
if (ForcedMovement == 0 && a->force != 0.0f && position_update_melee_push_timer.Check()) {
|
||||||
m_Delta.x += a->force * g_Math.FastSin(a->hit_heading);
|
m_Delta.x += a->force * g_Math.FastSin(a->hit_heading);
|
||||||
m_Delta.y += a->force * g_Math.FastCos(a->hit_heading);
|
m_Delta.y += a->force * g_Math.FastCos(a->hit_heading);
|
||||||
@@ -5015,7 +5041,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
|||||||
hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100;
|
hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100;
|
||||||
|
|
||||||
/* Female */
|
/* Female */
|
||||||
if (GetGender() == 1) {
|
if (GetGender() == Gender::Female) {
|
||||||
entity_list.FilteredMessageCloseString(
|
entity_list.FilteredMessageCloseString(
|
||||||
this, /* Sender */
|
this, /* Sender */
|
||||||
false, /* Skip Sender */
|
false, /* Skip Sender */
|
||||||
@@ -5183,7 +5209,6 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
|||||||
bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
||||||
{
|
{
|
||||||
float hp_limit = 10.0f;
|
float hp_limit = 10.0f;
|
||||||
|
|
||||||
auto fb_hp_limit = std::max(
|
auto fb_hp_limit = std::max(
|
||||||
{
|
{
|
||||||
aabonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO],
|
aabonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO],
|
||||||
@@ -5195,28 +5220,36 @@ bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
|||||||
if (fb_hp_limit) {
|
if (fb_hp_limit) {
|
||||||
hp_limit = fb_hp_limit/10.0f;
|
hp_limit = fb_hp_limit/10.0f;
|
||||||
}
|
}
|
||||||
if (defender && !defender->IsClient() && defender->GetHPRatio() < hp_limit) {
|
|
||||||
|
|
||||||
uint32 FB_Dmg =
|
if (defender && !defender->IsClient() && defender->GetHPRatio() < hp_limit) {
|
||||||
|
uint32 finishing_blow_damage =
|
||||||
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG];
|
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG];
|
||||||
|
|
||||||
uint32 FB_Level = 0;
|
uint32 finishing_blow_level = 0;
|
||||||
FB_Level = aabonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
finishing_blow_level = aabonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
||||||
if (FB_Level < spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX])
|
if (finishing_blow_level < spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX]) {
|
||||||
FB_Level = spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
finishing_blow_level = spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
||||||
else if (FB_Level < itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX])
|
} else if (finishing_blow_level < itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX]) {
|
||||||
FB_Level = itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
finishing_blow_level = itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
||||||
|
}
|
||||||
|
|
||||||
// modern AA description says rank 1 (500) is 50% chance
|
// modern AA description says rank 1 (500) is 50% chance
|
||||||
int ProcChance = (
|
int proc_chance = (
|
||||||
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] +
|
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] +
|
||||||
itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] +
|
itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] +
|
||||||
spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE]
|
spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) &&
|
if (
|
||||||
(ProcChance >= zone->random.Int(1, 1000))) {
|
(
|
||||||
|
(RuleB(Combat, FinishingBlowOnlyWhenFleeing) && !defender->currently_fleeing) ||
|
||||||
|
!RuleB(Combat, FinishingBlowOnlyWhenFleeing)
|
||||||
|
) &&
|
||||||
|
finishing_blow_level &&
|
||||||
|
finishing_blow_damage &&
|
||||||
|
defender->GetLevel() <= finishing_blow_level &&
|
||||||
|
proc_chance >= zone->random.Int(1, 1000)
|
||||||
|
) {
|
||||||
/* Finishing Blow Critical Message */
|
/* Finishing Blow Critical Message */
|
||||||
entity_list.FilteredMessageCloseString(
|
entity_list.FilteredMessageCloseString(
|
||||||
this, /* Sender */
|
this, /* Sender */
|
||||||
@@ -5229,7 +5262,7 @@ bool Mob::TryFinishingBlow(Mob *defender, int64 &damage)
|
|||||||
GetCleanName() /* Message1 */
|
GetCleanName() /* Message1 */
|
||||||
);
|
);
|
||||||
|
|
||||||
damage = FB_Dmg;
|
damage = finishing_blow_damage;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -49,9 +49,9 @@ Beacon::Beacon(const glm::vec4 &in_pos, int lifetime) : Mob(
|
|||||||
nullptr, // in_lastname
|
nullptr, // in_lastname
|
||||||
0, // in_cur_hp
|
0, // in_cur_hp
|
||||||
0, // in_max_hp
|
0, // in_max_hp
|
||||||
MALE, // in_gender
|
Gender::Male, // in_gender
|
||||||
INVISIBLE_MAN, // in_race
|
Race::InvisibleMan, // in_race
|
||||||
0, // in_class
|
Class::None, // in_class
|
||||||
BT_NoTarget, // in_bodytype
|
BT_NoTarget, // in_bodytype
|
||||||
0, // in_deity
|
0, // in_deity
|
||||||
0, // in_level
|
0, // in_level
|
||||||
|
|||||||
+20
-40
@@ -281,10 +281,10 @@ Bot::Bot(
|
|||||||
case SE_IllusionCopy:
|
case SE_IllusionCopy:
|
||||||
case SE_Illusion: {
|
case SE_Illusion: {
|
||||||
if (spell.base_value[x1] == -1) {
|
if (spell.base_value[x1] == -1) {
|
||||||
if (gender == FEMALE) {
|
if (gender == Gender::Female) {
|
||||||
gender = MALE;
|
gender = Gender::Male;
|
||||||
} else if (gender == MALE) {
|
} else if (gender == Gender::Male) {
|
||||||
gender = FEMALE;
|
gender = Gender::Female;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendIllusionPacket(
|
SendIllusionPacket(
|
||||||
@@ -325,30 +325,30 @@ Bot::Bot(
|
|||||||
|
|
||||||
switch (spell.base_value[x1]) {
|
switch (spell.base_value[x1]) {
|
||||||
case OGRE:
|
case OGRE:
|
||||||
SendAppearancePacket(AT_Size, 9);
|
SendAppearancePacket(AppearanceType::Size, 9);
|
||||||
break;
|
break;
|
||||||
case TROLL:
|
case TROLL:
|
||||||
SendAppearancePacket(AT_Size, 8);
|
SendAppearancePacket(AppearanceType::Size, 8);
|
||||||
break;
|
break;
|
||||||
case VAHSHIR:
|
case VAHSHIR:
|
||||||
case BARBARIAN:
|
case BARBARIAN:
|
||||||
SendAppearancePacket(AT_Size, 7);
|
SendAppearancePacket(AppearanceType::Size, 7);
|
||||||
break;
|
break;
|
||||||
case HALF_ELF:
|
case HALF_ELF:
|
||||||
case WOOD_ELF:
|
case WOOD_ELF:
|
||||||
case DARK_ELF:
|
case DARK_ELF:
|
||||||
case FROGLOK:
|
case FROGLOK:
|
||||||
SendAppearancePacket(AT_Size, 5);
|
SendAppearancePacket(AppearanceType::Size, 5);
|
||||||
break;
|
break;
|
||||||
case DWARF:
|
case DWARF:
|
||||||
SendAppearancePacket(AT_Size, 4);
|
SendAppearancePacket(AppearanceType::Size, 4);
|
||||||
break;
|
break;
|
||||||
case HALFLING:
|
case HALFLING:
|
||||||
case GNOME:
|
case GNOME:
|
||||||
SendAppearancePacket(AT_Size, 3);
|
SendAppearancePacket(AppearanceType::Size, 3);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SendAppearancePacket(AT_Size, 6);
|
SendAppearancePacket(AppearanceType::Size, 6);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -372,18 +372,18 @@ Bot::Bot(
|
|||||||
case SE_Invisibility:
|
case SE_Invisibility:
|
||||||
{
|
{
|
||||||
invisible = true;
|
invisible = true;
|
||||||
SendAppearancePacket(AT_Invis, 1);
|
SendAppearancePacket(AppearanceType::Invisibility, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SE_Levitate:
|
case SE_Levitate:
|
||||||
{
|
{
|
||||||
if (!zone->CanLevitate())
|
if (!zone->CanLevitate())
|
||||||
{
|
{
|
||||||
SendAppearancePacket(AT_Levitate, 0);
|
SendAppearancePacket(AppearanceType::FlyMode, 0);
|
||||||
BuffFadeByEffect(SE_Levitate);
|
BuffFadeByEffect(SE_Levitate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SendAppearancePacket(AT_Levitate, 2);
|
SendAppearancePacket(AppearanceType::FlyMode, 2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2783,10 +2783,12 @@ bool Bot::IsValidTarget(Client* bot_owner, Client* leash_owner, float lo_distanc
|
|||||||
// 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);
|
||||||
|
GetPet()->RemoveFromRampageList(tar);
|
||||||
GetPet()->SetTarget(nullptr);
|
GetPet()->SetTarget(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveFromHateList(tar);
|
RemoveFromHateList(tar);
|
||||||
|
RemoveFromRampageList(tar);
|
||||||
SetTarget(nullptr);
|
SetTarget(nullptr);
|
||||||
|
|
||||||
SetAttackFlag(false);
|
SetAttackFlag(false);
|
||||||
@@ -3674,7 +3676,7 @@ void Bot::LevelBotWithClient(Client* c, uint8 new_level, bool send_appearance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
e->SendHPUpdate();
|
e->SendHPUpdate();
|
||||||
e->SendAppearancePacket(AT_WhoLevel, new_level, true, true); // who level change
|
e->SendAppearancePacket(AppearanceType::WhoLevel, new_level, true, true); // who level change
|
||||||
e->AI_AddBotSpells(e->GetBotSpellID());
|
e->AI_AddBotSpells(e->GetBotSpellID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3706,7 +3708,7 @@ void Bot::BotAddEquipItem(uint16 slot_id, uint32 item_id) {
|
|||||||
|
|
||||||
UpdateEquipmentLight();
|
UpdateEquipmentLight();
|
||||||
if (UpdateActiveLight() && GetID()) { // temp hack fix
|
if (UpdateActiveLight() && GetID()) { // temp hack fix
|
||||||
SendAppearancePacket(AT_Light, GetActiveLightType());
|
SendAppearancePacket(AppearanceType::Light, GetActiveLightType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3726,7 +3728,7 @@ void Bot::BotRemoveEquipItem(uint16 slot_id)
|
|||||||
|
|
||||||
UpdateEquipmentLight();
|
UpdateEquipmentLight();
|
||||||
if (UpdateActiveLight()) {
|
if (UpdateActiveLight()) {
|
||||||
SendAppearancePacket(AT_Light, GetActiveLightType());
|
SendAppearancePacket(AppearanceType::Light, GetActiveLightType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7894,7 +7896,7 @@ void Bot::BotGroupSay(Mob *speaker, const char *msg, ...) {
|
|||||||
if (speaker->HasGroup()) {
|
if (speaker->HasGroup()) {
|
||||||
Group *g = speaker->GetGroup();
|
Group *g = speaker->GetGroup();
|
||||||
if (g)
|
if (g)
|
||||||
g->GroupMessage(speaker->CastToMob(), 0, 100, buf);
|
g->GroupMessage(speaker->CastToMob(), Language::CommonTongue, Language::MaxValue, buf);
|
||||||
} else
|
} else
|
||||||
speaker->Say("%s", buf);
|
speaker->Say("%s", buf);
|
||||||
}
|
}
|
||||||
@@ -8138,28 +8140,6 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Bot::CreateSayLink(Client* c, const char* message, const char* name)
|
|
||||||
{
|
|
||||||
// TODO: review
|
|
||||||
|
|
||||||
int saylink_size = strlen(message);
|
|
||||||
char* escaped_string = new char[saylink_size * 2];
|
|
||||||
|
|
||||||
database.DoEscapeString(escaped_string, message, saylink_size);
|
|
||||||
|
|
||||||
uint32 saylink_id = database.LoadSaylinkID(escaped_string);
|
|
||||||
safe_delete_array(escaped_string);
|
|
||||||
|
|
||||||
EQ::SayLinkEngine linker;
|
|
||||||
linker.SetLinkType(EQ::saylink::SayLinkItemData);
|
|
||||||
linker.SetProxyItemID(SAYLINK_ITEM_ID);
|
|
||||||
linker.SetProxyAugment1ID(saylink_id);
|
|
||||||
linker.SetProxyText(name);
|
|
||||||
|
|
||||||
auto saylink = linker.GenerateLink();
|
|
||||||
return saylink;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bot::Signal(int signal_id)
|
void Bot::Signal(int signal_id)
|
||||||
{
|
{
|
||||||
if (parse->BotHasQuestSub(EVENT_SIGNAL)) {
|
if (parse->BotHasQuestSub(EVENT_SIGNAL)) {
|
||||||
|
|||||||
@@ -659,8 +659,6 @@ public:
|
|||||||
void SetBotEnforceSpellSetting(bool enforcespellsettings, bool save = false);
|
void SetBotEnforceSpellSetting(bool enforcespellsettings, bool save = false);
|
||||||
bool GetBotEnforceSpellSetting() const { return m_enforce_spell_settings; }
|
bool GetBotEnforceSpellSetting() const { return m_enforce_spell_settings; }
|
||||||
|
|
||||||
std::string CreateSayLink(Client* botOwner, const char* message, const char* name);
|
|
||||||
|
|
||||||
// Class Destructors
|
// Class Destructors
|
||||||
~Bot() override;
|
~Bot() override;
|
||||||
|
|
||||||
|
|||||||
+58
-71
@@ -404,38 +404,38 @@ public:
|
|||||||
|
|
||||||
for (int i = EffectIDFirst; i <= EffectIDLast; ++i) {
|
for (int i = EffectIDFirst; i <= EffectIDLast; ++i) {
|
||||||
int effect_index = EFFECTIDTOINDEX(i);
|
int effect_index = EFFECTIDTOINDEX(i);
|
||||||
if (spells[spell_id].base_value[effect_index] <= 0)
|
if (spells[spell_id].max_value[effect_index] <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (spells[spell_id].effect_id[effect_index]) {
|
switch (spells[spell_id].effect_id[effect_index]) {
|
||||||
case SE_ResistFire:
|
case SE_ResistFire:
|
||||||
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
||||||
BCEnum::RT_Fire)] += spells[spell_id].base_value[effect_index];
|
BCEnum::RT_Fire)] += spells[spell_id].max_value[effect_index];
|
||||||
break;
|
break;
|
||||||
case SE_ResistCold:
|
case SE_ResistCold:
|
||||||
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
||||||
BCEnum::RT_Cold)] += spells[spell_id].base_value[effect_index];
|
BCEnum::RT_Cold)] += spells[spell_id].max_value[effect_index];
|
||||||
break;
|
break;
|
||||||
case SE_ResistPoison:
|
case SE_ResistPoison:
|
||||||
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
||||||
BCEnum::RT_Poison)] += spells[spell_id].base_value[effect_index];
|
BCEnum::RT_Poison)] += spells[spell_id].max_value[effect_index];
|
||||||
break;
|
break;
|
||||||
case SE_ResistDisease:
|
case SE_ResistDisease:
|
||||||
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
||||||
BCEnum::RT_Disease)] += spells[spell_id].base_value[effect_index];
|
BCEnum::RT_Disease)] += spells[spell_id].max_value[effect_index];
|
||||||
break;
|
break;
|
||||||
case SE_ResistMagic:
|
case SE_ResistMagic:
|
||||||
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
||||||
BCEnum::RT_Magic)] += spells[spell_id].base_value[effect_index];
|
BCEnum::RT_Magic)] += spells[spell_id].max_value[effect_index];
|
||||||
break;
|
break;
|
||||||
case SE_ResistCorruption:
|
case SE_ResistCorruption:
|
||||||
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(
|
||||||
BCEnum::RT_Corruption)] += spells[spell_id].base_value[effect_index];
|
BCEnum::RT_Corruption)] += spells[spell_id].max_value[effect_index];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
entry_prototype->SafeCastToResistance()->resist_total += spells[spell_id].base_value[effect_index];
|
entry_prototype->SafeCastToResistance()->resist_total += spells[spell_id].max_value[effect_index];
|
||||||
valid_spell = true;
|
valid_spell = true;
|
||||||
}
|
}
|
||||||
if (!valid_spell) {
|
if (!valid_spell) {
|
||||||
@@ -2870,7 +2870,7 @@ void bot_command_apply_poison(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
if (my_rogue_bot->GetLevel() < 18) {
|
if (my_rogue_bot->GetLevel() < 18) {
|
||||||
|
|
||||||
c->Message(Chat::White, "Your rogue bot must be level 18 before %s can apply poison!", (my_rogue_bot->GetGender() == 1 ? "she" : "he"));
|
c->Message(Chat::White, "Your rogue bot must be level 18 before %s can apply poison!", (my_rogue_bot->GetGender() == Gender::Female ? "she" : "he"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4003,8 +4003,6 @@ void bot_command_item_use(Client* c, const Seperator* sep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string text_link;
|
|
||||||
|
|
||||||
EQ::SayLinkEngine linker;
|
EQ::SayLinkEngine linker;
|
||||||
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
|
||||||
|
|
||||||
@@ -4050,15 +4048,6 @@ void bot_command_item_use(Client* c, const Seperator* sep)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
text_link = bot_iter->CreateSayLink(
|
|
||||||
c,
|
|
||||||
fmt::format(
|
|
||||||
"^inventorygive byname {}",
|
|
||||||
bot_iter->GetCleanName()
|
|
||||||
).c_str(),
|
|
||||||
bot_iter->GetCleanName()
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const auto& slot_iter : equipable_slot_list) {
|
for (const auto& slot_iter : equipable_slot_list) {
|
||||||
// needs more failure criteria - this should cover the bulk for now
|
// needs more failure criteria - this should cover the bulk for now
|
||||||
if (slot_iter == EQ::invslot::slotSecondary && item_data->Damage && !bot_iter->CanThisClassDualWield()) {
|
if (slot_iter == EQ::invslot::slotSecondary && item_data->Damage && !bot_iter->CanThisClassDualWield()) {
|
||||||
@@ -4074,7 +4063,13 @@ void bot_command_item_use(Client* c, const Seperator* sep)
|
|||||||
Chat::Say,
|
Chat::Say,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} says, 'I can use that for my {} instead of my {}! Would you like to {} my {}?'",
|
"{} says, 'I can use that for my {} instead of my {}! Would you like to {} my {}?'",
|
||||||
text_link,
|
Saylink::Silent(
|
||||||
|
fmt::format(
|
||||||
|
"^inventorygive byname {}",
|
||||||
|
bot_iter->GetCleanName()
|
||||||
|
),
|
||||||
|
bot_iter->GetCleanName()
|
||||||
|
),
|
||||||
EQ::invslot::GetInvPossessionsSlotName(slot_iter),
|
EQ::invslot::GetInvPossessionsSlotName(slot_iter),
|
||||||
linker.GenerateLink(),
|
linker.GenerateLink(),
|
||||||
Saylink::Silent(
|
Saylink::Silent(
|
||||||
@@ -4096,7 +4091,13 @@ void bot_command_item_use(Client* c, const Seperator* sep)
|
|||||||
Chat::Say,
|
Chat::Say,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} says, 'I can use that for my {}! Would you like to {} it to me?'",
|
"{} says, 'I can use that for my {}! Would you like to {} it to me?'",
|
||||||
text_link,
|
Saylink::Silent(
|
||||||
|
fmt::format(
|
||||||
|
"^inventorygive byname {}",
|
||||||
|
bot_iter->GetCleanName()
|
||||||
|
),
|
||||||
|
bot_iter->GetCleanName()
|
||||||
|
),
|
||||||
EQ::invslot::GetInvPossessionsSlotName(slot_iter),
|
EQ::invslot::GetInvPossessionsSlotName(slot_iter),
|
||||||
Saylink::Silent(
|
Saylink::Silent(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -5633,7 +5634,7 @@ void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep)
|
|||||||
uint8 uvalue = Strings::ToInt(sep->arg[1]);
|
uint8 uvalue = Strings::ToInt(sep->arg[1]);
|
||||||
|
|
||||||
auto fail_type = BCEnum::AFT_None;
|
auto fail_type = BCEnum::AFT_None;
|
||||||
if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF)
|
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF)
|
||||||
fail_type = BCEnum::AFT_GenderRace;
|
fail_type = BCEnum::AFT_GenderRace;
|
||||||
else if (!PlayerAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue))
|
else if (!PlayerAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue))
|
||||||
fail_type = BCEnum::AFT_Value;
|
fail_type = BCEnum::AFT_Value;
|
||||||
@@ -5670,7 +5671,7 @@ void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep)
|
|||||||
uint8 uvalue = Strings::ToInt(sep->arg[1]);
|
uint8 uvalue = Strings::ToInt(sep->arg[1]);
|
||||||
|
|
||||||
auto fail_type = BCEnum::AFT_None;
|
auto fail_type = BCEnum::AFT_None;
|
||||||
if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF)
|
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF)
|
||||||
fail_type = BCEnum::AFT_GenderRace;
|
fail_type = BCEnum::AFT_GenderRace;
|
||||||
else if (!PlayerAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue))
|
else if (!PlayerAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue))
|
||||||
fail_type = BCEnum::AFT_Value;
|
fail_type = BCEnum::AFT_Value;
|
||||||
@@ -6171,18 +6172,18 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bot_gender = MALE;
|
auto bot_gender = Gender::Male;
|
||||||
|
|
||||||
if (sep->IsNumber(4)) {
|
if (sep->IsNumber(4)) {
|
||||||
bot_gender = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[4]));
|
bot_gender = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[4]));
|
||||||
if (bot_gender == NEUTER) {
|
if (bot_gender == Gender::Neuter) {
|
||||||
bot_gender = MALE;
|
bot_gender = Gender::Male;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!strcasecmp(sep->arg[4], "m") || !strcasecmp(sep->arg[4], "male")) {
|
if (!strcasecmp(sep->arg[4], "m") || !strcasecmp(sep->arg[4], "male")) {
|
||||||
bot_gender = MALE;
|
bot_gender = Gender::Male;
|
||||||
} else if (!strcasecmp(sep->arg[4], "f") || !strcasecmp(sep->arg[4], "female")) {
|
} else if (!strcasecmp(sep->arg[4], "f") || !strcasecmp(sep->arg[4], "female")) {
|
||||||
bot_gender = FEMALE;
|
bot_gender = Gender::Female;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7594,7 +7595,7 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep)
|
|||||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
||||||
SpawnAppearance_Struct* saptr = (SpawnAppearance_Struct*)outapp->pBuffer;
|
SpawnAppearance_Struct* saptr = (SpawnAppearance_Struct*)outapp->pBuffer;
|
||||||
saptr->spawn_id = bot_iter->GetID();
|
saptr->spawn_id = bot_iter->GetID();
|
||||||
saptr->type = AT_ShowHelm;
|
saptr->type = AppearanceType::ShowHelm;
|
||||||
saptr->parameter = bot_iter->GetShowHelm();
|
saptr->parameter = bot_iter->GetShowHelm();
|
||||||
|
|
||||||
entity_list.QueueClients(bot_iter, outapp);
|
entity_list.QueueClients(bot_iter, outapp);
|
||||||
@@ -7667,7 +7668,7 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep)
|
|||||||
[10-16-2015 :: 22:15:40] [Packet :: Server -> Client (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10]
|
[10-16-2015 :: 22:15:40] [Packet :: Server -> Client (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10]
|
||||||
0: A2 02 2B 00 00 00 00 00 - showhelm = false
|
0: A2 02 2B 00 00 00 00 00 - showhelm = false
|
||||||
|
|
||||||
*** Bot did not update using the OP_SpawnAppearance packet with AT_ShowHelm appearance type ***
|
*** Bot did not update using the OP_SpawnAppearance packet with AppearanceType::ShowHelm appearance type ***
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7694,7 +7695,7 @@ void bot_subcommand_bot_update(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
bot_iter->SetPetChooser(false);
|
bot_iter->SetPetChooser(false);
|
||||||
bot_iter->CalcBotStats(c->GetBotOption(Client::booStatsUpdate));
|
bot_iter->CalcBotStats(c->GetBotOption(Client::booStatsUpdate));
|
||||||
bot_iter->SendAppearancePacket(AT_WhoLevel, bot_iter->GetLevel(), true, true);
|
bot_iter->SendAppearancePacket(AppearanceType::WhoLevel, bot_iter->GetLevel(), true, true);
|
||||||
++bot_count;
|
++bot_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9542,10 +9543,6 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
|||||||
if (!Bot::IsValidRaceClassCombo(bot_race, bot_class)) {
|
if (!Bot::IsValidRaceClassCombo(bot_race, bot_class)) {
|
||||||
const std::string bot_race_name = GetRaceIDName(bot_race);
|
const std::string bot_race_name = GetRaceIDName(bot_race);
|
||||||
const std::string bot_class_name = GetClassIDName(bot_class);
|
const std::string bot_class_name = GetClassIDName(bot_class);
|
||||||
const auto view_saylink = Saylink::Silent(
|
|
||||||
fmt::format("^viewcombos {}", bot_race),
|
|
||||||
"view"
|
|
||||||
);
|
|
||||||
|
|
||||||
bot_owner->Message(
|
bot_owner->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
@@ -9553,7 +9550,10 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
|||||||
"{} {} is an invalid race-class combination, would you like to {} proper combinations for {}?",
|
"{} {} is an invalid race-class combination, would you like to {} proper combinations for {}?",
|
||||||
bot_race_name,
|
bot_race_name,
|
||||||
bot_class_name,
|
bot_class_name,
|
||||||
view_saylink,
|
Saylink::Silent(
|
||||||
|
fmt::format("^viewcombos {}", bot_race),
|
||||||
|
"view"
|
||||||
|
),
|
||||||
bot_race_name
|
bot_race_name
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
@@ -9561,15 +9561,15 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
|
|||||||
return bot_id;
|
return bot_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EQ::ValueWithin(bot_gender, MALE, FEMALE)) {
|
if (!EQ::ValueWithin(bot_gender, Gender::Male, Gender::Female)) {
|
||||||
bot_owner->Message(
|
bot_owner->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Gender: {} ({}) or {} ({})",
|
"Gender: {} ({}) or {} ({})",
|
||||||
GetGenderName(MALE),
|
GetGenderName(Gender::Male),
|
||||||
MALE,
|
Gender::Male,
|
||||||
GetGenderName(FEMALE),
|
GetGenderName(Gender::Female),
|
||||||
FEMALE
|
Gender::Female
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
return bot_id;
|
return bot_id;
|
||||||
@@ -9871,9 +9871,6 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string msg;
|
|
||||||
std::string text_link;
|
|
||||||
|
|
||||||
auto destination_count = 0;
|
auto destination_count = 0;
|
||||||
auto destination_number = 1;
|
auto destination_number = 1;
|
||||||
for (auto list_iter : *local_list) {
|
for (auto list_iter : *local_list) {
|
||||||
@@ -9891,24 +9888,19 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = fmt::format(
|
|
||||||
"^circle {}{}",
|
|
||||||
spells[local_entry->spell_id].teleport_zone,
|
|
||||||
single_flag ? " single" : ""
|
|
||||||
);
|
|
||||||
|
|
||||||
text_link = druid_bot->CreateSayLink(
|
|
||||||
bot_owner,
|
|
||||||
msg.c_str(),
|
|
||||||
"Goto"
|
|
||||||
);
|
|
||||||
|
|
||||||
druid_bot->OwnerMessage(
|
druid_bot->OwnerMessage(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Destination {} | {} | {}",
|
"Destination {} | {} | {}",
|
||||||
destination_number,
|
destination_number,
|
||||||
local_entry->long_name,
|
local_entry->long_name,
|
||||||
text_link
|
Saylink::Silent(
|
||||||
|
fmt::format(
|
||||||
|
"^circle {}{}",
|
||||||
|
spells[local_entry->spell_id].teleport_zone,
|
||||||
|
single_flag ? " single" : ""
|
||||||
|
),
|
||||||
|
"Goto"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -9926,24 +9918,19 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = fmt::format(
|
|
||||||
"^portal {}{}",
|
|
||||||
spells[local_entry->spell_id].teleport_zone,
|
|
||||||
single_flag ? " single" : ""
|
|
||||||
);
|
|
||||||
|
|
||||||
text_link = wizard_bot->CreateSayLink(
|
|
||||||
bot_owner,
|
|
||||||
msg.c_str(),
|
|
||||||
"Goto"
|
|
||||||
);
|
|
||||||
|
|
||||||
wizard_bot->OwnerMessage(
|
wizard_bot->OwnerMessage(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Destination {} | {} | {}",
|
"Destination {} | {} | {}",
|
||||||
destination_number,
|
destination_number,
|
||||||
local_entry->long_name,
|
local_entry->long_name,
|
||||||
text_link
|
Saylink::Silent(
|
||||||
|
fmt::format(
|
||||||
|
"^portal {}{}",
|
||||||
|
spells[local_entry->spell_id].teleport_zone,
|
||||||
|
single_flag ? " single" : ""
|
||||||
|
),
|
||||||
|
"Goto"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
|||||||
if (casted_spell && GetClass() != Class::Bard) {
|
if (casted_spell && GetClass() != Class::Bard) {
|
||||||
if (raid) {
|
if (raid) {
|
||||||
const auto msg = fmt::format("Attempting to slow {}.", tar->GetCleanName());
|
const auto msg = fmt::format("Attempting to slow {}.", tar->GetCleanName());
|
||||||
raid->RaidSay(msg.c_str(), GetCleanName(), 0, 100);
|
raid->RaidSay(msg.c_str(), GetCleanName(), Language::CommonTongue, Language::MaxValue);
|
||||||
} else {
|
} else {
|
||||||
BotGroupSay(
|
BotGroupSay(
|
||||||
this,
|
this,
|
||||||
@@ -1159,7 +1159,7 @@ bool Bot::BotCastHeal(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
|
|||||||
} else if (IsRaidGrouped()) {
|
} else if (IsRaidGrouped()) {
|
||||||
uint32 r_group = raid->GetGroup(GetName());
|
uint32 r_group = raid->GetGroup(GetName());
|
||||||
const auto msg = fmt::format("Casting {}.", spells[botSpell.SpellId].name);
|
const auto msg = fmt::format("Casting {}.", spells[botSpell.SpellId].name);
|
||||||
raid->RaidGroupSay(msg.c_str(), GetCleanName(), 0, 100);
|
raid->RaidGroupSay(msg.c_str(), GetCleanName(), Language::CommonTongue, Language::MaxValue);
|
||||||
std::vector<RaidMember> raid_group_members = raid->GetRaidGroupMembers(r_group);
|
std::vector<RaidMember> raid_group_members = raid->GetRaidGroupMembers(r_group);
|
||||||
for (const auto& rgm : raid_group_members) {
|
for (const auto& rgm : raid_group_members) {
|
||||||
if (rgm.member && !rgm.member->qglobal) {
|
if (rgm.member && !rgm.member->qglobal) {
|
||||||
|
|||||||
@@ -349,10 +349,10 @@ void CheatManager::ProcessMovementHistory(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
void CheatManager::ProcessSpawnApperance(uint16 spawn_id, uint16 type, uint32 parameter)
|
void CheatManager::ProcessSpawnApperance(uint16 spawn_id, uint16 type, uint32 parameter)
|
||||||
{
|
{
|
||||||
if (type == AT_Anim && parameter == ANIM_SIT) {
|
if (type == AppearanceType::Animation && parameter == Animation::Sitting) {
|
||||||
m_time_since_last_memorization = Timer::GetCurrentTime();
|
m_time_since_last_memorization = Timer::GetCurrentTime();
|
||||||
}
|
}
|
||||||
else if (spawn_id == 0 && type == AT_AntiCheat) {
|
else if (spawn_id == 0 && type == AppearanceType::AntiCheat) {
|
||||||
m_time_since_last_action = parameter;
|
m_time_since_last_action = parameter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+245
-174
@@ -58,6 +58,7 @@ extern volatile bool RunLoops;
|
|||||||
#include "mob_movement_manager.h"
|
#include "mob_movement_manager.h"
|
||||||
#include "cheat_manager.h"
|
#include "cheat_manager.h"
|
||||||
|
|
||||||
|
#include "../common/repositories/character_alternate_abilities_repository.h"
|
||||||
#include "../common/repositories/account_flags_repository.h"
|
#include "../common/repositories/account_flags_repository.h"
|
||||||
#include "../common/repositories/bug_reports_repository.h"
|
#include "../common/repositories/bug_reports_repository.h"
|
||||||
#include "../common/repositories/char_recipe_list_repository.h"
|
#include "../common/repositories/char_recipe_list_repository.h"
|
||||||
@@ -86,9 +87,9 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
|||||||
"", // in_lastname
|
"", // in_lastname
|
||||||
0, // in_cur_hp
|
0, // in_cur_hp
|
||||||
0, // in_max_hp
|
0, // in_max_hp
|
||||||
0, // in_gender
|
Gender::Male, // in_gender
|
||||||
0, // in_race
|
Race::Doug, // in_race
|
||||||
0, // in_class
|
Class::None, // in_class
|
||||||
BT_Humanoid, // in_bodytype
|
BT_Humanoid, // in_bodytype
|
||||||
0, // in_deity
|
0, // in_deity
|
||||||
0, // in_level
|
0, // in_level
|
||||||
@@ -483,7 +484,7 @@ void Client::SendZoneInPackets()
|
|||||||
// Spawn Appearance Packet
|
// Spawn Appearance Packet
|
||||||
auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
||||||
SpawnAppearance_Struct* sa = (SpawnAppearance_Struct*)outapp->pBuffer;
|
SpawnAppearance_Struct* sa = (SpawnAppearance_Struct*)outapp->pBuffer;
|
||||||
sa->type = AT_SpawnID; // Is 0x10 used to set the player id?
|
sa->type = AppearanceType::SpawnID; // Is 0x10 used to set the player id?
|
||||||
sa->parameter = GetID(); // Four bytes for this parameter...
|
sa->parameter = GetID(); // Four bytes for this parameter...
|
||||||
outapp->priority = 6;
|
outapp->priority = 6;
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
@@ -498,7 +499,7 @@ void Client::SendZoneInPackets()
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
SetSpawned();
|
SetSpawned();
|
||||||
if (GetPVP(false)) //force a PVP update until we fix the spawn struct
|
if (GetPVP(false)) //force a PVP update until we fix the spawn struct
|
||||||
SendAppearancePacket(AT_PVP, GetPVP(false), true, false);
|
SendAppearancePacket(AppearanceType::PVP, GetPVP(false), true, false);
|
||||||
|
|
||||||
//Send AA Exp packet:
|
//Send AA Exp packet:
|
||||||
if (GetLevel() >= 51)
|
if (GetLevel() >= 51)
|
||||||
@@ -586,45 +587,52 @@ void Client::ReportConnectingState() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::SaveAA() {
|
bool Client::SaveAA()
|
||||||
std::string iquery;
|
{
|
||||||
int spentpoints = 0;
|
std::vector<CharacterAlternateAbilitiesRepository::CharacterAlternateAbilities> v;
|
||||||
int i = 0;
|
|
||||||
for(auto &rank : aa_ranks) {
|
uint32 aa_points_spent = 0;
|
||||||
AA::Ability *ability = zone->GetAlternateAdvancementAbility(rank.first);
|
|
||||||
if(!ability)
|
auto e = CharacterAlternateAbilitiesRepository::NewEntity();
|
||||||
|
|
||||||
|
for (auto &rank : aa_ranks) {
|
||||||
|
auto a = zone->GetAlternateAdvancementAbility(rank.first);
|
||||||
|
if (!a) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(rank.second.first > 0) {
|
if (rank.second.first > 0) {
|
||||||
AA::Rank *r = ability->GetRankByPointsSpent(rank.second.first);
|
auto r = a->GetRankByPointsSpent(rank.second.first);
|
||||||
|
if (!r) {
|
||||||
if(!r)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
spentpoints += r->total_cost;
|
|
||||||
|
|
||||||
if(i == 0) {
|
|
||||||
iquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, aa_id, aa_value, charges)"
|
|
||||||
" VALUES (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second);
|
|
||||||
} else {
|
|
||||||
iquery += StringFormat(", (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second);
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
|
aa_points_spent += r->total_cost;
|
||||||
|
|
||||||
|
e.id = character_id;
|
||||||
|
e.aa_id = a->first_rank_id;
|
||||||
|
e.aa_value = rank.second.first;
|
||||||
|
e.charges = rank.second.second;
|
||||||
|
|
||||||
|
v.emplace_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
|
m_pp.aapoints_spent = aa_points_spent + m_epp.expended_aa;
|
||||||
|
|
||||||
if(iquery.length() > 0) {
|
return CharacterAlternateAbilitiesRepository::ReplaceMany(database, v);
|
||||||
database.QueryDatabase(iquery);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::RemoveExpendedAA(int aa_id)
|
void Client::RemoveExpendedAA(int aa_id)
|
||||||
{
|
{
|
||||||
database.QueryDatabase(StringFormat("DELETE from `character_alternate_abilities` WHERE `id` = %d and `aa_id` = %d", character_id, aa_id));
|
CharacterAlternateAbilitiesRepository::DeleteWhere(
|
||||||
|
database,
|
||||||
|
fmt::format(
|
||||||
|
"`id` = {} AND `aa_id` = {}",
|
||||||
|
CharacterID(),
|
||||||
|
aa_id
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::Save(uint8 iCommitNow) {
|
bool Client::Save(uint8 iCommitNow) {
|
||||||
@@ -915,15 +923,19 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
|||||||
// Garble the message based on drunkness
|
// Garble the message based on drunkness
|
||||||
if (GetIntoxication() > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) {
|
if (GetIntoxication() > 0 && !(RuleB(Chat, ServerWideOOC) && chan_num == ChatChannel_OOC) && !GetGM()) {
|
||||||
GarbleMessage(message, (int)(GetIntoxication() / 3));
|
GarbleMessage(message, (int)(GetIntoxication() / 3));
|
||||||
language = 0; // No need for language when drunk
|
language = Language::CommonTongue; // No need for language when drunk
|
||||||
lang_skill = 100;
|
lang_skill = Language::MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// some channels don't use languages
|
// some channels don't use languages
|
||||||
if (chan_num == ChatChannel_OOC || chan_num == ChatChannel_GMSAY || chan_num == ChatChannel_Broadcast || chan_num == ChatChannel_Petition)
|
if (
|
||||||
{
|
chan_num == ChatChannel_OOC ||
|
||||||
language = 0;
|
chan_num == ChatChannel_GMSAY ||
|
||||||
lang_skill = 100;
|
chan_num == ChatChannel_Broadcast ||
|
||||||
|
chan_num == ChatChannel_Petition
|
||||||
|
) {
|
||||||
|
language = Language::CommonTongue;
|
||||||
|
lang_skill = Language::MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Censor the message
|
// Censor the message
|
||||||
@@ -1274,69 +1286,88 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...) {
|
void Client::ChannelMessageSend(
|
||||||
if ((chan_num==11 && !(GetGM())) || (chan_num==10 && Admin() < AccountStatus::QuestTroupe)) // dont need to send /pr & /petition to everybody
|
const char *from,
|
||||||
|
const char *to,
|
||||||
|
uint8 channel_id,
|
||||||
|
uint8 language_id,
|
||||||
|
uint8 language_skill,
|
||||||
|
const char *message,
|
||||||
|
...
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(channel_id == ChatChannel_Petition && Admin() < AccountStatus::QuestTroupe) ||
|
||||||
|
(channel_id == ChatChannel_GMSAY && !GetGM())
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
char message_sender[64];
|
char message_sender[64];
|
||||||
|
|
||||||
va_start(argptr, message);
|
va_start(argptr, message);
|
||||||
vsnprintf(buffer, 4096, message, argptr);
|
vsnprintf(buffer, 4096, message, argptr);
|
||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
|
|
||||||
EQApplicationPacket app(OP_ChannelMessage, sizeof(ChannelMessage_Struct)+strlen(buffer)+1);
|
EQApplicationPacket app(OP_ChannelMessage, sizeof(ChannelMessage_Struct) + strlen(buffer) + 1);
|
||||||
ChannelMessage_Struct* cm = (ChannelMessage_Struct*)app.pBuffer;
|
|
||||||
|
|
||||||
if (from == 0)
|
auto* cm = (ChannelMessage_Struct *) app.pBuffer;
|
||||||
|
|
||||||
|
if (from == 0) {
|
||||||
strcpy(cm->sender, "ZServer");
|
strcpy(cm->sender, "ZServer");
|
||||||
else if (from[0] == 0)
|
} else if (from[0] == 0) {
|
||||||
strcpy(cm->sender, "ZServer");
|
strcpy(cm->sender, "ZServer");
|
||||||
else {
|
} else {
|
||||||
CleanMobName(from, message_sender);
|
CleanMobName(from, message_sender);
|
||||||
strcpy(cm->sender, message_sender);
|
strcpy(cm->sender, message_sender);
|
||||||
}
|
}
|
||||||
if (to != 0)
|
|
||||||
|
if (to != 0) {
|
||||||
strcpy((char *) cm->targetname, to);
|
strcpy((char *) cm->targetname, to);
|
||||||
else if (chan_num == ChatChannel_Tell)
|
} else if (channel_id == ChatChannel_Tell) {
|
||||||
strcpy(cm->targetname, m_pp.name);
|
strcpy(cm->targetname, m_pp.name);
|
||||||
else
|
} else {
|
||||||
cm->targetname[0] = 0;
|
cm->targetname[0] = 0;
|
||||||
|
|
||||||
uint8 ListenerSkill;
|
|
||||||
|
|
||||||
if (language < MAX_PP_LANGUAGE) {
|
|
||||||
ListenerSkill = m_pp.languages[language];
|
|
||||||
if (ListenerSkill < 24) {
|
|
||||||
cm->language = (MAX_PP_LANGUAGE - 1); // in an unknown tongue
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cm->language = language;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
ListenerSkill = m_pp.languages[0];
|
uint8 listener_skill;
|
||||||
cm->language = 0;
|
|
||||||
|
const bool is_valid_language = EQ::ValueWithin(language_id, Language::CommonTongue, Language::Unknown27);
|
||||||
|
|
||||||
|
if (is_valid_language) {
|
||||||
|
listener_skill = m_pp.languages[language_id];
|
||||||
|
cm->language = listener_skill < 24 ? Language::Unknown27 : language_id;
|
||||||
|
} else {
|
||||||
|
listener_skill = m_pp.languages[Language::CommonTongue];
|
||||||
|
cm->language = Language::CommonTongue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set effective language skill = lower of sender and receiver skills
|
// set effective language skill = lower of sender and receiver skills
|
||||||
int32 EffSkill = (lang_skill < ListenerSkill ? lang_skill : ListenerSkill);
|
uint8 effective_skill = (language_skill < listener_skill ? language_skill : listener_skill);
|
||||||
if (EffSkill > 100) // maximum language skill is 100
|
if (effective_skill > Language::MaxValue) {
|
||||||
EffSkill = 100;
|
effective_skill = Language::MaxValue;
|
||||||
cm->skill_in_language = EffSkill;
|
}
|
||||||
|
|
||||||
cm->chan_num = chan_num;
|
cm->skill_in_language = effective_skill;
|
||||||
|
|
||||||
|
cm->chan_num = channel_id;
|
||||||
strcpy(&cm->message[0], buffer);
|
strcpy(&cm->message[0], buffer);
|
||||||
|
|
||||||
QueuePacket(&app);
|
QueuePacket(&app);
|
||||||
|
|
||||||
bool senderCanTrainSelf = RuleB(Client, SelfLanguageLearning);
|
const bool can_train_self = RuleB(Client, SelfLanguageLearning);
|
||||||
bool weAreNotSender = strcmp(GetCleanName(), cm->sender);
|
const bool is_not_sender = strcmp(GetCleanName(), cm->sender);
|
||||||
|
|
||||||
if (senderCanTrainSelf || weAreNotSender) {
|
if (can_train_self || is_not_sender) {
|
||||||
if ((chan_num == ChatChannel_Group) && (ListenerSkill < 100)) { // group message in unmastered language, check for skill up
|
if (
|
||||||
if (language < MAX_PP_LANGUAGE && m_pp.languages[language] <= lang_skill)
|
channel_id == ChatChannel_Group &&
|
||||||
CheckLanguageSkillIncrease(language, lang_skill);
|
listener_skill < Language::MaxValue
|
||||||
|
) { // group message in non-mastered language, check for skill up
|
||||||
|
if (is_valid_language && m_pp.languages[language_id] <= language_skill) {
|
||||||
|
CheckLanguageSkillIncrease(language_id, language_skill);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1637,26 +1668,30 @@ void Client::SetSkill(EQ::skills::SkillType skillid, uint16 value) {
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::IncreaseLanguageSkill(int skill_id, int value) {
|
void Client::IncreaseLanguageSkill(uint8 language_id, uint8 increase)
|
||||||
|
{
|
||||||
|
if (!EQ::ValueWithin(language_id, Language::CommonTongue, Language::Unknown27)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (skill_id >= MAX_PP_LANGUAGE)
|
m_pp.languages[language_id] += increase;
|
||||||
return; //Invalid lang id
|
|
||||||
|
|
||||||
m_pp.languages[skill_id] += value;
|
if (m_pp.languages[language_id] > Language::MaxValue) {
|
||||||
|
m_pp.languages[language_id] = Language::MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_pp.languages[skill_id] > 100) //Lang skill above max
|
database.SaveCharacterLanguage(CharacterID(), language_id, m_pp.languages[language_id]);
|
||||||
m_pp.languages[skill_id] = 100;
|
|
||||||
|
|
||||||
database.SaveCharacterLanguage(CharacterID(), skill_id, m_pp.languages[skill_id]);
|
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
|
auto outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
|
||||||
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
|
auto* s = (SkillUpdate_Struct*) outapp->pBuffer;
|
||||||
skill->skillId = 100 + skill_id;
|
|
||||||
skill->value = m_pp.languages[skill_id];
|
s->skillId = 100 + language_id;
|
||||||
|
s->value = m_pp.languages[language_id];
|
||||||
|
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
MessageString( Chat::Skills, LANG_SKILL_IMPROVED ); //Notify client
|
MessageString(Chat::Skills, LANG_SKILL_IMPROVED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::AddSkill(EQ::skills::SkillType skillid, uint16 value) {
|
void Client::AddSkill(EQ::skills::SkillType skillid, uint16 value) {
|
||||||
@@ -2221,7 +2256,7 @@ void Client::SetGM(bool toggle) {
|
|||||||
m_pp.gm ? "now" : "no longer"
|
m_pp.gm ? "now" : "no longer"
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
SendAppearancePacket(AT_GM, m_pp.gm);
|
SendAppearancePacket(AppearanceType::GM, m_pp.gm);
|
||||||
Save();
|
Save();
|
||||||
UpdateWho();
|
UpdateWho();
|
||||||
}
|
}
|
||||||
@@ -2272,9 +2307,9 @@ void Client::ReadBook(BookRequest_Struct *book) {
|
|||||||
|
|
||||||
memcpy(out->booktext, booktxt2.c_str(), length);
|
memcpy(out->booktext, booktxt2.c_str(), length);
|
||||||
|
|
||||||
if (book_language > 0 && book_language < MAX_PP_LANGUAGE) {
|
if (EQ::ValueWithin(book_language, Language::CommonTongue, Language::Unknown27)) {
|
||||||
if (m_pp.languages[book_language] < 100) {
|
if (m_pp.languages[book_language] < Language::MaxValue) {
|
||||||
GarbleMessage(out->booktext, (100 - m_pp.languages[book_language]));
|
GarbleMessage(out->booktext, (Language::MaxValue - m_pp.languages[book_language]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2673,38 +2708,43 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill) {
|
void Client::CheckLanguageSkillIncrease(uint8 language_id, uint8 teacher_skill) {
|
||||||
if (IsDead() || IsUnconscious())
|
if (IsDead() || IsUnconscious()) {
|
||||||
return;
|
return;
|
||||||
if (IsAIControlled())
|
}
|
||||||
|
|
||||||
|
if (IsAIControlled()) {
|
||||||
return;
|
return;
|
||||||
if (langid >= MAX_PP_LANGUAGE)
|
}
|
||||||
return; // do nothing if langid is an invalid language
|
|
||||||
|
|
||||||
int LangSkill = m_pp.languages[langid]; // get current language skill
|
if (!EQ::ValueWithin(language_id, Language::CommonTongue, Language::Unknown27)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (LangSkill < 100) { // if the language isn't already maxed
|
const uint8 language_skill = m_pp.languages[language_id]; // get current language skill
|
||||||
int32 Chance = 5 + ((TeacherSkill - LangSkill)/10); // greater chance to learn if teacher's skill is much higher than yours
|
|
||||||
Chance = (Chance * RuleI(Character, SkillUpModifier)/100);
|
|
||||||
|
|
||||||
if(zone->random.Real(0,100) < Chance) { // if they make the roll
|
if (language_skill < Language::MaxValue) { // if the language isn't already maxed
|
||||||
IncreaseLanguageSkill(langid); // increase the language skill by 1
|
int chance = 5 + ((teacher_skill - language_skill) / 10); // greater chance to learn if teacher's skill is much higher than yours
|
||||||
|
chance = (chance * RuleI(Character, SkillUpModifier) / 100);
|
||||||
|
|
||||||
|
if (zone->random.Real(0, 100) < chance) { // if they make the roll
|
||||||
|
IncreaseLanguageSkill(language_id);
|
||||||
|
|
||||||
if (parse->PlayerHasQuestSub(EVENT_LANGUAGE_SKILL_UP)) {
|
if (parse->PlayerHasQuestSub(EVENT_LANGUAGE_SKILL_UP)) {
|
||||||
const auto& export_string = fmt::format(
|
const auto &export_string = fmt::format(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
langid,
|
language_id,
|
||||||
LangSkill + 1,
|
language_skill + 1,
|
||||||
100
|
Language::MaxValue
|
||||||
);
|
);
|
||||||
|
|
||||||
parse->EventPlayer(EVENT_LANGUAGE_SKILL_UP, this, export_string, 0);
|
parse->EventPlayer(EVENT_LANGUAGE_SKILL_UP, this, export_string, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogSkills("Language [{}] at value [{}] successfully gain with [{}] % chance", langid, LangSkill, Chance);
|
LogSkills("Language [{}] at value [{}] successfully gain with [{}] % chance", language_id, language_skill, chance);
|
||||||
|
} else {
|
||||||
|
LogSkills("Language [{}] at value [{}] failed to gain with [{}] % chance", language_id, language_skill, chance);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
LogSkills("Language [{}] at value [{}] failed to gain with [{}] % chance", langid, LangSkill, Chance);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2839,7 +2879,7 @@ void Client::SetPVP(bool toggle, bool message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SendAppearancePacket(AT_PVP, GetPVP());
|
SendAppearancePacket(AppearanceType::PVP, GetPVP());
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3566,25 +3606,30 @@ void Client::SetHideMe(bool flag)
|
|||||||
UpdateWho();
|
UpdateWho();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetLanguageSkill(int langid, int value)
|
void Client::SetLanguageSkill(uint8 language_id, uint8 language_skill)
|
||||||
{
|
{
|
||||||
if (langid >= MAX_PP_LANGUAGE)
|
if (!EQ::ValueWithin(language_id, Language::CommonTongue, Language::Unknown27)) {
|
||||||
return; //Invalid Language
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (value > 100)
|
if (language_skill > Language::MaxValue) {
|
||||||
value = 100; //Max lang value
|
language_skill = Language::MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
m_pp.languages[langid] = value;
|
m_pp.languages[language_id] = language_skill;
|
||||||
database.SaveCharacterLanguage(CharacterID(), langid, value);
|
|
||||||
|
database.SaveCharacterLanguage(CharacterID(), language_id, language_skill);
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
|
auto outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
|
||||||
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
|
auto* s = (SkillUpdate_Struct*) outapp->pBuffer;
|
||||||
skill->skillId = 100 + langid;
|
|
||||||
skill->value = m_pp.languages[langid];
|
s->skillId = 100 + language_id;
|
||||||
|
s->value = m_pp.languages[language_id];
|
||||||
|
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
MessageString( Chat::Skills, LANG_SKILL_IMPROVED ); //Notify the client
|
MessageString(Chat::Skills, LANG_SKILL_IMPROVED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::LinkDead()
|
void Client::LinkDead()
|
||||||
@@ -3607,7 +3652,7 @@ void Client::LinkDead()
|
|||||||
|
|
||||||
// save_timer.Start(2500);
|
// save_timer.Start(2500);
|
||||||
linkdead_timer.Start(RuleI(Zone,ClientLinkdeadMS));
|
linkdead_timer.Start(RuleI(Zone,ClientLinkdeadMS));
|
||||||
SendAppearancePacket(AT_Linkdead, 1);
|
SendAppearancePacket(AppearanceType::Linkdead, 1);
|
||||||
client_state = CLIENT_LINKDEAD;
|
client_state = CLIENT_LINKDEAD;
|
||||||
AI_Start(CLIENT_LD_TIMEOUT);
|
AI_Start(CLIENT_LD_TIMEOUT);
|
||||||
}
|
}
|
||||||
@@ -3750,7 +3795,7 @@ void Client::EnteringMessages(Client* client)
|
|||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
client->SendAppearancePacket(AT_Anim, ANIM_FREEZE);
|
client->SendAppearancePacket(AppearanceType::Animation, Animation::Freeze);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4599,7 +4644,7 @@ void Client::ClearGroupAAs() {
|
|||||||
m_pp.raid_leadership_exp = 0;
|
m_pp.raid_leadership_exp = 0;
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
database.SaveCharacterLeadershipAA(CharacterID(), &m_pp);
|
database.SaveCharacterLeadershipAbilities(CharacterID(), &m_pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::UpdateGroupAAs(int32 points, uint32 type) {
|
void Client::UpdateGroupAAs(int32 points, uint32 type) {
|
||||||
@@ -6519,27 +6564,33 @@ void Client::RemoveFromInstance(uint16 instance_id)
|
|||||||
|
|
||||||
void Client::SendAltCurrencies() {
|
void Client::SendAltCurrencies() {
|
||||||
if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
|
if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
|
||||||
uint32 count = zone->AlternateCurrencies.size();
|
const uint32 currency_count = zone->AlternateCurrencies.size();
|
||||||
if(count == 0) {
|
if (!currency_count) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto outapp =
|
auto outapp = new EQApplicationPacket(
|
||||||
new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyPopulate_Struct) +
|
OP_AltCurrency,
|
||||||
sizeof(AltCurrencyPopulateEntry_Struct) * count);
|
sizeof(AltCurrencyPopulate_Struct) +
|
||||||
AltCurrencyPopulate_Struct *altc = (AltCurrencyPopulate_Struct*)outapp->pBuffer;
|
sizeof(AltCurrencyPopulateEntry_Struct) * currency_count
|
||||||
altc->opcode = ALT_CURRENCY_OP_POPULATE;
|
);
|
||||||
altc->count = count;
|
|
||||||
|
auto a = (AltCurrencyPopulate_Struct*) outapp->pBuffer;
|
||||||
|
|
||||||
|
a->opcode = AlternateCurrencyMode::Populate;
|
||||||
|
a->count = currency_count;
|
||||||
|
|
||||||
uint32 currency_id = 0;
|
uint32 currency_id = 0;
|
||||||
for (const auto& alternate_currency : zone->AlternateCurrencies) {
|
for (const auto& c : zone->AlternateCurrencies) {
|
||||||
const EQ::ItemData* item = database.GetItem(alternate_currency.item_id);
|
const auto* item = database.GetItem(c.item_id);
|
||||||
altc->entries[currency_id].currency_number = alternate_currency.id;
|
|
||||||
altc->entries[currency_id].unknown00 = 1;
|
a->entries[currency_id].currency_number = c.id;
|
||||||
altc->entries[currency_id].currency_number2 = alternate_currency.id;
|
a->entries[currency_id].unknown00 = 1;
|
||||||
altc->entries[currency_id].item_id = alternate_currency.item_id;
|
a->entries[currency_id].currency_number2 = c.id;
|
||||||
altc->entries[currency_id].item_icon = item ? item->Icon : 1000;
|
a->entries[currency_id].item_id = c.item_id;
|
||||||
altc->entries[currency_id].stack_size = item ? item->StackSize : 1000;
|
a->entries[currency_id].item_icon = item ? item->Icon : 1000;
|
||||||
|
a->entries[currency_id].stack_size = item ? item->StackSize : 1000;
|
||||||
|
|
||||||
currency_id++;
|
currency_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6636,11 +6687,8 @@ void Client::SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null)
|
|||||||
uint32 Client::GetAlternateCurrencyValue(uint32 currency_id) const
|
uint32 Client::GetAlternateCurrencyValue(uint32 currency_id) const
|
||||||
{
|
{
|
||||||
auto iter = alternate_currency.find(currency_id);
|
auto iter = alternate_currency.find(currency_id);
|
||||||
if(iter == alternate_currency.end()) {
|
|
||||||
return 0;
|
return iter == alternate_currency.end() ? 0 : (*iter).second;
|
||||||
} else {
|
|
||||||
return (*iter).second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ProcessAlternateCurrencyQueue() {
|
void Client::ProcessAlternateCurrencyQueue() {
|
||||||
@@ -8565,37 +8613,37 @@ bool Client::CanMedOnHorse()
|
|||||||
void Client::EnableAreaHPRegen(int value)
|
void Client::EnableAreaHPRegen(int value)
|
||||||
{
|
{
|
||||||
AreaHPRegen = value * 0.001f;
|
AreaHPRegen = value * 0.001f;
|
||||||
SendAppearancePacket(AT_AreaHPRegen, value, false);
|
SendAppearancePacket(AppearanceType::AreaHealthRegen, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::DisableAreaHPRegen()
|
void Client::DisableAreaHPRegen()
|
||||||
{
|
{
|
||||||
AreaHPRegen = 1.0f;
|
AreaHPRegen = 1.0f;
|
||||||
SendAppearancePacket(AT_AreaHPRegen, 1000, false);
|
SendAppearancePacket(AppearanceType::AreaHealthRegen, 1000, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::EnableAreaManaRegen(int value)
|
void Client::EnableAreaManaRegen(int value)
|
||||||
{
|
{
|
||||||
AreaManaRegen = value * 0.001f;
|
AreaManaRegen = value * 0.001f;
|
||||||
SendAppearancePacket(AT_AreaManaRegen, value, false);
|
SendAppearancePacket(AppearanceType::AreaManaRegen, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::DisableAreaManaRegen()
|
void Client::DisableAreaManaRegen()
|
||||||
{
|
{
|
||||||
AreaManaRegen = 1.0f;
|
AreaManaRegen = 1.0f;
|
||||||
SendAppearancePacket(AT_AreaManaRegen, 1000, false);
|
SendAppearancePacket(AppearanceType::AreaManaRegen, 1000, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::EnableAreaEndRegen(int value)
|
void Client::EnableAreaEndRegen(int value)
|
||||||
{
|
{
|
||||||
AreaEndRegen = value * 0.001f;
|
AreaEndRegen = value * 0.001f;
|
||||||
SendAppearancePacket(AT_AreaEndRegen, value, false);
|
SendAppearancePacket(AppearanceType::AreaEnduranceRegen, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::DisableAreaEndRegen()
|
void Client::DisableAreaEndRegen()
|
||||||
{
|
{
|
||||||
AreaEndRegen = 1.0f;
|
AreaEndRegen = 1.0f;
|
||||||
SendAppearancePacket(AT_AreaEndRegen, 1000, false);
|
SendAppearancePacket(AppearanceType::AreaEnduranceRegen, 1000, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::EnableAreaRegens(int value)
|
void Client::EnableAreaRegens(int value)
|
||||||
@@ -10011,7 +10059,7 @@ void Client::SetAnon(uint8 anon_flag) {
|
|||||||
auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
||||||
SpawnAppearance_Struct* spawn_appearance = (SpawnAppearance_Struct*)outapp->pBuffer;
|
SpawnAppearance_Struct* spawn_appearance = (SpawnAppearance_Struct*)outapp->pBuffer;
|
||||||
spawn_appearance->spawn_id = GetID();
|
spawn_appearance->spawn_id = GetID();
|
||||||
spawn_appearance->type = AT_Anon;
|
spawn_appearance->type = AppearanceType::Anonymous;
|
||||||
spawn_appearance->parameter = anon_flag;
|
spawn_appearance->parameter = anon_flag;
|
||||||
entity_list.QueueClients(this, outapp);
|
entity_list.QueueClients(this, outapp);
|
||||||
Save();
|
Save();
|
||||||
@@ -10024,7 +10072,7 @@ void Client::SetAFK(uint8 afk_flag) {
|
|||||||
auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
|
||||||
SpawnAppearance_Struct* spawn_appearance = (SpawnAppearance_Struct*)outapp->pBuffer;
|
SpawnAppearance_Struct* spawn_appearance = (SpawnAppearance_Struct*)outapp->pBuffer;
|
||||||
spawn_appearance->spawn_id = GetID();
|
spawn_appearance->spawn_id = GetID();
|
||||||
spawn_appearance->type = AT_AFK;
|
spawn_appearance->type = AppearanceType::AFK;
|
||||||
spawn_appearance->parameter = afk_flag;
|
spawn_appearance->parameter = afk_flag;
|
||||||
entity_list.QueueClients(this, outapp);
|
entity_list.QueueClients(this, outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
@@ -10269,7 +10317,7 @@ void Client::RemoveItem(uint32 item_id, uint32 quantity)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetGMStatus(int16 new_status) {
|
void Client::SetGMStatus(int new_status) {
|
||||||
if (Admin() != new_status) {
|
if (Admin() != new_status) {
|
||||||
database.UpdateGMStatus(AccountID(), new_status);
|
database.UpdateGMStatus(AccountID(), new_status);
|
||||||
UpdateAdmin();
|
UpdateAdmin();
|
||||||
@@ -10546,9 +10594,9 @@ void Client::ReadBookByName(std::string book_name, uint8 book_type)
|
|||||||
|
|
||||||
memcpy(out->booktext, book_text.c_str(), length);
|
memcpy(out->booktext, book_text.c_str(), length);
|
||||||
|
|
||||||
if (book_language > 0 && book_language < MAX_PP_LANGUAGE) {
|
if (EQ::ValueWithin(book_language, Language::CommonTongue, Language::Unknown27)) {
|
||||||
if (m_pp.languages[book_language] < 100) {
|
if (m_pp.languages[book_language] < Language::MaxValue) {
|
||||||
GarbleMessage(out->booktext, (100 - m_pp.languages[book_language]));
|
GarbleMessage(out->booktext, (Language::MaxValue - m_pp.languages[book_language]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10697,22 +10745,22 @@ void Client::SaveSpells()
|
|||||||
|
|
||||||
void Client::SaveDisciplines()
|
void Client::SaveDisciplines()
|
||||||
{
|
{
|
||||||
std::vector<CharacterDisciplinesRepository::CharacterDisciplines> character_discs = {};
|
std::vector<CharacterDisciplinesRepository::CharacterDisciplines> v;
|
||||||
|
|
||||||
for (int index = 0; index < MAX_PP_DISCIPLINES; index++) {
|
for (int slot_id = 0; slot_id < MAX_PP_DISCIPLINES; slot_id++) {
|
||||||
if (IsValidSpell(m_pp.disciplines.values[index])) {
|
if (IsValidSpell(m_pp.disciplines.values[slot_id])) {
|
||||||
auto discipline = CharacterDisciplinesRepository::NewEntity();
|
auto e = CharacterDisciplinesRepository::NewEntity();
|
||||||
discipline.id = CharacterID();
|
|
||||||
discipline.slot_id = index;
|
e.id = CharacterID();
|
||||||
discipline.disc_id = m_pp.disciplines.values[index];
|
e.slot_id = slot_id;
|
||||||
character_discs.emplace_back(discipline);
|
e.disc_id = m_pp.disciplines.values[slot_id];
|
||||||
|
|
||||||
|
v.emplace_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterDisciplinesRepository::DeleteWhere(database, fmt::format("id = {}", CharacterID()));
|
if (!v.empty()) {
|
||||||
|
CharacterDisciplinesRepository::ReplaceMany(database, v);
|
||||||
if (!character_discs.empty()) {
|
|
||||||
CharacterDisciplinesRepository::InsertMany(database, character_discs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10883,8 +10931,8 @@ void Client::ReconnectUCS()
|
|||||||
|
|
||||||
buffer = StringFormat(
|
buffer = StringFormat(
|
||||||
"%s,%i,%s.%s,%c%s",
|
"%s,%i,%s.%s,%c%s",
|
||||||
Config->ChatHost.c_str(),
|
Config->GetUCSHost().c_str(),
|
||||||
Config->ChatPort,
|
Config->GetUCSPort(),
|
||||||
Config->ShortName.c_str(),
|
Config->ShortName.c_str(),
|
||||||
GetName(),
|
GetName(),
|
||||||
connection_type,
|
connection_type,
|
||||||
@@ -10910,8 +10958,8 @@ void Client::ReconnectUCS()
|
|||||||
|
|
||||||
buffer = StringFormat(
|
buffer = StringFormat(
|
||||||
"%s,%i,%s.%s,%c%s",
|
"%s,%i,%s.%s,%c%s",
|
||||||
Config->MailHost.c_str(),
|
Config->GetUCSHost().c_str(),
|
||||||
Config->MailPort,
|
Config->GetUCSPort(),
|
||||||
Config->ShortName.c_str(),
|
Config->ShortName.c_str(),
|
||||||
GetName(),
|
GetName(),
|
||||||
connection_type,
|
connection_type,
|
||||||
@@ -11224,7 +11272,7 @@ void Client::Undye()
|
|||||||
SendWearChange(slot);
|
SendWearChange(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
database.DeleteCharacterDye(CharacterID());
|
database.DeleteCharacterMaterialColor(CharacterID());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SetTrackingID(uint32 entity_id)
|
void Client::SetTrackingID(uint32 entity_id)
|
||||||
@@ -11944,3 +11992,26 @@ std::string GetZoneModeString(ZoneMode mode)
|
|||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::ClearXTargets()
|
||||||
|
{
|
||||||
|
if (!XTargettingAvailable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < GetMaxXTargets(); ++i) {
|
||||||
|
if (XTargets[i].ID) {
|
||||||
|
Mob* m = entity_list.GetMob(XTargets[i].ID);
|
||||||
|
|
||||||
|
if (m) {
|
||||||
|
RemoveXTarget(m, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
XTargets[i].ID = 0;
|
||||||
|
XTargets[i].Name[0] = 0;
|
||||||
|
XTargets[i].dirty = false;
|
||||||
|
|
||||||
|
SendXTargetPacket(i, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+9
-7
@@ -335,7 +335,7 @@ public:
|
|||||||
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
|
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
|
||||||
void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
|
void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
|
||||||
void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname = nullptr, bool is_silent = false);
|
void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname = nullptr, bool is_silent = false);
|
||||||
void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
|
void ChannelMessageSend(const char* from, const char* to, uint8 channel_id, uint8 language_id, uint8 language_skill, const char* message, ...);
|
||||||
void Message(uint32 type, const char* message, ...);
|
void Message(uint32 type, const char* message, ...);
|
||||||
void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...);
|
void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...);
|
||||||
void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber);
|
void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber);
|
||||||
@@ -382,7 +382,7 @@ public:
|
|||||||
inline ExtendedProfile_Struct& GetEPP() { return m_epp; }
|
inline ExtendedProfile_Struct& GetEPP() { return m_epp; }
|
||||||
inline EQ::InventoryProfile& GetInv() { return m_inv; }
|
inline EQ::InventoryProfile& GetInv() { return m_inv; }
|
||||||
inline const EQ::InventoryProfile& GetInv() const { return m_inv; }
|
inline const EQ::InventoryProfile& GetInv() const { return m_inv; }
|
||||||
inline PetInfo* GetPetInfo(uint16 pet) { return (pet==1)?&m_suspendedminion:&m_petinfo; }
|
inline PetInfo* GetPetInfo(int pet_info_type) { return pet_info_type == PetInfoType::Suspended ? &m_suspendedminion : &m_petinfo; }
|
||||||
inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; }
|
inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; }
|
||||||
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
|
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
|
||||||
void ReloadExpansionProfileSetting();
|
void ReloadExpansionProfileSetting();
|
||||||
@@ -452,7 +452,7 @@ public:
|
|||||||
void SendSingleTraderItem(uint32 char_id, int uniqueid);
|
void SendSingleTraderItem(uint32 char_id, int uniqueid);
|
||||||
void BulkSendMerchantInventory(int merchant_id, int npcid);
|
void BulkSendMerchantInventory(int merchant_id, int npcid);
|
||||||
|
|
||||||
inline uint8 GetLanguageSkill(uint16 n) const { return m_pp.languages[n]; }
|
inline uint8 GetLanguageSkill(uint8 language_id) const { return m_pp.languages[language_id]; }
|
||||||
|
|
||||||
void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQ::ItemData* item = nullptr);
|
void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQ::ItemData* item = nullptr);
|
||||||
|
|
||||||
@@ -767,7 +767,7 @@ public:
|
|||||||
void SetSkillPoints(int inp) { m_pp.points = inp;}
|
void SetSkillPoints(int inp) { m_pp.points = inp;}
|
||||||
|
|
||||||
void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= EQ::skills::HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } }
|
void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= EQ::skills::HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } }
|
||||||
void IncreaseLanguageSkill(int skill_id, int value = 1);
|
void IncreaseLanguageSkill(uint8 language_id, uint8 increase = 1);
|
||||||
virtual uint16 GetSkill(EQ::skills::SkillType skill_id) const { if (skill_id <= EQ::skills::HIGHEST_SKILL) { return(itembonuses.skillmod[skill_id] > 0 ? (itembonuses.skillmodmax[skill_id] > 0 ? std::min(m_pp.skills[skill_id] + itembonuses.skillmodmax[skill_id], m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id]); } return 0; }
|
virtual uint16 GetSkill(EQ::skills::SkillType skill_id) const { if (skill_id <= EQ::skills::HIGHEST_SKILL) { return(itembonuses.skillmod[skill_id] > 0 ? (itembonuses.skillmodmax[skill_id] > 0 ? std::min(m_pp.skills[skill_id] + itembonuses.skillmodmax[skill_id], m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id]); } return 0; }
|
||||||
uint32 GetRawSkill(EQ::skills::SkillType skill_id) const { if (skill_id <= EQ::skills::HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; }
|
uint32 GetRawSkill(EQ::skills::SkillType skill_id) const { if (skill_id <= EQ::skills::HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; }
|
||||||
bool HasSkill(EQ::skills::SkillType skill_id) const;
|
bool HasSkill(EQ::skills::SkillType skill_id) const;
|
||||||
@@ -777,8 +777,8 @@ public:
|
|||||||
void CheckSpecializeIncrease(uint16 spell_id);
|
void CheckSpecializeIncrease(uint16 spell_id);
|
||||||
void CheckSongSkillIncrease(uint16 spell_id);
|
void CheckSongSkillIncrease(uint16 spell_id);
|
||||||
bool CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who, int chancemodi = 0);
|
bool CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who, int chancemodi = 0);
|
||||||
void CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill);
|
void CheckLanguageSkillIncrease(uint8 language_id, uint8 teacher_skill);
|
||||||
void SetLanguageSkill(int langid, int value);
|
void SetLanguageSkill(uint8 language_id, uint8 language_skill);
|
||||||
void SetHoTT(uint32 mobid);
|
void SetHoTT(uint32 mobid);
|
||||||
void ShowSkillsWindow();
|
void ShowSkillsWindow();
|
||||||
|
|
||||||
@@ -988,6 +988,7 @@ public:
|
|||||||
void IncStats(uint8 type,int16 increase_val);
|
void IncStats(uint8 type,int16 increase_val);
|
||||||
void DropItem(int16 slot_id, bool recurse = true);
|
void DropItem(int16 slot_id, bool recurse = true);
|
||||||
void DropItemQS(EQ::ItemInstance* inst, bool pickup);
|
void DropItemQS(EQ::ItemInstance* inst, bool pickup);
|
||||||
|
bool HasItemOnCorpse(uint32 item_id);
|
||||||
|
|
||||||
bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction);
|
bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction);
|
||||||
|
|
||||||
@@ -1527,6 +1528,7 @@ public:
|
|||||||
void JoinGroupXTargets(Group *g);
|
void JoinGroupXTargets(Group *g);
|
||||||
void LeaveGroupXTargets(Group *g);
|
void LeaveGroupXTargets(Group *g);
|
||||||
void LeaveRaidXTargets(Raid *r);
|
void LeaveRaidXTargets(Raid *r);
|
||||||
|
void ClearXTargets();
|
||||||
bool GroupFollow(Client* inviter);
|
bool GroupFollow(Client* inviter);
|
||||||
inline bool GetRunMode() const { return runmode; }
|
inline bool GetRunMode() const { return runmode; }
|
||||||
|
|
||||||
@@ -1605,7 +1607,7 @@ public:
|
|||||||
void SetAccountFlag(const std::string& flag, const std::string& value);
|
void SetAccountFlag(const std::string& flag, const std::string& value);
|
||||||
std::string GetAccountFlag(const std::string& flag);
|
std::string GetAccountFlag(const std::string& flag);
|
||||||
std::vector<std::string> GetAccountFlags();
|
std::vector<std::string> GetAccountFlags();
|
||||||
void SetGMStatus(int16 new_status);
|
void SetGMStatus(int new_status);
|
||||||
void Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto_consume);
|
void Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto_consume);
|
||||||
void PlayMP3(const char* fname);
|
void PlayMP3(const char* fname);
|
||||||
void ExpeditionSay(const char *str, int ExpID);
|
void ExpeditionSay(const char *str, int ExpID);
|
||||||
|
|||||||
@@ -1455,7 +1455,7 @@ int32 Client::CalcATK()
|
|||||||
|
|
||||||
uint32 Mob::GetInstrumentMod(uint16 spell_id)
|
uint32 Mob::GetInstrumentMod(uint16 spell_id)
|
||||||
{
|
{
|
||||||
if (GetClass() != Class::Bard) {
|
if (GetClass() != Class::Bard || spells[spell_id].is_discipline || spell_id == SPELL_AMPLIFICATION) {
|
||||||
//Other classes can get a base effects mod using SPA 413
|
//Other classes can get a base effects mod using SPA 413
|
||||||
if (HasBaseEffectFocus()) {
|
if (HasBaseEffectFocus()) {
|
||||||
return (10 + (GetFocusEffect(focusFcBaseEffects, spell_id) / 10));//TODO: change action->instrument mod to float to support < 10% focus values
|
return (10 + (GetFocusEffect(focusFcBaseEffects, spell_id) / 10));//TODO: change action->instrument mod to float to support < 10% focus values
|
||||||
|
|||||||
+168
-109
@@ -547,8 +547,8 @@ void Client::CompleteConnect()
|
|||||||
default: { break; } // GUILD_NONE
|
default: { break; } // GUILD_NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SendAppearancePacket(AT_GuildID, GuildID(), false);
|
SendAppearancePacket(AppearanceType::GuildID, GuildID(), false);
|
||||||
SendAppearancePacket(AT_GuildRank, rank, false);
|
SendAppearancePacket(AppearanceType::GuildRank, rank, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// moved to dbload and translators since we iterate there also .. keep m_pp values whatever they are when they get here
|
// moved to dbload and translators since we iterate there also .. keep m_pp values whatever they are when they get here
|
||||||
@@ -681,8 +681,11 @@ void Client::CompleteConnect()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SE_SummonHorse: {
|
case SE_SummonHorse: {
|
||||||
SummonHorse(buffs[j1].spellid);
|
if (RuleB(Character, PreventMountsFromZoning)) {
|
||||||
//hasmount = true; //this was false, is that the correct thing?
|
BuffFadeByEffect(SE_SummonHorse);
|
||||||
|
} else {
|
||||||
|
SummonHorse(buffs[j1].spellid);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SE_Silence:
|
case SE_Silence:
|
||||||
@@ -703,7 +706,7 @@ void Client::CompleteConnect()
|
|||||||
case SE_Invisibility2:
|
case SE_Invisibility2:
|
||||||
case SE_Invisibility:
|
case SE_Invisibility:
|
||||||
{
|
{
|
||||||
SendAppearancePacket(AT_Invis, Invisibility::Invisible);
|
SendAppearancePacket(AppearanceType::Invisibility, Invisibility::Invisible);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SE_Levitate:
|
case SE_Levitate:
|
||||||
@@ -712,17 +715,17 @@ void Client::CompleteConnect()
|
|||||||
{
|
{
|
||||||
if (!GetGM())
|
if (!GetGM())
|
||||||
{
|
{
|
||||||
SendAppearancePacket(AT_Levitate, 0);
|
SendAppearancePacket(AppearanceType::FlyMode, 0);
|
||||||
BuffFadeByEffect(SE_Levitate);
|
BuffFadeByEffect(SE_Levitate);
|
||||||
Message(Chat::Red, "You can't levitate in this zone.");
|
Message(Chat::Red, "You can't levitate in this zone.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (spell.limit_value[x1] == 1) {
|
if (spell.limit_value[x1] == 1) {
|
||||||
SendAppearancePacket(AT_Levitate, EQ::constants::GravityBehavior::LevitateWhileRunning, true, true);
|
SendAppearancePacket(AppearanceType::FlyMode, EQ::constants::GravityBehavior::LevitateWhileRunning, true, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SendAppearancePacket(AT_Levitate, EQ::constants::GravityBehavior::Levitating, true, true);
|
SendAppearancePacket(AppearanceType::FlyMode, EQ::constants::GravityBehavior::Levitating, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -747,7 +750,7 @@ void Client::CompleteConnect()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sends appearances for all mobs not doing anim_stand aka sitting, looting, playing dead */
|
/* Sends appearances for all mobs not doing Animation::Standing aka sitting, looting, playing dead */
|
||||||
entity_list.SendZoneAppearance(this);
|
entity_list.SendZoneAppearance(this);
|
||||||
/* Sends the Nimbus particle effects (up to 3) for any mob using them */
|
/* Sends the Nimbus particle effects (up to 3) for any mob using them */
|
||||||
entity_list.SendNimbusEffects(this);
|
entity_list.SendNimbusEffects(this);
|
||||||
@@ -1268,7 +1271,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
|
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
|
||||||
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
|
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
|
||||||
database.LoadCharacterMaterialColor(cid, &m_pp); /* Load Character Material */
|
database.LoadCharacterMaterialColor(cid, &m_pp); /* Load Character Material */
|
||||||
database.LoadCharacterPotions(cid, &m_pp); /* Load Character Potion Belt */
|
database.LoadCharacterPotionBelt(cid, &m_pp); /* Load Character Potion Belt */
|
||||||
database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency into PP */
|
database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency into PP */
|
||||||
database.LoadCharacterData(cid, &m_pp, &m_epp); /* Load Character Data from DB into PP as well as E_PP */
|
database.LoadCharacterData(cid, &m_pp, &m_epp); /* Load Character Data from DB into PP as well as E_PP */
|
||||||
database.LoadCharacterSkills(cid, &m_pp); /* Load Character Skills */
|
database.LoadCharacterSkills(cid, &m_pp); /* Load Character Skills */
|
||||||
@@ -1277,7 +1280,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */
|
database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */
|
||||||
database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */
|
database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */
|
||||||
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
|
database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */
|
||||||
database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */
|
database.LoadCharacterLeadershipAbilities(cid, &m_pp); /* Load Character Leadership AA's */
|
||||||
database.LoadCharacterTribute(this); /* Load CharacterTribute */
|
database.LoadCharacterTribute(this); /* Load CharacterTribute */
|
||||||
|
|
||||||
// this pattern is strange
|
// this pattern is strange
|
||||||
@@ -1316,7 +1319,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
/* If GM, not trackable */
|
/* If GM, not trackable */
|
||||||
if (gm_hide_me) { trackable = false; }
|
if (gm_hide_me) { trackable = false; }
|
||||||
if (gminvul) { invulnerable = true; }
|
if (gminvul) { invulnerable = true; }
|
||||||
if (flymode > 0) { SendAppearancePacket(AT_Levitate, flymode); }
|
if (flymode > 0) { SendAppearancePacket(AppearanceType::FlyMode, flymode); }
|
||||||
/* Set Con State for Reporting */
|
/* Set Con State for Reporting */
|
||||||
conn_state = PlayerProfileLoaded;
|
conn_state = PlayerProfileLoaded;
|
||||||
|
|
||||||
@@ -4326,6 +4329,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
|
|||||||
LogSpells("OP CastSpell: slot [{}] spell [{}] target [{}] inv [{}]", castspell->slot, castspell->spell_id, castspell->target_id, (unsigned long)castspell->inventoryslot);
|
LogSpells("OP CastSpell: slot [{}] spell [{}] target [{}] inv [{}]", castspell->slot, castspell->spell_id, castspell->target_id, (unsigned long)castspell->inventoryslot);
|
||||||
CastingSlot slot = static_cast<CastingSlot>(castspell->slot);
|
CastingSlot slot = static_cast<CastingSlot>(castspell->slot);
|
||||||
|
|
||||||
|
if (RuleB(Spells, RequireMnemonicRetention)) {
|
||||||
|
if (EQ::ValueWithin(castspell->slot, 8, 11) && GetAA(aaMnemonicRetention) < (castspell->slot - 7)) {
|
||||||
|
InterruptSpell(castspell->spell_id);
|
||||||
|
Message(Chat::Red, "You do not have the required AA to use this spell slot.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Memorized Spell */
|
/* Memorized Spell */
|
||||||
if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id) {
|
if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id) {
|
||||||
uint16 spell_to_cast = 0;
|
uint16 spell_to_cast = 0;
|
||||||
@@ -4505,23 +4516,24 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
void Client::Handle_OP_ChannelMessage(const EQApplicationPacket *app)
|
void Client::Handle_OP_ChannelMessage(const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
ChannelMessage_Struct* cm = (ChannelMessage_Struct*)app->pBuffer;
|
auto* cm = (ChannelMessage_Struct*) app->pBuffer;
|
||||||
|
|
||||||
if (app->size < sizeof(ChannelMessage_Struct)) {
|
if (app->size < sizeof(ChannelMessage_Struct)) {
|
||||||
std::cout << "Wrong size " << app->size << ", should be " << sizeof(ChannelMessage_Struct) << "+ on 0x" << std::hex << std::setfill('0') << std::setw(4) << app->GetOpcode() << std::dec << std::endl;
|
LogDebug("Size mismatch in OP_ChannelMessage expected [{}] got [{}]", sizeof(ChannelMessage_Struct), app->size);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (IsAIControlled() && !GetGM()) {
|
|
||||||
Message(Chat::Red, "You try to speak but cant move your mouth!");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 skill_in_language = 100;
|
if (IsAIControlled() && !GetGM()) {
|
||||||
if (cm->language < MAX_PP_LANGUAGE)
|
Message(Chat::Red, "You try to speak but can't move your mouth!");
|
||||||
{
|
return;
|
||||||
skill_in_language = m_pp.languages[cm->language];
|
|
||||||
}
|
}
|
||||||
ChannelMessageReceived(cm->chan_num, cm->language, skill_in_language, cm->message, cm->targetname);
|
|
||||||
|
uint8 language_skill = Language::MaxValue;
|
||||||
|
if (EQ::ValueWithin(cm->language, Language::CommonTongue, Language::Unknown27)) {
|
||||||
|
language_skill = m_pp.languages[cm->language];
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelMessageReceived(cm->chan_num, cm->language, language_skill, cm->message, cm->targetname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4887,8 +4899,13 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
CheckIncreaseSkill(EQ::skills::SkillTracking, nullptr, -20);
|
CheckIncreaseSkill(EQ::skills::SkillTracking, nullptr, -20);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
|
||||||
if (cy != m_Position.y || cx != m_Position.x) {
|
if (cy != m_Position.y || cx != m_Position.x) {
|
||||||
|
// End trader mode if we move
|
||||||
|
if (Trader) {
|
||||||
|
Trader_EndTrader();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
||||||
if ((hidden || improved_hidden) && !sneaking) {
|
if ((hidden || improved_hidden) && !sneaking) {
|
||||||
hidden = false;
|
hidden = false;
|
||||||
improved_hidden = false;
|
improved_hidden = false;
|
||||||
@@ -5053,7 +5070,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (zone->watermap) {
|
if (zone->watermap) {
|
||||||
if (zone->watermap->InLiquid(glm::vec3(m_Position))) {
|
if (zone->watermap->InLiquid(glm::vec3(m_Position)) && IsMoving()) {
|
||||||
CheckIncreaseSkill(EQ::skills::SkillSwimming, nullptr, -17);
|
CheckIncreaseSkill(EQ::skills::SkillSwimming, nullptr, -17);
|
||||||
|
|
||||||
// Dismount horses when entering water
|
// Dismount horses when entering water
|
||||||
@@ -5770,7 +5787,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
if (m_pp.spell_book[dss->spell_slot] != SPELLBOOK_UNKNOWN) {
|
if (m_pp.spell_book[dss->spell_slot] != SPELLBOOK_UNKNOWN) {
|
||||||
m_pp.spell_book[dss->spell_slot] = SPELLBOOK_UNKNOWN;
|
m_pp.spell_book[dss->spell_slot] = SPELLBOOK_UNKNOWN;
|
||||||
database.DeleteCharacterSpell(CharacterID(), m_pp.spell_book[dss->spell_slot], dss->spell_slot);
|
database.DeleteCharacterSpell(CharacterID(), dss->spell_slot);
|
||||||
dss->success = 1;
|
dss->success = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -6233,6 +6250,13 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ed->dmgtype == EQ::constants::EnvironmentalDamage::Falling) {
|
if (ed->dmgtype == EQ::constants::EnvironmentalDamage::Falling) {
|
||||||
|
if (zone->HasWaterMap()) {
|
||||||
|
auto target_position = glm::vec3(GetX(), GetY(), GetZ());
|
||||||
|
if (!zone->watermap->InLiquid(target_position)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32 mod = spellbonuses.ReduceFallDamage + itembonuses.ReduceFallDamage + aabonuses.ReduceFallDamage;
|
uint32 mod = spellbonuses.ReduceFallDamage + itembonuses.ReduceFallDamage + aabonuses.ReduceFallDamage;
|
||||||
damage -= damage * mod / 100;
|
damage -= damage * mod / 100;
|
||||||
}
|
}
|
||||||
@@ -6481,7 +6505,7 @@ void Client::Handle_OP_GMBecomeNPC(const EQApplicationPacket *app)
|
|||||||
t->SetGM(false);
|
t->SetGM(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m->SendAppearancePacket(AT_NPCName, 1, true);
|
m->SendAppearancePacket(AppearanceType::NPCName, 1, true);
|
||||||
t->SetBecomeNPC(true);
|
t->SetBecomeNPC(true);
|
||||||
t->SetBecomeNPCLevel(b->maxlevel);
|
t->SetBecomeNPCLevel(b->maxlevel);
|
||||||
m->MessageString(Chat::White, TOGGLE_OFF);
|
m->MessageString(Chat::White, TOGGLE_OFF);
|
||||||
@@ -6598,17 +6622,26 @@ void Client::Handle_OP_GMGoto(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
auto *gmg = (GMSummon_Struct *) app->pBuffer;
|
auto *gmg = (GMSummon_Struct *) app->pBuffer;
|
||||||
Mob *gt = entity_list.GetMob(gmg->charname);
|
Mob *gt = entity_list.GetMob(gmg->charname);
|
||||||
if (!gt) {
|
if (gt) {
|
||||||
MovePC(zone->GetZoneID(), zone->GetInstanceID(), gt->GetX(), gt->GetY(), gt->GetZ(), gt->GetHeading());
|
MovePC(
|
||||||
|
zone->GetZoneID(),
|
||||||
|
zone->GetInstanceID(),
|
||||||
|
gt->GetX(),
|
||||||
|
gt->GetY(),
|
||||||
|
gt->GetZ(),
|
||||||
|
gt->GetHeading()
|
||||||
|
);
|
||||||
} else if (!worldserver.Connected()) {
|
} else if (!worldserver.Connected()) {
|
||||||
Message(Chat::Red, "Error: World server disconnected.");
|
Message(Chat::Red, "Error: World server disconnected.");
|
||||||
} else {
|
} else {
|
||||||
auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct));
|
auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct));
|
||||||
memset(pack->pBuffer, 0, pack->size);
|
memset(pack->pBuffer, 0, pack->size);
|
||||||
ServerGMGoto_Struct *wsgmg = (ServerGMGoto_Struct *) pack->pBuffer;
|
|
||||||
strcpy(wsgmg->myname, GetName());
|
auto* g = (ServerGMGoto_Struct *) pack->pBuffer;
|
||||||
strcpy(wsgmg->gotoname, gmg->charname);
|
strcpy(g->myname, GetName());
|
||||||
wsgmg->admin = admin;
|
strcpy(g->gotoname, gmg->charname);
|
||||||
|
g->admin = admin;
|
||||||
|
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
@@ -7304,63 +7337,80 @@ void Client::Handle_OP_GroupInvite2(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
GroupInvite_Struct* gis = (GroupInvite_Struct*)app->pBuffer;
|
GroupInvite_Struct* gis = (GroupInvite_Struct*)app->pBuffer;
|
||||||
|
|
||||||
Mob *Invitee = entity_list.GetMob(gis->invitee_name);
|
Mob* invitee = nullptr;
|
||||||
|
|
||||||
if (Invitee == this)
|
if (RuleB(Character, GroupInvitesRequireTarget)) {
|
||||||
{
|
// We can only invite the current target.
|
||||||
|
invitee = GetTarget();
|
||||||
|
} else {
|
||||||
|
invitee = entity_list.GetMob(gis->invitee_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invitee == this) {
|
||||||
MessageString(Chat::LightGray, GROUP_INVITEE_SELF);
|
MessageString(Chat::LightGray, GROUP_INVITEE_SELF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Invitee)
|
if (invitee) {
|
||||||
{
|
if (invitee->IsClient()) {
|
||||||
if (Invitee->IsClient())
|
if (invitee->CastToClient()->MercOnlyOrNoGroup() && !invitee->IsRaidGrouped()) {
|
||||||
{
|
if (app->GetOpcode() == OP_GroupInvite2) {
|
||||||
if (Invitee->CastToClient()->MercOnlyOrNoGroup() && !Invitee->IsRaidGrouped())
|
|
||||||
{
|
|
||||||
if (app->GetOpcode() == OP_GroupInvite2)
|
|
||||||
{
|
|
||||||
//Make a new packet using all the same information but make sure it's a fixed GroupInvite opcode so we
|
//Make a new packet using all the same information but make sure it's a fixed GroupInvite opcode so we
|
||||||
//Don't have to deal with GroupFollow2 crap.
|
//Don't have to deal with GroupFollow2 crap.
|
||||||
auto outapp =
|
auto outapp =
|
||||||
new EQApplicationPacket(OP_GroupInvite, sizeof(GroupInvite_Struct));
|
new EQApplicationPacket(OP_GroupInvite, sizeof(GroupInvite_Struct));
|
||||||
memcpy(outapp->pBuffer, app->pBuffer, outapp->size);
|
memcpy(outapp->pBuffer, app->pBuffer, outapp->size);
|
||||||
Invitee->CastToClient()->QueuePacket(outapp);
|
invitee->CastToClient()->QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
//The correct opcode, no reason to bother wasting time reconstructing the packet
|
//The correct opcode, no reason to bother wasting time reconstructing the packet
|
||||||
Invitee->CastToClient()->QueuePacket(app);
|
invitee->CastToClient()->QueuePacket(app);
|
||||||
}
|
}
|
||||||
}
|
} else if (invitee->IsRaidGrouped()) {
|
||||||
else {
|
Raid* inviter_raid = GetRaid();
|
||||||
|
Raid* invitee_raid = invitee->CastToClient()->GetRaid();
|
||||||
|
|
||||||
|
bool leader = false;
|
||||||
|
|
||||||
|
if (invitee_raid) {
|
||||||
|
leader = invitee_raid->IsGroupLeader(invitee->GetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inviter_raid != invitee_raid || leader) {
|
||||||
|
MessageString(Chat::Default, ALREADY_IN_GRP_RAID, invitee->GetCleanName());
|
||||||
|
} else {
|
||||||
|
MessageString(Chat::Default, TARGET_ALREADY_IN_GROUP, invitee->GetCleanName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
if (RuleB(Character, OnInviteReceiveAlreadyinGroupMessage)) {
|
if (RuleB(Character, OnInviteReceiveAlreadyinGroupMessage)) {
|
||||||
if (!Invitee->CastToClient()->MercOnlyOrNoGroup()) {
|
if (!invitee->CastToClient()->MercOnlyOrNoGroup()) {
|
||||||
Message(Chat::LightGray, "%s is already in another group.", Invitee->GetCleanName());
|
MessageString(Chat::Default, TARGET_ALREADY_IN_GROUP, invitee->GetCleanName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (invitee->IsBot()) {
|
||||||
else if (Invitee->IsBot()) {
|
|
||||||
Client* inviter = entity_list.GetClientByName(gis->inviter_name);
|
Client* inviter = entity_list.GetClientByName(gis->inviter_name);
|
||||||
if (inviter && inviter->IsRaidGrouped() && !Invitee->HasRaid()) {
|
if (inviter && inviter->IsRaidGrouped() && !invitee->HasRaid()) {
|
||||||
Bot::ProcessRaidInvite(Invitee->CastToBot(), inviter, true);
|
Bot::ProcessRaidInvite(invitee->CastToBot(), inviter, true);
|
||||||
}
|
} else if (!invitee->HasRaid()) {
|
||||||
else if (!Invitee->HasRaid()) {
|
Bot::ProcessBotGroupInvite(this, std::string(invitee->GetName()));
|
||||||
Bot::ProcessBotGroupInvite(this, std::string(Invitee->GetName()));
|
|
||||||
} else {
|
} else {
|
||||||
MessageString(Chat::LightGray, ALREADY_IN_RAID, Invitee->GetCleanName());
|
MessageString(Chat::LightGray, ALREADY_IN_RAID, invitee->GetCleanName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (RuleB(Character, GroupInvitesRequireTarget)) {
|
||||||
{
|
Message(Chat::White, "You must target a player first to invite to join your group.");
|
||||||
auto pack = new ServerPacket(ServerOP_GroupInvite, sizeof(GroupInvite_Struct));
|
} else {
|
||||||
memcpy(pack->pBuffer, gis, sizeof(GroupInvite_Struct));
|
auto pack = new ServerPacket(ServerOP_GroupInvite, sizeof(GroupInvite_Struct));
|
||||||
worldserver.SendPacket(pack);
|
memcpy(pack->pBuffer, gis, sizeof(GroupInvite_Struct));
|
||||||
safe_delete(pack);
|
worldserver.SendPacket(pack);
|
||||||
|
safe_delete(pack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -8853,7 +8903,7 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app)
|
|||||||
Message(Chat::LightGray, "You say, '%s'", response.c_str());
|
Message(Chat::LightGray, "You say, '%s'", response.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
|
ChannelMessageReceived(ChatChannel_Say, Language::CommonTongue, Language::MaxValue, response.c_str(), nullptr, true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -10842,7 +10892,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
// Set Sit button to unpressed - send stand anim/end hpregen
|
// Set Sit button to unpressed - send stand anim/end hpregen
|
||||||
mypet->SetFeigned(false);
|
mypet->SetFeigned(false);
|
||||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
||||||
|
|
||||||
mypet->SayString(this, Chat::PetResponse, PET_GUARDINGLIFE);
|
mypet->SayString(this, Chat::PetResponse, PET_GUARDINGLIFE);
|
||||||
mypet->SetPetOrder(SPO_Guard);
|
mypet->SetPetOrder(SPO_Guard);
|
||||||
@@ -10867,7 +10917,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
// fix GUI sit button to be unpressed - send stand anim/end hpregen
|
// fix GUI sit button to be unpressed - send stand anim/end hpregen
|
||||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
||||||
|
|
||||||
if (mypet->IsPetStop()) {
|
if (mypet->IsPetStop()) {
|
||||||
mypet->SetPetStop(false);
|
mypet->SetPetStop(false);
|
||||||
@@ -10915,7 +10965,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
// Set Sit button to unpressed - send stand anim/end hpregen
|
// Set Sit button to unpressed - send stand anim/end hpregen
|
||||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
||||||
|
|
||||||
if (mypet->IsPetStop()) {
|
if (mypet->IsPetStop()) {
|
||||||
mypet->SetPetStop(false);
|
mypet->SetPetStop(false);
|
||||||
@@ -10933,7 +10983,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
mypet->SetFeigned(false);
|
mypet->SetFeigned(false);
|
||||||
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
||||||
mypet->SetPetOrder(SPO_Follow);
|
mypet->SetPetOrder(SPO_Follow);
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -10943,7 +10993,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
mypet->SetRunAnimSpeed(0);
|
mypet->SetRunAnimSpeed(0);
|
||||||
if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet
|
if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet
|
||||||
mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting
|
mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_SIT);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Sitting);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -10956,7 +11006,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING);
|
||||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||||
mypet->SetPetOrder(SPO_Follow);
|
mypet->SetPetOrder(SPO_Follow);
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -10971,7 +11021,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
mypet->SetRunAnimSpeed(0);
|
mypet->SetRunAnimSpeed(0);
|
||||||
if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet
|
if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet
|
||||||
mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting
|
mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_SIT);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Sitting);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -11176,7 +11226,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
|||||||
mypet->SetPetOrder(SPO_FeignDeath);
|
mypet->SetPetOrder(SPO_FeignDeath);
|
||||||
mypet->SetRunAnimSpeed(0);
|
mypet->SetRunAnimSpeed(0);
|
||||||
mypet->StopNavigation();
|
mypet->StopNavigation();
|
||||||
mypet->SendAppearancePacket(AT_Anim, ANIM_DEATH);
|
mypet->SendAppearancePacket(AppearanceType::Animation, Animation::Lying);
|
||||||
mypet->SetFeigned(true);
|
mypet->SetFeigned(true);
|
||||||
mypet->SetTarget(nullptr);
|
mypet->SetTarget(nullptr);
|
||||||
if (!mypet->UseBardSpellLogic()) {
|
if (!mypet->UseBardSpellLogic()) {
|
||||||
@@ -11564,7 +11614,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
|||||||
if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY)) {
|
if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY)) {
|
||||||
response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY);
|
response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY);
|
||||||
if (!response.empty()) {
|
if (!response.empty()) {
|
||||||
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
|
ChannelMessageReceived(ChatChannel_Say, Language::CommonTongue, Language::MaxValue, response.c_str(), nullptr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -11573,7 +11623,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
|||||||
if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY)) {
|
if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY)) {
|
||||||
response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY);
|
response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY);
|
||||||
if (!response.empty()) {
|
if (!response.empty()) {
|
||||||
ChannelMessageReceived(ChatChannel_Say, 0, 100, response.c_str(), nullptr, true);
|
ChannelMessageReceived(ChatChannel_Say, Language::CommonTongue, Language::MaxValue, response.c_str(), nullptr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -11671,7 +11721,7 @@ void Client::Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app)
|
|||||||
m_pp.raid_leadership_points -= cost;
|
m_pp.raid_leadership_points -= cost;
|
||||||
m_pp.leader_abilities.ranks[aaid]++;
|
m_pp.leader_abilities.ranks[aaid]++;
|
||||||
|
|
||||||
database.SaveCharacterLeadershipAA(CharacterID(), &m_pp);
|
database.SaveCharacterLeadershipAbilities(CharacterID(), &m_pp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//it is a group ability.
|
//it is a group ability.
|
||||||
@@ -11684,7 +11734,7 @@ void Client::Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app)
|
|||||||
m_pp.group_leadership_points -= cost;
|
m_pp.group_leadership_points -= cost;
|
||||||
m_pp.leader_abilities.ranks[aaid]++;
|
m_pp.leader_abilities.ranks[aaid]++;
|
||||||
|
|
||||||
database.SaveCharacterLeadershipAA(CharacterID(), &m_pp);
|
database.SaveCharacterLeadershipAbilities(CharacterID(), &m_pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//success, send them an update
|
//success, send them an update
|
||||||
@@ -11808,8 +11858,8 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||||
Config->ChatHost.c_str(),
|
Config->GetUCSHost().c_str(),
|
||||||
Config->ChatPort,
|
Config->GetUCSPort(),
|
||||||
Config->ShortName.c_str(),
|
Config->ShortName.c_str(),
|
||||||
GetName(),
|
GetName(),
|
||||||
ConnectionType,
|
ConnectionType,
|
||||||
@@ -11834,8 +11884,8 @@ void Client::Handle_OP_QueryUCSServerStatus(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
buffer = StringFormat("%s,%i,%s.%s,%c%s",
|
||||||
Config->MailHost.c_str(),
|
Config->GetUCSHost().c_str(),
|
||||||
Config->MailPort,
|
Config->GetUCSPort(),
|
||||||
Config->ShortName.c_str(),
|
Config->ShortName.c_str(),
|
||||||
GetName(),
|
GetName(),
|
||||||
ConnectionType,
|
ConnectionType,
|
||||||
@@ -12044,6 +12094,13 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
|
|||||||
{
|
{
|
||||||
auto player_sending_invite_group = player_sending_invite->GetGroup();
|
auto player_sending_invite_group = player_sending_invite->GetGroup();
|
||||||
Group* group = GetGroup();
|
Group* group = GetGroup();
|
||||||
|
|
||||||
|
/* Prevent scenario where player had joined group with Raid invitor before accepting Raid invite */
|
||||||
|
if (group && group == player_sending_invite_group) {
|
||||||
|
player_sending_invite->MessageString(Chat::Red, INVITE_GROUP_LEADER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (group) //if our target has a group
|
if (group) //if our target has a group
|
||||||
{
|
{
|
||||||
raid = new Raid(player_sending_invite);
|
raid = new Raid(player_sending_invite);
|
||||||
@@ -14247,14 +14304,14 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
|||||||
if (sa->spawn_id != GetID())
|
if (sa->spawn_id != GetID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sa->type == AT_Invis) {
|
if (sa->type == AppearanceType::Invisibility) {
|
||||||
if (sa->parameter != 0)
|
if (sa->parameter != 0)
|
||||||
{
|
{
|
||||||
if (!HasSkill(EQ::skills::SkillHide) && GetSkill(EQ::skills::SkillHide) == 0)
|
if (!HasSkill(EQ::skills::SkillHide) && GetSkill(EQ::skills::SkillHide) == 0)
|
||||||
{
|
{
|
||||||
if (ClientVersion() < EQ::versions::ClientVersion::SoF)
|
if (ClientVersion() < EQ::versions::ClientVersion::SoF)
|
||||||
{
|
{
|
||||||
auto message = fmt::format("Player sent OP_SpawnAppearance with AT_Invis [{}]", sa->parameter);
|
auto message = fmt::format("Player sent OP_SpawnAppearance with AppearanceType::Invisibility [{}]", sa->parameter);
|
||||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
|
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14266,18 +14323,18 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
|||||||
entity_list.QueueClients(this, app, true);
|
entity_list.QueueClients(this, app, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_Anim) {
|
else if (sa->type == AppearanceType::Animation) {
|
||||||
if (IsAIControlled())
|
if (IsAIControlled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sa->parameter == ANIM_STAND) {
|
if (sa->parameter == Animation::Standing) {
|
||||||
SetAppearance(eaStanding);
|
SetAppearance(eaStanding);
|
||||||
playeraction = 0;
|
playeraction = 0;
|
||||||
SetFeigned(false);
|
SetFeigned(false);
|
||||||
BindWound(this, false, true);
|
BindWound(this, false, true);
|
||||||
camp_timer.Disable();
|
camp_timer.Disable();
|
||||||
}
|
}
|
||||||
else if (sa->parameter == ANIM_SIT) {
|
else if (sa->parameter == Animation::Sitting) {
|
||||||
SetAppearance(eaSitting);
|
SetAppearance(eaSitting);
|
||||||
playeraction = 1;
|
playeraction = 1;
|
||||||
if (!UseBardSpellLogic())
|
if (!UseBardSpellLogic())
|
||||||
@@ -14287,19 +14344,19 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
|||||||
tmSitting = Timer::GetCurrentTime();
|
tmSitting = Timer::GetCurrentTime();
|
||||||
BuffFadeBySitModifier();
|
BuffFadeBySitModifier();
|
||||||
}
|
}
|
||||||
else if (sa->parameter == ANIM_CROUCH) {
|
else if (sa->parameter == Animation::Crouching) {
|
||||||
if (!UseBardSpellLogic())
|
if (!UseBardSpellLogic())
|
||||||
InterruptSpell();
|
InterruptSpell();
|
||||||
SetAppearance(eaCrouching);
|
SetAppearance(eaCrouching);
|
||||||
playeraction = 2;
|
playeraction = 2;
|
||||||
SetFeigned(false);
|
SetFeigned(false);
|
||||||
}
|
}
|
||||||
else if (sa->parameter == ANIM_DEATH) { // feign death too
|
else if (sa->parameter == Animation::Lying) { // feign death too
|
||||||
SetAppearance(eaDead);
|
SetAppearance(eaDead);
|
||||||
playeraction = 3;
|
playeraction = 3;
|
||||||
InterruptSpell();
|
InterruptSpell();
|
||||||
}
|
}
|
||||||
else if (sa->parameter == ANIM_LOOT) {
|
else if (sa->parameter == Animation::Looting) {
|
||||||
SetAppearance(eaLooting);
|
SetAppearance(eaLooting);
|
||||||
playeraction = 4;
|
playeraction = 4;
|
||||||
SetFeigned(false);
|
SetFeigned(false);
|
||||||
@@ -14312,7 +14369,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
entity_list.QueueClients(this, app, true);
|
entity_list.QueueClients(this, app, true);
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_Anon) {
|
else if (sa->type == AppearanceType::Anonymous) {
|
||||||
if (!anon_toggle_timer.Check()) {
|
if (!anon_toggle_timer.Check()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -14334,19 +14391,19 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
|||||||
entity_list.QueueClients(this, app, true);
|
entity_list.QueueClients(this, app, true);
|
||||||
UpdateWho();
|
UpdateWho();
|
||||||
}
|
}
|
||||||
else if ((sa->type == AT_HP) && (dead == 0)) {
|
else if ((sa->type == AppearanceType::Health) && (dead == 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_AFK) {
|
else if (sa->type == AppearanceType::AFK) {
|
||||||
if (afk_toggle_timer.Check()) {
|
if (afk_toggle_timer.Check()) {
|
||||||
AFK = (sa->parameter == 1);
|
AFK = (sa->parameter == 1);
|
||||||
entity_list.QueueClients(this, app, true);
|
entity_list.QueueClients(this, app, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_Split) {
|
else if (sa->type == AppearanceType::Split) {
|
||||||
m_pp.autosplit = (sa->parameter == 1);
|
m_pp.autosplit = (sa->parameter == 1);
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_Sneak) {
|
else if (sa->type == AppearanceType::Sneak) {
|
||||||
if (sneaking == 0)
|
if (sneaking == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -14354,7 +14411,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
if (!HasSkill(EQ::skills::SkillSneak))
|
if (!HasSkill(EQ::skills::SkillSneak))
|
||||||
{
|
{
|
||||||
auto message = fmt::format("Player sent OP_SpawnAppearance with AT_Sneak [{}]", sa->parameter);
|
auto message = fmt::format("Player sent OP_SpawnAppearance with AppearanceType::Sneak [{}]", sa->parameter);
|
||||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
|
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -14362,38 +14419,38 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app)
|
|||||||
sneaking = 0;
|
sneaking = 0;
|
||||||
entity_list.QueueClients(this, app, true);
|
entity_list.QueueClients(this, app, true);
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_Size)
|
else if (sa->type == AppearanceType::Size)
|
||||||
{
|
{
|
||||||
auto message = fmt::format("Player sent OP_SpawnAppearance with AT_Size [{}]", sa->parameter);
|
auto message = fmt::format("Player sent OP_SpawnAppearance with AppearanceType::Size [{}]", sa->parameter);
|
||||||
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
|
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = message});
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_Light) // client emitting light (lightstone, shiny shield)
|
else if (sa->type == AppearanceType::Light) // client emitting light (lightstone, shiny shield)
|
||||||
{
|
{
|
||||||
//don't do anything with this
|
//don't do anything with this
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_Levitate)
|
else if (sa->type == AppearanceType::FlyMode)
|
||||||
{
|
{
|
||||||
// don't do anything with this, we tell the client when it's
|
// don't do anything with this, we tell the client when it's
|
||||||
// levitating, not the other way around
|
// levitating, not the other way around
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_ShowHelm)
|
else if (sa->type == AppearanceType::ShowHelm)
|
||||||
{
|
{
|
||||||
if (helm_toggle_timer.Check()) {
|
if (helm_toggle_timer.Check()) {
|
||||||
m_pp.showhelm = (sa->parameter == 1);
|
m_pp.showhelm = (sa->parameter == 1);
|
||||||
entity_list.QueueClients(this, app, true);
|
entity_list.QueueClients(this, app, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_GroupConsent)
|
else if (sa->type == AppearanceType::GroupAutoConsent)
|
||||||
{
|
{
|
||||||
m_pp.groupAutoconsent = (sa->parameter == 1);
|
m_pp.groupAutoconsent = (sa->parameter == 1);
|
||||||
ConsentCorpses("Group", (sa->parameter != 1));
|
ConsentCorpses("Group", (sa->parameter != 1));
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_RaidConsent)
|
else if (sa->type == AppearanceType::RaidAutoConsent)
|
||||||
{
|
{
|
||||||
m_pp.raidAutoconsent = (sa->parameter == 1);
|
m_pp.raidAutoconsent = (sa->parameter == 1);
|
||||||
ConsentCorpses("Raid", (sa->parameter != 1));
|
ConsentCorpses("Raid", (sa->parameter != 1));
|
||||||
}
|
}
|
||||||
else if (sa->type == AT_GuildConsent)
|
else if (sa->type == AppearanceType::GuildAutoConsent)
|
||||||
{
|
{
|
||||||
m_pp.guildAutoconsent = (sa->parameter == 1);
|
m_pp.guildAutoconsent = (sa->parameter == 1);
|
||||||
ConsentCorpses("Guild", (sa->parameter != 1));
|
ConsentCorpses("Guild", (sa->parameter != 1));
|
||||||
@@ -14533,10 +14590,10 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
/* Save Spell Swaps */
|
/* Save Spell Swaps */
|
||||||
if (!database.SaveCharacterSpell(CharacterID(), m_pp.spell_book[swapspell->from_slot], swapspell->from_slot)) {
|
if (!database.SaveCharacterSpell(CharacterID(), m_pp.spell_book[swapspell->from_slot], swapspell->from_slot)) {
|
||||||
database.DeleteCharacterSpell(CharacterID(), m_pp.spell_book[swapspell->from_slot], swapspell->from_slot);
|
database.DeleteCharacterSpell(CharacterID(), swapspell->from_slot);
|
||||||
}
|
}
|
||||||
if (!database.SaveCharacterSpell(CharacterID(), swapspelltemp, swapspell->to_slot)) {
|
if (!database.SaveCharacterSpell(CharacterID(), swapspelltemp, swapspell->to_slot)) {
|
||||||
database.DeleteCharacterSpell(CharacterID(), swapspelltemp, swapspell->to_slot);
|
database.DeleteCharacterSpell(CharacterID(), swapspell->to_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
QueuePacket(app);
|
QueuePacket(app);
|
||||||
@@ -15504,6 +15561,8 @@ void Client::Handle_OP_Translocate(const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_list.ClearAggro(this);
|
||||||
|
|
||||||
////Was sending the packet back to initiate client zone...
|
////Was sending the packet back to initiate client zone...
|
||||||
////but that could be abusable, so lets go through proper channels
|
////but that could be abusable, so lets go through proper channels
|
||||||
MovePC(
|
MovePC(
|
||||||
|
|||||||
+26
-14
@@ -572,7 +572,7 @@ bool Client::Process() {
|
|||||||
linkdead_timer.Start(RuleI(Zone, ClientLinkdeadMS));
|
linkdead_timer.Start(RuleI(Zone, ClientLinkdeadMS));
|
||||||
client_state = CLIENT_LINKDEAD;
|
client_state = CLIENT_LINKDEAD;
|
||||||
AI_Start(CLIENT_LD_TIMEOUT);
|
AI_Start(CLIENT_LD_TIMEOUT);
|
||||||
SendAppearancePacket(AT_Linkdead, 1);
|
SendAppearancePacket(AppearanceType::Linkdead, 1);
|
||||||
|
|
||||||
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::LinkDead);
|
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::LinkDead);
|
||||||
}
|
}
|
||||||
@@ -763,10 +763,12 @@ void Client::BulkSendInventoryItems()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool deletenorent = database.NoRentExpired(GetName());
|
const bool delete_no_rent = database.NoRentExpired(GetName());
|
||||||
if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items
|
if (delete_no_rent) { //client was offline for more than 30 minutes, delete no rent items
|
||||||
if (RuleB(Inventory, TransformSummonedBags))
|
if (RuleB(Inventory, TransformSummonedBags)) {
|
||||||
DisenchantSummonedBags(false);
|
DisenchantSummonedBags(false);
|
||||||
|
}
|
||||||
|
|
||||||
RemoveNoRent(false);
|
RemoveNoRent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1184,10 +1186,10 @@ void Client::CancelSneakHide()
|
|||||||
if (hidden || improved_hidden) {
|
if (hidden || improved_hidden) {
|
||||||
auto app = new EQApplicationPacket(OP_CancelSneakHide, 0);
|
auto app = new EQApplicationPacket(OP_CancelSneakHide, 0);
|
||||||
FastQueuePacket(&app);
|
FastQueuePacket(&app);
|
||||||
// SoF and Tit send back a OP_SpawnAppearance turning off AT_Invis
|
// SoF and Tit send back a OP_SpawnAppearance turning off AppearanceType::Invisibility
|
||||||
// so we need to handle our sneaking flag only
|
// so we need to handle our sneaking flag only
|
||||||
// The later clients send back a OP_Hide (this has a size but data is 0)
|
// The later clients send back a OP_Hide (this has a size but data is 0)
|
||||||
// as well as OP_SpawnAppearance with AT_Invis and one with AT_Sneak
|
// as well as OP_SpawnAppearance with AppearanceType::Invisibility and one with AppearanceType::Sneak
|
||||||
// So we don't have to handle any of those flags
|
// So we don't have to handle any of those flags
|
||||||
if (ClientVersionBit() & EQ::versions::maskSoFAndEarlier)
|
if (ClientVersionBit() & EQ::versions::maskSoFAndEarlier)
|
||||||
sneaking = false;
|
sneaking = false;
|
||||||
@@ -1552,19 +1554,24 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
Mob* pTrainer = entity_list.GetMob(gmtrain->npcid);
|
Mob* pTrainer = entity_list.GetMob(gmtrain->npcid);
|
||||||
|
|
||||||
if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < Class::WarriorGM || pTrainer->GetClass() > Class::BerserkerGM)
|
if (!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < Class::WarriorGM || pTrainer->GetClass() > Class::BerserkerGM) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//you can only use your own trainer, client enforces this, but why trust it
|
//you can only use your own trainer, client enforces this, but why trust it
|
||||||
if (!RuleB(Character, AllowCrossClassTrainers)) {
|
if (!RuleB(Character, AllowCrossClassTrainers)) {
|
||||||
int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior);
|
int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior);
|
||||||
if (GetClass() != trains_class)
|
if (GetClass() != trains_class) {
|
||||||
|
safe_delete(outapp);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//you have to be somewhat close to a trainer to be properly using them
|
//you have to be somewhat close to a trainer to be properly using them
|
||||||
if(DistanceSquared(m_Position,pTrainer->GetPosition()) > USE_NPC_RANGE2)
|
if (DistanceSquared(m_Position,pTrainer->GetPosition()) > USE_NPC_RANGE2) {
|
||||||
|
safe_delete(outapp);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// if this for-loop acts up again (crashes linux), try enabling the before and after #pragmas
|
// if this for-loop acts up again (crashes linux), try enabling the before and after #pragmas
|
||||||
//#pragma GCC push_options
|
//#pragma GCC push_options
|
||||||
@@ -1657,7 +1664,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
|||||||
// languages go here
|
// languages go here
|
||||||
if (gmskill->skill_id > 25)
|
if (gmskill->skill_id > 25)
|
||||||
{
|
{
|
||||||
std::cout << "Wrong Training Skill (languages)" << std::endl;
|
LogSkills("Wrong Training Skill (languages)");
|
||||||
DumpPacket(app);
|
DumpPacket(app);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1672,7 +1679,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
|||||||
// normal skills go here
|
// normal skills go here
|
||||||
if (gmskill->skill_id > EQ::skills::HIGHEST_SKILL)
|
if (gmskill->skill_id > EQ::skills::HIGHEST_SKILL)
|
||||||
{
|
{
|
||||||
std::cout << "Wrong Training Skill (abilities)" << std::endl;
|
LogSkills("Wrong Training Skill (abilities)");
|
||||||
DumpPacket(app);
|
DumpPacket(app);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1691,11 +1698,12 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
uint16 skilllevel = GetRawSkill(skill);
|
uint16 skilllevel = GetRawSkill(skill);
|
||||||
|
|
||||||
if(skilllevel == 0) {
|
if (skilllevel == 0) {
|
||||||
//this is a new skill..
|
//this is a new skill..
|
||||||
uint16 t_level = SkillTrainLevel(skill, GetClass());
|
uint16 t_level = SkillTrainLevel(skill, GetClass());
|
||||||
if (t_level == 0)
|
|
||||||
{
|
if (t_level == 0) {
|
||||||
|
LogSkills("Tried to train a new skill [{}] which is invalid for this race/class.", skill);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1715,6 +1723,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
|||||||
case EQ::skills::SkillPottery:
|
case EQ::skills::SkillPottery:
|
||||||
if(skilllevel >= RuleI(Skills, MaxTrainTradeskills)) {
|
if(skilllevel >= RuleI(Skills, MaxTrainTradeskills)) {
|
||||||
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
||||||
|
SetSkill(skill, skilllevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1725,6 +1734,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
|||||||
case EQ::skills::SkillSpecializeEvocation:
|
case EQ::skills::SkillSpecializeEvocation:
|
||||||
if(skilllevel >= RuleI(Skills, MaxTrainSpecializations)) {
|
if(skilllevel >= RuleI(Skills, MaxTrainSpecializations)) {
|
||||||
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
||||||
|
SetSkill(skill, skilllevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -1736,6 +1746,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
// Don't allow training over max skill level
|
// Don't allow training over max skill level
|
||||||
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
||||||
|
SetSkill(skill, skilllevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1746,6 +1757,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
// Restrict specialization training to follow the rules
|
// Restrict specialization training to follow the rules
|
||||||
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
|
||||||
|
SetSkill(skill, skilllevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -100,6 +100,7 @@ int command_init(void)
|
|||||||
command_add("camerashake", "[Duration (Milliseconds)] [Intensity (1-10)] - Shakes the camera on everyone's screen globally.", AccountStatus::QuestTroupe, command_camerashake) ||
|
command_add("camerashake", "[Duration (Milliseconds)] [Intensity (1-10)] - Shakes the camera on everyone's screen globally.", AccountStatus::QuestTroupe, command_camerashake) ||
|
||||||
command_add("castspell", "[Spell ID] [Instant (0 = False, 1 = True, Default is 1 if Unused)] - Cast a spell", AccountStatus::Guide, command_castspell) ||
|
command_add("castspell", "[Spell ID] [Instant (0 = False, 1 = True, Default is 1 if Unused)] - Cast a spell", AccountStatus::Guide, command_castspell) ||
|
||||||
command_add("chat", "[Channel ID] [Message] - Send a channel message to all zones", AccountStatus::GMMgmt, command_chat) ||
|
command_add("chat", "[Channel ID] [Message] - Send a channel message to all zones", AccountStatus::GMMgmt, command_chat) ||
|
||||||
|
command_add("clearxtargets", "Clears XTargets", AccountStatus::Player, command_clearxtargets) ||
|
||||||
command_add("copycharacter", "[source_char_name] [dest_char_name] [dest_account_name] - Copies character to destination account", AccountStatus::GMImpossible, command_copycharacter) ||
|
command_add("copycharacter", "[source_char_name] [dest_char_name] [dest_account_name] - Copies character to destination account", AccountStatus::GMImpossible, command_copycharacter) ||
|
||||||
command_add("corpse", "Manipulate corpses, use with no arguments for help", AccountStatus::Guide, command_corpse) ||
|
command_add("corpse", "Manipulate corpses, use with no arguments for help", AccountStatus::Guide, command_corpse) ||
|
||||||
command_add("corpsefix", "Attempts to bring corpses from underneath the ground within close proximity of the player", AccountStatus::Player, command_corpsefix) ||
|
command_add("corpsefix", "Attempts to bring corpses from underneath the ground within close proximity of the player", AccountStatus::Player, command_corpsefix) ||
|
||||||
@@ -238,7 +239,6 @@ int command_init(void)
|
|||||||
command_add("zonebootup", "[ZoneServerID] [shortname] - Make a zone server boot a specific zone", AccountStatus::GMLeadAdmin, command_zonebootup) ||
|
command_add("zonebootup", "[ZoneServerID] [shortname] - Make a zone server boot a specific zone", AccountStatus::GMLeadAdmin, command_zonebootup) ||
|
||||||
command_add("zoneinstance", "[Instance ID] [X] [Y] [Z] - Teleport to specified Instance by ID (coordinates are optional)", AccountStatus::Guide, command_zone_instance) ||
|
command_add("zoneinstance", "[Instance ID] [X] [Y] [Z] - Teleport to specified Instance by ID (coordinates are optional)", AccountStatus::Guide, command_zone_instance) ||
|
||||||
command_add("zoneshutdown", "[shortname] - Shut down a zone server", AccountStatus::GMLeadAdmin, command_zoneshutdown) ||
|
command_add("zoneshutdown", "[shortname] - Shut down a zone server", AccountStatus::GMLeadAdmin, command_zoneshutdown) ||
|
||||||
command_add("zopp", "Troubleshooting command - Sends a fake item packet to you. No server reference is created.", AccountStatus::GMImpossible, command_zopp) ||
|
|
||||||
command_add("zsave", " Saves zheader to the database", AccountStatus::QuestTroupe, command_zsave)
|
command_add("zsave", " Saves zheader to the database", AccountStatus::QuestTroupe, command_zsave)
|
||||||
) {
|
) {
|
||||||
command_deinit();
|
command_deinit();
|
||||||
@@ -792,6 +792,7 @@ void command_bot(Client *c, const Seperator *sep)
|
|||||||
#include "gm_commands/camerashake.cpp"
|
#include "gm_commands/camerashake.cpp"
|
||||||
#include "gm_commands/castspell.cpp"
|
#include "gm_commands/castspell.cpp"
|
||||||
#include "gm_commands/chat.cpp"
|
#include "gm_commands/chat.cpp"
|
||||||
|
#include "gm_commands/clearxtargets.cpp"
|
||||||
#include "gm_commands/copycharacter.cpp"
|
#include "gm_commands/copycharacter.cpp"
|
||||||
#include "gm_commands/corpse.cpp"
|
#include "gm_commands/corpse.cpp"
|
||||||
#include "gm_commands/corpsefix.cpp"
|
#include "gm_commands/corpsefix.cpp"
|
||||||
@@ -925,5 +926,4 @@ void command_bot(Client *c, const Seperator *sep)
|
|||||||
#include "gm_commands/zonebootup.cpp"
|
#include "gm_commands/zonebootup.cpp"
|
||||||
#include "gm_commands/zoneshutdown.cpp"
|
#include "gm_commands/zoneshutdown.cpp"
|
||||||
#include "gm_commands/zone_instance.cpp"
|
#include "gm_commands/zone_instance.cpp"
|
||||||
#include "gm_commands/zopp.cpp"
|
|
||||||
#include "gm_commands/zsave.cpp"
|
#include "gm_commands/zsave.cpp"
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ void SendNPCEditSubCommands(Client *c);
|
|||||||
void SendRuleSubCommands(Client *c);
|
void SendRuleSubCommands(Client *c);
|
||||||
void SendGuildSubCommands(Client *c);
|
void SendGuildSubCommands(Client *c);
|
||||||
void SendShowInventorySubCommands(Client *c);
|
void SendShowInventorySubCommands(Client *c);
|
||||||
|
void SendFixMobSubCommands(Client *c);
|
||||||
|
void SendDataBucketsSubCommands(Client *c);
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
void command_acceptrules(Client *c, const Seperator *sep);
|
void command_acceptrules(Client *c, const Seperator *sep);
|
||||||
@@ -51,6 +53,7 @@ void command_bugs(Client *c, const Seperator *sep);
|
|||||||
void command_camerashake(Client *c, const Seperator *sep);
|
void command_camerashake(Client *c, const Seperator *sep);
|
||||||
void command_castspell(Client *c, const Seperator *sep);
|
void command_castspell(Client *c, const Seperator *sep);
|
||||||
void command_chat(Client *c, const Seperator *sep);
|
void command_chat(Client *c, const Seperator *sep);
|
||||||
|
void command_clearxtargets(Client *c, const Seperator *sep);
|
||||||
void command_copycharacter(Client *c, const Seperator *sep);
|
void command_copycharacter(Client *c, const Seperator *sep);
|
||||||
void command_corpse(Client *c, const Seperator *sep);
|
void command_corpse(Client *c, const Seperator *sep);
|
||||||
void command_corpsefix(Client *c, const Seperator *sep);
|
void command_corpsefix(Client *c, const Seperator *sep);
|
||||||
|
|||||||
+1
-1
@@ -927,7 +927,7 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data)
|
|||||||
|
|
||||||
UpdateEquipmentLight();
|
UpdateEquipmentLight();
|
||||||
if (UpdateActiveLight())
|
if (UpdateActiveLight())
|
||||||
SendAppearancePacket(AT_Light, GetActiveLightType());
|
SendAppearancePacket(AppearanceType::Light, GetActiveLightType());
|
||||||
|
|
||||||
safe_delete(sitem);
|
safe_delete(sitem);
|
||||||
return;
|
return;
|
||||||
|
|||||||
+18
-2
@@ -592,6 +592,22 @@ int32 Mob::GetActSpellCost(uint16 spell_id, int32 cost)
|
|||||||
|
|
||||||
int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration)
|
int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration)
|
||||||
{
|
{
|
||||||
|
// focuses don't affect discipline duration (Except War Cries)
|
||||||
|
if (
|
||||||
|
IsDiscipline(spell_id) &&
|
||||||
|
(
|
||||||
|
spell_id != SPELL_BATTLE_CRY &&
|
||||||
|
spell_id != SPELL_WAR_CRY &&
|
||||||
|
spell_id != SPELL_BATTLE_CRY_OF_DRAVEL &&
|
||||||
|
spell_id != SPELL_WAR_CRY_OF_DRAVEL &&
|
||||||
|
spell_id != SPELL_BATTLE_CRY_OF_THE_MASTRUQ &&
|
||||||
|
spell_id != SPELL_ANCIENT_CRY_OF_CHAOS &&
|
||||||
|
spell_id != SPELL_BLOODTHIRST
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
int increase = 100;
|
int increase = 100;
|
||||||
increase += GetFocusEffect(focusSpellDuration, spell_id);
|
increase += GetFocusEffect(focusSpellDuration, spell_id);
|
||||||
int tic_inc = 0;
|
int tic_inc = 0;
|
||||||
@@ -690,7 +706,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
|
|||||||
return false;
|
return false;
|
||||||
} else if (m_pp.disciplines.values[r] == 0) {
|
} else if (m_pp.disciplines.values[r] == 0) {
|
||||||
m_pp.disciplines.values[r] = spell_id;
|
m_pp.disciplines.values[r] = spell_id;
|
||||||
database.SaveCharacterDisc(CharacterID(), r, spell_id);
|
database.SaveCharacterDiscipline(CharacterID(), r, spell_id);
|
||||||
SendDisciplineUpdate();
|
SendDisciplineUpdate();
|
||||||
Message(Chat::White, "You have learned a new discipline!");
|
Message(Chat::White, "You have learned a new discipline!");
|
||||||
return true;
|
return true;
|
||||||
@@ -789,7 +805,7 @@ void Client::TrainDiscBySpellID(int32 spell_id)
|
|||||||
for(i = 0; i < MAX_PP_DISCIPLINES; i++) {
|
for(i = 0; i < MAX_PP_DISCIPLINES; i++) {
|
||||||
if(m_pp.disciplines.values[i] == 0) {
|
if(m_pp.disciplines.values[i] == 0) {
|
||||||
m_pp.disciplines.values[i] = spell_id;
|
m_pp.disciplines.values[i] = spell_id;
|
||||||
database.SaveCharacterDisc(CharacterID(), i, spell_id);
|
database.SaveCharacterDiscipline(CharacterID(), i, spell_id);
|
||||||
SendDisciplineUpdate();
|
SendDisciplineUpdate();
|
||||||
Message(Chat::Yellow, "You have learned a new combat ability!");
|
Message(Chat::Yellow, "You have learned a new combat ability!");
|
||||||
return;
|
return;
|
||||||
|
|||||||
+1
-1
@@ -1891,6 +1891,7 @@ void PerlembParser::ExportEventVariables(
|
|||||||
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
|
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
|
||||||
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
|
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
|
||||||
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
|
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
|
||||||
|
ExportVar(package_name.c_str(), "killed_entity_id", sep.arg[4]);
|
||||||
|
|
||||||
if (extra_pointers && extra_pointers->size() >= 1) {
|
if (extra_pointers && extra_pointers->size() >= 1) {
|
||||||
Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0));
|
Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0));
|
||||||
@@ -1902,7 +1903,6 @@ void PerlembParser::ExportEventVariables(
|
|||||||
if (extra_pointers && extra_pointers->size() >= 2) {
|
if (extra_pointers && extra_pointers->size() >= 2) {
|
||||||
NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1));
|
NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1));
|
||||||
if (killed) {
|
if (killed) {
|
||||||
ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID());
|
|
||||||
ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
|
ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
|
||||||
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
|
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
|
||||||
ExportVar(package_name.c_str(), "killed_x", killed->GetX());
|
ExportVar(package_name.c_str(), "killed_x", killed->GetX());
|
||||||
|
|||||||
+12
-12
@@ -93,13 +93,13 @@ void Perl__say(const char* message)
|
|||||||
// we currently default to these
|
// we currently default to these
|
||||||
opts.speak_mode = Journal::SpeakMode::Say;
|
opts.speak_mode = Journal::SpeakMode::Say;
|
||||||
opts.journal_mode = Journal::Mode::Log2;
|
opts.journal_mode = Journal::Mode::Log2;
|
||||||
opts.language = 0;
|
opts.language = Language::CommonTongue;
|
||||||
opts.message_type = Chat::NPCQuestSay;
|
opts.message_type = Chat::NPCQuestSay;
|
||||||
|
|
||||||
quest_manager.say(message, opts);
|
quest_manager.say(message, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__say(const char* message, int language_id)
|
void Perl__say(const char* message, uint8 language_id)
|
||||||
{
|
{
|
||||||
Journal::Options opts;
|
Journal::Options opts;
|
||||||
opts.speak_mode = Journal::SpeakMode::Say;
|
opts.speak_mode = Journal::SpeakMode::Say;
|
||||||
@@ -110,7 +110,7 @@ void Perl__say(const char* message, int language_id)
|
|||||||
quest_manager.say(message, opts);
|
quest_manager.say(message, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__say(const char* message, int language_id, int message_type)
|
void Perl__say(const char* message, uint8 language_id, int message_type)
|
||||||
{
|
{
|
||||||
Journal::Options opts;
|
Journal::Options opts;
|
||||||
opts.speak_mode = Journal::SpeakMode::Say;
|
opts.speak_mode = Journal::SpeakMode::Say;
|
||||||
@@ -121,7 +121,7 @@ void Perl__say(const char* message, int language_id, int message_type)
|
|||||||
quest_manager.say(message, opts);
|
quest_manager.say(message, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__say(const char* message, int language_id, int message_type, int speak_mode)
|
void Perl__say(const char* message, uint8 language_id, int message_type, int speak_mode)
|
||||||
{
|
{
|
||||||
Journal::Options opts;
|
Journal::Options opts;
|
||||||
opts.speak_mode = static_cast<Journal::SpeakMode>(speak_mode);
|
opts.speak_mode = static_cast<Journal::SpeakMode>(speak_mode);
|
||||||
@@ -132,7 +132,7 @@ void Perl__say(const char* message, int language_id, int message_type, int speak
|
|||||||
quest_manager.say(message, opts);
|
quest_manager.say(message, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__say(const char* message, int language_id, int message_type, int speak_mode, int journal_mode)
|
void Perl__say(const char* message, uint8 language_id, int message_type, int speak_mode, int journal_mode)
|
||||||
{
|
{
|
||||||
Journal::Options opts;
|
Journal::Options opts;
|
||||||
opts.speak_mode = static_cast<Journal::SpeakMode>(speak_mode);
|
opts.speak_mode = static_cast<Journal::SpeakMode>(speak_mode);
|
||||||
@@ -674,9 +674,9 @@ void Perl__addskill(int skill_id, int value)
|
|||||||
quest_manager.addskill(skill_id, value);
|
quest_manager.addskill(skill_id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__setlanguage(int skill_id, int value)
|
void Perl__setlanguage(uint8 language_id, uint8 language_skill)
|
||||||
{
|
{
|
||||||
quest_manager.setlanguage(skill_id, value);
|
quest_manager.setlanguage(language_id, language_skill);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perl__setskill(int skill_id, int value)
|
void Perl__setskill(int skill_id, int value)
|
||||||
@@ -4713,7 +4713,7 @@ std::string Perl__getfactionname(int faction_id)
|
|||||||
return quest_manager.getfactionname(faction_id);
|
return quest_manager.getfactionname(faction_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Perl__getlanguagename(int language_id)
|
std::string Perl__getlanguagename(uint8 language_id)
|
||||||
{
|
{
|
||||||
return quest_manager.getlanguagename(language_id);
|
return quest_manager.getlanguagename(language_id);
|
||||||
}
|
}
|
||||||
@@ -6532,10 +6532,10 @@ void perl_register_quest()
|
|||||||
package.add("safemove", &Perl__safemove);
|
package.add("safemove", &Perl__safemove);
|
||||||
package.add("save", &Perl__save);
|
package.add("save", &Perl__save);
|
||||||
package.add("say", (void(*)(const char*))&Perl__say);
|
package.add("say", (void(*)(const char*))&Perl__say);
|
||||||
package.add("say", (void(*)(const char*, int))&Perl__say);
|
package.add("say", (void(*)(const char*, uint8))&Perl__say);
|
||||||
package.add("say", (void(*)(const char*, int, int))&Perl__say);
|
package.add("say", (void(*)(const char*, uint8, int))&Perl__say);
|
||||||
package.add("say", (void(*)(const char*, int, int, int))&Perl__say);
|
package.add("say", (void(*)(const char*, uint8, int, int))&Perl__say);
|
||||||
package.add("say", (void(*)(const char*, int, 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(*)(const char*))&Perl__saylink);
|
||||||
package.add("saylink", (std::string(*)(const char*, bool))&Perl__saylink);
|
package.add("saylink", (std::string(*)(const char*, bool))&Perl__saylink);
|
||||||
package.add("saylink", (std::string(*)(const char*, bool, const char*))&Perl__saylink);
|
package.add("saylink", (std::string(*)(const char*, bool, const char*))&Perl__saylink);
|
||||||
|
|||||||
+3
-3
@@ -37,9 +37,9 @@ Encounter::Encounter(const char *enc_name) : Mob(
|
|||||||
nullptr, // in_lastname
|
nullptr, // in_lastname
|
||||||
0, // in_cur_hp
|
0, // in_cur_hp
|
||||||
0, // in_max_hp
|
0, // in_max_hp
|
||||||
MALE, // in_gender
|
Gender::Male, // in_gender
|
||||||
INVISIBLE_MAN, // in_race
|
Race::InvisibleMan, // in_race
|
||||||
0, // in_class
|
Class::None, // in_class
|
||||||
BT_NoTarget, // in_bodytype
|
BT_NoTarget, // in_bodytype
|
||||||
0, // in_deity
|
0, // in_deity
|
||||||
0, // in_level
|
0, // in_level
|
||||||
|
|||||||
+45
-21
@@ -1282,7 +1282,7 @@ uint16 EntityList::GetFreeID()
|
|||||||
// if no language skill is specified, sent with 100 skill
|
// if no language skill is specified, sent with 100 skill
|
||||||
void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language, const char *message, ...)
|
void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language, const char *message, ...)
|
||||||
{
|
{
|
||||||
ChannelMessage(from, chan_num, language, 100, message);
|
ChannelMessage(from, chan_num, language, Language::MaxValue, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language,
|
void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language,
|
||||||
@@ -1411,7 +1411,7 @@ void EntityList::SendZonePVPUpdates(Client *to)
|
|||||||
while (it != client_list.end()) {
|
while (it != client_list.end()) {
|
||||||
Client *c = it->second;
|
Client *c = it->second;
|
||||||
if(c->GetPVP())
|
if(c->GetPVP())
|
||||||
c->SendAppearancePacket(AT_PVP, c->GetPVP(), true, false, to);
|
c->SendAppearancePacket(AppearanceType::PVP, c->GetPVP(), true, false, to);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1491,18 +1491,21 @@ void EntityList::RemoveFromTargets(Mob *mob, bool RemoveFromXTargets)
|
|||||||
Mob *m = it->second;
|
Mob *m = it->second;
|
||||||
++it;
|
++it;
|
||||||
|
|
||||||
if (!m)
|
if (!m) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (RemoveFromXTargets && mob) {
|
if (RemoveFromXTargets && mob) {
|
||||||
if (m->IsClient() && (mob->CheckAggro(m) || mob->IsOnFeignMemory(m)))
|
if (m->IsClient() && (mob->CheckAggro(m) || mob->IsOnFeignMemory(m))) {
|
||||||
m->CastToClient()->RemoveXTarget(mob, false);
|
m->CastToClient()->RemoveXTarget(mob, false);
|
||||||
// FadingMemories calls this function passing the client.
|
// FadingMemories calls this function passing the client.
|
||||||
else if (mob->IsClient() && (m->CheckAggro(mob) || m->IsOnFeignMemory(mob)))
|
} else if (mob->IsClient() && (m->CheckAggro(mob) || m->IsOnFeignMemory(mob))) {
|
||||||
mob->CastToClient()->RemoveXTarget(m, false);
|
mob->CastToClient()->RemoveXTarget(m, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m->RemoveFromHateList(mob);
|
m->RemoveFromHateList(mob);
|
||||||
|
m->RemoveFromRampageList(mob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1515,20 +1518,24 @@ void EntityList::RemoveFromTargetsFadingMemories(Mob *spell_target, bool RemoveF
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_level && mob->GetLevel() > max_level)
|
if (max_level && mob->GetLevel() > max_level) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (mob->GetSpecialAbility(IMMUNE_FADING_MEMORIES))
|
if (mob->GetSpecialAbility(IMMUNE_FADING_MEMORIES)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (RemoveFromXTargets && spell_target) {
|
if (RemoveFromXTargets && spell_target) {
|
||||||
if (mob->IsClient() && (spell_target->CheckAggro(mob) || spell_target->IsOnFeignMemory(mob)))
|
if (mob->IsClient() && (spell_target->CheckAggro(mob) || spell_target->IsOnFeignMemory(mob))) {
|
||||||
mob->CastToClient()->RemoveXTarget(spell_target, false);
|
mob->CastToClient()->RemoveXTarget(spell_target, false);
|
||||||
else if (spell_target->IsClient() && (mob->CheckAggro(spell_target) || mob->IsOnFeignMemory(spell_target)))
|
} else if (spell_target->IsClient() && (mob->CheckAggro(spell_target) || mob->IsOnFeignMemory(spell_target))) {
|
||||||
spell_target->CastToClient()->RemoveXTarget(mob, false);
|
spell_target->CastToClient()->RemoveXTarget(mob, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mob->RemoveFromHateList(spell_target);
|
mob->RemoveFromHateList(spell_target);
|
||||||
|
mob->RemoveFromRampageList(spell_target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1814,14 +1821,14 @@ void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Client *EntityList::GetClientByName(const char *checkname)
|
Client *EntityList::GetClientByName(const char* name)
|
||||||
{
|
{
|
||||||
auto it = client_list.begin();
|
for (const auto& e : client_list) {
|
||||||
while (it != client_list.end()) {
|
if (e.second && Strings::EqualFold(e.second->GetName(), name)) {
|
||||||
if (strcasecmp(it->second->GetName(), checkname) == 0)
|
return e.second;
|
||||||
return it->second;
|
}
|
||||||
++it;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3188,8 +3195,10 @@ void EntityList::RemoveFromHateLists(Mob *mob, bool settoone)
|
|||||||
if (it->second->CheckAggro(mob)) {
|
if (it->second->CheckAggro(mob)) {
|
||||||
if (!settoone) {
|
if (!settoone) {
|
||||||
it->second->RemoveFromHateList(mob);
|
it->second->RemoveFromHateList(mob);
|
||||||
if (mob->IsClient())
|
it->second->RemoveFromRampageList(mob);
|
||||||
|
if (mob->IsClient()) {
|
||||||
mob->CastToClient()->RemoveXTarget(it->second, false); // gotta do book keeping
|
mob->CastToClient()->RemoveXTarget(it->second, false); // gotta do book keeping
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
it->second->SetHateAmountOnEnt(mob, 1);
|
it->second->SetHateAmountOnEnt(mob, 1);
|
||||||
}
|
}
|
||||||
@@ -3536,20 +3545,29 @@ void EntityList::HalveAggro(Mob *who)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//removes "targ" from all hate lists, including feigned, in the zone
|
//removes "targ" from all hate lists, including feigned, in the zone
|
||||||
void EntityList::ClearAggro(Mob* targ)
|
void EntityList::ClearAggro(Mob* targ, bool clear_caster_id)
|
||||||
{
|
{
|
||||||
Client *c = nullptr;
|
Client *c = nullptr;
|
||||||
|
|
||||||
if (targ->IsClient()) {
|
if (targ->IsClient()) {
|
||||||
c = targ->CastToClient();
|
c = targ->CastToClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = npc_list.begin();
|
auto it = npc_list.begin();
|
||||||
while (it != npc_list.end()) {
|
while (it != npc_list.end()) {
|
||||||
|
if (clear_caster_id) {
|
||||||
|
it->second->BuffDetachCaster(targ);
|
||||||
|
}
|
||||||
|
|
||||||
if (it->second->CheckAggro(targ)) {
|
if (it->second->CheckAggro(targ)) {
|
||||||
if (c) {
|
if (c) {
|
||||||
c->RemoveXTarget(it->second, false);
|
c->RemoveXTarget(it->second, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
it->second->RemoveFromHateList(targ);
|
it->second->RemoveFromHateList(targ);
|
||||||
|
it->second->RemoveFromRampageList(targ, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c && it->second->IsOnFeignMemory(c)) {
|
if (c && it->second->IsOnFeignMemory(c)) {
|
||||||
it->second->RemoveFromFeignMemory(c); //just in case we feigned
|
it->second->RemoveFromFeignMemory(c); //just in case we feigned
|
||||||
c->RemoveXTarget(it->second, false);
|
c->RemoveXTarget(it->second, false);
|
||||||
@@ -3573,6 +3591,7 @@ void EntityList::ClearWaterAggro(Mob* targ)
|
|||||||
c->RemoveXTarget(it->second, false);
|
c->RemoveXTarget(it->second, false);
|
||||||
}
|
}
|
||||||
it->second->RemoveFromHateList(targ);
|
it->second->RemoveFromHateList(targ);
|
||||||
|
it->second->RemoveFromRampageList(targ);
|
||||||
}
|
}
|
||||||
if (c && it->second->IsOnFeignMemory(c)) {
|
if (c && it->second->IsOnFeignMemory(c)) {
|
||||||
it->second->RemoveFromFeignMemory(c); //just in case we feigned
|
it->second->RemoveFromFeignMemory(c); //just in case we feigned
|
||||||
@@ -3618,6 +3637,11 @@ void EntityList::ClearFeignAggro(Mob *targ)
|
|||||||
}
|
}
|
||||||
|
|
||||||
it->second->RemoveFromHateList(targ);
|
it->second->RemoveFromHateList(targ);
|
||||||
|
|
||||||
|
if (it->second->GetSpecialAbility(SPECATK_RAMPAGE)) {
|
||||||
|
it->second->RemoveFromRampageList(targ, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (targ->IsClient()) {
|
if (targ->IsClient()) {
|
||||||
if (it->second->GetLevel() >= 35 && zone->random.Roll(60)) {
|
if (it->second->GetLevel() >= 35 && zone->random.Roll(60)) {
|
||||||
it->second->AddFeignMemory(targ);
|
it->second->AddFeignMemory(targ);
|
||||||
@@ -4588,7 +4612,7 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message)
|
|||||||
g = it->second->GetGroup();
|
g = it->second->GetGroup();
|
||||||
if (g) {
|
if (g) {
|
||||||
if (g->GetID() == gid)
|
if (g->GetID() == gid)
|
||||||
it->second->ChannelMessageSend(from, it->second->GetName(), ChatChannel_Group, 0, 100, message);
|
it->second->ChannelMessageSend(from, it->second->GetName(), ChatChannel_Group, Language::CommonTongue, Language::MaxValue, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
@@ -4704,10 +4728,10 @@ void EntityList::SendZoneAppearance(Client *c)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cur->GetAppearance() != eaStanding) {
|
if (cur->GetAppearance() != eaStanding) {
|
||||||
cur->SendAppearancePacket(AT_Anim, cur->GetAppearanceValue(cur->GetAppearance()), false, true, c);
|
cur->SendAppearancePacket(AppearanceType::Animation, cur->GetAppearanceValue(cur->GetAppearance()), false, true, c);
|
||||||
}
|
}
|
||||||
if (cur->GetSize() != cur->GetBaseSize()) {
|
if (cur->GetSize() != cur->GetBaseSize()) {
|
||||||
cur->SendAppearancePacket(AT_Size, (uint32) cur->GetSize(), false, true, c);
|
cur->SendAppearancePacket(AppearanceType::Size, (uint32) cur->GetSize(), false, true, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
@@ -4781,7 +4805,7 @@ void EntityList::SendAppearanceEffects(Client *c)
|
|||||||
++it;
|
++it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cur->SendSavedAppearenceEffects(c);
|
cur->SendSavedAppearanceEffects(c);
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -171,7 +171,7 @@ public:
|
|||||||
return it->second;
|
return it->second;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
Client *GetClientByName(const char *name);
|
Client *GetClientByName(const char* name);
|
||||||
Client *GetClientByAccID(uint32 accid);
|
Client *GetClientByAccID(uint32 accid);
|
||||||
inline Client *GetClientByID(uint16 id)
|
inline Client *GetClientByID(uint16 id)
|
||||||
{
|
{
|
||||||
@@ -463,7 +463,7 @@ public:
|
|||||||
void UpdateHoTT(Mob* target);
|
void UpdateHoTT(Mob* target);
|
||||||
|
|
||||||
void Process();
|
void Process();
|
||||||
void ClearAggro(Mob* targ);
|
void ClearAggro(Mob* targ, bool clear_caster_id = false);
|
||||||
void ClearWaterAggro(Mob* targ);
|
void ClearWaterAggro(Mob* targ);
|
||||||
void ClearFeignAggro(Mob* targ);
|
void ClearFeignAggro(Mob* targ);
|
||||||
void ClearZoneFeignAggro(Mob* targ);
|
void ClearZoneFeignAggro(Mob* targ);
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with this library; if not, write to the Free
|
|
||||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
||||||
MA 02111-1307, USA */
|
|
||||||
|
|
||||||
/* Error messages for mysql clients */
|
|
||||||
/* error messages for the demon is in share/language/errmsg.sys */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void init_client_errs(void);
|
|
||||||
extern const char *client_errors[]; /* Error messages */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CR_MIN_ERROR 2000 /* For easier client code */
|
|
||||||
#define CR_MAX_ERROR 2999
|
|
||||||
#if defined(OS2) && defined( MYSQL_SERVER)
|
|
||||||
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
|
|
||||||
#else
|
|
||||||
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
|
|
||||||
#endif
|
|
||||||
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
|
|
||||||
|
|
||||||
#define CR_UNKNOWN_ERROR 2000
|
|
||||||
#define CR_SOCKET_CREATE_ERROR 2001
|
|
||||||
#define CR_CONNECTION_ERROR 2002
|
|
||||||
#define CR_CONN_HOST_ERROR 2003
|
|
||||||
#define CR_IPSOCK_ERROR 2004
|
|
||||||
#define CR_UNKNOWN_HOST 2005
|
|
||||||
#define CR_SERVER_GONE_ERROR 2006
|
|
||||||
#define CR_VERSION_ERROR 2007
|
|
||||||
#define CR_OUT_OF_MEMORY 2008
|
|
||||||
#define CR_WRONG_HOST_INFO 2009
|
|
||||||
#define CR_LOCALHOST_CONNECTION 2010
|
|
||||||
#define CR_TCP_CONNECTION 2011
|
|
||||||
#define CR_SERVER_HANDSHAKE_ERR 2012
|
|
||||||
#define CR_SERVER_LOST 2013
|
|
||||||
#define CR_COMMANDS_OUT_OF_SYNC 2014
|
|
||||||
#define CR_NAMEDPIPE_CONNECTION 2015
|
|
||||||
#define CR_NAMEDPIPEWAIT_ERROR 2016
|
|
||||||
#define CR_NAMEDPIPEOPEN_ERROR 2017
|
|
||||||
#define CR_NAMEDPIPESETSTATE_ERROR 2018
|
|
||||||
#define CR_CANT_READ_CHARSET 2019
|
|
||||||
#define CR_NET_PACKET_TOO_LARGE 2020
|
|
||||||
|
|
||||||
+1
-1
@@ -950,7 +950,7 @@ void Client::SetLevel(uint8 set_level, bool command)
|
|||||||
|
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
SendAppearancePacket(AT_WhoLevel, set_level); // who level change
|
SendAppearancePacket(AppearanceType::WhoLevel, set_level); // who level change
|
||||||
|
|
||||||
LogInfo("Setting Level for [{}] to [{}]", GetName(), set_level);
|
LogInfo("Setting Level for [{}] to [{}]", GetName(), set_level);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ void command_acceptrules(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
database.SetAgreementFlag(c->AccountID());
|
database.SetAgreementFlag(c->AccountID());
|
||||||
c->SendAppearancePacket(AT_Anim, ANIM_STAND);
|
c->SendAppearancePacket(AppearanceType::Animation, Animation::Standing);
|
||||||
c->Message(Chat::White, "It is recorded you have agreed to the rules.");
|
c->Message(Chat::White, "It is recorded you have agreed to the rules.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,25 +2,43 @@
|
|||||||
|
|
||||||
void command_appearance(Client *c, const Seperator *sep)
|
void command_appearance(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
Mob *t = c->CastToMob();
|
const int arguments = sep->argnum;
|
||||||
|
if (!arguments || !sep->IsNumber(1) || !sep->IsNumber(2)) {
|
||||||
|
c->Message(Chat::White, "Usage: #appearance [Type] [Value]");
|
||||||
|
c->Message(Chat::White, "Note: Types are as follows:");
|
||||||
|
|
||||||
// sends any appearance packet
|
for (const auto& a : EQ::constants::GetAppearanceTypeMap()) {
|
||||||
// Dev debug command, for appearance types
|
c->Message(
|
||||||
if (sep->arg[2][0] == 0) {
|
Chat::White,
|
||||||
c->Message(Chat::White, "Usage: #appearance type value");
|
fmt::format(
|
||||||
}
|
"Appearance Type {} | {}",
|
||||||
else {
|
a.first,
|
||||||
if ((c->GetTarget())) {
|
a.second
|
||||||
t = c->GetTarget();
|
).c_str()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
t->SendAppearancePacket(Strings::ToInt(sep->arg[1]), Strings::ToInt(sep->arg[2]));
|
|
||||||
c->Message(
|
|
||||||
Chat::White,
|
|
||||||
"Sending appearance packet: target=%s, type=%s, value=%s",
|
|
||||||
t->GetName(),
|
|
||||||
sep->arg[1],
|
|
||||||
sep->arg[2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mob *t = c;
|
||||||
|
if (c->GetTarget()) {
|
||||||
|
t = c->GetTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 type = Strings::ToUnsignedInt(sep->arg[1]);
|
||||||
|
const uint32 value = Strings::ToUnsignedInt(sep->arg[2]);
|
||||||
|
|
||||||
|
t->SendAppearancePacket(type, value);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Appearance Sent to {} | Type: {} ({}) Value: {}",
|
||||||
|
c->GetTargetDescription(t, TargetDescriptionType::UCSelf),
|
||||||
|
EQ::constants::GetAppearanceTypeName(type),
|
||||||
|
type,
|
||||||
|
value
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ void command_appearanceeffects(Client *c, const Seperator *sep)
|
|||||||
.texture = t->GetTexture(),
|
.texture = t->GetTexture(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
t->ClearAppearenceEffects();
|
t->ClearAppearanceEffects();
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ void command_chat(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
auto channel_id = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1]));
|
auto channel_id = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1]));
|
||||||
std::string message = sep->argplus[2];
|
std::string message = sep->argplus[2];
|
||||||
if (!worldserver.SendChannelMessage(0, 0, channel_id, 0, 0, 100, message.c_str())) {
|
if (!worldserver.SendChannelMessage(0, 0, channel_id, 0, Language::CommonTongue, Language::MaxValue, message.c_str())) {
|
||||||
c->Message(Chat::White, "World server is disconnected.");
|
c->Message(Chat::White, "World server is disconnected.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#include "../client.h"
|
||||||
|
|
||||||
|
void command_clearxtargets(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
const int reuse_timer = RuleI(Character, ClearXTargetDelay);
|
||||||
|
|
||||||
|
const int arguments = sep->argnum;
|
||||||
|
if (arguments) {
|
||||||
|
const bool is_help = !strcasecmp(sep->arg[1], "help");
|
||||||
|
|
||||||
|
if (is_help) {
|
||||||
|
c->Message(Chat::White, "Usage: #clearxtargets");
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
"Note: Use this if your Extended Target window is bugged or has lingering targets that are invalid."
|
||||||
|
);
|
||||||
|
if (reuse_timer) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Note: This can only be used every {}.",
|
||||||
|
Strings::SecondsToTime(reuse_timer)
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reuse_timer) {
|
||||||
|
const uint32 time_left = c->GetPTimers().GetRemainingTime(pTimerClearXTarget);
|
||||||
|
if (!c->GetPTimers().Expired(&database, pTimerClearXTarget, false)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"You must wait {} before using this command again.",
|
||||||
|
Strings::SecondsToTime(time_left)
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c->ClearXTargets();
|
||||||
|
c->Message(Chat::White, "Extended Target window has been cleared.");
|
||||||
|
|
||||||
|
if (reuse_timer) {
|
||||||
|
c->GetPTimers().Start(pTimerClearXTarget, reuse_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,92 +1,262 @@
|
|||||||
#include "../client.h"
|
#include "../client.h"
|
||||||
#include "../data_bucket.h"
|
#include "../data_bucket.h"
|
||||||
|
#include "../dialogue_window.h"
|
||||||
|
#include "../../common/repositories/data_buckets_repository.h"
|
||||||
|
|
||||||
void command_databuckets(Client *c, const Seperator *sep)
|
void command_databuckets(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
if (sep->arg[1][0] == 0) {
|
const int arguments = sep->argnum;
|
||||||
c->Message(Chat::Yellow, "Usage: #databuckets view (partial key)|(limit) OR #databuckets delete (key)");
|
if (!arguments) {
|
||||||
|
SendDataBucketsSubCommands(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcasecmp(sep->arg[1], "view") == 0) {
|
|
||||||
|
|
||||||
std::string key_filter;
|
const bool is_delete = !strcasecmp(sep->arg[1], "delete");
|
||||||
uint8 limit = 50;
|
const bool is_edit = !strcasecmp(sep->arg[1], "edit");
|
||||||
for (int i = 2; i < 4; i++) {
|
const bool is_view = !strcasecmp(sep->arg[1], "view");
|
||||||
if (sep->arg[i][0] == '\0') {
|
|
||||||
break;
|
if (
|
||||||
}
|
!is_delete &&
|
||||||
if (strcasecmp(sep->arg[i], "limit") == 0) {
|
!is_edit &&
|
||||||
limit = (uint8) Strings::ToInt(sep->arg[i + 1]);
|
!is_view
|
||||||
continue;
|
) {
|
||||||
}
|
SendDataBucketsSubCommands(c);
|
||||||
}
|
return;
|
||||||
if (sep->arg[2]) {
|
}
|
||||||
key_filter = Strings::ToLower(sep->arg[2]);
|
|
||||||
}
|
if (is_delete) {
|
||||||
std::string query = "SELECT `id`, `key`, `value`, `expires` FROM data_buckets";
|
if (arguments < 2) {
|
||||||
if (!key_filter.empty()) { query += StringFormat(" WHERE `key` LIKE '%%%s%%'", key_filter.c_str()); }
|
SendDataBucketsSubCommands(c);
|
||||||
query += StringFormat(" LIMIT %u", limit);
|
|
||||||
auto results = database.QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (results.RowCount() == 0) {
|
|
||||||
c->Message(Chat::Yellow, "No data_buckets found");
|
const std::string& key_filter = sep->arg[2];
|
||||||
return;
|
|
||||||
}
|
const uint32 character_id = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0;
|
||||||
int _ctr = 0;
|
const uint32 npc_id = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0;
|
||||||
// put in window for easier readability in case want command line for something else
|
const uint32 bot_id = sep->IsNumber(5) ? Strings::ToUnsignedInt(sep->arg[5]) : 0;
|
||||||
std::string window_title = "Data Buckets";
|
|
||||||
std::string window_text =
|
if (
|
||||||
"<table>"
|
!character_id &&
|
||||||
"<tr>"
|
!npc_id &&
|
||||||
"<td>ID</td>"
|
!bot_id
|
||||||
"<td>Expires</td>"
|
) {
|
||||||
"<td>Key</td>"
|
if (!DataBucket::DeleteData(key_filter)) {
|
||||||
"<td>Value</td>"
|
c->Message(
|
||||||
"</tr>";
|
Chat::White,
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
fmt::format(
|
||||||
auto id = static_cast<uint32>(Strings::ToInt(row[0]));
|
"An error occurred deleting data bucket '{}'.",
|
||||||
std::string key = row[1];
|
key_filter
|
||||||
std::string value = row[2];
|
).c_str()
|
||||||
std::string expires = row[3];
|
);
|
||||||
window_text.append(
|
return;
|
||||||
StringFormat(
|
}
|
||||||
"<tr>"
|
|
||||||
"<td>%u</td>"
|
|
||||||
"<td>%s</td>"
|
|
||||||
"<td>%s</td>"
|
|
||||||
"<td>%s</td>"
|
|
||||||
"</tr>",
|
|
||||||
id,
|
|
||||||
expires.c_str(),
|
|
||||||
key.c_str(),
|
|
||||||
value.c_str()
|
|
||||||
));
|
|
||||||
_ctr++;
|
|
||||||
std::string del_saylink = StringFormat("#databuckets delete %s", key.c_str());
|
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
"%s : %s",
|
fmt::format(
|
||||||
Saylink::Silent(del_saylink, "Delete").c_str(),
|
"Data bucket '{}' deleted.",
|
||||||
key.c_str(),
|
key_filter
|
||||||
" Value: ",
|
).c_str()
|
||||||
value.c_str());
|
);
|
||||||
|
} else {
|
||||||
|
DataBucketKey k = {};
|
||||||
|
|
||||||
|
k.key = key_filter;
|
||||||
|
k.character_id = character_id;
|
||||||
|
k.npc_id = npc_id;
|
||||||
|
k.bot_id = bot_id;
|
||||||
|
|
||||||
|
if (!DataBucket::DeleteData(k)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"An error occurred deleting data bucket '{}'.",
|
||||||
|
key_filter
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Data bucket '{}' deleted.",
|
||||||
|
key_filter
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
window_text.append("</table>");
|
} else if (is_edit) {
|
||||||
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
|
if (arguments < 6) {
|
||||||
std::string response = _ctr > 0 ? StringFormat("Found %i matching data buckets", _ctr).c_str()
|
SendDataBucketsSubCommands(c);
|
||||||
: "No Databuckets found.";
|
return;
|
||||||
c->Message(Chat::Yellow, response.c_str());
|
|
||||||
}
|
|
||||||
else if (strcasecmp(sep->arg[1], "delete") == 0) {
|
|
||||||
if (DataBucket::DeleteData(sep->argplus[2])) {
|
|
||||||
c->Message(Chat::Yellow, "data bucket %s deleted.", sep->argplus[2]);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
c->Message(Chat::Red, "An error occurred deleting data bucket %s", sep->argplus[2]);
|
const std::string& key_filter = sep->arg[2];
|
||||||
|
const std::string& value = sep->arg[6];
|
||||||
|
|
||||||
|
const uint32 character_id = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0;
|
||||||
|
const uint32 npc_id = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0;
|
||||||
|
const uint32 bot_id = sep->IsNumber(5) ? Strings::ToUnsignedInt(sep->arg[5]) : 0;
|
||||||
|
const uint32 expires = arguments > 6 && sep->IsNumber(7) ? Strings::ToUnsignedInt(sep->arg[7]) : 0;
|
||||||
|
|
||||||
|
DataBucketKey k = {};
|
||||||
|
|
||||||
|
k.key = key_filter;
|
||||||
|
k.character_id = character_id;
|
||||||
|
k.npc_id = npc_id;
|
||||||
|
k.bot_id = bot_id;
|
||||||
|
k.value = value;
|
||||||
|
|
||||||
|
if (arguments > 6) {
|
||||||
|
k.expires = expires;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
const std::string& expires_string = expires == 0 ? "Never" : std::to_string(expires);
|
||||||
|
|
||||||
|
DataBucket::SetData(k);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Bucket Edited | Key: {} Value: {} Expires: {} Character ID: {} NPC ID: {} Bot ID: {}",
|
||||||
|
key_filter,
|
||||||
|
value,
|
||||||
|
expires_string,
|
||||||
|
character_id,
|
||||||
|
npc_id,
|
||||||
|
bot_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
} else if (is_view) {
|
||||||
|
if (arguments < 2) {
|
||||||
|
SendDataBucketsSubCommands(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& key_filter = sep->arg[2];
|
||||||
|
|
||||||
|
const uint32 character_id = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0;
|
||||||
|
const uint32 npc_id = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0;
|
||||||
|
const uint32 bot_id = sep->IsNumber(5) ? Strings::ToUnsignedInt(sep->arg[5]) : 0;
|
||||||
|
|
||||||
|
std::string where_filter = fmt::format(
|
||||||
|
"`key` LIKE '%{}%'",
|
||||||
|
Strings::Escape(key_filter)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (character_id) {
|
||||||
|
where_filter += fmt::format(
|
||||||
|
" AND `character_id` = {}",
|
||||||
|
character_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npc_id) {
|
||||||
|
where_filter += fmt::format(
|
||||||
|
" AND `npc_id` = {}",
|
||||||
|
npc_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bot_id) {
|
||||||
|
where_filter += fmt::format(
|
||||||
|
" AND `bot_id` = {}",
|
||||||
|
bot_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
where_filter += " LIMIT 50";
|
||||||
|
|
||||||
|
const auto& l = DataBucketsRepository::GetWhere(database, where_filter);
|
||||||
|
|
||||||
|
if (l.empty()) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"No data buckets found matching '{}'.",
|
||||||
|
key_filter
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string window_text = DialogueWindow::TableRow(
|
||||||
|
DialogueWindow::TableCell("ID") +
|
||||||
|
DialogueWindow::TableCell("Key") +
|
||||||
|
DialogueWindow::TableCell("Value") +
|
||||||
|
DialogueWindow::TableCell("Expires") +
|
||||||
|
DialogueWindow::TableCell("Character ID") +
|
||||||
|
DialogueWindow::TableCell("NPC ID") +
|
||||||
|
DialogueWindow::TableCell("Bot ID")
|
||||||
|
);
|
||||||
|
|
||||||
|
uint16 bucket_count = 0;
|
||||||
|
uint16 bucket_number = 1;
|
||||||
|
|
||||||
|
for (const auto& e : l) {
|
||||||
|
const std::string& expires_string = e.expires == 0 ? "Never" : std::to_string(e.expires);
|
||||||
|
|
||||||
|
window_text += DialogueWindow::TableRow(
|
||||||
|
DialogueWindow::TableCell(std::to_string(e.id)) +
|
||||||
|
DialogueWindow::TableCell(e.key_) +
|
||||||
|
DialogueWindow::TableCell(e.value) +
|
||||||
|
DialogueWindow::TableCell(expires_string) +
|
||||||
|
DialogueWindow::TableCell(std::to_string(e.character_id)) +
|
||||||
|
DialogueWindow::TableCell(std::to_string(e.npc_id)) +
|
||||||
|
DialogueWindow::TableCell(std::to_string(e.bot_id))
|
||||||
|
);
|
||||||
|
|
||||||
|
const std::string& delete_link = Saylink::Silent(
|
||||||
|
fmt::format(
|
||||||
|
"#databuckets delete {} {} {} {}",
|
||||||
|
e.key_,
|
||||||
|
e.character_id,
|
||||||
|
e.npc_id,
|
||||||
|
e.bot_id
|
||||||
|
),
|
||||||
|
"Delete"
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Bucket {} | Key: {} | Value: {} | Character ID: {} NPC ID: {} Bot ID: {} | {}",
|
||||||
|
bucket_number,
|
||||||
|
e.key_,
|
||||||
|
e.value,
|
||||||
|
e.character_id,
|
||||||
|
e.npc_id,
|
||||||
|
e.bot_id,
|
||||||
|
delete_link
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
bucket_count++;
|
||||||
|
bucket_number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_text = DialogueWindow::Table(window_text);
|
||||||
|
|
||||||
|
c->SendPopupToClient("Data Buckets", window_text.c_str());
|
||||||
|
|
||||||
|
const std::string& response = fmt::format(
|
||||||
|
"Found {} data bucket{} matching '{}'{}.",
|
||||||
|
bucket_count,
|
||||||
|
bucket_count != 1 ? "s" : "",
|
||||||
|
key_filter,
|
||||||
|
bucket_count == 50 ? ", max reached" : ""
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(Chat::White, response.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendDataBucketsSubCommands(Client *c)
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, "Usage: #databuckets delete [Key] [Character ID] [NPC ID] [Bot ID]");
|
||||||
|
c->Message(Chat::White, "Usage: #databuckets edit [Key] [Character ID] [NPC ID] [Bot ID] [Value] [Expires]");
|
||||||
|
c->Message(Chat::White, "Usage: #databuckets view [Partial Key] [Character ID] [NPC ID] [Bot ID]");
|
||||||
|
c->Message(Chat::White, "Note: Character ID, NPC ID, and Bot ID are optional if not needed, if needed they are required for specificity");
|
||||||
|
c->Message(Chat::White, "Note: Edit requires Character ID, NPC ID, Bot ID, and Value, Expires is optional and does not modify the existing expiration time if not provided");
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#include "../../client.h"
|
#include "../../client.h"
|
||||||
#include "../../common/languages.h"
|
|
||||||
|
|
||||||
void FindLanguage(Client *c, const Seperator *sep)
|
void FindLanguage(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
if (sep->IsNumber(2)) {
|
if (sep->IsNumber(2)) {
|
||||||
const auto language_id = Strings::ToInt(sep->arg[2]);
|
const auto language_id = Strings::ToInt(sep->arg[2]);
|
||||||
if (EQ::ValueWithin(language_id, LANG_COMMON_TONGUE, LANG_UNKNOWN)) {
|
if (EQ::ValueWithin(language_id, Language::CommonTongue, Language::Unknown27)) {
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
|
|||||||
+266
-243
@@ -2,262 +2,285 @@
|
|||||||
|
|
||||||
void command_fixmob(Client *c, const Seperator *sep)
|
void command_fixmob(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
Mob *target = c->GetTarget();
|
const int arguments = sep->argnum;
|
||||||
const char *Usage = "Usage: #fixmob [race|gender|texture|helm|face|hair|haircolor|beard|beardcolor|heritage|tattoo|detail] [next|prev]";
|
if (arguments < 2) {
|
||||||
|
SendFixMobSubCommands(c);
|
||||||
if (!sep->arg[1]) {
|
return;
|
||||||
c->Message(Chat::White, Usage);
|
|
||||||
}
|
}
|
||||||
else if (!target) {
|
|
||||||
c->Message(Chat::White, "Error: this command requires a target");
|
Mob* t = c;
|
||||||
|
if (c->GetTarget()) {
|
||||||
|
t = c->GetTarget();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
|
||||||
uint32 Adjustment = 1; // Previous or Next
|
const std::string& type = sep->arg[1];
|
||||||
char codeMove = 0;
|
const std::string& move_type = Strings::ToLower(sep->arg[2]);
|
||||||
|
|
||||||
if (sep->arg[2]) {
|
std::string change_type;
|
||||||
char *command2 = sep->arg[2];
|
std::string change_value;
|
||||||
codeMove = (command2[0] | 0x20); // First character, lower-cased
|
|
||||||
if (codeMove == 'n') {
|
const bool is_next = move_type[0] == 'n';
|
||||||
Adjustment = 1;
|
const bool is_previous = move_type[0] == 'p';
|
||||||
}
|
|
||||||
else if (codeMove == 'p') {
|
const uint32 adjustment = is_next ? 1 : -1;
|
||||||
Adjustment = -1;
|
|
||||||
}
|
uint16 race_id = t->GetRace();
|
||||||
|
uint8 gender_id = t->GetGender();
|
||||||
|
uint8 texture = UINT8_MAX;
|
||||||
|
uint8 helm_texture = UINT8_MAX;
|
||||||
|
uint8 hair_color = t->GetHairColor();
|
||||||
|
uint8 beard_color = t->GetBeardColor();
|
||||||
|
uint8 eye_color_1 = t->GetEyeColor1();
|
||||||
|
uint8 eye_color_2 = t->GetEyeColor2();
|
||||||
|
uint8 hair_style = t->GetHairStyle();
|
||||||
|
uint8 face = t->GetLuclinFace();
|
||||||
|
uint8 beard_style = t->GetBeard();
|
||||||
|
uint8 drakkin_heritage = t->GetDrakkinHeritage();
|
||||||
|
uint8 drakkin_tattoo = t->GetDrakkinTattoo();
|
||||||
|
uint8 drakkin_details = t->GetDrakkinDetails();
|
||||||
|
|
||||||
|
const bool is_beard = Strings::EqualFold(type, "beard");
|
||||||
|
const bool is_beard_color = Strings::EqualFold(type, "beard_color");
|
||||||
|
const bool is_drakkin_details = Strings::EqualFold(type, "drakkin_details");
|
||||||
|
const bool is_drakkin_heritage = Strings::EqualFold(type, "drakkin_heritage");
|
||||||
|
const bool is_drakkin_tattoo = Strings::EqualFold(type, "drakkin_tattoo");
|
||||||
|
const bool is_face = Strings::EqualFold(type, "face");
|
||||||
|
const bool is_gender = Strings::EqualFold(type, "gender");
|
||||||
|
const bool is_hair = Strings::EqualFold(type, "hair");
|
||||||
|
const bool is_hair_color = Strings::EqualFold(type, "hair_color");
|
||||||
|
const bool is_helm = Strings::EqualFold(type, "helm");
|
||||||
|
const bool is_race = Strings::EqualFold(type, "race");
|
||||||
|
const bool is_texture = Strings::EqualFold(type, "texture");
|
||||||
|
|
||||||
|
if (
|
||||||
|
!is_beard &&
|
||||||
|
!is_beard_color &&
|
||||||
|
!is_drakkin_details &&
|
||||||
|
!is_drakkin_heritage &&
|
||||||
|
!is_drakkin_tattoo &&
|
||||||
|
!is_face &&
|
||||||
|
!is_gender &&
|
||||||
|
!is_hair &&
|
||||||
|
!is_hair_color &&
|
||||||
|
!is_helm &&
|
||||||
|
!is_race &&
|
||||||
|
!is_texture
|
||||||
|
) {
|
||||||
|
SendFixMobSubCommands(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_race) {
|
||||||
|
if (race_id == Race::Human && is_previous) {
|
||||||
|
race_id = RuleI(NPC, MaxRaceID);
|
||||||
|
} else if (race_id >= RuleI(NPC, MaxRaceID) && is_next) {
|
||||||
|
race_id = Race::Human;
|
||||||
|
} else {
|
||||||
|
race_id += adjustment;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Race = target->GetRace();
|
change_type = "Race";
|
||||||
uint8 Gender = target->GetGender();
|
change_value = std::to_string(race_id);
|
||||||
uint8 Texture = 0xFF;
|
} else if (is_gender) {
|
||||||
uint8 HelmTexture = 0xFF;
|
if (gender_id == Gender::Male && is_previous) {
|
||||||
uint8 HairColor = target->GetHairColor();
|
gender_id = Gender::Neuter;
|
||||||
uint8 BeardColor = target->GetBeardColor();
|
} else if (gender_id >= Gender::Neuter && is_next) {
|
||||||
uint8 EyeColor1 = target->GetEyeColor1();
|
gender_id = Gender::Male;
|
||||||
uint8 EyeColor2 = target->GetEyeColor2();
|
} else {
|
||||||
uint8 HairStyle = target->GetHairStyle();
|
gender_id += adjustment;
|
||||||
uint8 LuclinFace = target->GetLuclinFace();
|
|
||||||
uint8 Beard = target->GetBeard();
|
|
||||||
uint32 DrakkinHeritage = target->GetDrakkinHeritage();
|
|
||||||
uint32 DrakkinTattoo = target->GetDrakkinTattoo();
|
|
||||||
uint32 DrakkinDetails = target->GetDrakkinDetails();
|
|
||||||
|
|
||||||
const char *ChangeType = nullptr; // If it's still nullptr after processing, they didn't send a valid command
|
|
||||||
uint32 ChangeSetting;
|
|
||||||
char *command = sep->arg[1];
|
|
||||||
|
|
||||||
if (strcasecmp(command, "race") == 0) {
|
|
||||||
if (Race == 1 && codeMove == 'p') {
|
|
||||||
Race = RuleI(NPC, MaxRaceID);
|
|
||||||
}
|
|
||||||
else if (Race >= RuleI(NPC, MaxRaceID) && codeMove != 'p') {
|
|
||||||
Race = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Race += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "Race";
|
|
||||||
ChangeSetting = Race;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "gender") == 0) {
|
|
||||||
if (Gender == MALE && codeMove == 'p') {
|
|
||||||
Gender = NEUTER;
|
|
||||||
}
|
|
||||||
else if (Gender >= NEUTER && codeMove != 'p') {
|
|
||||||
Gender = MALE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Gender += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "Gender";
|
|
||||||
ChangeSetting = Gender;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "texture") == 0) {
|
|
||||||
Texture = target->GetTexture();
|
|
||||||
|
|
||||||
if (Texture == 0 && codeMove == 'p') {
|
|
||||||
Texture = 25;
|
|
||||||
}
|
|
||||||
else if (Texture >= 25 && codeMove != 'p') {
|
|
||||||
Texture = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Texture += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "Texture";
|
|
||||||
ChangeSetting = Texture;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "helm") == 0) {
|
|
||||||
HelmTexture = target->GetHelmTexture();
|
|
||||||
if (HelmTexture == 0 && codeMove == 'p') {
|
|
||||||
HelmTexture = 25;
|
|
||||||
}
|
|
||||||
else if (HelmTexture >= 25 && codeMove != 'p') {
|
|
||||||
HelmTexture = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
HelmTexture += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "HelmTexture";
|
|
||||||
ChangeSetting = HelmTexture;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "face") == 0) {
|
|
||||||
if (LuclinFace == 0 && codeMove == 'p') {
|
|
||||||
LuclinFace = 87;
|
|
||||||
}
|
|
||||||
else if (LuclinFace >= 87 && codeMove != 'p') {
|
|
||||||
LuclinFace = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LuclinFace += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "LuclinFace";
|
|
||||||
ChangeSetting = LuclinFace;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "hair") == 0) {
|
|
||||||
if (HairStyle == 0 && codeMove == 'p') {
|
|
||||||
HairStyle = 8;
|
|
||||||
}
|
|
||||||
else if (HairStyle >= 8 && codeMove != 'p') {
|
|
||||||
HairStyle = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
HairStyle += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "HairStyle";
|
|
||||||
ChangeSetting = HairStyle;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "haircolor") == 0) {
|
|
||||||
if (HairColor == 0 && codeMove == 'p') {
|
|
||||||
HairColor = 24;
|
|
||||||
}
|
|
||||||
else if (HairColor >= 24 && codeMove != 'p') {
|
|
||||||
HairColor = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
HairColor += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "HairColor";
|
|
||||||
ChangeSetting = HairColor;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "beard") == 0) {
|
|
||||||
if (Beard == 0 && codeMove == 'p') {
|
|
||||||
Beard = 11;
|
|
||||||
}
|
|
||||||
else if (Beard >= 11 && codeMove != 'p') {
|
|
||||||
Beard = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Beard += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "Beard";
|
|
||||||
ChangeSetting = Beard;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "beardcolor") == 0) {
|
|
||||||
if (BeardColor == 0 && codeMove == 'p') {
|
|
||||||
BeardColor = 24;
|
|
||||||
}
|
|
||||||
else if (BeardColor >= 24 && codeMove != 'p') {
|
|
||||||
BeardColor = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BeardColor += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "BeardColor";
|
|
||||||
ChangeSetting = BeardColor;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "heritage") == 0) {
|
|
||||||
if (DrakkinHeritage == 0 && codeMove == 'p') {
|
|
||||||
DrakkinHeritage = 6;
|
|
||||||
}
|
|
||||||
else if (DrakkinHeritage >= 6 && codeMove != 'p') {
|
|
||||||
DrakkinHeritage = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DrakkinHeritage += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "DrakkinHeritage";
|
|
||||||
ChangeSetting = DrakkinHeritage;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "tattoo") == 0) {
|
|
||||||
if (DrakkinTattoo == 0 && codeMove == 'p') {
|
|
||||||
DrakkinTattoo = 8;
|
|
||||||
}
|
|
||||||
else if (DrakkinTattoo >= 8 && codeMove != 'p') {
|
|
||||||
DrakkinTattoo = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DrakkinTattoo += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "DrakkinTattoo";
|
|
||||||
ChangeSetting = DrakkinTattoo;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(command, "detail") == 0) {
|
|
||||||
if (DrakkinDetails == 0 && codeMove == 'p') {
|
|
||||||
DrakkinDetails = 7;
|
|
||||||
}
|
|
||||||
else if (DrakkinDetails >= 7 && codeMove != 'p') {
|
|
||||||
DrakkinDetails = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DrakkinDetails += Adjustment;
|
|
||||||
}
|
|
||||||
ChangeType = "DrakkinDetails";
|
|
||||||
ChangeSetting = DrakkinDetails;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack to fix some races that base features from face
|
change_type = "Gender";
|
||||||
switch (Race) {
|
change_value = std::to_string(gender_id);
|
||||||
case 2: // Barbarian
|
} else if (is_texture) {
|
||||||
if (LuclinFace > 10) {
|
texture = t->GetTexture();
|
||||||
LuclinFace -= ((DrakkinTattoo - 1) * 10);
|
|
||||||
}
|
if (texture == 0 && is_previous) {
|
||||||
LuclinFace += (DrakkinTattoo * 10);
|
texture = 25;
|
||||||
break;
|
} else if (texture >= 25 && is_next) {
|
||||||
case 3: // Erudite
|
texture = 0;
|
||||||
if (LuclinFace > 10) {
|
} else {
|
||||||
LuclinFace -= ((HairStyle - 1) * 10);
|
texture += adjustment;
|
||||||
}
|
|
||||||
LuclinFace += (HairStyle * 10);
|
|
||||||
break;
|
|
||||||
case 5: // HighElf
|
|
||||||
case 6: // DarkElf
|
|
||||||
case 7: // HalfElf
|
|
||||||
if (LuclinFace > 10) {
|
|
||||||
LuclinFace -= ((Beard - 1) * 10);
|
|
||||||
}
|
|
||||||
LuclinFace += (Beard * 10);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
change_type = "Texture";
|
||||||
if (ChangeType == nullptr) {
|
change_value = std::to_string(texture);
|
||||||
c->Message(Chat::White, Usage);
|
} else if (is_helm) {
|
||||||
|
helm_texture = t->GetHelmTexture();
|
||||||
|
if (helm_texture == 0 && is_previous) {
|
||||||
|
helm_texture = 25;
|
||||||
|
} else if (helm_texture >= 25 && is_next) {
|
||||||
|
helm_texture = 0;
|
||||||
|
} else {
|
||||||
|
helm_texture += adjustment;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
target->SendIllusionPacket(
|
|
||||||
AppearanceStruct{
|
|
||||||
.beard = Beard,
|
|
||||||
.beard_color = BeardColor,
|
|
||||||
.drakkin_details = DrakkinDetails,
|
|
||||||
.drakkin_heritage = DrakkinHeritage,
|
|
||||||
.drakkin_tattoo = DrakkinTattoo,
|
|
||||||
.eye_color_one = EyeColor1,
|
|
||||||
.eye_color_two = EyeColor2,
|
|
||||||
.face = LuclinFace,
|
|
||||||
.gender_id = Gender,
|
|
||||||
.hair = HairStyle,
|
|
||||||
.hair_color = HairColor,
|
|
||||||
.helmet_texture = HelmTexture,
|
|
||||||
.race_id = Race,
|
|
||||||
.texture = Texture,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
c->Message(Chat::White, "%s=%i", ChangeType, ChangeSetting);
|
change_type = "Helm Texture";
|
||||||
|
change_value = std::to_string(helm_texture);
|
||||||
|
} else if (is_face) {
|
||||||
|
if (face == 0 && is_previous) {
|
||||||
|
face = 87;
|
||||||
|
} else if (face >= 87 && is_next) {
|
||||||
|
face = 0;
|
||||||
|
} else {
|
||||||
|
face += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Face";
|
||||||
|
change_value = std::to_string(face);
|
||||||
|
} else if (is_hair) {
|
||||||
|
if (hair_style == 0 && is_previous) {
|
||||||
|
hair_style = 8;
|
||||||
|
} else if (hair_style >= 8 && is_next) {
|
||||||
|
hair_style = 0;
|
||||||
|
} else {
|
||||||
|
hair_style += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Hair Style";
|
||||||
|
change_value = std::to_string(hair_style);
|
||||||
|
} else if (is_hair_color) {
|
||||||
|
if (hair_color == 0 && is_previous) {
|
||||||
|
hair_color = 24;
|
||||||
|
} else if (hair_color >= 24 && is_next) {
|
||||||
|
hair_color = 0;
|
||||||
|
} else {
|
||||||
|
hair_color += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Hair Color";
|
||||||
|
change_value = std::to_string(hair_color);
|
||||||
|
} else if (is_beard) {
|
||||||
|
if (beard_style == 0 && is_previous) {
|
||||||
|
beard_style = 11;
|
||||||
|
} else if (beard_style >= 11 && is_next) {
|
||||||
|
beard_style = 0;
|
||||||
|
} else {
|
||||||
|
beard_style += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Beard Style";
|
||||||
|
change_value = std::to_string(beard_style);
|
||||||
|
} else if (is_beard_color) {
|
||||||
|
if (beard_color == 0 && is_previous) {
|
||||||
|
beard_color = 24;
|
||||||
|
} else if (beard_color >= 24 && is_next) {
|
||||||
|
beard_color = 0;
|
||||||
|
} else {
|
||||||
|
beard_color += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Beard Color";
|
||||||
|
change_value = std::to_string(beard_color);
|
||||||
|
} else if (is_drakkin_heritage) {
|
||||||
|
if (drakkin_heritage == 0 && is_previous) {
|
||||||
|
drakkin_heritage = 6;
|
||||||
|
} else if (drakkin_heritage >= 6 && is_next) {
|
||||||
|
drakkin_heritage = 0;
|
||||||
|
} else {
|
||||||
|
drakkin_heritage += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Drakkin Heritage";
|
||||||
|
change_value = std::to_string(drakkin_heritage);
|
||||||
|
} else if (is_drakkin_tattoo) {
|
||||||
|
if (drakkin_tattoo == 0 && is_previous) {
|
||||||
|
drakkin_tattoo = 8;
|
||||||
|
} else if (drakkin_tattoo >= 8 && is_next) {
|
||||||
|
drakkin_tattoo = 0;
|
||||||
|
} else {
|
||||||
|
drakkin_tattoo += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Drakkin Tattoo";
|
||||||
|
change_value = std::to_string(drakkin_tattoo);
|
||||||
|
} else if (is_drakkin_details) {
|
||||||
|
if (drakkin_details == 0 && is_previous) {
|
||||||
|
drakkin_details = 7;
|
||||||
|
} else if (drakkin_details >= 7 && is_next) {
|
||||||
|
drakkin_details = 0;
|
||||||
|
} else {
|
||||||
|
drakkin_details += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
change_type = "Drakkin Details";
|
||||||
|
change_value = std::to_string(drakkin_details);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (race_id) {
|
||||||
|
case Race::Barbarian: {
|
||||||
|
if (face > 10) {
|
||||||
|
face -= ((drakkin_tattoo - 1) * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
face += (drakkin_tattoo * 10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Race::Erudite: {
|
||||||
|
if (face > 10) {
|
||||||
|
face -= ((hair_style - 1) * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
face += (hair_style * 10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Race::HighElf:
|
||||||
|
case Race::DarkElf:
|
||||||
|
case Race::HalfElf: {
|
||||||
|
if (face > 10) {
|
||||||
|
face -= ((beard_style - 1) * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
face += (beard_style * 10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t->SendIllusionPacket(
|
||||||
|
AppearanceStruct{
|
||||||
|
.beard = beard_style,
|
||||||
|
.beard_color = beard_color,
|
||||||
|
.drakkin_details = drakkin_details,
|
||||||
|
.drakkin_heritage = drakkin_heritage,
|
||||||
|
.drakkin_tattoo = drakkin_tattoo,
|
||||||
|
.eye_color_one = eye_color_1,
|
||||||
|
.eye_color_two = eye_color_2,
|
||||||
|
.face = face,
|
||||||
|
.gender_id = gender_id,
|
||||||
|
.hair = hair_style,
|
||||||
|
.hair_color = hair_color,
|
||||||
|
.helmet_texture = helm_texture,
|
||||||
|
.race_id = race_id,
|
||||||
|
.texture = texture,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Appearance for {} | Type: {} Value: {}",
|
||||||
|
c->GetTargetDescription(t, TargetDescriptionType::UCSelf),
|
||||||
|
change_type,
|
||||||
|
change_value
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendFixMobSubCommands(Client *c)
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob beard [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob beard_color [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob drakkin_details [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob drakkin_heritage [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob drakkin_tattoo [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob face [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob gender [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob hair [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob hair_color [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob helm [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob race [Next|Previous]");
|
||||||
|
c->Message(Chat::White, "Usage: #fixmob texture [Next|Previous]");
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,21 +2,44 @@
|
|||||||
|
|
||||||
void command_petname(Client *c, const Seperator *sep)
|
void command_petname(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
Mob *target;
|
Mob *t = nullptr;
|
||||||
target = c->GetTarget();
|
if (c->GetTarget()) {
|
||||||
|
t = c->GetTarget();
|
||||||
|
}
|
||||||
|
|
||||||
if (!target || !target->IsPet()) {
|
if (!t) {
|
||||||
c->Message(Chat::White, "Usage: #petname newname (requires a pet target)");
|
c->Message(Chat::White, "You must target your pet to use this command.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (target->GetOwnerID() == c->GetID() && strlen(sep->arg[1]) > 0) {
|
|
||||||
char *oldname = strdup(target->GetName());
|
if (!t->IsPet()) {
|
||||||
target->TempName(sep->arg[1]);
|
c->Message(Chat::White, "You must target your pet to use this command.");
|
||||||
c->Message(Chat::White, "Renamed %s to %s", oldname, sep->arg[1]);
|
return;
|
||||||
free(oldname);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
target->TempName();
|
if (t->GetOwnerID() != c->GetID()) {
|
||||||
c->Message(Chat::White, "Restored the original name");
|
c->Message(Chat::White, "You must target your pet to use this command.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sep->arg[1]) {
|
||||||
|
const std::string& old_name = t->GetCleanName();
|
||||||
|
const std::string& new_name = sep->arg[1];
|
||||||
|
|
||||||
|
t->TempName(new_name.c_str());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Renamed your pet from {} to {}.",
|
||||||
|
old_name,
|
||||||
|
new_name
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->TempName();
|
||||||
|
c->Message(Chat::White, "Restored the original name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void SetFlymode(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
t->SetFlyMode(static_cast<GravityBehavior>(flymode_id));
|
t->SetFlyMode(static_cast<GravityBehavior>(flymode_id));
|
||||||
t->SendAppearancePacket(AT_Levitate, flymode_id);
|
t->SendAppearancePacket(AppearanceType::FlyMode, flymode_id);
|
||||||
|
|
||||||
const uint32 account = c->AccountID();
|
const uint32 account = c->AccountID();
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ void SetFrozen(Client *c, const Seperator *sep)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->SendAppearancePacket(AT_Anim, is_frozen ? ANIM_FREEZE : ANIM_STAND);
|
t->SendAppearancePacket(AppearanceType::Animation, is_frozen ? Animation::Freeze : Animation::Standing);
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ void SetGender(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint8 gender_id = Strings::ToUnsignedInt(sep->arg[2]);
|
const uint8 gender_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||||
if (!EQ::ValueWithin(gender_id, MALE, NEUTER)) {
|
if (!EQ::ValueWithin(gender_id, Gender::Male, Gender::Neuter)) {
|
||||||
c->Message(Chat::White, "Usage: #set gender [Gender ID]");
|
c->Message(Chat::White, "Usage: #set gender [Gender ID]");
|
||||||
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
|
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ void SetGenderPermanent(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint8 gender_id = Strings::ToInt(sep->arg[2]);
|
const uint8 gender_id = Strings::ToInt(sep->arg[2]);
|
||||||
if (!EQ::ValueWithin(gender_id, MALE, NEUTER)) {
|
if (!EQ::ValueWithin(gender_id, Gender::Male, Gender::Neuter)) {
|
||||||
c->Message(Chat::White, "Usage: #set gender_permanent [Gender ID]");
|
c->Message(Chat::White, "Usage: #set gender_permanent [Gender ID]");
|
||||||
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
|
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ void SetGodMode(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
c->SetInvul(god_mode);
|
c->SetInvul(god_mode);
|
||||||
c->SendAppearancePacket(AT_Levitate, god_mode);
|
c->SendAppearancePacket(AppearanceType::FlyMode, god_mode);
|
||||||
c->SetHideMe(god_mode);
|
c->SetHideMe(god_mode);
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user