mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-24 10:02:28 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b92eafd21b | |||
| d6d5d992cb | |||
| d524cb6a5a | |||
| e6469878ce | |||
| 9583099ace | |||
| cf3483b402 | |||
| 311af7bbe9 | |||
| be42b73f5c | |||
| f76c798910 | |||
| ae198ae043 | |||
| 520943ebf1 | |||
| 9ac306fe67 | |||
| 7a1d69d0d4 |
@@ -1,3 +1,69 @@
|
||||
## [22.57.1] 10/22/2024
|
||||
|
||||
### Bots
|
||||
|
||||
* Enable Bot Commands Only if Rule Enabled ([#4519](https://github.com/EQEmu/Server/pull/4519)) @Kinglykrab 2024-10-22
|
||||
* Fix pet buffs from saving duplicates every save ([#4520](https://github.com/EQEmu/Server/pull/4520)) @nytmyr 2024-10-22
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Automatic Opcode File Creation ([#4521](https://github.com/EQEmu/Server/pull/4521)) @KimLS 2024-10-22
|
||||
|
||||
## [22.57.0] 10/20/2024
|
||||
|
||||
### Bots
|
||||
|
||||
* Add "silent" option to ^spawn and mute raid spawn ([#4494](https://github.com/EQEmu/Server/pull/4494)) @nytmyr 2024-10-05
|
||||
* Add attack flag when told to attack ([#4490](https://github.com/EQEmu/Server/pull/4490)) @nytmyr 2024-09-29
|
||||
* Fix timers loading on spawn and zone ([#4516](https://github.com/EQEmu/Server/pull/4516)) @nytmyr 2024-10-20
|
||||
|
||||
### Code
|
||||
|
||||
* Fixed a typo in Zoning.cpp ([#4515](https://github.com/EQEmu/Server/pull/4515)) @carolus21rex 2024-10-20
|
||||
* Optimization Code Cleanup ([#4489](https://github.com/EQEmu/Server/pull/4489)) @Akkadius 2024-09-30
|
||||
* Remove Extra Skill in EQ::skills::GetExtraDamageSkills() ([#4486](https://github.com/EQEmu/Server/pull/4486)) @Kinglykrab 2024-10-03
|
||||
|
||||
### Crash
|
||||
|
||||
* Fixes a crash when the faction_list db table is empty. ([#4511](https://github.com/EQEmu/Server/pull/4511)) @KimLS 2024-10-14
|
||||
|
||||
### Fixes
|
||||
|
||||
* Add character_instance_safereturns to tables_to_zero_id ([#4485](https://github.com/EQEmu/Server/pull/4485)) @Morzain 2024-09-26
|
||||
* Correctly limit max targets of PBAOE ([#4507](https://github.com/EQEmu/Server/pull/4507)) @catapultam-habeo 2024-10-11
|
||||
* FindBestZ selecting false zone floor as bestz - Results in roambox failures ([#4504](https://github.com/EQEmu/Server/pull/4504)) @fryguy503 2024-10-13
|
||||
* Fix #set motd Crash ([#4495](https://github.com/EQEmu/Server/pull/4495)) @Kinglykrab 2024-10-05
|
||||
* Fix `character_exp_modifiers` Default Values ([#4502](https://github.com/EQEmu/Server/pull/4502)) @Kinglykrab 2024-10-09
|
||||
* Fix a display error regarding a few trader/buyer query errors ([#4514](https://github.com/EQEmu/Server/pull/4514)) @neckkola 2024-10-17
|
||||
* Fix Group ID 0 in Group::SaveGroupLeaderAA() ([#4487](https://github.com/EQEmu/Server/pull/4487)) @Kinglykrab 2024-10-03
|
||||
* Fix Mercenary Encounter Crash ([#4509](https://github.com/EQEmu/Server/pull/4509)) @Kinglykrab 2024-10-12
|
||||
* Fix NPC::CanTalk() Crash ([#4499](https://github.com/EQEmu/Server/pull/4499)) @Kinglykrab 2024-10-07
|
||||
* Fix Spells:DefaultAOEMaxTargets Default Value ([#4508](https://github.com/EQEmu/Server/pull/4508)) @Kinglykrab 2024-10-12
|
||||
* Fix Targeted AOE Max Targets Rule ([#4488](https://github.com/EQEmu/Server/pull/4488)) @Kinglykrab 2024-10-03
|
||||
* fixed a bug where it would use npc value instead of faction value in the database. ([#4491](https://github.com/EQEmu/Server/pull/4491)) @regneq 2024-09-29
|
||||
* Master of Disguise should apply to illusions casted by others. ([#4506](https://github.com/EQEmu/Server/pull/4506)) @fryguy503 2024-10-11
|
||||
* Spells - Self Only (Yellow) cast when non group member is targeted ([#4503](https://github.com/EQEmu/Server/pull/4503)) @fryguy503 2024-10-11
|
||||
|
||||
### Loginserver
|
||||
|
||||
* Larion loginserver support ([#4492](https://github.com/EQEmu/Server/pull/4492)) @KimLS 2024-10-03
|
||||
* Login Fatal Error Spamming ([#4476](https://github.com/EQEmu/Server/pull/4476)) @KimLS 2024-10-09
|
||||
|
||||
### Logs
|
||||
|
||||
* Add NPC Trades to Player Events ([#4505](https://github.com/EQEmu/Server/pull/4505)) @Kinglykrab 2024-10-13
|
||||
|
||||
### Quest API
|
||||
|
||||
* Add Buff Fade Methods to Perl/Lua ([#4501](https://github.com/EQEmu/Server/pull/4501)) @Kinglykrab 2024-10-09
|
||||
* Add EVENT_READ_ITEM to Perl/Lua ([#4497](https://github.com/EQEmu/Server/pull/4497)) @Kinglykrab 2024-10-08
|
||||
* Add NPC List Filter Methods to Perl/Lua ([#4493](https://github.com/EQEmu/Server/pull/4493)) @Kinglykrab 2024-10-04
|
||||
* Add Scripting Support to Mercenaries ([#4500](https://github.com/EQEmu/Server/pull/4500)) @Kinglykrab 2024-10-11
|
||||
|
||||
### Rules
|
||||
|
||||
* Add Rule to disable PVP Regions ([#4513](https://github.com/EQEmu/Server/pull/4513)) @Kinglykrab 2024-10-17
|
||||
|
||||
## [22.56.3] 9/23/2024
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -514,12 +514,6 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
|
||||
c.raid_auto_consent = pp->raidAutoconsent;
|
||||
c.guild_auto_consent = pp->guildAutoconsent;
|
||||
c.RestTimer = pp->RestTimer;
|
||||
c.cold_resist = pp->cold_resist;
|
||||
c.fire_resist = pp->fire_resist;
|
||||
c.magic_resist = pp->magic_resist;
|
||||
c.disease_resist = pp->disease_resist;
|
||||
c.poison_resist = pp->poison_resist;
|
||||
c.corruption_resist = pp->corruption_resist;
|
||||
|
||||
CharacterDataRepository::ReplaceOne(*this, c);
|
||||
|
||||
|
||||
@@ -1121,12 +1121,6 @@ struct PlayerProfile_Struct
|
||||
/*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005)
|
||||
/*19564*/ uint32 RestTimer;
|
||||
/*19568*/ uint32 char_id; // Found as part of bazaar revamp (5/15/2024)
|
||||
/*19572*/ uint32 cold_resist;
|
||||
/*19576*/ uint32 fire_resist;
|
||||
/*19580*/ uint32 magic_resist;
|
||||
/*19584*/ uint32 disease_resist;
|
||||
/*19588*/ uint32 poison_resist;
|
||||
/*19592*/ uint32 corruption_resist;
|
||||
|
||||
// All player profile packets are translated and this overhead is ignored in out-bound packets
|
||||
PlayerProfile_Struct() : m_player_profile_version(EQ::versions::MobVersion::Unknown) { }
|
||||
|
||||
@@ -171,6 +171,7 @@ void EQEmuConfig::parse_config()
|
||||
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
|
||||
LuaModuleDir = _root["server"]["directories"].get("lua_modules", "lua_modules/").asString();
|
||||
PatchDir = _root["server"]["directories"].get("patches", "./").asString();
|
||||
OpcodeDir = _root["server"]["directories"].get("opcodes", "./").asString();
|
||||
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
|
||||
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ class EQEmuConfig
|
||||
std::string PluginDir;
|
||||
std::string LuaModuleDir;
|
||||
std::string PatchDir;
|
||||
std::string OpcodeDir;
|
||||
std::string SharedMemDir;
|
||||
std::string LogDir;
|
||||
|
||||
|
||||
@@ -789,50 +789,36 @@ std::string PlayerEventDiscordFormatter::FormatNPCHandinEvent(
|
||||
);
|
||||
}
|
||||
|
||||
std::string npc_info = fmt::format(
|
||||
"{} ({})\n",
|
||||
e.npc_name,
|
||||
e.npc_id
|
||||
);
|
||||
|
||||
npc_info += fmt::format(
|
||||
"Is Quest Handin: {}",
|
||||
e.is_quest_handin ? "Yes" : "No"
|
||||
);
|
||||
|
||||
std::vector<DiscordField> f = {};
|
||||
|
||||
|
||||
BuildDiscordField(&f, "NPC", npc_info);
|
||||
|
||||
if (!handin_items_info.empty()) {
|
||||
BuildDiscordField(
|
||||
&f,
|
||||
"Handin Items",
|
||||
fmt::format(
|
||||
"{}",
|
||||
handin_items_info
|
||||
)
|
||||
);
|
||||
BuildDiscordField(&f, "Handin Items", handin_items_info);
|
||||
}
|
||||
|
||||
if (!handin_money_info.empty()) {
|
||||
BuildDiscordField(
|
||||
&f,
|
||||
"Handin Money",
|
||||
fmt::format(
|
||||
"{}",
|
||||
handin_money_info
|
||||
)
|
||||
);
|
||||
BuildDiscordField(&f, "Handin Money", handin_money_info);
|
||||
}
|
||||
|
||||
if (!return_items_info.empty()) {
|
||||
BuildDiscordField(
|
||||
&f,
|
||||
"Return Items",
|
||||
fmt::format(
|
||||
"{}",
|
||||
return_items_info
|
||||
)
|
||||
);
|
||||
BuildDiscordField(&f, "Return Items", return_items_info);
|
||||
}
|
||||
|
||||
if (!return_money_info.empty()) {
|
||||
BuildDiscordField(
|
||||
&f,
|
||||
"Return Money",
|
||||
fmt::format(
|
||||
"{}",
|
||||
return_money_info
|
||||
)
|
||||
);
|
||||
BuildDiscordField(&f, "Return Money", return_money_info);
|
||||
}
|
||||
|
||||
std::vector<DiscordEmbed> embeds = {};
|
||||
|
||||
@@ -654,53 +654,53 @@ const int32_t RETENTION_DAYS_DEFAULT = 7;
|
||||
|
||||
void PlayerEventLogs::SetSettingsDefaults()
|
||||
{
|
||||
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
|
||||
m_settings[PlayerEvent::ZONING].event_enabled = 1;
|
||||
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
|
||||
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
|
||||
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
|
||||
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
|
||||
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
|
||||
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
|
||||
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
|
||||
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
|
||||
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TRADE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::SAY].event_enabled = 0;
|
||||
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DEATH].event_enabled = 1;
|
||||
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
|
||||
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
|
||||
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
|
||||
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
|
||||
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
|
||||
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
|
||||
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GM_COMMAND].event_enabled = 1;
|
||||
m_settings[PlayerEvent::ZONING].event_enabled = 1;
|
||||
m_settings[PlayerEvent::AA_GAIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::AA_PURCHASE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::FORAGE_SUCCESS].event_enabled = 0;
|
||||
m_settings[PlayerEvent::FORAGE_FAILURE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::FISH_SUCCESS].event_enabled = 0;
|
||||
m_settings[PlayerEvent::FISH_FAILURE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::ITEM_DESTROY].event_enabled = 1;
|
||||
m_settings[PlayerEvent::WENT_ONLINE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::WENT_OFFLINE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::LEVEL_GAIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::LEVEL_LOSS].event_enabled = 1;
|
||||
m_settings[PlayerEvent::LOOT_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::MERCHANT_PURCHASE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::MERCHANT_SELL].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GROUP_JOIN].event_enabled = 0;
|
||||
m_settings[PlayerEvent::GROUP_LEAVE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::RAID_JOIN].event_enabled = 0;
|
||||
m_settings[PlayerEvent::RAID_LEAVE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::GROUNDSPAWN_PICKUP].event_enabled = 1;
|
||||
m_settings[PlayerEvent::NPC_HANDIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::SKILL_UP].event_enabled = 0;
|
||||
m_settings[PlayerEvent::TASK_ACCEPT].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TASK_UPDATE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TASK_COMPLETE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TRADE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GIVE_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::SAY].event_enabled = 0;
|
||||
m_settings[PlayerEvent::REZ_ACCEPTED].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DEATH].event_enabled = 1;
|
||||
m_settings[PlayerEvent::COMBINE_FAILURE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::COMBINE_SUCCESS].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DROPPED_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::SPLIT_MONEY].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DZ_JOIN].event_enabled = 1;
|
||||
m_settings[PlayerEvent::DZ_LEAVE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TRADER_PURCHASE].event_enabled = 1;
|
||||
m_settings[PlayerEvent::TRADER_SELL].event_enabled = 1;
|
||||
m_settings[PlayerEvent::BANDOLIER_CREATE].event_enabled = 0;
|
||||
m_settings[PlayerEvent::BANDOLIER_SWAP].event_enabled = 0;
|
||||
m_settings[PlayerEvent::DISCOVER_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::POSSIBLE_HACK].event_enabled = 1;
|
||||
m_settings[PlayerEvent::KILLED_NPC].event_enabled = 0;
|
||||
m_settings[PlayerEvent::KILLED_NAMED_NPC].event_enabled = 1;
|
||||
m_settings[PlayerEvent::KILLED_RAID_NPC].event_enabled = 1;
|
||||
m_settings[PlayerEvent::ITEM_CREATION].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM].event_enabled = 1;
|
||||
m_settings[PlayerEvent::GUILD_TRIBUTE_DONATE_PLAT].event_enabled = 1;
|
||||
m_settings[PlayerEvent::PARCEL_SEND].event_enabled = 1;
|
||||
|
||||
@@ -860,10 +860,12 @@ namespace PlayerEvent {
|
||||
|
||||
class HandinEntry {
|
||||
public:
|
||||
uint32 item_id;
|
||||
std::string item_name;
|
||||
uint16 charges;
|
||||
bool attuned;
|
||||
uint32 item_id;
|
||||
std::string item_name;
|
||||
std::vector<uint32> augment_ids;
|
||||
std::vector<std::string> augment_names;
|
||||
uint16 charges;
|
||||
bool attuned;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
@@ -872,6 +874,8 @@ namespace PlayerEvent {
|
||||
ar(
|
||||
CEREAL_NVP(item_id),
|
||||
CEREAL_NVP(item_name),
|
||||
CEREAL_NVP(augment_ids),
|
||||
CEREAL_NVP(augment_names),
|
||||
CEREAL_NVP(charges),
|
||||
CEREAL_NVP(attuned)
|
||||
);
|
||||
@@ -905,6 +909,7 @@ namespace PlayerEvent {
|
||||
HandinMoney handin_money;
|
||||
std::vector<HandinEntry> return_items;
|
||||
HandinMoney return_money;
|
||||
bool is_quest_handin;
|
||||
|
||||
// cereal
|
||||
template<class Archive>
|
||||
@@ -916,7 +921,8 @@ namespace PlayerEvent {
|
||||
CEREAL_NVP(handin_items),
|
||||
CEREAL_NVP(handin_money),
|
||||
CEREAL_NVP(return_items),
|
||||
CEREAL_NVP(return_money)
|
||||
CEREAL_NVP(return_money),
|
||||
CEREAL_NVP(is_quest_handin)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2288,13 +2288,13 @@ namespace RoF
|
||||
outapp->WriteSInt32(345); // Mana Total ?
|
||||
|
||||
// these are needed to fix display bugs
|
||||
outapp->WriteUInt32(emu->cold_resist); // base CR
|
||||
outapp->WriteUInt32(emu->fire_resist); // base FR
|
||||
outapp->WriteUInt32(emu->magic_resist); // base MR
|
||||
outapp->WriteUInt32(emu->disease_resist); // base DR
|
||||
outapp->WriteUInt32(emu->poison_resist); // base PR
|
||||
outapp->WriteUInt32(0x19); // base CR
|
||||
outapp->WriteUInt32(0x19); // base FR
|
||||
outapp->WriteUInt32(0x19); // base MR
|
||||
outapp->WriteUInt32(0xf); // base DR
|
||||
outapp->WriteUInt32(0xf); // base PR
|
||||
outapp->WriteUInt32(0xf); // base PhR?
|
||||
outapp->WriteUInt32(emu->corruption_resist); // base Corrup
|
||||
outapp->WriteUInt32(0xf); // base Corrup
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
@@ -2806,13 +2806,13 @@ namespace RoF2
|
||||
outapp->WriteSInt32(345); // Mana Total ?
|
||||
|
||||
// these are needed to fix display bugs
|
||||
outapp->WriteUInt32(emu->cold_resist); // base CR
|
||||
outapp->WriteUInt32(emu->fire_resist); // base FR
|
||||
outapp->WriteUInt32(emu->magic_resist); // base MR
|
||||
outapp->WriteUInt32(emu->disease_resist); // base DR
|
||||
outapp->WriteUInt32(emu->poison_resist); // base PR
|
||||
outapp->WriteUInt32(0x19); // base CR
|
||||
outapp->WriteUInt32(0x19); // base FR
|
||||
outapp->WriteUInt32(0x19); // base MR
|
||||
outapp->WriteUInt32(0xf); // base DR
|
||||
outapp->WriteUInt32(0xf); // base PR
|
||||
outapp->WriteUInt32(0xf); // base PhR?
|
||||
outapp->WriteUInt32(emu->corruption_resist); // base Corrup
|
||||
outapp->WriteUInt32(0xf); // base Corrup
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
+7
-19
@@ -1669,27 +1669,15 @@ namespace SoD
|
||||
// OUT(unknown19584[4]);
|
||||
// OUT(unknown19588);
|
||||
|
||||
const uint8 unknown12864_bytes[] = {
|
||||
0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
const uint8 bytes[] = {
|
||||
0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F,
|
||||
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(eq->unknown12864, unknown12864_bytes, sizeof(unknown12864_bytes));
|
||||
|
||||
eq->cold_resist = emu->cold_resist;
|
||||
eq->fire_resist = emu->fire_resist;
|
||||
eq->magic_resist = emu->magic_resist;
|
||||
eq->disease_resist = emu->disease_resist;
|
||||
eq->poison_resist = emu->poison_resist;
|
||||
eq->physical_resist = 15;
|
||||
eq->corruption_resist = emu->corruption_resist;
|
||||
|
||||
const uint8 unknown15112_bytes[] = {
|
||||
0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(eq->unknown15112, unknown15112_bytes, sizeof(unknown15112_bytes));
|
||||
memcpy(eq->unknown12864, bytes, sizeof(bytes));
|
||||
|
||||
//set the checksum...
|
||||
CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4);
|
||||
|
||||
@@ -944,15 +944,7 @@ struct PlayerProfile_Struct
|
||||
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*15060*/ uint8 unknown12852[8];
|
||||
/*15068*/ uint32 available_slots;
|
||||
/*15072*/ uint8 unknown12864[12]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80]
|
||||
/*15084*/ uint32 cold_resist;
|
||||
/*15088*/ uint32 fire_resist;
|
||||
/*15092*/ uint32 magic_resist;
|
||||
/*15096*/ uint32 disease_resist;
|
||||
/*15100*/ uint32 poison_resist;
|
||||
/*15104*/ uint32 physical_resist;
|
||||
/*15108*/ uint32 corruption_resist;
|
||||
/*15112*/ uint8 unknown15112[40];
|
||||
/*15072*/ uint8 unknown12864[80]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80]
|
||||
//END SUB-STRUCT used for shrouding.
|
||||
/*15152*/ char name[64]; // Name of player
|
||||
/*15216*/ char last_name[32]; // Last name of player
|
||||
|
||||
+7
-19
@@ -1339,27 +1339,15 @@ namespace SoF
|
||||
// OUT(unknown19584[4]);
|
||||
// OUT(unknown19588);
|
||||
|
||||
const uint8 unknown12864_bytes[] = {
|
||||
0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
const uint8 bytes[] = {
|
||||
0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F,
|
||||
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(eq->unknown12864, unknown12864_bytes, sizeof(unknown12864_bytes));
|
||||
|
||||
eq->cold_resist = emu->cold_resist;
|
||||
eq->fire_resist = emu->fire_resist;
|
||||
eq->magic_resist = emu->magic_resist;
|
||||
eq->disease_resist = emu->disease_resist;
|
||||
eq->poison_resist = emu->poison_resist;
|
||||
eq->physical_resist = 15;
|
||||
eq->corruption_resist = emu->corruption_resist;
|
||||
|
||||
const uint8 unknown15112_bytes[] = {
|
||||
0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(eq->unknown15112, unknown15112_bytes, sizeof(unknown15112_bytes));
|
||||
memcpy(eq->unknown12864, bytes, sizeof(bytes));
|
||||
|
||||
//set the checksum...
|
||||
CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4);
|
||||
|
||||
@@ -944,16 +944,7 @@ struct PlayerProfile_Struct //23576 Octets
|
||||
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
|
||||
/*15060*/ uint8 unknown12852[8];
|
||||
/*15068*/ uint32 available_slots;
|
||||
/*15072*/ uint8 unknown12864[12]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80]
|
||||
/*15084*/ uint32 cold_resist;
|
||||
/*15088*/ uint32 fire_resist;
|
||||
/*15092*/ uint32 magic_resist;
|
||||
/*15096*/ uint32 disease_resist;
|
||||
/*15100*/ uint32 poison_resist;
|
||||
/*15104*/ uint32 physical_resist;
|
||||
/*15108*/ uint32 corruption_resist;
|
||||
/*15112*/ uint8 unknown15112[40];
|
||||
|
||||
/*15072*/ uint8 unknown12864[80]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80]
|
||||
//END SUB-STRUCT used for shrouding.
|
||||
/*15120*/ char name[64]; // Name of player
|
||||
/*15184*/ char last_name[32]; // Last name of player
|
||||
|
||||
@@ -1600,25 +1600,14 @@ namespace Titanium
|
||||
// OUT(unknown19584[4]);
|
||||
// OUT(unknown19588);
|
||||
|
||||
const uint8 unknown12864_bytes[] = {
|
||||
0x78, 0x03, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(eq->unknown12864, unknown12864_bytes, sizeof(unknown12864_bytes));
|
||||
|
||||
eq->cold_resist = emu->cold_resist;
|
||||
eq->fire_resist = emu->fire_resist;
|
||||
eq->magic_resist = emu->magic_resist;
|
||||
eq->disease_resist = emu->disease_resist;
|
||||
eq->poison_resist = emu->poison_resist;
|
||||
eq->physical_resist = 15;
|
||||
|
||||
const uint8 unknown12900_bytes[] = {
|
||||
0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x09, 0x00, 0x00, 0x00,
|
||||
const uint8 bytes[] = {
|
||||
0x78, 0x03, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x09, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14
|
||||
};
|
||||
|
||||
memcpy(eq->unknown12900, unknown12900_bytes, sizeof(unknown12900_bytes));
|
||||
memcpy(eq->unknown12864, bytes, sizeof(bytes));
|
||||
|
||||
//set the checksum...
|
||||
CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4);
|
||||
|
||||
@@ -879,14 +879,7 @@ struct PlayerProfile_Struct
|
||||
/*12564*/ PotionBelt_Struct potionbelt; // potion belt
|
||||
/*12852*/ uint8 unknown12852[8];
|
||||
/*12860*/ uint32 available_slots;
|
||||
/*12864*/ uint8 unknown12864[12];
|
||||
/*12876*/ uint32 cold_resist;
|
||||
/*12880*/ uint32 fire_resist;
|
||||
/*12884*/ uint32 magic_resist;
|
||||
/*12888*/ uint32 disease_resist;
|
||||
/*12892*/ uint32 poison_resist;
|
||||
/*12896*/ uint32 physical_resist;
|
||||
/*12900*/ uint8 unknown12900[40];
|
||||
/*12864*/ uint8 unknown12864[76];
|
||||
/*12940*/ char name[64]; // Name of player
|
||||
/*13004*/ char last_name[32]; // Last name of player
|
||||
/*13036*/ uint32 guild_id; // guildid
|
||||
|
||||
@@ -74,6 +74,11 @@ void PathManager::LoadPaths()
|
||||
m_patch_path = fs::relative(fs::path{m_server_path + "/" + c->PatchDir}).string();
|
||||
}
|
||||
|
||||
// patches
|
||||
if (File::Exists(fs::path{ m_server_path + "/" + c->OpcodeDir }.string())) {
|
||||
m_opcode_path = fs::relative(fs::path{ m_server_path + "/" + c->OpcodeDir }).string();
|
||||
}
|
||||
|
||||
// shared_memory_path
|
||||
if (File::Exists(fs::path{m_server_path + "/" + c->SharedMemDir}.string())) {
|
||||
m_shared_memory_path = fs::relative(fs::path{ m_server_path + "/" + c->SharedMemDir }).string();
|
||||
@@ -89,6 +94,7 @@ void PathManager::LoadPaths()
|
||||
LogInfo("lua_modules path [{}]", m_lua_modules_path);
|
||||
LogInfo("maps path [{}]", m_maps_path);
|
||||
LogInfo("patches path [{}]", m_patch_path);
|
||||
LogInfo("opcode path [{}]", m_opcode_path);
|
||||
LogInfo("plugins path [{}]", m_plugins_path);
|
||||
LogInfo("quests path [{}]", m_quests_path);
|
||||
LogInfo("shared_memory path [{}]", m_shared_memory_path);
|
||||
@@ -129,6 +135,11 @@ const std::string &PathManager::GetPatchPath() const
|
||||
return m_patch_path;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetOpcodePath() const
|
||||
{
|
||||
return m_opcode_path;
|
||||
}
|
||||
|
||||
const std::string &PathManager::GetLuaModulesPath() const
|
||||
{
|
||||
return m_lua_modules_path;
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
[[nodiscard]] const std::string &GetLuaModulesPath() const;
|
||||
[[nodiscard]] const std::string &GetMapsPath() const;
|
||||
[[nodiscard]] const std::string &GetPatchPath() const;
|
||||
[[nodiscard]] const std::string &GetOpcodePath() const;
|
||||
[[nodiscard]] const std::string &GetPluginsPath() const;
|
||||
[[nodiscard]] const std::string &GetQuestsPath() const;
|
||||
[[nodiscard]] const std::string &GetServerPath() const;
|
||||
@@ -24,6 +25,7 @@ private:
|
||||
std::string m_lua_modules_path;
|
||||
std::string m_maps_path;
|
||||
std::string m_patch_path;
|
||||
std::string m_opcode_path;
|
||||
std::string m_plugins_path;
|
||||
std::string m_quests_path;
|
||||
std::string m_server_path;
|
||||
|
||||
@@ -34,12 +34,6 @@ public:
|
||||
uint32_t alloc_int;
|
||||
uint32_t alloc_wis;
|
||||
uint32_t alloc_cha;
|
||||
uint32_t base_cr;
|
||||
uint32_t base_fr;
|
||||
uint32_t base_mr;
|
||||
uint32_t base_dr;
|
||||
uint32_t base_pr;
|
||||
uint32_t base_corrup;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -65,12 +59,6 @@ public:
|
||||
"alloc_int",
|
||||
"alloc_wis",
|
||||
"alloc_cha",
|
||||
"base_cr",
|
||||
"base_fr",
|
||||
"base_mr",
|
||||
"base_dr",
|
||||
"base_pr",
|
||||
"base_corrup",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -92,12 +80,6 @@ public:
|
||||
"alloc_int",
|
||||
"alloc_wis",
|
||||
"alloc_cha",
|
||||
"base_cr",
|
||||
"base_fr",
|
||||
"base_mr",
|
||||
"base_dr",
|
||||
"base_pr",
|
||||
"base_corrup",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -138,27 +120,21 @@ public:
|
||||
{
|
||||
CharCreatePointAllocations e{};
|
||||
|
||||
e.id = 0;
|
||||
e.base_str = 0;
|
||||
e.base_sta = 0;
|
||||
e.base_dex = 0;
|
||||
e.base_agi = 0;
|
||||
e.base_int = 0;
|
||||
e.base_wis = 0;
|
||||
e.base_cha = 0;
|
||||
e.alloc_str = 0;
|
||||
e.alloc_sta = 0;
|
||||
e.alloc_dex = 0;
|
||||
e.alloc_agi = 0;
|
||||
e.alloc_int = 0;
|
||||
e.alloc_wis = 0;
|
||||
e.alloc_cha = 0;
|
||||
e.base_cr = 0;
|
||||
e.base_fr = 0;
|
||||
e.base_mr = 0;
|
||||
e.base_dr = 0;
|
||||
e.base_pr = 0;
|
||||
e.base_corrup = 0;
|
||||
e.id = 0;
|
||||
e.base_str = 0;
|
||||
e.base_sta = 0;
|
||||
e.base_dex = 0;
|
||||
e.base_agi = 0;
|
||||
e.base_int = 0;
|
||||
e.base_wis = 0;
|
||||
e.base_cha = 0;
|
||||
e.alloc_str = 0;
|
||||
e.alloc_sta = 0;
|
||||
e.alloc_dex = 0;
|
||||
e.alloc_agi = 0;
|
||||
e.alloc_int = 0;
|
||||
e.alloc_wis = 0;
|
||||
e.alloc_cha = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -195,27 +171,21 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
CharCreatePointAllocations e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.base_str = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.base_sta = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.base_dex = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.base_agi = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.base_int = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.base_wis = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.base_cha = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.alloc_str = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.alloc_sta = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.alloc_dex = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.alloc_agi = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
|
||||
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.base_cr = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.base_fr = row[16] ? static_cast<uint32_t>(strtoul(row[16], nullptr, 10)) : 0;
|
||||
e.base_mr = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
|
||||
e.base_dr = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
|
||||
e.base_pr = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
|
||||
e.base_corrup = row[20] ? static_cast<uint32_t>(strtoul(row[20], nullptr, 10)) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.base_str = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.base_sta = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.base_dex = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.base_agi = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.base_int = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.base_wis = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.base_cha = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.alloc_str = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.alloc_sta = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.alloc_dex = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.alloc_agi = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
|
||||
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -264,12 +234,6 @@ public:
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.alloc_int));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.alloc_wis));
|
||||
v.push_back(columns[14] + " = " + std::to_string(e.alloc_cha));
|
||||
v.push_back(columns[15] + " = " + std::to_string(e.base_cr));
|
||||
v.push_back(columns[16] + " = " + std::to_string(e.base_fr));
|
||||
v.push_back(columns[17] + " = " + std::to_string(e.base_mr));
|
||||
v.push_back(columns[18] + " = " + std::to_string(e.base_dr));
|
||||
v.push_back(columns[19] + " = " + std::to_string(e.base_pr));
|
||||
v.push_back(columns[20] + " = " + std::to_string(e.base_corrup));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -306,12 +270,6 @@ public:
|
||||
v.push_back(std::to_string(e.alloc_int));
|
||||
v.push_back(std::to_string(e.alloc_wis));
|
||||
v.push_back(std::to_string(e.alloc_cha));
|
||||
v.push_back(std::to_string(e.base_cr));
|
||||
v.push_back(std::to_string(e.base_fr));
|
||||
v.push_back(std::to_string(e.base_mr));
|
||||
v.push_back(std::to_string(e.base_dr));
|
||||
v.push_back(std::to_string(e.base_pr));
|
||||
v.push_back(std::to_string(e.base_corrup));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -356,12 +314,6 @@ public:
|
||||
v.push_back(std::to_string(e.alloc_int));
|
||||
v.push_back(std::to_string(e.alloc_wis));
|
||||
v.push_back(std::to_string(e.alloc_cha));
|
||||
v.push_back(std::to_string(e.base_cr));
|
||||
v.push_back(std::to_string(e.base_fr));
|
||||
v.push_back(std::to_string(e.base_mr));
|
||||
v.push_back(std::to_string(e.base_dr));
|
||||
v.push_back(std::to_string(e.base_pr));
|
||||
v.push_back(std::to_string(e.base_corrup));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -395,27 +347,21 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharCreatePointAllocations e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.base_str = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.base_sta = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.base_dex = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.base_agi = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.base_int = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.base_wis = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.base_cha = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.alloc_str = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.alloc_sta = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.alloc_dex = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.alloc_agi = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
|
||||
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.base_cr = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.base_fr = row[16] ? static_cast<uint32_t>(strtoul(row[16], nullptr, 10)) : 0;
|
||||
e.base_mr = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
|
||||
e.base_dr = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
|
||||
e.base_pr = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
|
||||
e.base_corrup = row[20] ? static_cast<uint32_t>(strtoul(row[20], nullptr, 10)) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.base_str = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.base_sta = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.base_dex = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.base_agi = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.base_int = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.base_wis = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.base_cha = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.alloc_str = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.alloc_sta = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.alloc_dex = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.alloc_agi = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
|
||||
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -440,27 +386,21 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharCreatePointAllocations e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.base_str = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.base_sta = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.base_dex = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.base_agi = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.base_int = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.base_wis = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.base_cha = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.alloc_str = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.alloc_sta = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.alloc_dex = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.alloc_agi = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
|
||||
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
e.base_cr = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
|
||||
e.base_fr = row[16] ? static_cast<uint32_t>(strtoul(row[16], nullptr, 10)) : 0;
|
||||
e.base_mr = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
|
||||
e.base_dr = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
|
||||
e.base_pr = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
|
||||
e.base_corrup = row[20] ? static_cast<uint32_t>(strtoul(row[20], nullptr, 10)) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.base_str = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
|
||||
e.base_sta = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.base_dex = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.base_agi = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.base_int = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
|
||||
e.base_wis = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
|
||||
e.base_cha = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
|
||||
e.alloc_str = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
|
||||
e.alloc_sta = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
|
||||
e.alloc_dex = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
|
||||
e.alloc_agi = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
|
||||
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
|
||||
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
|
||||
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -550,12 +490,6 @@ public:
|
||||
v.push_back(std::to_string(e.alloc_int));
|
||||
v.push_back(std::to_string(e.alloc_wis));
|
||||
v.push_back(std::to_string(e.alloc_cha));
|
||||
v.push_back(std::to_string(e.base_cr));
|
||||
v.push_back(std::to_string(e.base_fr));
|
||||
v.push_back(std::to_string(e.base_mr));
|
||||
v.push_back(std::to_string(e.base_dr));
|
||||
v.push_back(std::to_string(e.base_pr));
|
||||
v.push_back(std::to_string(e.base_corrup));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -593,12 +527,6 @@ public:
|
||||
v.push_back(std::to_string(e.alloc_int));
|
||||
v.push_back(std::to_string(e.alloc_wis));
|
||||
v.push_back(std::to_string(e.alloc_cha));
|
||||
v.push_back(std::to_string(e.base_cr));
|
||||
v.push_back(std::to_string(e.base_fr));
|
||||
v.push_back(std::to_string(e.base_mr));
|
||||
v.push_back(std::to_string(e.base_dr));
|
||||
v.push_back(std::to_string(e.base_pr));
|
||||
v.push_back(std::to_string(e.base_corrup));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -123,12 +123,6 @@ public:
|
||||
uint32_t aa_points_old;
|
||||
uint32_t e_last_invsnapshot;
|
||||
time_t deleted_at;
|
||||
uint32_t cold_resist;
|
||||
uint32_t fire_resist;
|
||||
uint32_t magic_resist;
|
||||
uint32_t disease_resist;
|
||||
uint32_t poison_resist;
|
||||
uint32_t corruption_resist;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@@ -243,12 +237,6 @@ public:
|
||||
"aa_points_old",
|
||||
"e_last_invsnapshot",
|
||||
"deleted_at",
|
||||
"cold_resist",
|
||||
"fire_resist",
|
||||
"magic_resist",
|
||||
"disease_resist",
|
||||
"poison_resist",
|
||||
"corruption_resist",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -359,12 +347,6 @@ public:
|
||||
"aa_points_old",
|
||||
"e_last_invsnapshot",
|
||||
"UNIX_TIMESTAMP(deleted_at)",
|
||||
"cold_resist",
|
||||
"fire_resist",
|
||||
"magic_resist",
|
||||
"disease_resist",
|
||||
"poison_resist",
|
||||
"corruption_resist",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -509,12 +491,6 @@ public:
|
||||
e.aa_points_old = 0;
|
||||
e.e_last_invsnapshot = 0;
|
||||
e.deleted_at = 0;
|
||||
e.cold_resist = 0;
|
||||
e.fire_resist = 0;
|
||||
e.magic_resist = 0;
|
||||
e.disease_resist = 0;
|
||||
e.poison_resist = 0;
|
||||
e.corruption_resist = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -655,12 +631,6 @@ public:
|
||||
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
|
||||
e.cold_resist = row[104] ? static_cast<uint32_t>(strtoul(row[104], nullptr, 10)) : 0;
|
||||
e.fire_resist = row[105] ? static_cast<uint32_t>(strtoul(row[105], nullptr, 10)) : 0;
|
||||
e.magic_resist = row[106] ? static_cast<uint32_t>(strtoul(row[106], nullptr, 10)) : 0;
|
||||
e.disease_resist = row[107] ? static_cast<uint32_t>(strtoul(row[107], nullptr, 10)) : 0;
|
||||
e.poison_resist = row[108] ? static_cast<uint32_t>(strtoul(row[108], nullptr, 10)) : 0;
|
||||
e.corruption_resist = row[109] ? static_cast<uint32_t>(strtoul(row[109], nullptr, 10)) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -797,12 +767,6 @@ public:
|
||||
v.push_back(columns[101] + " = " + std::to_string(e.aa_points_old));
|
||||
v.push_back(columns[102] + " = " + std::to_string(e.e_last_invsnapshot));
|
||||
v.push_back(columns[103] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
|
||||
v.push_back(columns[104] + " = " + std::to_string(e.cold_resist));
|
||||
v.push_back(columns[105] + " = " + std::to_string(e.fire_resist));
|
||||
v.push_back(columns[106] + " = " + std::to_string(e.magic_resist));
|
||||
v.push_back(columns[107] + " = " + std::to_string(e.disease_resist));
|
||||
v.push_back(columns[108] + " = " + std::to_string(e.poison_resist));
|
||||
v.push_back(columns[109] + " = " + std::to_string(e.corruption_resist));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -928,12 +892,6 @@ public:
|
||||
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") + ")");
|
||||
v.push_back(std::to_string(e.cold_resist));
|
||||
v.push_back(std::to_string(e.fire_resist));
|
||||
v.push_back(std::to_string(e.magic_resist));
|
||||
v.push_back(std::to_string(e.disease_resist));
|
||||
v.push_back(std::to_string(e.poison_resist));
|
||||
v.push_back(std::to_string(e.corruption_resist));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -1067,12 +1025,6 @@ public:
|
||||
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") + ")");
|
||||
v.push_back(std::to_string(e.cold_resist));
|
||||
v.push_back(std::to_string(e.fire_resist));
|
||||
v.push_back(std::to_string(e.magic_resist));
|
||||
v.push_back(std::to_string(e.disease_resist));
|
||||
v.push_back(std::to_string(e.poison_resist));
|
||||
v.push_back(std::to_string(e.corruption_resist));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@@ -1210,12 +1162,6 @@ public:
|
||||
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
|
||||
e.cold_resist = row[104] ? static_cast<uint32_t>(strtoul(row[104], nullptr, 10)) : 0;
|
||||
e.fire_resist = row[105] ? static_cast<uint32_t>(strtoul(row[105], nullptr, 10)) : 0;
|
||||
e.magic_resist = row[106] ? static_cast<uint32_t>(strtoul(row[106], nullptr, 10)) : 0;
|
||||
e.disease_resist = row[107] ? static_cast<uint32_t>(strtoul(row[107], nullptr, 10)) : 0;
|
||||
e.poison_resist = row[108] ? static_cast<uint32_t>(strtoul(row[108], nullptr, 10)) : 0;
|
||||
e.corruption_resist = row[109] ? static_cast<uint32_t>(strtoul(row[109], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -1344,12 +1290,6 @@ public:
|
||||
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
|
||||
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
|
||||
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
|
||||
e.cold_resist = row[104] ? static_cast<uint32_t>(strtoul(row[104], nullptr, 10)) : 0;
|
||||
e.fire_resist = row[105] ? static_cast<uint32_t>(strtoul(row[105], nullptr, 10)) : 0;
|
||||
e.magic_resist = row[106] ? static_cast<uint32_t>(strtoul(row[106], nullptr, 10)) : 0;
|
||||
e.disease_resist = row[107] ? static_cast<uint32_t>(strtoul(row[107], nullptr, 10)) : 0;
|
||||
e.poison_resist = row[108] ? static_cast<uint32_t>(strtoul(row[108], nullptr, 10)) : 0;
|
||||
e.corruption_resist = row[109] ? static_cast<uint32_t>(strtoul(row[109], nullptr, 10)) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@@ -1528,12 +1468,6 @@ public:
|
||||
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") + ")");
|
||||
v.push_back(std::to_string(e.cold_resist));
|
||||
v.push_back(std::to_string(e.fire_resist));
|
||||
v.push_back(std::to_string(e.magic_resist));
|
||||
v.push_back(std::to_string(e.disease_resist));
|
||||
v.push_back(std::to_string(e.poison_resist));
|
||||
v.push_back(std::to_string(e.corruption_resist));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@@ -1660,12 +1594,6 @@ public:
|
||||
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") + ")");
|
||||
v.push_back(std::to_string(e.cold_resist));
|
||||
v.push_back(std::to_string(e.fire_resist));
|
||||
v.push_back(std::to_string(e.magic_resist));
|
||||
v.push_back(std::to_string(e.disease_resist));
|
||||
v.push_back(std::to_string(e.poison_resist));
|
||||
v.push_back(std::to_string(e.corruption_resist));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@@ -236,6 +236,10 @@ public:
|
||||
)
|
||||
);
|
||||
|
||||
if (buyers.empty()) {
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
std::vector<std::string> char_ids{};
|
||||
for (auto const &bl : buyers) {
|
||||
char_ids.push_back((std::to_string(bl.char_id)));
|
||||
|
||||
@@ -120,6 +120,10 @@ public:
|
||||
}
|
||||
|
||||
DeleteWhere(db, fmt::format("`char_id` = '{}';", char_id));
|
||||
if (buy_line_ids.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseBuyerBuyLinesRepository::DeleteWhere(
|
||||
db,
|
||||
fmt::format("`id` IN({})", Strings::Implode(", ", buy_line_ids))
|
||||
|
||||
@@ -217,6 +217,10 @@ public:
|
||||
delete_ids.push_back(std::to_string(e.id));
|
||||
}
|
||||
|
||||
if (delete_ids.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DeleteWhere(db, fmt::format("`id` IN({})", Strings::Implode(",", delete_ids)));
|
||||
}
|
||||
};
|
||||
|
||||
+2
-1
@@ -338,6 +338,7 @@ RULE_STRING(World, IPExemptionZones, "", "Comma-delimited list of zones to exclu
|
||||
RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to have this be used instead of variables table 'motd' value")
|
||||
RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be used instead of variables table 'rules' value, lines are pipe (|) separated, example: A|B|C")
|
||||
RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame")
|
||||
RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Zone)
|
||||
@@ -516,7 +517,7 @@ RULE_INT(Spells, HealAmountMessageFilterThreshold, 100, "Lifetaps below this thr
|
||||
RULE_BOOL(Spells, SnareOverridesSpeedBonuses, false, "Enabling will allow snares to override any speed bonuses the entity may have. Default: False")
|
||||
RULE_INT(Spells, TargetedAOEMaxTargets, 4, "Max number of targets a Targeted AOE spell can cast on. Set to 0 for no limit.")
|
||||
RULE_INT(Spells, PointBlankAOEMaxTargets, 0, "Max number of targets a Point-Blank AOE spell can cast on. Set to 0 for no limit.")
|
||||
RULE_INT(Spells, DefaultAOEMaxTargets, 4, "Max number of targets that an AOE spell which does not meet other descriptions can cast on. Set to 0 for no limit.")
|
||||
RULE_INT(Spells, DefaultAOEMaxTargets, 0, "Max number of targets that an AOE spell which does not meet other descriptions can cast on. Set to 0 for no limit.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Combat)
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
|
||||
// Build variables
|
||||
// these get injected during the build pipeline
|
||||
#define CURRENT_VERSION "22.56.3-dev" // always append -dev to the current version for custom-builds
|
||||
#define CURRENT_VERSION "22.57.1-dev" // always append -dev to the current version for custom-builds
|
||||
#define LOGIN_VERSION "0.8.0"
|
||||
#define COMPILE_DATE __DATE__
|
||||
#define COMPILE_TIME __TIME__
|
||||
|
||||
@@ -7,6 +7,79 @@ extern bool run_server;
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/misc.h"
|
||||
#include "../common/path_manager.h"
|
||||
#include "../common/file.h"
|
||||
|
||||
void CheckTitaniumOpcodeFile(const std::string &path) {
|
||||
if (File::Exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto f = fopen(path.c_str(), "w");
|
||||
if (f) {
|
||||
fprintf(f, "#EQEmu Public Login Server OPCodes\n");
|
||||
fprintf(f, "OP_SessionReady=0x0001\n");
|
||||
fprintf(f, "OP_Login=0x0002\n");
|
||||
fprintf(f, "OP_ServerListRequest=0x0004\n");
|
||||
fprintf(f, "OP_PlayEverquestRequest=0x000d\n");
|
||||
fprintf(f, "OP_PlayEverquestResponse=0x0021\n");
|
||||
fprintf(f, "OP_ChatMessage=0x0016\n");
|
||||
fprintf(f, "OP_LoginAccepted=0x0017\n");
|
||||
fprintf(f, "OP_ServerListResponse=0x0018\n");
|
||||
fprintf(f, "OP_Poll=0x0029\n");
|
||||
fprintf(f, "OP_EnterChat=0x000f\n");
|
||||
fprintf(f, "OP_PollResponse=0x0011\n");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckSoDOpcodeFile(const std::string& path) {
|
||||
if (File::Exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto f = fopen(path.c_str(), "w");
|
||||
if (f) {
|
||||
fprintf(f, "#EQEmu Public Login Server OPCodes\n");
|
||||
fprintf(f, "OP_SessionReady=0x0001\n");
|
||||
fprintf(f, "OP_Login=0x0002\n");
|
||||
fprintf(f, "OP_ServerListRequest=0x0004\n");
|
||||
fprintf(f, "OP_PlayEverquestRequest=0x000d\n");
|
||||
fprintf(f, "OP_PlayEverquestResponse=0x0022\n");
|
||||
fprintf(f, "OP_ChatMessage=0x0017\n");
|
||||
fprintf(f, "OP_LoginAccepted=0x0018\n");
|
||||
fprintf(f, "OP_ServerListResponse=0x0019\n");
|
||||
fprintf(f, "OP_Poll=0x0029\n");
|
||||
fprintf(f, "OP_LoginExpansionPacketData=0x0031\n");
|
||||
fprintf(f, "OP_EnterChat=0x000f\n");
|
||||
fprintf(f, "OP_PollResponse=0x0011\n");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckLarionOpcodeFile(const std::string& path) {
|
||||
if (File::Exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto f = fopen(path.c_str(), "w");
|
||||
if (f) {
|
||||
fprintf(f, "#EQEmu Public Login Server OPCodes\n");
|
||||
fprintf(f, "OP_SessionReady=0x0001\n");
|
||||
fprintf(f, "OP_Login=0x0002\n");
|
||||
fprintf(f, "OP_ServerListRequest=0x0004\n");
|
||||
fprintf(f, "OP_PlayEverquestRequest=0x000d\n");
|
||||
fprintf(f, "OP_PlayEverquestResponse=0x0022\n");
|
||||
fprintf(f, "OP_ChatMessage=0x0017\n");
|
||||
fprintf(f, "OP_LoginAccepted=0x0018\n");
|
||||
fprintf(f, "OP_ServerListResponse=0x0019\n");
|
||||
fprintf(f, "OP_Poll=0x0029\n");
|
||||
fprintf(f, "OP_EnterChat=0x000f\n");
|
||||
fprintf(f, "OP_PollResponse=0x0011\n");
|
||||
fprintf(f, "OP_SystemFingerprint=0x0016\n");
|
||||
fprintf(f, "OP_ExpansionList=0x0030\n");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
ClientManager::ClientManager()
|
||||
{
|
||||
@@ -19,14 +92,12 @@ ClientManager::ClientManager()
|
||||
|
||||
std::string opcodes_path = fmt::format(
|
||||
"{}/{}",
|
||||
path.GetServerPath(),
|
||||
server.config.GetVariableString(
|
||||
"client_configuration",
|
||||
"titanium_opcodes",
|
||||
"login_opcodes.conf"
|
||||
)
|
||||
path.GetOpcodePath(),
|
||||
"login_opcodes.conf"
|
||||
);
|
||||
|
||||
CheckTitaniumOpcodeFile(opcodes_path);
|
||||
|
||||
if (!titanium_ops->LoadOpcodes(opcodes_path.c_str())) {
|
||||
LogError(
|
||||
"ClientManager fatal error: couldn't load opcodes for Titanium file [{0}]",
|
||||
@@ -58,14 +129,12 @@ ClientManager::ClientManager()
|
||||
|
||||
opcodes_path = fmt::format(
|
||||
"{}/{}",
|
||||
path.GetServerPath(),
|
||||
server.config.GetVariableString(
|
||||
"client_configuration",
|
||||
"sod_opcodes",
|
||||
"login_opcodes.conf"
|
||||
)
|
||||
path.GetOpcodePath(),
|
||||
"login_opcodes_sod.conf"
|
||||
);
|
||||
|
||||
CheckSoDOpcodeFile(opcodes_path);
|
||||
|
||||
if (!sod_ops->LoadOpcodes(opcodes_path.c_str())) {
|
||||
LogError(
|
||||
"ClientManager fatal error: couldn't load opcodes for SoD file {0}",
|
||||
@@ -98,14 +167,12 @@ ClientManager::ClientManager()
|
||||
|
||||
opcodes_path = fmt::format(
|
||||
"{}/{}",
|
||||
path.GetServerPath(),
|
||||
server.config.GetVariableString(
|
||||
"client_configuration",
|
||||
"larion_opcodes",
|
||||
"login_opcodes.conf"
|
||||
)
|
||||
path.GetOpcodePath(),
|
||||
"login_opcodes_larion.conf"
|
||||
);
|
||||
|
||||
CheckLarionOpcodeFile(opcodes_path);
|
||||
|
||||
if (!larion_ops->LoadOpcodes(opcodes_path.c_str())) {
|
||||
LogError(
|
||||
"ClientManager fatal error: couldn't load opcodes for Larion file [{0}]",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eqemu-server",
|
||||
"version": "22.56.3",
|
||||
"version": "22.57.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EQEmu/Server.git"
|
||||
|
||||
@@ -56,7 +56,6 @@ SET(world_headers
|
||||
login_server.h
|
||||
login_server_list.h
|
||||
queryserv.h
|
||||
race_combos.h
|
||||
shared_task_manager.h
|
||||
shared_task_world_messaging.h
|
||||
sof_char_create_data.h
|
||||
|
||||
+269
-354
@@ -47,7 +47,6 @@
|
||||
#include "clientlist.h"
|
||||
#include "wguild_mgr.h"
|
||||
#include "sof_char_create_data.h"
|
||||
#include "race_combos.h"
|
||||
#include "../common/zone_store.h"
|
||||
#include "../common/repositories/account_repository.h"
|
||||
#include "../common/repositories/player_event_logs_repository.h"
|
||||
@@ -86,8 +85,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
std::vector<CharCreatePointAllocation> character_create_allocations;
|
||||
std::vector<CharCreateCombination> character_create_race_class_combos;
|
||||
std::vector<RaceClassAllocation> character_create_allocations;
|
||||
std::vector<RaceClassCombos> character_create_race_class_combos;
|
||||
|
||||
extern ZSList zoneserver_list;
|
||||
extern LoginServerList loginserverlist;
|
||||
@@ -1643,348 +1642,6 @@ void Client::SendApproveWorld()
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
// returns true if the request is ok, false if there's an error
|
||||
bool CheckCharCreateInfoSoF(CharCreate_Struct* cc)
|
||||
{
|
||||
if (!cc)
|
||||
return false;
|
||||
|
||||
LogInfo("Validating char creation info");
|
||||
|
||||
CharCreateCombination class_combo;
|
||||
bool found = false;
|
||||
int combos = character_create_race_class_combos.size();
|
||||
for (int i = 0; i < combos; ++i) {
|
||||
if (character_create_race_class_combos[i].Class == cc->class_ &&
|
||||
character_create_race_class_combos[i].Race == cc->race &&
|
||||
character_create_race_class_combos[i].Deity == cc->deity &&
|
||||
character_create_race_class_combos[i].Zone == cc->start_zone) {
|
||||
class_combo = character_create_race_class_combos[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LogInfo("Could not find class/race/deity/start_zone combination");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 allocs = character_create_allocations.size();
|
||||
CharCreatePointAllocation allocation = { 0 };
|
||||
found = false;
|
||||
for (int i = 0; i < allocs; ++i) {
|
||||
if (character_create_allocations[i].Index == class_combo.AllocationIndex) {
|
||||
allocation = character_create_allocations[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LogInfo("Could not find starting stats for selected character combo, cannot verify stats");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 max_stats = allocation.DefaultPointAllocation[0] +
|
||||
allocation.DefaultPointAllocation[1] +
|
||||
allocation.DefaultPointAllocation[2] +
|
||||
allocation.DefaultPointAllocation[3] +
|
||||
allocation.DefaultPointAllocation[4] +
|
||||
allocation.DefaultPointAllocation[5] +
|
||||
allocation.DefaultPointAllocation[6];
|
||||
|
||||
if (cc->STR > allocation.BaseStats[0] + max_stats || cc->STR < allocation.BaseStats[0]) {
|
||||
LogInfo("Strength out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->DEX > allocation.BaseStats[1] + max_stats || cc->DEX < allocation.BaseStats[1]) {
|
||||
LogInfo("Dexterity out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->AGI > allocation.BaseStats[2] + max_stats || cc->AGI < allocation.BaseStats[2]) {
|
||||
LogInfo("Agility out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->STA > allocation.BaseStats[3] + max_stats || cc->STA < allocation.BaseStats[3]) {
|
||||
LogInfo("Stamina out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->INT > allocation.BaseStats[4] + max_stats || cc->INT < allocation.BaseStats[4]) {
|
||||
LogInfo("Intelligence out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->WIS > allocation.BaseStats[5] + max_stats || cc->WIS < allocation.BaseStats[5]) {
|
||||
LogInfo("Wisdom out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->CHA > allocation.BaseStats[6] + max_stats || cc->CHA < allocation.BaseStats[6]) {
|
||||
LogInfo("Charisma out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 current_stats = 0;
|
||||
current_stats += cc->STR - allocation.BaseStats[0];
|
||||
current_stats += cc->DEX - allocation.BaseStats[1];
|
||||
current_stats += cc->AGI - allocation.BaseStats[2];
|
||||
current_stats += cc->STA - allocation.BaseStats[3];
|
||||
current_stats += cc->INT - allocation.BaseStats[4];
|
||||
current_stats += cc->WIS - allocation.BaseStats[5];
|
||||
current_stats += cc->CHA - allocation.BaseStats[6];
|
||||
if (current_stats > max_stats) {
|
||||
LogInfo("Current Stats > Maximum Stats");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckCharCreateInfoTitanium(CharCreate_Struct* cc)
|
||||
{
|
||||
uint32 bSTR, bSTA, bAGI, bDEX, bWIS, bINT, bCHA, bTOTAL, cTOTAL, stat_points; //these are all uint32 in CharCreate_Struct, so we'll make them uint32 here to make the compiler shut up
|
||||
int classtemp, racetemp;
|
||||
int Charerrors = 0;
|
||||
|
||||
|
||||
// if this is increased you'll have to add a column to the classrace
|
||||
// table below
|
||||
#define _TABLE_RACES 16
|
||||
|
||||
static const int BaseRace[_TABLE_RACES][7] =
|
||||
{ /* STR STA AGI DEX WIS INT CHR */
|
||||
{ /*Human*/ 75, 75, 75, 75, 75, 75, 75},
|
||||
{ /*Barbarian*/ 103, 95, 82, 70, 70, 60, 55},
|
||||
{ /*Erudite*/ 60, 70, 70, 70, 83, 107, 70},
|
||||
{ /*Wood Elf*/ 65, 65, 95, 80, 80, 75, 75},
|
||||
{ /*High Elf*/ 55, 65, 85, 70, 95, 92, 80},
|
||||
{ /*Dark Elf*/ 60, 65, 90, 75, 83, 99, 60},
|
||||
{ /*Half Elf*/ 70, 70, 90, 85, 60, 75, 75},
|
||||
{ /*Dwarf*/ 90, 90, 70, 90, 83, 60, 45},
|
||||
{ /*Troll*/ 108, 109, 83, 75, 60, 52, 40},
|
||||
{ /*Ogre*/ 130, 122, 70, 70, 67, 60, 37},
|
||||
{ /*Halfling*/ 70, 75, 95, 90, 80, 67, 50},
|
||||
{ /*Gnome*/ 60, 70, 85, 85, 67, 98, 60},
|
||||
{ /*Iksar*/ 70, 70, 90, 85, 80, 75, 55},
|
||||
{ /*Vah Shir*/ 90, 75, 90, 70, 70, 65, 65},
|
||||
{ /*Froglok*/ 70, 80, 100, 100, 75, 75, 50},
|
||||
{ /*Drakkin*/ 70, 80, 85, 75, 80, 85, 75}
|
||||
};
|
||||
|
||||
static const int BaseClass[Class::PLAYER_CLASS_COUNT][8] =
|
||||
{ /* STR STA AGI DEX WIS INT CHR ADD*/
|
||||
{ /*Warrior*/ 10, 10, 5, 0, 0, 0, 0, 25},
|
||||
{ /*Cleric*/ 5, 5, 0, 0, 10, 0, 0, 30},
|
||||
{ /*Paladin*/ 10, 5, 0, 0, 5, 0, 10, 20},
|
||||
{ /*Ranger*/ 5, 10, 10, 0, 5, 0, 0, 20},
|
||||
{ /*ShadowKnight*/ 10, 5, 0, 0, 0, 10, 5, 20},
|
||||
{ /*Druid*/ 0, 10, 0, 0, 10, 0, 0, 30},
|
||||
{ /*Monk*/ 5, 5, 10, 10, 0, 0, 0, 20},
|
||||
{ /*Bard*/ 5, 0, 0, 10, 0, 0, 10, 25},
|
||||
{ /*Rouge*/ 0, 0, 10, 10, 0, 0, 0, 30},
|
||||
{ /*Shaman*/ 0, 5, 0, 0, 10, 0, 5, 30},
|
||||
{ /*Necromancer*/ 0, 0, 0, 10, 0, 10, 0, 30},
|
||||
{ /*Wizard*/ 0, 10, 0, 0, 0, 10, 0, 30},
|
||||
{ /*Magician*/ 0, 10, 0, 0, 0, 10, 0, 30},
|
||||
{ /*Enchanter*/ 0, 0, 0, 0, 0, 10, 10, 30},
|
||||
{ /*Beastlord*/ 0, 10, 5, 0, 10, 0, 5, 20},
|
||||
{ /*Berserker*/ 10, 5, 0, 10, 0, 0, 0, 25}
|
||||
};
|
||||
|
||||
static const bool ClassRaceLookupTable[Class::PLAYER_CLASS_COUNT][_TABLE_RACES] =
|
||||
{ /*Human Barbarian Erudite Woodelf Highelf Darkelf Halfelf Dwarf Troll Ogre Halfling Gnome Iksar Vahshir Froglok Drakkin*/
|
||||
{ /*Warrior*/ true, true, false, true, false, true, true, true, true, true, true, true, true, true, true, true},
|
||||
{ /*Cleric*/ true, false, true, false, true, true, true, true, false, false, true, true, false, false, true, true},
|
||||
{ /*Paladin*/ true, false, true, false, true, false, true, true, false, false, true, true, false, false, true, true},
|
||||
{ /*Ranger*/ true, false, false, true, false, false, true, false, false, false, true, false, false, false, false, true},
|
||||
{ /*ShadowKnight*/ true, false, true, false, false, true, false, false, true, true, false, true, true, false, true, true},
|
||||
{ /*Druid*/ true, false, false, true, false, false, true, false, false, false, true, false, false, false, false, true},
|
||||
{ /*Monk*/ true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true},
|
||||
{ /*Bard*/ true, false, false, true, false, false, true, false, false, false, false, false, false, true, false, true},
|
||||
{ /*Rogue*/ true, true, false, true, false, true, true, true, false, false, true, true, false, true, true, true},
|
||||
{ /*Shaman*/ false, true, false, false, false, false, false, false, true, true, false, false, true, true, true, false},
|
||||
{ /*Necromancer*/ true, false, true, false, false, true, false, false, false, false, false, true, true, false, true, true},
|
||||
{ /*Wizard*/ true, false, true, false, true, true, false, false, false, false, false, true, false, false, true, true},
|
||||
{ /*Magician*/ true, false, true, false, true, true, false, false, false, false, false, true, false, false, false, true},
|
||||
{ /*Enchanter*/ true, false, true, false, true, true, false, false, false, false, false, true, false, false, false, true},
|
||||
{ /*Beastlord*/ false, true, false, false, false, false, false, false, true, true, false, false, true, true, false, false},
|
||||
{ /*Berserker*/ false, true, false, false, false, false, false, true, true, true, false, false, false, true, false, false}
|
||||
};
|
||||
|
||||
if (!cc)
|
||||
return false;
|
||||
|
||||
LogInfo("Validating char creation info");
|
||||
|
||||
classtemp = cc->class_ - 1;
|
||||
racetemp = cc->race - 1;
|
||||
// these have non sequential race numbers so they need to be mapped
|
||||
if (cc->race == FROGLOK) racetemp = 14;
|
||||
if (cc->race == VAHSHIR) racetemp = 13;
|
||||
if (cc->race == IKSAR) racetemp = 12;
|
||||
if (cc->race == DRAKKIN) racetemp = 15;
|
||||
|
||||
// if out of range looking it up in the table would crash stuff
|
||||
// so we return from these
|
||||
if (classtemp >= Class::PLAYER_CLASS_COUNT) {
|
||||
LogInfo(" class is out of range");
|
||||
return false;
|
||||
}
|
||||
if (racetemp >= _TABLE_RACES) {
|
||||
LogInfo(" race is out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ClassRaceLookupTable[classtemp][racetemp]) { //Lookup table better than a bunch of ifs?
|
||||
LogInfo(" invalid race/class combination");
|
||||
// we return from this one, since if it's an invalid combination our table
|
||||
// doesn't have meaningful values for the stats
|
||||
return false;
|
||||
}
|
||||
|
||||
// add up the base values for this class/race
|
||||
// this is what they start with, and they have stat_points more
|
||||
// that can distributed
|
||||
bSTR = BaseClass[classtemp][0] + BaseRace[racetemp][0];
|
||||
bSTA = BaseClass[classtemp][1] + BaseRace[racetemp][1];
|
||||
bAGI = BaseClass[classtemp][2] + BaseRace[racetemp][2];
|
||||
bDEX = BaseClass[classtemp][3] + BaseRace[racetemp][3];
|
||||
bWIS = BaseClass[classtemp][4] + BaseRace[racetemp][4];
|
||||
bINT = BaseClass[classtemp][5] + BaseRace[racetemp][5];
|
||||
bCHA = BaseClass[classtemp][6] + BaseRace[racetemp][6];
|
||||
stat_points = BaseClass[classtemp][7];
|
||||
bTOTAL = bSTR + bSTA + bAGI + bDEX + bWIS + bINT + bCHA;
|
||||
cTOTAL = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA;
|
||||
|
||||
// the first check makes sure the total is exactly what was expected.
|
||||
// this will catch all the stat cheating, but there's still the issue
|
||||
// of reducing CHA or INT or something, to use for STR, so we check
|
||||
// that none are lower than the base or higher than base + stat_points
|
||||
// NOTE: these could just be else if, but i want to see all the stats
|
||||
// that are messed up not just the first hit
|
||||
|
||||
if (bTOTAL + stat_points != cTOTAL) {
|
||||
LogInfo(" stat points total doesn't match expected value: expecting [{}] got [{}]", bTOTAL + stat_points, cTOTAL);
|
||||
Charerrors++;
|
||||
}
|
||||
|
||||
if (cc->STR > bSTR + stat_points || cc->STR < bSTR) {
|
||||
LogInfo(" stat STR is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->STA > bSTA + stat_points || cc->STA < bSTA) {
|
||||
LogInfo(" stat STA is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->AGI > bAGI + stat_points || cc->AGI < bAGI) {
|
||||
LogInfo(" stat AGI is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->DEX > bDEX + stat_points || cc->DEX < bDEX) {
|
||||
LogInfo(" stat DEX is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->WIS > bWIS + stat_points || cc->WIS < bWIS) {
|
||||
LogInfo(" stat WIS is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->INT > bINT + stat_points || cc->INT < bINT) {
|
||||
LogInfo(" stat INT is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->CHA > bCHA + stat_points || cc->CHA < bCHA) {
|
||||
LogInfo(" stat CHA is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
|
||||
/*TODO: Check for deity/class/race.. it'd be nice, but probably of any real use to hack(faction, deity based items are all I can think of)
|
||||
I am NOT writing those tables - kathgar*/
|
||||
|
||||
LogInfo("Found [{}] errors in character creation request", Charerrors);
|
||||
|
||||
return Charerrors == 0;
|
||||
}
|
||||
|
||||
//TODO: these hard coded values should be settable somewhere somehow.
|
||||
//Also they're not 100% accurate so if I don't make them settable somehow
|
||||
//we need to go back and match them to the logic that was ripped out of zone
|
||||
void GetResistsForCharacterCreate(CharCreate_Struct* cc,
|
||||
bool sofAndLater,
|
||||
uint32 &cold_resist,
|
||||
uint32& fire_resist,
|
||||
uint32& magic_resist,
|
||||
uint32& disease_resist,
|
||||
uint32& poison_resist,
|
||||
uint32& corruption_resist)
|
||||
{
|
||||
if (!sofAndLater) {
|
||||
cold_resist = 25;
|
||||
fire_resist = 25;
|
||||
magic_resist = 25;
|
||||
disease_resist = 15;
|
||||
poison_resist = 15;
|
||||
corruption_resist = 15;
|
||||
return;
|
||||
}
|
||||
|
||||
CharCreateCombination class_combo;
|
||||
bool found = false;
|
||||
int combos = character_create_race_class_combos.size();
|
||||
for (int i = 0; i < combos; ++i) {
|
||||
if (character_create_race_class_combos[i].Class == cc->class_ &&
|
||||
character_create_race_class_combos[i].Race == cc->race &&
|
||||
character_create_race_class_combos[i].Deity == cc->deity &&
|
||||
character_create_race_class_combos[i].Zone == cc->start_zone) {
|
||||
class_combo = character_create_race_class_combos[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
cold_resist = 25;
|
||||
fire_resist = 25;
|
||||
magic_resist = 25;
|
||||
disease_resist = 15;
|
||||
poison_resist = 15;
|
||||
corruption_resist = 15;
|
||||
return;
|
||||
}
|
||||
|
||||
CharCreatePointAllocation allocation;
|
||||
found = false;
|
||||
combos = character_create_allocations.size();
|
||||
for (int i = 0; i < combos; ++i) {
|
||||
if (character_create_allocations[i].Index == class_combo.AllocationIndex) {
|
||||
allocation = character_create_allocations[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
cold_resist = 25;
|
||||
fire_resist = 25;
|
||||
magic_resist = 25;
|
||||
disease_resist = 15;
|
||||
poison_resist = 15;
|
||||
corruption_resist = 15;
|
||||
return;
|
||||
}
|
||||
|
||||
cold_resist = allocation.BaseResists[0];
|
||||
fire_resist = allocation.BaseResists[1];
|
||||
magic_resist = allocation.BaseResists[2];
|
||||
disease_resist = allocation.BaseResists[3];
|
||||
poison_resist = allocation.BaseResists[4];
|
||||
corruption_resist = allocation.BaseResists[5];
|
||||
}
|
||||
|
||||
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
{
|
||||
PlayerProfile_Struct pp;
|
||||
@@ -2088,15 +1745,6 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
pp.hunger_level = 6000;
|
||||
pp.thirst_level = 6000;
|
||||
|
||||
GetResistsForCharacterCreate(cc,
|
||||
m_ClientVersionBit & EQ::versions::maskSoFAndLater,
|
||||
pp.cold_resist,
|
||||
pp.fire_resist,
|
||||
pp.magic_resist,
|
||||
pp.disease_resist,
|
||||
pp.poison_resist,
|
||||
pp.corruption_resist);
|
||||
|
||||
/* Set default skills for everybody */
|
||||
pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue);
|
||||
pp.skills[EQ::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue);
|
||||
@@ -2217,6 +1865,273 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
|
||||
return success;
|
||||
}
|
||||
|
||||
// returns true if the request is ok, false if there's an error
|
||||
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc)
|
||||
{
|
||||
if (!cc)
|
||||
return false;
|
||||
|
||||
LogInfo("Validating char creation info");
|
||||
|
||||
RaceClassCombos class_combo;
|
||||
bool found = false;
|
||||
int combos = character_create_race_class_combos.size();
|
||||
for (int i = 0; i < combos; ++i) {
|
||||
if (character_create_race_class_combos[i].Class == cc->class_ &&
|
||||
character_create_race_class_combos[i].Race == cc->race &&
|
||||
character_create_race_class_combos[i].Deity == cc->deity &&
|
||||
character_create_race_class_combos[i].Zone == cc->start_zone) {
|
||||
class_combo = character_create_race_class_combos[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LogInfo("Could not find class/race/deity/start_zone combination");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 allocs = character_create_allocations.size();
|
||||
RaceClassAllocation allocation = {0};
|
||||
found = false;
|
||||
for (int i = 0; i < allocs; ++i) {
|
||||
if (character_create_allocations[i].Index == class_combo.AllocationIndex) {
|
||||
allocation = character_create_allocations[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LogInfo("Could not find starting stats for selected character combo, cannot verify stats");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 max_stats = allocation.DefaultPointAllocation[0] +
|
||||
allocation.DefaultPointAllocation[1] +
|
||||
allocation.DefaultPointAllocation[2] +
|
||||
allocation.DefaultPointAllocation[3] +
|
||||
allocation.DefaultPointAllocation[4] +
|
||||
allocation.DefaultPointAllocation[5] +
|
||||
allocation.DefaultPointAllocation[6];
|
||||
|
||||
if (cc->STR > allocation.BaseStats[0] + max_stats || cc->STR < allocation.BaseStats[0]) {
|
||||
LogInfo("Strength out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->DEX > allocation.BaseStats[1] + max_stats || cc->DEX < allocation.BaseStats[1]) {
|
||||
LogInfo("Dexterity out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->AGI > allocation.BaseStats[2] + max_stats || cc->AGI < allocation.BaseStats[2]) {
|
||||
LogInfo("Agility out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->STA > allocation.BaseStats[3] + max_stats || cc->STA < allocation.BaseStats[3]) {
|
||||
LogInfo("Stamina out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->INT > allocation.BaseStats[4] + max_stats || cc->INT < allocation.BaseStats[4]) {
|
||||
LogInfo("Intelligence out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->WIS > allocation.BaseStats[5] + max_stats || cc->WIS < allocation.BaseStats[5]) {
|
||||
LogInfo("Wisdom out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cc->CHA > allocation.BaseStats[6] + max_stats || cc->CHA < allocation.BaseStats[6]) {
|
||||
LogInfo("Charisma out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 current_stats = 0;
|
||||
current_stats += cc->STR - allocation.BaseStats[0];
|
||||
current_stats += cc->DEX - allocation.BaseStats[1];
|
||||
current_stats += cc->AGI - allocation.BaseStats[2];
|
||||
current_stats += cc->STA - allocation.BaseStats[3];
|
||||
current_stats += cc->INT - allocation.BaseStats[4];
|
||||
current_stats += cc->WIS - allocation.BaseStats[5];
|
||||
current_stats += cc->CHA - allocation.BaseStats[6];
|
||||
if (current_stats > max_stats) {
|
||||
LogInfo("Current Stats > Maximum Stats");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
|
||||
{
|
||||
uint32 bSTR, bSTA, bAGI, bDEX, bWIS, bINT, bCHA, bTOTAL, cTOTAL, stat_points; //these are all uint32 in CharCreate_Struct, so we'll make them uint32 here to make the compiler shut up
|
||||
int classtemp, racetemp;
|
||||
int Charerrors = 0;
|
||||
|
||||
|
||||
// if this is increased you'll have to add a column to the classrace
|
||||
// table below
|
||||
#define _TABLE_RACES 16
|
||||
|
||||
static const int BaseRace[_TABLE_RACES][7] =
|
||||
{ /* STR STA AGI DEX WIS INT CHR */
|
||||
{ /*Human*/ 75, 75, 75, 75, 75, 75, 75},
|
||||
{ /*Barbarian*/ 103, 95, 82, 70, 70, 60, 55},
|
||||
{ /*Erudite*/ 60, 70, 70, 70, 83, 107, 70},
|
||||
{ /*Wood Elf*/ 65, 65, 95, 80, 80, 75, 75},
|
||||
{ /*High Elf*/ 55, 65, 85, 70, 95, 92, 80},
|
||||
{ /*Dark Elf*/ 60, 65, 90, 75, 83, 99, 60},
|
||||
{ /*Half Elf*/ 70, 70, 90, 85, 60, 75, 75},
|
||||
{ /*Dwarf*/ 90, 90, 70, 90, 83, 60, 45},
|
||||
{ /*Troll*/ 108, 109, 83, 75, 60, 52, 40},
|
||||
{ /*Ogre*/ 130, 122, 70, 70, 67, 60, 37},
|
||||
{ /*Halfling*/ 70, 75, 95, 90, 80, 67, 50},
|
||||
{ /*Gnome*/ 60, 70, 85, 85, 67, 98, 60},
|
||||
{ /*Iksar*/ 70, 70, 90, 85, 80, 75, 55},
|
||||
{ /*Vah Shir*/ 90, 75, 90, 70, 70, 65, 65},
|
||||
{ /*Froglok*/ 70, 80, 100, 100, 75, 75, 50},
|
||||
{ /*Drakkin*/ 70, 80, 85, 75, 80, 85, 75}
|
||||
};
|
||||
|
||||
static const int BaseClass[Class::PLAYER_CLASS_COUNT][8] =
|
||||
{ /* STR STA AGI DEX WIS INT CHR ADD*/
|
||||
{ /*Warrior*/ 10, 10, 5, 0, 0, 0, 0, 25},
|
||||
{ /*Cleric*/ 5, 5, 0, 0, 10, 0, 0, 30},
|
||||
{ /*Paladin*/ 10, 5, 0, 0, 5, 0, 10, 20},
|
||||
{ /*Ranger*/ 5, 10, 10, 0, 5, 0, 0, 20},
|
||||
{ /*ShadowKnight*/ 10, 5, 0, 0, 0, 10, 5, 20},
|
||||
{ /*Druid*/ 0, 10, 0, 0, 10, 0, 0, 30},
|
||||
{ /*Monk*/ 5, 5, 10, 10, 0, 0, 0, 20},
|
||||
{ /*Bard*/ 5, 0, 0, 10, 0, 0, 10, 25},
|
||||
{ /*Rouge*/ 0, 0, 10, 10, 0, 0, 0, 30},
|
||||
{ /*Shaman*/ 0, 5, 0, 0, 10, 0, 5, 30},
|
||||
{ /*Necromancer*/ 0, 0, 0, 10, 0, 10, 0, 30},
|
||||
{ /*Wizard*/ 0, 10, 0, 0, 0, 10, 0, 30},
|
||||
{ /*Magician*/ 0, 10, 0, 0, 0, 10, 0, 30},
|
||||
{ /*Enchanter*/ 0, 0, 0, 0, 0, 10, 10, 30},
|
||||
{ /*Beastlord*/ 0, 10, 5, 0, 10, 0, 5, 20},
|
||||
{ /*Berserker*/ 10, 5, 0, 10, 0, 0, 0, 25}
|
||||
};
|
||||
|
||||
static const bool ClassRaceLookupTable[Class::PLAYER_CLASS_COUNT][_TABLE_RACES]=
|
||||
{ /*Human Barbarian Erudite Woodelf Highelf Darkelf Halfelf Dwarf Troll Ogre Halfling Gnome Iksar Vahshir Froglok Drakkin*/
|
||||
{ /*Warrior*/ true, true, false, true, false, true, true, true, true, true, true, true, true, true, true, true},
|
||||
{ /*Cleric*/ true, false, true, false, true, true, true, true, false, false, true, true, false, false, true, true},
|
||||
{ /*Paladin*/ true, false, true, false, true, false, true, true, false, false, true, true, false, false, true, true},
|
||||
{ /*Ranger*/ true, false, false, true, false, false, true, false, false, false, true, false, false, false, false, true},
|
||||
{ /*ShadowKnight*/ true, false, true, false, false, true, false, false, true, true, false, true, true, false, true, true},
|
||||
{ /*Druid*/ true, false, false, true, false, false, true, false, false, false, true, false, false, false, false, true},
|
||||
{ /*Monk*/ true, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true},
|
||||
{ /*Bard*/ true, false, false, true, false, false, true, false, false, false, false, false, false, true, false, true},
|
||||
{ /*Rogue*/ true, true, false, true, false, true, true, true, false, false, true, true, false, true, true, true},
|
||||
{ /*Shaman*/ false, true, false, false, false, false, false, false, true, true, false, false, true, true, true, false},
|
||||
{ /*Necromancer*/ true, false, true, false, false, true, false, false, false, false, false, true, true, false, true, true},
|
||||
{ /*Wizard*/ true, false, true, false, true, true, false, false, false, false, false, true, false, false, true, true},
|
||||
{ /*Magician*/ true, false, true, false, true, true, false, false, false, false, false, true, false, false, false, true},
|
||||
{ /*Enchanter*/ true, false, true, false, true, true, false, false, false, false, false, true, false, false, false, true},
|
||||
{ /*Beastlord*/ false, true, false, false, false, false, false, false, true, true, false, false, true, true, false, false},
|
||||
{ /*Berserker*/ false, true, false, false, false, false, false, true, true, true, false, false, false, true, false, false}
|
||||
};
|
||||
|
||||
if (!cc)
|
||||
return false;
|
||||
|
||||
LogInfo("Validating char creation info");
|
||||
|
||||
classtemp = cc->class_ - 1;
|
||||
racetemp = cc->race - 1;
|
||||
// these have non sequential race numbers so they need to be mapped
|
||||
if (cc->race == FROGLOK) racetemp = 14;
|
||||
if (cc->race == VAHSHIR) racetemp = 13;
|
||||
if (cc->race == IKSAR) racetemp = 12;
|
||||
if (cc->race == DRAKKIN) racetemp = 15;
|
||||
|
||||
// if out of range looking it up in the table would crash stuff
|
||||
// so we return from these
|
||||
if (classtemp >= Class::PLAYER_CLASS_COUNT) {
|
||||
LogInfo(" class is out of range");
|
||||
return false;
|
||||
}
|
||||
if (racetemp >= _TABLE_RACES) {
|
||||
LogInfo(" race is out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ClassRaceLookupTable[classtemp][racetemp]) { //Lookup table better than a bunch of ifs?
|
||||
LogInfo(" invalid race/class combination");
|
||||
// we return from this one, since if it's an invalid combination our table
|
||||
// doesn't have meaningful values for the stats
|
||||
return false;
|
||||
}
|
||||
|
||||
// add up the base values for this class/race
|
||||
// this is what they start with, and they have stat_points more
|
||||
// that can distributed
|
||||
bSTR = BaseClass[classtemp][0] + BaseRace[racetemp][0];
|
||||
bSTA = BaseClass[classtemp][1] + BaseRace[racetemp][1];
|
||||
bAGI = BaseClass[classtemp][2] + BaseRace[racetemp][2];
|
||||
bDEX = BaseClass[classtemp][3] + BaseRace[racetemp][3];
|
||||
bWIS = BaseClass[classtemp][4] + BaseRace[racetemp][4];
|
||||
bINT = BaseClass[classtemp][5] + BaseRace[racetemp][5];
|
||||
bCHA = BaseClass[classtemp][6] + BaseRace[racetemp][6];
|
||||
stat_points = BaseClass[classtemp][7];
|
||||
bTOTAL = bSTR + bSTA + bAGI + bDEX + bWIS + bINT + bCHA;
|
||||
cTOTAL = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA;
|
||||
|
||||
// the first check makes sure the total is exactly what was expected.
|
||||
// this will catch all the stat cheating, but there's still the issue
|
||||
// of reducing CHA or INT or something, to use for STR, so we check
|
||||
// that none are lower than the base or higher than base + stat_points
|
||||
// NOTE: these could just be else if, but i want to see all the stats
|
||||
// that are messed up not just the first hit
|
||||
|
||||
if (bTOTAL + stat_points != cTOTAL) {
|
||||
LogInfo(" stat points total doesn't match expected value: expecting [{}] got [{}]", bTOTAL + stat_points, cTOTAL);
|
||||
Charerrors++;
|
||||
}
|
||||
|
||||
if (cc->STR > bSTR + stat_points || cc->STR < bSTR) {
|
||||
LogInfo(" stat STR is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->STA > bSTA + stat_points || cc->STA < bSTA) {
|
||||
LogInfo(" stat STA is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->AGI > bAGI + stat_points || cc->AGI < bAGI) {
|
||||
LogInfo(" stat AGI is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->DEX > bDEX + stat_points || cc->DEX < bDEX) {
|
||||
LogInfo(" stat DEX is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->WIS > bWIS + stat_points || cc->WIS < bWIS) {
|
||||
LogInfo(" stat WIS is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->INT > bINT + stat_points || cc->INT < bINT) {
|
||||
LogInfo(" stat INT is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
if (cc->CHA > bCHA + stat_points || cc->CHA < bCHA) {
|
||||
LogInfo(" stat CHA is out of range");
|
||||
Charerrors++;
|
||||
}
|
||||
|
||||
/*TODO: Check for deity/class/race.. it'd be nice, but probably of any real use to hack(faction, deity based items are all I can think of)
|
||||
I am NOT writing those tables - kathgar*/
|
||||
|
||||
LogInfo("Found [{}] errors in character creation request", Charerrors);
|
||||
|
||||
return Charerrors == 0;
|
||||
}
|
||||
|
||||
void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
|
||||
{
|
||||
for (uint32 i = 0; i <= EQ::skills::HIGHEST_SKILL; ++i) {
|
||||
|
||||
@@ -122,4 +122,7 @@ private:
|
||||
void RecordPossibleHack(const std::string& message);
|
||||
};
|
||||
|
||||
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc);
|
||||
bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
struct CharCreatePointAllocation
|
||||
{
|
||||
unsigned int Index;
|
||||
unsigned int BaseStats[7];
|
||||
unsigned int DefaultPointAllocation[7];
|
||||
unsigned int BaseResists[7];
|
||||
};
|
||||
|
||||
struct CharCreateCombination {
|
||||
unsigned int ExpansionRequired;
|
||||
unsigned int Race;
|
||||
unsigned int Class;
|
||||
unsigned int Deity;
|
||||
unsigned int AllocationIndex;
|
||||
unsigned int Zone;
|
||||
};
|
||||
@@ -294,6 +294,13 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
|
||||
database.ClearBuyerDetails();
|
||||
LogInfo("Clearing buyer table details");
|
||||
|
||||
if (RuleB(Bots, Enabled)) {
|
||||
LogInfo("Clearing [bot_pet_buffs] table of stale entries");
|
||||
database.QueryDatabase(
|
||||
"DELETE FROM bot_pet_buffs WHERE NOT EXISTS (SELECT * FROM bot_pets WHERE bot_pets.pets_index = bot_pet_buffs.pets_index)"
|
||||
);
|
||||
}
|
||||
|
||||
if (!content_db.LoadItems(hotfix_name)) {
|
||||
LogError("Error: Could not load item data. But ignoring");
|
||||
}
|
||||
|
||||
+4
-11
@@ -25,15 +25,14 @@
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include "sof_char_create_data.h"
|
||||
#include "race_combos.h"
|
||||
#include "../common/repositories/character_instance_safereturns_repository.h"
|
||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||
#include "../common/zone_store.h"
|
||||
|
||||
WorldDatabase database;
|
||||
WorldDatabase content_db;
|
||||
extern std::vector<CharCreatePointAllocation> character_create_allocations;
|
||||
extern std::vector<CharCreateCombination> character_create_race_class_combos;
|
||||
extern std::vector<RaceClassAllocation> character_create_allocations;
|
||||
extern std::vector<RaceClassCombos> character_create_race_class_combos;
|
||||
|
||||
|
||||
/**
|
||||
@@ -808,7 +807,7 @@ bool WorldDatabase::LoadCharacterCreateAllocations()
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharCreatePointAllocation allocate;
|
||||
RaceClassAllocation allocate;
|
||||
allocate.Index = Strings::ToInt(row[0]);
|
||||
allocate.BaseStats[0] = Strings::ToInt(row[1]);
|
||||
allocate.BaseStats[3] = Strings::ToInt(row[2]);
|
||||
@@ -824,12 +823,6 @@ bool WorldDatabase::LoadCharacterCreateAllocations()
|
||||
allocate.DefaultPointAllocation[4] = Strings::ToInt(row[12]);
|
||||
allocate.DefaultPointAllocation[5] = Strings::ToInt(row[13]);
|
||||
allocate.DefaultPointAllocation[6] = Strings::ToInt(row[14]);
|
||||
allocate.BaseResists[0] = Strings::ToInt(row[15]);
|
||||
allocate.BaseResists[1] = Strings::ToInt(row[16]);
|
||||
allocate.BaseResists[2] = Strings::ToInt(row[17]);
|
||||
allocate.BaseResists[3] = Strings::ToInt(row[18]);
|
||||
allocate.BaseResists[4] = Strings::ToInt(row[19]);
|
||||
allocate.BaseResists[5] = Strings::ToInt(row[20]);
|
||||
|
||||
character_create_allocations.push_back(allocate);
|
||||
}
|
||||
@@ -847,7 +840,7 @@ bool WorldDatabase::LoadCharacterCreateCombos()
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
CharCreateCombination combo;
|
||||
RaceClassCombos combo;
|
||||
combo.AllocationIndex = Strings::ToInt(row[0]);
|
||||
combo.Race = Strings::ToInt(row[1]);
|
||||
combo.Class = Strings::ToInt(row[2]);
|
||||
|
||||
@@ -828,7 +828,7 @@ bool BotDatabase::LoadTimers(Bot* b)
|
||||
BotTimer_Struct t{ };
|
||||
|
||||
for (const auto& e : l) {
|
||||
if (t.timer_value < (Timer::GetCurrentTime() + t.recast_time)) {
|
||||
if (e.timer_value < (Timer::GetCurrentTime() + e.recast_time)) {
|
||||
t.timer_id = e.timer_id;
|
||||
t.timer_value = e.timer_value;
|
||||
t.recast_time = e.recast_time;
|
||||
@@ -1451,7 +1451,7 @@ bool BotDatabase::DeletePetBuffs(const uint32 bot_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
BotPetBuffsRepository::DeleteOne(database, saved_pet_index);
|
||||
BotPetBuffsRepository::DeleteWhere(database, fmt::format("pets_index = {}", saved_pet_index));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+251
-5
@@ -8677,14 +8677,16 @@ int Client::GetAccountAge() {
|
||||
|
||||
void Client::CheckRegionTypeChanges()
|
||||
{
|
||||
if (!zone->HasWaterMap())
|
||||
if (!zone->HasWaterMap()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_region = zone->watermap->ReturnRegionType(glm::vec3(m_Position));
|
||||
|
||||
// still same region, do nothing
|
||||
if (last_region_type == new_region)
|
||||
if (last_region_type == new_region) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we got out of water clear any water aggro for water only npcs
|
||||
if (last_region_type == RegionTypeWater) {
|
||||
@@ -8695,13 +8697,15 @@ void Client::CheckRegionTypeChanges()
|
||||
last_region_type = new_region;
|
||||
|
||||
// PVP is the only state we need to keep track of, so we can just return now for PVP servers
|
||||
if (RuleI(World, PVPSettings) > 0)
|
||||
if (RuleI(World, PVPSettings) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (last_region_type == RegionTypePVP)
|
||||
if (last_region_type == RegionTypePVP && RuleB(World, EnablePVPRegions)) {
|
||||
temp_pvp = true;
|
||||
else if (temp_pvp)
|
||||
} else if (temp_pvp) {
|
||||
temp_pvp = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::ProcessAggroMeter()
|
||||
@@ -12316,6 +12320,248 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2)
|
||||
RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e);
|
||||
}
|
||||
|
||||
void Client::NPCHandinEventLog(Trade* t, NPC* n)
|
||||
{
|
||||
Client* c = t->GetOwner()->CastToClient();
|
||||
|
||||
std::vector<PlayerEvent::HandinEntry> hi = {};
|
||||
std::vector<PlayerEvent::HandinEntry> ri = {};
|
||||
PlayerEvent::HandinMoney hm{};
|
||||
PlayerEvent::HandinMoney rm{};
|
||||
|
||||
if (
|
||||
c->EntityVariableExists("HANDIN_ITEMS") &&
|
||||
c->EntityVariableExists("HANDIN_MONEY") &&
|
||||
c->EntityVariableExists("RETURN_ITEMS") &&
|
||||
c->EntityVariableExists("RETURN_MONEY")
|
||||
) {
|
||||
const std::string& handin_items = c->GetEntityVariable("HANDIN_ITEMS");
|
||||
const std::string& return_items = c->GetEntityVariable("RETURN_ITEMS");
|
||||
const std::string& handin_money = c->GetEntityVariable("HANDIN_MONEY");
|
||||
const std::string& return_money = c->GetEntityVariable("RETURN_MONEY");
|
||||
|
||||
// Handin Items
|
||||
if (!handin_items.empty()) {
|
||||
if (Strings::Contains(handin_items, ",")) {
|
||||
const auto handin_data = Strings::Split(handin_items, ",");
|
||||
for (const auto& h : handin_data) {
|
||||
const auto item_data = Strings::Split(h, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const uint32 item_id = Strings::ToUnsignedInt(item_data[0]);
|
||||
if (item_id != 0) {
|
||||
const auto* item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
hi.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Strings::Contains(handin_items, "|")) {
|
||||
const auto item_data = Strings::Split(handin_items, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const uint32 item_id = Strings::ToUnsignedInt(item_data[0]);
|
||||
const auto* item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
hi.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handin Money
|
||||
if (!handin_money.empty()) {
|
||||
const auto hms = Strings::Split(handin_money, "|");
|
||||
|
||||
hm.copper = Strings::ToUnsignedInt(hms[0]);
|
||||
hm.silver = Strings::ToUnsignedInt(hms[1]);
|
||||
hm.gold = Strings::ToUnsignedInt(hms[2]);
|
||||
hm.platinum = Strings::ToUnsignedInt(hms[3]);
|
||||
}
|
||||
|
||||
// Return Items
|
||||
if (!return_items.empty()) {
|
||||
if (Strings::Contains(return_items, ",")) {
|
||||
const auto return_data = Strings::Split(return_items, ",");
|
||||
for (const auto& r : return_data) {
|
||||
const auto item_data = Strings::Split(r, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const uint32 item_id = Strings::ToUnsignedInt(item_data[0]);
|
||||
const auto* item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
ri.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Strings::Contains(return_items, "|")) {
|
||||
const auto item_data = Strings::Split(return_items, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const uint32 item_id = Strings::ToUnsignedInt(item_data[0]);
|
||||
const auto* item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
ri.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return Money
|
||||
if (!return_money.empty()) {
|
||||
const auto rms = Strings::Split(return_money, "|");
|
||||
rm.copper = static_cast<uint32>(Strings::ToUnsignedInt(rms[0]));
|
||||
rm.silver = static_cast<uint32>(Strings::ToUnsignedInt(rms[1]));
|
||||
rm.gold = static_cast<uint32>(Strings::ToUnsignedInt(rms[2]));
|
||||
rm.platinum = static_cast<uint32>(Strings::ToUnsignedInt(rms[3]));
|
||||
}
|
||||
|
||||
c->DeleteEntityVariable("HANDIN_ITEMS");
|
||||
c->DeleteEntityVariable("HANDIN_MONEY");
|
||||
c->DeleteEntityVariable("RETURN_ITEMS");
|
||||
c->DeleteEntityVariable("RETURN_MONEY");
|
||||
|
||||
const bool handed_in_money = hm.platinum > 0 || hm.gold > 0 || hm.silver > 0 || hm.copper > 0;
|
||||
|
||||
const bool event_has_data_to_record = (
|
||||
!hi.empty() || handed_in_money
|
||||
);
|
||||
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::NPC_HANDIN) && event_has_data_to_record) {
|
||||
auto e = PlayerEvent::HandinEvent{
|
||||
.npc_id = n->GetNPCTypeID(),
|
||||
.npc_name = n->GetCleanName(),
|
||||
.handin_items = hi,
|
||||
.handin_money = hm,
|
||||
.return_items = ri,
|
||||
.return_money = rm,
|
||||
.is_quest_handin = true
|
||||
};
|
||||
|
||||
RecordPlayerEventLogWithClient(c, PlayerEvent::NPC_HANDIN, e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 item_count = 0;
|
||||
|
||||
hm.platinum = t->pp;
|
||||
hm.gold = t->gp;
|
||||
hm.silver = t->sp;
|
||||
hm.copper = t->cp;
|
||||
|
||||
for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_NPC_END; i++) {
|
||||
if (c->GetInv().GetItem(i)) {
|
||||
item_count++;
|
||||
}
|
||||
}
|
||||
|
||||
hi.reserve(item_count);
|
||||
|
||||
if (item_count > 0) {
|
||||
for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_NPC_END; i++) {
|
||||
const EQ::ItemInstance* inst = c->GetInv().GetItem(i);
|
||||
if (inst) {
|
||||
hi.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = inst->GetItem()->ID,
|
||||
.item_name = inst->GetItem()->Name,
|
||||
.charges = static_cast<uint16>(inst->GetCharges()),
|
||||
.attuned = inst->IsAttuned()
|
||||
}
|
||||
);
|
||||
|
||||
if (inst->IsClassBag()) {
|
||||
for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) {
|
||||
inst = c->GetInv().GetItem(i, j);
|
||||
if (inst) {
|
||||
hi.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = inst->GetItem()->ID,
|
||||
.item_name = inst->GetItem()->Name,
|
||||
.charges = static_cast<uint16>(inst->GetCharges()),
|
||||
.attuned = inst->IsAttuned()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool handed_in_money = hm.platinum > 0 || hm.gold > 0 || hm.silver > 0 || hm.copper > 0;
|
||||
|
||||
ri = hi;
|
||||
rm = hm;
|
||||
|
||||
const bool event_has_data_to_record = !hi.empty() || handed_in_money;
|
||||
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::NPC_HANDIN) && event_has_data_to_record) {
|
||||
auto e = PlayerEvent::HandinEvent{
|
||||
.npc_id = n->GetNPCTypeID(),
|
||||
.npc_name = n->GetCleanName(),
|
||||
.handin_items = hi,
|
||||
.handin_money = hm,
|
||||
.return_items = ri,
|
||||
.return_money = rm,
|
||||
.is_quest_handin = false
|
||||
};
|
||||
|
||||
RecordPlayerEventLogWithClient(c, PlayerEvent::NPC_HANDIN, e);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::ShowSpells(Client* c, ShowSpellType show_spell_type)
|
||||
{
|
||||
std::string spell_string;
|
||||
|
||||
+2
-1
@@ -597,7 +597,7 @@ public:
|
||||
inline uint8 GetBaseINT() const { return m_pp.INT; }
|
||||
inline uint8 GetBaseAGI() const { return m_pp.AGI; }
|
||||
inline uint8 GetBaseWIS() const { return m_pp.WIS; }
|
||||
inline uint8 GetBaseCorrup() const { return m_pp.corruption_resist; }
|
||||
inline uint8 GetBaseCorrup() const { return 15; } // Same for all
|
||||
inline uint8 GetBasePhR() const { return 0; } // Guessing at 0 as base
|
||||
|
||||
inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
|
||||
@@ -2227,6 +2227,7 @@ private:
|
||||
bool CanTradeFVNoDropItem();
|
||||
void SendMobPositions();
|
||||
void PlayerTradeEventLog(Trade *t, Trade *t2);
|
||||
void NPCHandinEventLog(Trade* t, NPC* n);
|
||||
|
||||
// full and partial mail key cache
|
||||
std::string m_mail_key_full;
|
||||
|
||||
+295
-5
@@ -1009,7 +1009,65 @@ int Client::CalcHaste()
|
||||
//in Mob::ResistSpell
|
||||
int32 Client::CalcMR()
|
||||
{
|
||||
MR = m_pp.magic_resist;
|
||||
//racial bases
|
||||
switch (GetBaseRace()) {
|
||||
case HUMAN:
|
||||
MR = 25;
|
||||
break;
|
||||
case BARBARIAN:
|
||||
MR = 25;
|
||||
break;
|
||||
case ERUDITE:
|
||||
MR = 30;
|
||||
break;
|
||||
case WOOD_ELF:
|
||||
MR = 25;
|
||||
break;
|
||||
case HIGH_ELF:
|
||||
MR = 25;
|
||||
break;
|
||||
case DARK_ELF:
|
||||
MR = 25;
|
||||
break;
|
||||
case HALF_ELF:
|
||||
MR = 25;
|
||||
break;
|
||||
case DWARF:
|
||||
MR = 30;
|
||||
break;
|
||||
case TROLL:
|
||||
MR = 25;
|
||||
break;
|
||||
case OGRE:
|
||||
MR = 25;
|
||||
break;
|
||||
case HALFLING:
|
||||
MR = 25;
|
||||
break;
|
||||
case GNOME:
|
||||
MR = 25;
|
||||
break;
|
||||
case IKSAR:
|
||||
MR = 25;
|
||||
break;
|
||||
case VAHSHIR:
|
||||
MR = 25;
|
||||
break;
|
||||
case FROGLOK:
|
||||
MR = 30;
|
||||
break;
|
||||
case DRAKKIN:
|
||||
{
|
||||
MR = 25;
|
||||
if (GetDrakkinHeritage() == 2)
|
||||
MR += 10;
|
||||
else if (GetDrakkinHeritage() == 5)
|
||||
MR += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MR = 20;
|
||||
}
|
||||
MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR;
|
||||
if (GetClass() == Class::Warrior || GetClass() == Class::Berserker) {
|
||||
MR += GetLevel() / 2;
|
||||
@@ -1025,7 +1083,65 @@ int32 Client::CalcMR()
|
||||
|
||||
int32 Client::CalcFR()
|
||||
{
|
||||
FR = m_pp.fire_resist;
|
||||
//racial bases
|
||||
switch (GetBaseRace()) {
|
||||
case HUMAN:
|
||||
FR = 25;
|
||||
break;
|
||||
case BARBARIAN:
|
||||
FR = 25;
|
||||
break;
|
||||
case ERUDITE:
|
||||
FR = 25;
|
||||
break;
|
||||
case WOOD_ELF:
|
||||
FR = 25;
|
||||
break;
|
||||
case HIGH_ELF:
|
||||
FR = 25;
|
||||
break;
|
||||
case DARK_ELF:
|
||||
FR = 25;
|
||||
break;
|
||||
case HALF_ELF:
|
||||
FR = 25;
|
||||
break;
|
||||
case DWARF:
|
||||
FR = 25;
|
||||
break;
|
||||
case TROLL:
|
||||
FR = 5;
|
||||
break;
|
||||
case OGRE:
|
||||
FR = 25;
|
||||
break;
|
||||
case HALFLING:
|
||||
FR = 25;
|
||||
break;
|
||||
case GNOME:
|
||||
FR = 25;
|
||||
break;
|
||||
case IKSAR:
|
||||
FR = 30;
|
||||
break;
|
||||
case VAHSHIR:
|
||||
FR = 25;
|
||||
break;
|
||||
case FROGLOK:
|
||||
FR = 25;
|
||||
break;
|
||||
case DRAKKIN:
|
||||
{
|
||||
FR = 25;
|
||||
if (GetDrakkinHeritage() == 0)
|
||||
FR += 10;
|
||||
else if (GetDrakkinHeritage() == 5)
|
||||
FR += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FR = 20;
|
||||
}
|
||||
int c = GetClass();
|
||||
if (c == Class::Ranger) {
|
||||
FR += 4;
|
||||
@@ -1053,7 +1169,65 @@ int32 Client::CalcFR()
|
||||
|
||||
int32 Client::CalcDR()
|
||||
{
|
||||
DR = m_pp.disease_resist;
|
||||
//racial bases
|
||||
switch (GetBaseRace()) {
|
||||
case HUMAN:
|
||||
DR = 15;
|
||||
break;
|
||||
case BARBARIAN:
|
||||
DR = 15;
|
||||
break;
|
||||
case ERUDITE:
|
||||
DR = 10;
|
||||
break;
|
||||
case WOOD_ELF:
|
||||
DR = 15;
|
||||
break;
|
||||
case HIGH_ELF:
|
||||
DR = 15;
|
||||
break;
|
||||
case DARK_ELF:
|
||||
DR = 15;
|
||||
break;
|
||||
case HALF_ELF:
|
||||
DR = 15;
|
||||
break;
|
||||
case DWARF:
|
||||
DR = 15;
|
||||
break;
|
||||
case TROLL:
|
||||
DR = 15;
|
||||
break;
|
||||
case OGRE:
|
||||
DR = 15;
|
||||
break;
|
||||
case HALFLING:
|
||||
DR = 20;
|
||||
break;
|
||||
case GNOME:
|
||||
DR = 15;
|
||||
break;
|
||||
case IKSAR:
|
||||
DR = 15;
|
||||
break;
|
||||
case VAHSHIR:
|
||||
DR = 15;
|
||||
break;
|
||||
case FROGLOK:
|
||||
DR = 15;
|
||||
break;
|
||||
case DRAKKIN:
|
||||
{
|
||||
DR = 15;
|
||||
if (GetDrakkinHeritage() == 1)
|
||||
DR += 10;
|
||||
else if (GetDrakkinHeritage() == 5)
|
||||
DR += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DR = 15;
|
||||
}
|
||||
int c = GetClass();
|
||||
// the monk one is part of base resist
|
||||
if (c == Class::Monk) {
|
||||
@@ -1087,7 +1261,65 @@ int32 Client::CalcDR()
|
||||
|
||||
int32 Client::CalcPR()
|
||||
{
|
||||
PR = m_pp.poison_resist;
|
||||
//racial bases
|
||||
switch (GetBaseRace()) {
|
||||
case HUMAN:
|
||||
PR = 15;
|
||||
break;
|
||||
case BARBARIAN:
|
||||
PR = 15;
|
||||
break;
|
||||
case ERUDITE:
|
||||
PR = 15;
|
||||
break;
|
||||
case WOOD_ELF:
|
||||
PR = 15;
|
||||
break;
|
||||
case HIGH_ELF:
|
||||
PR = 15;
|
||||
break;
|
||||
case DARK_ELF:
|
||||
PR = 15;
|
||||
break;
|
||||
case HALF_ELF:
|
||||
PR = 15;
|
||||
break;
|
||||
case DWARF:
|
||||
PR = 20;
|
||||
break;
|
||||
case TROLL:
|
||||
PR = 15;
|
||||
break;
|
||||
case OGRE:
|
||||
PR = 15;
|
||||
break;
|
||||
case HALFLING:
|
||||
PR = 20;
|
||||
break;
|
||||
case GNOME:
|
||||
PR = 15;
|
||||
break;
|
||||
case IKSAR:
|
||||
PR = 15;
|
||||
break;
|
||||
case VAHSHIR:
|
||||
PR = 15;
|
||||
break;
|
||||
case FROGLOK:
|
||||
PR = 30;
|
||||
break;
|
||||
case DRAKKIN:
|
||||
{
|
||||
PR = 15;
|
||||
if (GetDrakkinHeritage() == 3)
|
||||
PR += 10;
|
||||
else if (GetDrakkinHeritage() == 5)
|
||||
PR += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
PR = 15;
|
||||
}
|
||||
int c = GetClass();
|
||||
// this monk bonus is part of the base
|
||||
if (c == Class::Monk) {
|
||||
@@ -1121,7 +1353,65 @@ int32 Client::CalcPR()
|
||||
|
||||
int32 Client::CalcCR()
|
||||
{
|
||||
CR = m_pp.cold_resist;
|
||||
//racial bases
|
||||
switch (GetBaseRace()) {
|
||||
case HUMAN:
|
||||
CR = 25;
|
||||
break;
|
||||
case BARBARIAN:
|
||||
CR = 35;
|
||||
break;
|
||||
case ERUDITE:
|
||||
CR = 25;
|
||||
break;
|
||||
case WOOD_ELF:
|
||||
CR = 25;
|
||||
break;
|
||||
case HIGH_ELF:
|
||||
CR = 25;
|
||||
break;
|
||||
case DARK_ELF:
|
||||
CR = 25;
|
||||
break;
|
||||
case HALF_ELF:
|
||||
CR = 25;
|
||||
break;
|
||||
case DWARF:
|
||||
CR = 25;
|
||||
break;
|
||||
case TROLL:
|
||||
CR = 25;
|
||||
break;
|
||||
case OGRE:
|
||||
CR = 25;
|
||||
break;
|
||||
case HALFLING:
|
||||
CR = 25;
|
||||
break;
|
||||
case GNOME:
|
||||
CR = 25;
|
||||
break;
|
||||
case IKSAR:
|
||||
CR = 15;
|
||||
break;
|
||||
case VAHSHIR:
|
||||
CR = 25;
|
||||
break;
|
||||
case FROGLOK:
|
||||
CR = 25;
|
||||
break;
|
||||
case DRAKKIN:
|
||||
{
|
||||
CR = 25;
|
||||
if (GetDrakkinHeritage() == 4)
|
||||
CR += 10;
|
||||
else if (GetDrakkinHeritage() == 5)
|
||||
CR += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CR = 25;
|
||||
}
|
||||
int c = GetClass();
|
||||
if (c == Class::Ranger || c == Class::Beastlord) {
|
||||
CR += 4;
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ extern FastMath g_Math;
|
||||
void CatchSignal(int sig_num);
|
||||
|
||||
|
||||
int command_count; // how many commands we have
|
||||
int command_count; // how many commands we have
|
||||
|
||||
// this is the pointer to the dispatch function, updated once
|
||||
// init has been performed to point at the real function
|
||||
@@ -96,7 +96,7 @@ int command_init(void)
|
||||
command_add("augmentitem", "Force augments an item. Must have the augment item window open.", AccountStatus::GMImpossible, command_augmentitem) ||
|
||||
command_add("ban", "[Character Name] [Reason] - Ban by character name", AccountStatus::GMLeadAdmin, command_ban) ||
|
||||
command_add("bugs", "[Close|Delete|Review|Search|View] - Handles player bug reports", AccountStatus::QuestTroupe, command_bugs) ||
|
||||
command_add("bot", "Type \"#bot help\" or \"^help\" to the see the list of available commands for bots.", AccountStatus::Player, command_bot) ||
|
||||
(RuleB(Bots, Enabled) && command_add("bot", "Type \"#bot help\" or \"^help\" to the see the list of available commands for bots.", AccountStatus::Player, command_bot)) ||
|
||||
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("chat", "[Channel ID] [Message] - Send a channel message to all zones", AccountStatus::GMMgmt, command_chat) ||
|
||||
|
||||
+14
-6
@@ -31,12 +31,14 @@ Map::~Map() {
|
||||
}
|
||||
|
||||
float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result) const {
|
||||
if (!imp)
|
||||
if (!imp) {
|
||||
return BEST_Z_INVALID;
|
||||
}
|
||||
|
||||
glm::vec3 tmp;
|
||||
if(!result)
|
||||
if (!result) {
|
||||
result = &tmp;
|
||||
}
|
||||
|
||||
start.z += RuleI(Map, FindBestZHeightAdjust);
|
||||
glm::vec3 from(start.x, start.y, start.z);
|
||||
@@ -45,16 +47,22 @@ float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result) const {
|
||||
bool hit = false;
|
||||
|
||||
hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance);
|
||||
if(hit) {
|
||||
if (hit && zone->newzone_data.underworld != 0.0f && result->z < zone->newzone_data.underworld) {
|
||||
hit = false;
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
return result->z;
|
||||
}
|
||||
|
||||
// Find nearest Z above us
|
||||
|
||||
to.z = -BEST_Z_INVALID;
|
||||
hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance);
|
||||
if (hit)
|
||||
{
|
||||
if (zone->newzone_data.max_z != 0.0f && result->z > zone->newzone_data.max_z) {
|
||||
hit = false;
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
return result->z;
|
||||
}
|
||||
|
||||
|
||||
+1
-173
@@ -4611,179 +4611,7 @@ int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id, uin
|
||||
}
|
||||
|
||||
void QuestManager::SendPlayerHandinEvent() {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if (!owner || !owner->IsNPC() || !initiator) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!initiator->EntityVariableExists("HANDIN_ITEMS") &&
|
||||
!initiator->EntityVariableExists("HANDIN_MONEY") &&
|
||||
!initiator->EntityVariableExists("RETURN_ITEMS") &&
|
||||
!initiator->EntityVariableExists("RETURN_MONEY")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto handin_items = initiator->GetEntityVariable("HANDIN_ITEMS");
|
||||
auto return_items = initiator->GetEntityVariable("RETURN_ITEMS");
|
||||
auto handin_money = initiator->GetEntityVariable("HANDIN_MONEY");
|
||||
auto return_money = initiator->GetEntityVariable("RETURN_MONEY");
|
||||
|
||||
std::vector<PlayerEvent::HandinEntry> hi = {};
|
||||
std::vector<PlayerEvent::HandinEntry> ri = {};
|
||||
PlayerEvent::HandinMoney hm{};
|
||||
PlayerEvent::HandinMoney rm{};
|
||||
|
||||
// Handin Items
|
||||
if (!handin_items.empty()) {
|
||||
if (Strings::Contains(handin_items, ",")) {
|
||||
const auto handin_data = Strings::Split(handin_items, ",");
|
||||
for (const auto &h: handin_data) {
|
||||
const auto item_data = Strings::Split(h, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const auto item_id = static_cast<uint32>(Strings::ToUnsignedInt(item_data[0]));
|
||||
if (item_id != 0) {
|
||||
const auto *item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
hi.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Strings::Contains(handin_items, "|")) {
|
||||
const auto item_data = Strings::Split(handin_items, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const auto item_id = static_cast<uint32>(Strings::ToUnsignedInt(item_data[0]));
|
||||
const auto *item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
hi.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handin Money
|
||||
if (!handin_money.empty()) {
|
||||
const auto hms = Strings::Split(handin_money, "|");
|
||||
hm.copper = static_cast<uint32>(Strings::ToUnsignedInt(hms[0]));
|
||||
hm.silver = static_cast<uint32>(Strings::ToUnsignedInt(hms[1]));
|
||||
hm.gold = static_cast<uint32>(Strings::ToUnsignedInt(hms[2]));
|
||||
hm.platinum = static_cast<uint32>(Strings::ToUnsignedInt(hms[3]));
|
||||
}
|
||||
|
||||
// Return Items
|
||||
if (!return_items.empty()) {
|
||||
if (Strings::Contains(return_items, ",")) {
|
||||
const auto return_data = Strings::Split(return_items, ",");
|
||||
for (const auto &r: return_data) {
|
||||
const auto item_data = Strings::Split(r, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const auto item_id = static_cast<uint32>(Strings::ToUnsignedInt(item_data[0]));
|
||||
const auto *item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
ri.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Strings::Contains(return_items, "|")) {
|
||||
const auto item_data = Strings::Split(return_items, "|");
|
||||
if (
|
||||
item_data.size() == 3 &&
|
||||
Strings::IsNumber(item_data[0]) &&
|
||||
Strings::IsNumber(item_data[1]) &&
|
||||
Strings::IsNumber(item_data[2])
|
||||
) {
|
||||
const auto item_id = static_cast<uint32>(Strings::ToUnsignedInt(item_data[0]));
|
||||
const auto *item = database.GetItem(item_id);
|
||||
|
||||
if (item) {
|
||||
ri.emplace_back(
|
||||
PlayerEvent::HandinEntry{
|
||||
.item_id = item_id,
|
||||
.item_name = item->Name,
|
||||
.charges = static_cast<uint16>(Strings::ToUnsignedInt(item_data[1])),
|
||||
.attuned = Strings::ToInt(item_data[2]) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return Money
|
||||
if (!return_money.empty()) {
|
||||
const auto rms = Strings::Split(return_money, "|");
|
||||
rm.copper = static_cast<uint32>(Strings::ToUnsignedInt(rms[0]));
|
||||
rm.silver = static_cast<uint32>(Strings::ToUnsignedInt(rms[1]));
|
||||
rm.gold = static_cast<uint32>(Strings::ToUnsignedInt(rms[2]));
|
||||
rm.platinum = static_cast<uint32>(Strings::ToUnsignedInt(rms[3]));
|
||||
}
|
||||
|
||||
initiator->DeleteEntityVariable("HANDIN_ITEMS");
|
||||
initiator->DeleteEntityVariable("HANDIN_MONEY");
|
||||
initiator->DeleteEntityVariable("RETURN_ITEMS");
|
||||
initiator->DeleteEntityVariable("RETURN_MONEY");
|
||||
|
||||
bool handed_in_money = hm.platinum > 0 || hm.gold > 0 || hm.silver > 0 || hm.copper > 0;
|
||||
|
||||
bool event_has_data_to_record = (
|
||||
!hi.empty() || handed_in_money
|
||||
);
|
||||
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::NPC_HANDIN) && event_has_data_to_record) {
|
||||
auto e = PlayerEvent::HandinEvent{
|
||||
.npc_id = owner->CastToNPC()->GetNPCTypeID(),
|
||||
.npc_name = owner->GetCleanName(),
|
||||
.handin_items = hi,
|
||||
.handin_money = hm,
|
||||
.return_items = ri,
|
||||
.return_money = rm
|
||||
};
|
||||
|
||||
RecordPlayerEventLogWithClient(initiator, PlayerEvent::NPC_HANDIN, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::string QuestManager::GetAutoLoginCharacterNameByAccountID(uint32 account_id)
|
||||
|
||||
+18
-16
@@ -664,6 +664,8 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
||||
}
|
||||
}
|
||||
else if(tradingWith && tradingWith->IsNPC()) {
|
||||
NPCHandinEventLog(trade, tradingWith->CastToNPC());
|
||||
|
||||
QSPlayerLogHandin_Struct* qs_audit = nullptr;
|
||||
bool qs_log = false;
|
||||
|
||||
@@ -832,13 +834,13 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
||||
);
|
||||
}
|
||||
|
||||
auto loot_drop_entry = LootdropEntriesRepository::NewNpcEntity();
|
||||
loot_drop_entry.equip_item = 1;
|
||||
loot_drop_entry.item_charges = static_cast<int8>(baginst->GetCharges());
|
||||
auto lde = LootdropEntriesRepository::NewNpcEntity();
|
||||
lde.equip_item = 1;
|
||||
lde.item_charges = static_cast<int8>(baginst->GetCharges());
|
||||
|
||||
tradingWith->CastToNPC()->AddLootDrop(
|
||||
bagitem,
|
||||
loot_drop_entry,
|
||||
lde,
|
||||
true
|
||||
);
|
||||
// Return quest items being traded to non-quest NPC when the rule is true
|
||||
@@ -857,17 +859,17 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto lde = LootdropEntriesRepository::NewNpcEntity();
|
||||
lde.equip_item = 1;
|
||||
lde.item_charges = static_cast<int8>(inst->GetCharges());
|
||||
|
||||
tradingWith->CastToNPC()->AddLootDrop(
|
||||
item,
|
||||
lde,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
auto new_loot_drop_entry = LootdropEntriesRepository::NewNpcEntity();
|
||||
new_loot_drop_entry.equip_item = 1;
|
||||
new_loot_drop_entry.item_charges = static_cast<int8>(inst->GetCharges());
|
||||
|
||||
tradingWith->CastToNPC()->AddLootDrop(
|
||||
item,
|
||||
new_loot_drop_entry,
|
||||
true
|
||||
);
|
||||
}
|
||||
// Return quest items being traded to non-quest NPC when the rule is true
|
||||
else if (restrict_quest_items_to_quest_npc && (!is_quest_npc && item->IsQuestItem())) {
|
||||
@@ -2382,7 +2384,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app)
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -4257,4 +4259,4 @@ bool Client::DoBarterSellerChecks(BuyerLineSellItem_Struct &sell_line)
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-12
@@ -561,12 +561,6 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct*
|
||||
m_epp->expended_aa = e.e_expended_aa_spent;
|
||||
m_epp->last_invsnapshot_time = e.e_last_invsnapshot;
|
||||
m_epp->next_invsnapshot_time = m_epp->last_invsnapshot_time + (RuleI(Character, InvSnapshotMinIntervalM) * 60);
|
||||
pp->cold_resist = e.cold_resist;
|
||||
pp->fire_resist = e.fire_resist;
|
||||
pp->magic_resist = e.magic_resist;
|
||||
pp->disease_resist = e.disease_resist;
|
||||
pp->poison_resist = e.poison_resist;
|
||||
pp->corruption_resist = e.corruption_resist;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1164,12 +1158,6 @@ bool ZoneDatabase::SaveCharacterData(
|
||||
e.e_expended_aa_spent = m_epp->expended_aa;
|
||||
e.e_last_invsnapshot = m_epp->last_invsnapshot_time;
|
||||
e.mailkey = c->GetMailKeyFull();
|
||||
e.cold_resist = pp->cold_resist;
|
||||
e.fire_resist = pp->fire_resist;
|
||||
e.magic_resist = pp->magic_resist;
|
||||
e.disease_resist = pp->disease_resist;
|
||||
e.poison_resist = pp->poison_resist;
|
||||
e.corruption_resist = pp->corruption_resist;
|
||||
|
||||
const int replaced = CharacterDataRepository::ReplaceOne(database, e);
|
||||
|
||||
@@ -3484,6 +3472,9 @@ bool ZoneDatabase::LoadFactionData()
|
||||
}
|
||||
|
||||
auto& fmr_row = faction_max_results.begin();
|
||||
if (fmr_row[0] == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
max_faction = Strings::ToUnsignedInt(fmr_row[0]);
|
||||
faction_array = new Faction *[max_faction + 1];
|
||||
|
||||
+1
-1
@@ -737,7 +737,7 @@ void Client::ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y,
|
||||
ZonePC(zoneID, instance_id, x, y, z, heading, ignorerestrictions, zm);
|
||||
break;
|
||||
default:
|
||||
LogError("Client::ProcessMovePC received a reguest to perform an unsupported client zone operation");
|
||||
LogError("Received a request to perform an unsupported client zone operation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user