Compare commits

...

360 Commits

Author SHA1 Message Date
Chris Miles 453106439f [Release] 22.55.0 (#4464) 2024-08-26 22:03:37 -05:00
Mitch Freeman 3da24fffa4 [Bug Fix] Fix client hotbar exchanging items when zoning (#4460)
* Add an exception process to assigning item serial numbers to correct a bug in the client hot bar clicky system.

* fixed missing guid in replace statement

* added snapshot support

* upate #show inventory command to protect against crash conditions
2024-08-26 21:58:07 -05:00
Kurt Gilpin 8d8ef6d480 [Bug Fix] Correct missed maxlevel reference in exp.cpp (#4463)
This was causing characters to de-level when gaining experience and was missed as part of https://github.com/EQEmu/Server/pull/4455
2024-08-26 22:34:22 -04:00
Chris Miles 1f9c4b3a22 [World] Fix slow world bootup bug (#4461)
* [World] Fix slow world bootup bug

* Update ip_util.cpp

* Add timeout

* Update ip_util.cpp

* Cross platform timeout
2024-08-26 20:59:43 -05:00
Alex King 7dfda95d86 [Bug Fix] Fix Bot Spell Entries IDs Capping at 32,767 (#4444)
* [Bug Fix] Fix Bot Spell Entries IDs Capping at 32,767

* Fix manifest
2024-08-26 20:29:50 -05:00
Alex King 40738b29e3 [Quest API] Add Area-Based Quest Methods to Perl/Lua (#4447)
* [Quest API] Add Area-Based Quest Methods to Perl/Lua

* Convert some to mob

* Fix
2024-08-26 20:29:07 -05:00
Alex King 080865faa2 [Feature] Add Optional Return to EVENT_DAMAGE_TAKEN (#4454)
* [Feature] Add Optional Return to EVENT_DAMAGE_TAKEN

# Description
- Allows operators to return a value from `EVENT_DAMAGE_TAKEN` to override the amount of damage taken based on any arbitrary criteria they'd like to apply.

* Update attack.cpp
2024-08-26 20:27:29 -05:00
Alex King e2b545991a [Quest API] Add AreTasksCompleted() to Perl/Lua. (#4456)
* [Quest API] Add AreTasksCompleted() to Perl/Lua.

* Bool
2024-08-22 20:21:14 -04:00
Alex King b7f8d0f179 [Feature] Extend Spell Buckets Functionality (#4441) 2024-08-22 18:49:52 -04:00
Alex King e3588781aa [Cleanup] Remove unused methods (#4449) 2024-08-22 11:48:02 -04:00
Alex King e9b84f4d11 [Bug Fix] Fix issue with killed mob coordinates (#4457) 2024-08-22 11:45:31 -04:00
Alex King 4f03970fd1 [Bug Fix] Fix Character ID of 0 being inserted into character_stats_record (#4458) 2024-08-22 11:45:19 -04:00
catapultam-habeo 4979da6932 [Bug Fix] Apply Race & Class restrictions to Auto-Combines (#4452) 2024-08-19 21:57:34 -04:00
Fryguy 9987029791 [Bug Fix] client_max_level allow leveling to end of level (#4455)
When using a method that leverages client_max_level (e.g. Max Level by bucket / qglobal / quest API) it would stop xp at 0% into the level rather than maximum xp for the level.

This could pose an issue where: If you had a max level of 65 via a databucket and a raid zone required level 65, one death would de-level them and potentially prevent them from entering the zone.

I reorganized the code to leverage the existing max_level logic which allows max xp in the max level.

I also cleaned up the overall functions formating (Mostly brackets and implied if statements).
2024-08-19 21:56:14 -04:00
Alex King eece0a92e3 [Quest API] Add Several Door Methods to Perl/Lua (#4451) 2024-08-16 15:52:49 -04:00
Alex King 057f96796a [Bug Fix] Fix Issue with Removed #setfaction Command (#4448) 2024-08-10 21:21:46 -04:00
Alex King f475cecdb1 [Bug Fix] Fix AddCrystals() in Perl/Lua (#4445) 2024-08-09 22:48:32 -04:00
Fryguy 6296ed6d41 [Bug Fix] Attune Augments when Equipped (#4446) 2024-08-09 22:27:04 -04:00
Alex King ac0f729aa2 [Feature] Add Character:DefaultGuildRank Rule (#4438)
* [Feature] Add Character:DefaultGuildRank Rule

* Update ruletypes.h

* Update ruletypes.h

* Update database.cpp
2024-08-03 22:48:30 -04:00
JJ 2937852cf9 [Bug Fix] Ensure close of Tribute Item search (#4439) 2024-08-03 20:25:07 -04:00
Alex King 2cf5bae571 [Bug Fix] Fix Lua Client FilteredMessage (#4437) 2024-07-31 19:39:57 -04:00
Fryguy 2feb05be18 [Improvement] Filtered Messages Extension (#4435)
* [Improvment] Filtered Messages Extension

Added:
ItemSpeech 25
Strikethrough 26
Stuns 27
BardSongsOnPets 28

I wired up Strikethrough and Stuns as they already had message entries.

ItemSpeech and BardSongsOnPets do not appear to be currently used in the source.

Note: There are still 5 unknown Filters in RoF2 that need to be investigated:

Achievments
Fellowships
Mercenary Messages
PVP Messages
Spam

* Spelling Error

* Missed some stun calls
2024-07-31 18:28:45 -04:00
Fryguy 421767e1e5 [Bug Fix] Imitate Death should also clear zone feign aggro (#4436) 2024-07-31 18:28:36 -04:00
JJ 6e9ff52dce [Release] 22.54.0 (#4434)
* Update CHANGELOG.md

* Update version.h

* Update package.json

* Update CHANGELOG.md
2024-07-30 20:30:38 -04:00
Alex King aa700f8960 [Cleanup] Cleanup Client File Exporting (#4348)
* [Cleanup] Cleanup Client File Exporting

* Update base_data_repository.h

* Update db_str_repository.h

* Update base_data_repository.h

* Update skill_caps_repository.h

* Update skill_caps_repository.h

* Update skill_caps_repository.h

* Update main.cpp

* Push
2024-07-30 20:10:00 -04:00
Fryguy 2ef959c5ed [Improvement] Flee Overhaul (#4407)
* Lots of flee updates primarily based on TAKPs source

* Update Values to EQEmu values.

* Add rule

* Adjustments to fear pathing

* Flee/Pathing adjustments (More TAKP code adjusted)

* updates

* Updates (Massaged functions from TAKP source)

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-07-30 18:27:47 -04:00
Mitch Freeman e49ab924cc [Feature] Add Barter/Buyer Features (#4405)
* Add Barter/Buyer Features

Adds barter and buyer features, for ROF2 only at this time including item compensation

* Remove FKs from buyer tables

Remove FKs from buyer tables

* Bug fix for Find Buyer and mutli item selling

Update for quantity purchases not correctly providing multi items.
Update for Find Buyer functionality based on zone instancing.
Update buyer messaging
Update buyer LORE duplicate check

* Revert zone instance comment

* Revert zone_id packet size field

* Add zone instancing to barter/buyer

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-07-30 16:23:37 -04:00
catapultam-habeo fc3c691588 [Feature] Implement Move Multiple Items (#4259)
* Implement Move Multiple Items

* Send LinkDead on invalid packet

* structure this more like MoveItem

* implement all modes

* remove un-needed debug message

* handle mode 3 swaps in bank\shared bank correctly.

* Revert "handle mode 3 swaps in bank\shared bank correctly."

This reverts commit ce01fbfde70d52e88381772a6c7a77b4b650c7c5.

* Revert "remove un-needed debug message"

This reverts commit f4b662459e11a60c3a46a97e5320757c4b2b9a84.

* handle mode 3 swaps without extra unintended code

* correct variable type

* remove magic numbers

* forgot a semicolon in emu_constants.h

* fix bad rebase artifact

* Remove unused struct

* apply changes discussed in PR

* last rebase conflict

* last rebase conflict

fix more inventory type enum refs

* fix windows build error

* fix other windows build error.

* fix duplication bug
2024-07-30 13:40:48 -04:00
catapultam-habeo d465a3deba [Bug Fix] Stop DOSing ourselves with OP_WearChange (#4432)
* initial commit to start convo

* additional potential problem

* Revert "additional potential problem"

This reverts commit 689e94ea95.
2024-07-30 13:00:26 -04:00
Alex King 40c9c8044b [Bug Fix] Fix issue with quest::echo and quest::me (#4433) 2024-07-30 09:25:05 -04:00
Chris Miles 70a96ea098 [Zoning] Improve zone routing (#4428)
* [Zoning] Improvements to zone routing

* Update world_content_service.h

* Update world_content_service.h
2024-07-30 09:12:31 -04:00
Chris Miles d5cbec714e Revert "[Zone Instances] Handle routing to instances when using evac/succor (#4297)" (#4429)
This reverts commit dfd1bfbd49.
2024-07-30 09:12:19 -04:00
Mitch Freeman 6903205484 [Bug Fix] Fix #parcels add subcommand (#4431)
The parcel object was not be initialized correctly resulting in the possibility of incorrect data being written for the uninitialized members.
2024-07-28 21:56:21 -04:00
Chris Miles 4c81321847 [Databuckets] Remove memory reserve from bulk load (#4427) 2024-07-23 00:37:34 -05:00
Alex King e5cea73e0c [Bug Fix] Fix Client::RemoveTitle (#4421)
* [Bug Fix] Fix Client::RemoveTitle

* Remove title/suffix if in use.

* Update titles.cpp

* Non static
2024-07-23 00:33:09 -05:00
Alex King 23308192b5 [Bug Fix] Fix #setlevel Allowing Skills Above Max (#4423) 2024-07-22 20:46:38 -05:00
Alex King 29fdf7e2ae [Bug Fix] Fix EVENT_USE_SKILL with Sense Heading (#4424) 2024-07-22 20:45:32 -05:00
Alex King 098498dedd [Commands] Extend #devtools Functionality (#4425) 2024-07-22 20:44:34 -05:00
Alex King b6fb8daae8 [Bug Fix] Fix Bot::SetBotStance (#4426) 2024-07-22 20:43:18 -05:00
nytmyr 563f7d5564 [Cleanup] Mask GM Show Buff message behind EntityVariable (#4419)
* [Cleanup] Mask GM Show Buff message behind EntityVariable

Removes the spam of "Your GM flag allows you to always see your targets' buffs." for GMs every time a buff lands on a target.

It will now lock to an Entity Variable and only show once per zone.

* Convert string to constexpr

* Switch from string to char
2024-07-22 12:51:41 -04:00
Fryguy 1e5abc456b [Bug Fix] Proximity Aggro for Frustrated and Undead (#4411)
* [Bug Fix] Prox aggro for frustrated and undead.

If mob is frustrated (Rooted and has no one to kill or is undead will add prox aggro to hate list.

* Update aggro.cpp

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-07-22 07:01:12 -04:00
Fryguy 3b0fa015a7 [Bug Fix] Corpse Call removing Resurrection Effects (#4410)
* [Bug Fix] Corpse Call removing Rez Effects

When calling a corpse, it should not remove rez effects.

* Update client_process.cpp

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-07-22 06:26:40 -04:00
nytmyr c73a1e8bea [Rules] Add HasteCap and Hastev3Cap rules for NPCs, Bots and Mercs (#4406)
* [Rules] Add HasteCap and Hastev3Cap rules for NPCs, Bots and Mercs

Previously NPCs, bots and mercs all had a flat haste cap of 150 whereas clients were capped at 100.

NPCs, bots and mercs used the character rule for v3 cap, they now each have their own.

Rules for v3 cap are the default of 25 as they were using.
Rules for haste caps are the default of 150 for NPCs they were using but lowered to 100 for bots and mercs, the same as clients.

This also adds haste output to the GM target stat window

* Fix for stat windows to account for client haste
2024-07-22 06:06:49 -04:00
Fryguy 3bfdc0cf71 [Bug Fix] Potential fix for some undesired ranged explotative behavior. (#4413)
Original Commit: 33fecd68d4eab36885eb7f8067102ba6bce95bac

Conditional ranged double attack
2024-07-22 06:05:46 -04:00
Mitch Freeman a23ac4628f [Feature] Add Parcel notification for online players when using the Quest API (#4418)
* Add parcel notification for online players when using the quest api for send_parcel

* Compile fix

fix for compile issues
2024-07-22 05:57:42 -04:00
nytmyr 5ef4612249 [Bug Fix] [Quest API] Fix getraididbycharid and getgroupidbycharid (#4417) 2024-07-16 15:53:22 -04:00
Mitch Freeman 17f66c5d60 [Bug Fix] Personal tributes for bard items were not applying correctly (#4416)
* Fixes Personal Tributes for bard items not being applied.

* Fix for bots
2024-07-16 11:18:42 -04:00
Mitch Freeman 51eb95ed31 Revert "Fixes Personal Tributes for bard items not being applied. (#4414)" (#4415)
This reverts commit 080abaede1.
2024-07-16 10:49:08 -04:00
Mitch Freeman 080abaede1 Fixes Personal Tributes for bard items not being applied. (#4414) 2024-07-15 23:02:35 -04:00
Mitch Freeman 97e332819d When searching in the bazaar, the minimum cost was not be honoured. (#4412) 2024-07-15 08:41:04 -04:00
Mitch Freeman 1e41c5517e [Bug Fix] Fix for random disconnects when a large number of guild members zone or disconnect (#4402) 2024-07-10 00:10:33 -05:00
Fryguy c7a88af11a [Bug Fix] AutoSplit unknown bug and cleanup. (#4401)
Code Credit TAKP:

Bug Post: https://discord.com/channels/212663220849213441/1258430167764832319

Resolved issue with split message being sent to group members when no split is present which creates an "Unknown Split".

Also added the random remainder split portion unless using a manual /split

Converted manual messages to Strings
2024-07-07 00:53:57 -04:00
KayenEQ d8ddd0aab9 [Bug Fix] Aegolism Spell line stacking (#4399)
* fix stacking issues with Aegolism spell line

Issue: When casting buffing a player with aegolism spell line, who already has cleric AC, symbol and heroism spell, it would overwrite heorism buff and leave other two.

Aegolism spell line when applied when a client has Heroism spell line, AC spell line, and symbol spell line. Should overwrite the Heroism spell and fade the AC and Symbol buffs.

* Update spdat.cpp
2024-07-07 00:53:46 -04:00
Fryguy 95cbadade5 [Bug Fix] Slay Adjustments (#4389)
Previous change did not account for the modern slay undead and holyforge spells.

Reverted some of the changes and cleaned up others.

Rule Renamed (Default value was incorrect, this was a clean way to fix that) - SlayDamageAdjustment -> SlayDamageMultiplier

Also added a rate multiplier

RULE_REAL(Combat, SlayRateMultiplier, 1.0, "Slay Rate Adjustments - Multiply final slay rate check by this value. Default: 1.0")

Fixed the ordering of the constants for the slay undead SPA that were backwards and causing major headaches with tuning and setting up slay undead correctly.

Base = Damage Mod (100 is base, so 240 = 140% more)
Limit = Proc Rate - Value is divided by 10000 for a Float %. e.g. 1700 becomes 0.17 (Or 17% proc rate).

Damage bonus should be additive not std::max as AA, Spells and Item bonuses should stack.

e.g. Slay Undead RK3 240 + Holy Forge 140 should = 380 (280% damage)
2024-07-07 00:53:29 -04:00
Alex King a85f4fb703 [Cleanup] Cleanup Stance Code (#4368)
* [Cleanup] Cleanup Stance-based Code

* Command

* Update emu_constants.h

* Update stance.cpp

* Cleanup
2024-07-02 21:50:34 -04:00
Fryguy e63f34638b [Bug Fix] AllowRaidTargetBlind logic backwards (#4400) 2024-07-01 08:15:36 -04:00
JJ 7918fed81c [Release] 22.53.1 (#4398) 2024-06-16 21:17:16 -04:00
JJ ac24c9bf5a [Bug Fix] Fix trader mode (#4397)
* Fix bazaar trading

* Update `constexpr`

* Added world trader table truncate on boot to ensure that the trader table is always empty when world starts.

---------

Co-authored-by: Mitch Freeman <65987027+neckkola@users.noreply.github.com>
2024-06-16 20:55:14 -04:00
Chris Miles 7b914c731b [Release] 22.53.0 (#4395) 2024-06-14 12:44:57 -05:00
Fryguy 7362c0ebb5 [Bug] Anon players should not show in /who all (#4392)
Updated to properly filter anon players from /who all.

The code formatting was very inconsistant and needed cleanup.
2024-06-14 12:39:41 -05:00
Fryguy ae213a4e4b [Rule] Classic Harm Touch Formula (#4394)
* [Rule] Classic Harm Touch Formula

Pre 2007 Harm Touch was handled differently with base harm Touch ( Ability or 2 ranks aa) and Improved Harm Touch AA. It was converted into 10 ranks of Harm Touch -

http://www.tski.co.jp/baldio/patch/20071113.html

It was further refined in 2008 to have a DoT component.

http://www.tski.co.jp/baldio/patch/20080709.html

This rule focuses on the pre 2007 version and allows the damage to properly scale

* Updated logic

* Update per feedback.
2024-06-14 12:28:43 -05:00
Alex King 187288f3aa [Rules] Add Invisible Augment Rules (#4385)
* [Rules] Add Invisible Augment Slot Rule

* Update item_instance.cpp

* Second rule

* Update ruletypes.h
2024-06-14 12:02:21 -05:00
Alex King abc8c3d886 [Cleanup] Remove unused code in emu_constants.h (#4384)
# Description
- Remove unused code that was missed as a result of resolving merge conflicts and this being left behind.
2024-06-14 11:59:13 -05:00
Alex King 0b2493beb8 [Cleanup] Cleanup Object Type Code (#4375)
* [Cleanup] Cleanup Object Type Code

* Move to object.cpp/object.h
2024-06-14 11:58:59 -05:00
JJ 9cebba5911 [Bug Fix] Fix potential trader crash when serialized item not found (#4386) 2024-06-14 11:58:00 -05:00
Fryguy 4478328b2a [Rules] Mend/Sneak allow success tuning (#4390)
MendAlwaysSucceedValue allows you to adjust skill at which mend will always succeed its check.

SneakAlwaysSucceedOver100 allows sneak to always succeed when over skill 100 (Higher skill increases the movement speed).
2024-06-14 11:57:31 -05:00
JJ 55a7e1646d Check that an event actually exists (#4387) 2024-06-14 11:56:33 -05:00
Mitch Freeman b6b8491060 [Bug Fix] Fix for players having empty bazaar window dropdown list, even though trader is tagged as a trader. (#4391)
* Potential fix for players having empty bazaar window dropdown list, even though trader is tagged as a trader.

* Update the truncate of the trader table to avoid inappropriate deletions if an instance of bazaar was started.
2024-06-14 11:53:34 -05:00
Fryguy 850053a136 [Bug] Prevent Resurrection Spells from being resisted (#4393)
* [Bug] Prevent Ressurection Spells from being resisted

Added IsRessurectionSpell(uint16 spell_id) to assist with checking on a spell is a ressurection spell.

This was noticed when Dragons of Norrath launched and the Tier 5 Progression AA provided SPA 180 2% SE_ResistSpellChance

* Helps if I spell it correctly

* Update per feedback
2024-06-14 11:51:33 -05:00
Fryguy 1aa8758b0a [Bug] Escape should put player into SOS if owned. (#4388)
When you escape if you have the Shroud of Stealth bonus (AA, Spell, item) you will go straight into SOS mode.
2024-06-07 13:57:54 -04:00
Alex King b1aa087b9f [Bug Fix] Fix Swarm Pet Damage Messages (#4383) 2024-06-04 18:50:08 -04:00
Alex King 1e57a0372f [Bug Fix] Fix #goto Target (#4382) 2024-06-03 03:02:27 -04:00
Fryguy 9614ea59ec [Rule] Snare Override Movement Bonus (#4381)
* [Rule] Snare Override Movement Bonus

This rule allows snare to override any movement bonuses.

RULE_BOOL(Spells, AllowSnareEffectsOverrideBonus, false, "Enabling will allow snares to override any speed bonuses the entity may have. Default: False")

Default: False

* Rule name

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-06-02 17:50:41 -04:00
Alex King 7a648cce16 [Cleanup] Cleanup Account Status Code (#4376)
* [Cleanup] Cleanup Account Status Code

* Update emu_constants.cpp

* Update emu_constants.h
2024-06-02 16:40:52 -04:00
Alex King 8640776a21 [Cleanup] Cleanup Body Type Code (#4366)
* [Cleanup] Cleanup Body Type-based Code

* Update bodytypes.cpp

* Final

* Update body_type.cpp

* Cleanup

* Cleanup

* Formatting

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-06-02 04:25:06 -04:00
Chris Miles 0c45d3b09e [Release] 22.52.0 (#4380) 2024-06-01 20:37:21 -05:00
Mitch Freeman 59e4adb117 [Fix] Bazaar Search not working correctly for Iksar, Vashir, Drakkin and Froglok races (#4379) 2024-06-01 19:17:18 -05:00
Alex King d5a06bfe2e [Cleanup] Cleanup Bucket Comparison Code (#4374)
* [Cleanup] Cleanup Bucket Comparison-based Code

* Final
2024-06-01 19:11:56 -05:00
Alex King 0f0676824c [Cleanup] Cleanup Bug Category Code (#4367)
* [Cleanup] Cleanup Bug Category-based Code

* Command

* Cleanup

* Cleanup

* Cleanup
2024-06-01 18:25:02 -05:00
Alex King caa647dc6b [Cleanup] Cleanup Deity Code (#4363)
* [Cleanup] Cleanup Deity-based Code

* Final push.

* Update deity.cpp

* Update deity.cpp

* Update deity.cpp

* Cleanup

* Cleanup

* [Cleanup] Cleanup Skill-based Code

* Update deity.cpp

* Update lua_client.cpp
2024-06-01 18:21:26 -05:00
Alex King 76b9ce0ac1 [Cleanup] Cleanup Special Ability Code (#4365)
* [Cleanup] Cleanup Special Ability-based Code

* Update emu_constants.cpp

* Update emu_constants.cpp

* Update emu_constants.cpp

* Update special_ability.cpp

* Cleanup

* Update emu_constants.cpp
2024-06-01 18:20:43 -05:00
Chris Miles d01d091b47 [Quests] Fix issue with Lua encounters loading in certain circumstances (#4378)
* [Quests] Fix issue with Lua encounters loading in certain circumstances

* Update quest_parser_collection.cpp

* Constant

* Move constant

* Fix

* Update quest_parser_collection.cpp
2024-06-01 18:07:38 -05:00
Alex King 47ddcb54f1 [Cleanup] Remove unused code in common/eq_constants.h (#4364) 2024-06-01 16:10:37 -05:00
Alex King dda0e410ff [Quest API] Add Item Link Methods to Perl/Lua (#4359) 2024-06-01 16:10:05 -05:00
Chris Miles eae05167f8 [Skills] Fix caps out of bounds issue (#4377)
* wip

* More adjustments
2024-06-01 16:09:34 -05:00
Alex King 16f21893a3 [Rules] Add Skill Base Damage Rules (#4360)
* [Rules] Add Skill Base Damage Rules

* Final

* Update ruletypes.h

* Update ruletypes.h
2024-06-01 16:09:21 -05:00
Alex King 4ca724956b [Bug Fix] Fix Unescaped String in Client::GotoPlayer (#4373)
* [Bug Fix] Fix Unescaped String in Client::GotoPlayer

* Final

* Update client.cpp
2024-06-01 16:09:00 -05:00
regneq 217a80ee76 [NPC Spells] Fixed an issue where the repository spell adj value was overriding the spell difficulty default value (#4370)
* [NPC Spells} fixed an issue where the repository spell adj value was overriding the spell difficulty default value.
[Command] Add resist adj to #show spells_list command to see the resist value.

* True fix, do IsValidSpell on actual spell

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-06-01 16:08:14 -05:00
JJ 8b166bf5b9 [Bug Fix] Add protection to ensure adventure points award are only attempted on players (#4371) 2024-05-31 17:47:23 -04:00
Chris Miles 4c614661e7 [Quests] Fix Lua encounter double register (#4369) 2024-05-30 20:27:21 -04:00
Fryguy 9392f86333 [Bug Fix] Adjust Kick/RoundKick Damage Lower levels (#4355)
Code for Kick and Bash were causing Warriors/Rangers to deal almost as much damage with low level abilities as a Monk using Flying Kick
2024-05-28 10:01:11 -04:00
Fryguy 0d888268a8 [Combat] Adjustments to Crippling Blows/Slay Undead and Confirmed Critical Code (#4354)
* Adjustments to Crippling Blows/Slay Undead and Confirmed Critical Code

* Adjustments per comments
2024-05-27 19:53:24 -04:00
Fryguy b044d8533e [Release] 22.51.1 (#4353)
### Fixes

* Adjust return for perl release check  @Akkadius 2024-05-26
* Corrected issue with bazaar purchase via parcels where an incorrect quantity would be calculated. ([#4352](https://github.com/EQEmu/Server/pull/4352)) @neckkola 2024-05-27

### Performance

* Improve SkillCaps::GetTrainLevel() Efficiency ([#4350](https://github.com/EQEmu/Server/pull/4350)) @Kinglykrab 2024-05-26

### Rules

* Legacy Compute Defense against modern agi based defense. ([#4349](https://github.com/EQEmu/Server/pull/4349)) @fryguy503 2024-05-27
2024-05-27 16:21:55 -05:00
Mitch Freeman d810cb02c3 [Fix] Corrected issue with bazaar purchase via parcels where an incorrect quantity would be calculated. (#4352) 2024-05-27 17:06:30 -04:00
Fryguy 992a5cc132 [Rule] Legacy Compute Defense against modern agi based defense. (#4349)
* [Rule] Legacy Compute Defense against modern agi based defense.

In new code, AGI becomes a large contributor to avoidance at low levels, since AGI isn't capped by Level but Defense is A scale factor is implemented for PCs to reduce the effect of AGI at low levels.  This isn't applied to NPCs since they can be easily controlled via the Database.

* `snake_case`

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-05-26 20:27:18 -04:00
Alex King c50fda0f73 [Performance] Improve SkillCaps::GetTrainLevel() Efficiency (#4350)
* [Performance] Improve SkillCaps::GetTrainLevel() Efficiency

* Finalize
2024-05-26 18:55:00 -05:00
Akkadius 1b15f16e3e [Hotfix] Adjust return for perl release check 2024-05-26 16:01:44 -05:00
Chris Miles 983cc1e82a [Release] 22.51.0 (#4347) 2024-05-26 15:44:28 -05:00
Mitch Freeman fc79614fac [Feature] Add RoF2 Bazaar Support (#4315)
* Add RoF2 Bazaar Support

Enable RoF2 bazaar features

* Add augments to Trader Items

* Cleanup

Cleanup of formatting and unused functions

* Update PlayerProfile for correct char_id in trader transactions.  Further cleanup.

* Add parcel delivery price functionality

Add parcel delivery price functionality via rules and new delivery cost struct.

* Add RoF support for bazaar window outside of bazaar with parcel delivery

* Further Testing and ActiveTransaction added

Further testing and a few fixes and messages added.  Add active transaction check to ensure two clients cannot purchase from the bazaar window at the same time

* Cleanup and Formatting updates

Cleanup and Formatting updates

* Update database manifest for the trader table against default peq trader table

* Logs and formatting

* Update bazaarsearch to be content_db aware

* Fix crash

* Simplify search

* Search fixes

* Push up more search logging

* More search fixes

* Formatting

* Update trader_repository.h

* Add Rule for Bazaar Parcel Delivery

Add a rule Bazaar:EnableParcelDelivery to enable/disable bazaar parcel delivery.  Default is True.

* Fix crash

* Update Bazaar Search

Adds/Tested bazaar search with move to content_db
- race, class, money, number of returned items, stats, name, slot, level, traders, local traders, specific trader.
Outstanding
- type, more stats to add (heroic, etc)

* Formatting

* Push

* Update bazaarsearch to include all stats that are available in RoF2

* Update BazaarSearch

Updates the bazaar search for item types.  They should be working as per RoF2+ types.

* Formatting

* Final updates to BazaarSearch

Add search by augmentation slots available on the item.
This enables all but Prestige, which I believe are not implemented yet.

* Add Titanium functionality correct ItemType Search

Add Titanium /trader /bazaar functionality.
Added itemtype=armor bazaar search.  It was missed in the search work

* Close off for loops

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-05-26 15:38:25 -05:00
Chris Miles d767217461 [Perl] Linux /opt/eqemu-perl checks when using release binaries (#4346) 2024-05-26 15:14:06 -05:00
Chris Miles 1310c5d528 [Scripts] Fix zone data load ordering issue (#4343)
* [Scripts] Fix zone data load ordering issue

* Move more around

* More
2024-05-26 14:26:06 -05:00
Chris Miles b253fce0d5 [Lua Mod] Fix issue with SetAAEXP and SetEXP firing when uninitialized (#4345) 2024-05-26 14:20:07 -05:00
Chris Miles 421857026d [NPC Spells] Fix an issue where procs wouldn't fire if no spell entries in list (#4344) 2024-05-26 14:53:30 -04:00
Fryguy 68f40c9255 [Rule] Backstab Haste Correction (#4337)
- Haste should only provide a max of a 2 s reduction to Backstab cooldown, but it seems that while BackstabReuseTimer can be reduced, there is another timer (repop on the button) that is controlling the actual cooldown.  I'm not sure how this is implemented, but it is impacted by spell haste (including bard v2 and v3), but not worn haste. This code applies an adjustment to backstab accuracy to compensate for this so that Rogue DPS doesn't significantly outclass other classes.
2024-05-26 11:34:36 -04:00
Fryguy 0bceee5622 [Bug Fix] Fix mistaken removed RULE_CATEGORY_END() (#4341) 2024-05-26 10:10:22 -04:00
Alex King cd03152550 [Quest API] Add Zone Uptime Exports to Perl/Lua (#4339) 2024-05-26 10:06:38 -04:00
Alex King 316fa54bd8 [Bug Fix] Fix Using Bind Wound Above 70% Health (#4340)
* [Bug Fix] Fix Using Bind Wound Above 70% Health

* Update client.cpp

* Update client.cpp
2024-05-26 10:06:26 -04:00
Fryguy 49957e3269 [Bug Fix] Raid Targets should not be Blindable as this will break all spell casting AI. (#4334)
* [Bug] Raid Targets should not be Blindable as this will break all spell casting AI.

* Add rule.

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-05-26 09:40:18 -04:00
Fryguy 9638d9af3a [Rule] Added MeleeMitigation Level Difference Roll Adjusted for level diffs (#4332)
* Added MeleeMitigation LevelDifferent Roll Adjusted for level diffs

* Adjustments per comments

* Tune method and const.

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-05-26 08:57:32 -04:00
Fryguy 87c207e862 [Feature] Add SE_IncreaseArchery and rules to tune archery (#4335)
* [Feature] Add SE_IncreaseArchery and rules to tune archery

* Adjustments per comments, also added to the tune system.

* Update bonuses.cpp

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-05-26 08:37:23 -04:00
Fryguy 2df5f3f55a [Bug Fix] When refreshing buffs, attempt to use the same buffslot if the buff still exists. (#4338) 2024-05-26 06:59:22 -04:00
Fryguy e803d3e1e1 [Bug Fix] Accuracy, Avoidance and Atk adjustments (#4336)
* [Bug Fix] Accuracy, Avoidance and Atk adjustments

- Applied Fix to Attack Power contributing too much to damage.
   Rule of thumb for era was 100 attack = 10% damage increase, but I was seeing closer to 15-25%.  Found that in the GetATK() function it seemed to be double counting attack power from items and spells, so I applied a /2 to remedy this.

* Update Tune
2024-05-26 06:57:30 -04:00
Fryguy fccb205a1d [Rule] Remove hard coded initial aggro in favor or an adjustable Rule (#4333)
* [Rule] Remove hard coded initial aggro in favor or an adjustable Rule

* Adjustments per comments
2024-05-26 06:56:36 -04:00
Fryguy f70078d62a [Hotfix] Missed a mob offense section for PR #4328 (#4331) 2024-05-26 00:02:30 -04:00
Fryguy 34ae3094d6 [Bug Fix] When Mounts are allowed to zone, block them from zoning to disallowed zones. (#4330) 2024-05-25 18:03:23 -04:00
Fryguy c56742a2a8 [Rule] Allow maximum per kill AA amount (#4329)
* [Rule] Allow maximum per kill AA amount

* Adjustments per comments

* Finalize.

* Update ruletypes.h

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-05-25 17:48:58 -04:00
Fryguy 3e34447172 [Rule] Mob Offensive and Weapon Skill static tables (#4328)
* [Rule] Mob Offensive and Weapon Skill static tables

* Adjustments per comments

* Adjustments - Thanks KK
2024-05-25 17:38:45 -04:00
Fryguy ca25122bfa [Rule] Allow servers to adjust the filtering threshold for heals from damage (e.g. Mark of Kings). (#4327) 2024-05-25 14:28:20 -04:00
Chris Miles 13a7532ef8 [Crash] Fix player event crash in ITEM_DESTROY (#4326) 2024-05-24 21:54:22 -04:00
Chris Miles e1344039ff [Crash] Fix Zone deconstructor crashes (#4325) 2024-05-24 21:54:16 -04:00
Chris Miles 98b137154a [Crash] Add validation to RemoveXTarget (#4324) 2024-05-24 21:54:10 -04:00
Chris Miles fc9ef2fb7b [Mobs] Remove entity type checks from ScanCloseMobs (#4323) 2024-05-24 21:54:01 -04:00
Chris Miles 6dc661032f [Crash] Fix crash when map name is null (#4322) 2024-05-24 21:53:54 -04:00
Chris Miles 2586527157 [Crash] Fix player events reload when out of bounds (#4321) 2024-05-24 21:53:47 -04:00
Chris Miles 3a51f04291 [Crash] Fix crash issue when dividing by zero in CalcHPRegen (#4320)
* [Crash] Fix crash issue when dividing by zero in CalcHPRegen

* Update zone.cpp
2024-05-24 21:53:40 -04:00
Chris Miles 66af3d2f63 [Crash] Fix rarer crash in EntityList::MobProcess (#4319) 2024-05-24 21:53:33 -04:00
Alex King 6bcd8fea18 [Bug Fix] Fix Crash with null Argument in #modifynpcstat (#4318)
* [Bug Fix] Fix Crash with null Argument in #modifynpcstat

* Update modifynpcstat.cpp

* Update modifynpcstat.cpp
2024-05-24 19:27:43 -04:00
Alex King 0d1cbecb55 [Bug Fix] Fix RemoveAlternateCurrencyValue not updating Client (#4317)
* [Bug Fix] Fix issue with Client::RemoveAlternateCurrencyValue

* Update client.cpp
2024-05-23 17:47:43 -04:00
Alex King e33e076b2a [Bug Fix] Fix issue with #suspend (#4314)
* [Bug Fix] Fix issue with #suspend

* Add suspension clearing

* Update character_data_repository.h

* Final push.
2024-05-23 16:45:21 -04:00
Alex King e26d17182e [Bug Fix] Fix issue with KeepOneRecordPerCompletedTask (#4313) 2024-05-22 21:25:36 -05:00
Alex King 7e40c5bac2 [Commands] Cleanup #resetaa Command (#4310)
* [Commands] Cleanup #resetaa Command

* Update resetaa.cpp
2024-05-22 16:06:51 -05:00
Alex King ca69cc67e8 [Bug Fix] Fix issue with #hotfix (#4316) 2024-05-22 15:38:47 -05:00
Chris Miles 099c6d657b [Spells] Add content filtering to NPC spells (#4309)
* [Spells] Add content filtering to NPC spells

* Update mob_ai.cpp

* Add NPC spell reloading

* Oops

* Naming

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-05-17 11:59:20 -04:00
Paul Coene c0a8fd097e [Merchants] Add New Classic Greed/Faction/Charisma Prices Rule (#4301)
* [Merchants] Add New Classic Greed/Faction/Charisma Prices Rule

* Fix size of greed field.

* Fix { formatting and add {} to one liners

* Fix return type of GetGreedPercent

* Remove code that slipped in from another patch

* Fix greed to be unsigned

* Update client.cpp

* Update client_packet.cpp

* Update client.cpp

Fix bad name in extra log message added manually from merge.

* Update client_packet.cpp

Spacing.

* Update client.cpp

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-05-17 11:16:02 -04:00
Mitch Freeman a80ab75260 [Feature] Add parcel container support (#4305)
* Add parcel container support

This allows sending containers with items as a parcel
When sending a item via a parcel, if the player had multiples of that item, the wrong item would be removed from inventory.

* Rebase updates
2024-05-17 01:58:26 -04:00
twincannon c87aadbf0c [Commands] #npcspawn Changes (#4311)
* Changes to npcspawn create command so it takes more stats from the target npc

* Add see invis stats to npccreate command

* WIP npcspawn command changes

* Add npcspawn clone and help args, fix some broken things with npcspawn

* Cleanup comments and add apostraphes to zone shortname query

* Make it so npcspawn remove only removes spawn2 row and optionally removes spawngroup and spawnentry, make create and add spawn the npc at client loc

* Make npcspawn create use the same syntax for spawngroup naming as npcspawn add

* Revert npcspawn create and add to use npc location rather than client, other misc tweaks
2024-05-16 15:17:37 -04:00
Akkadius 1be86edf20 [Release] 22.50.1 2024-05-12 14:56:55 -05:00
Mitch Freeman b49b564940 [Fix] Clear GuildOnlineStatus on world boot (#4306)
Ensure that the guild member online status is set to offline (0) when world boots.
2024-05-12 14:02:06 -05:00
Mitch Freeman d302b9c02e [Fix} Correct a guild bank dup issue (#4308)
When depositing an item in the guild bank with an unlimited charge (-1) a db error would occur resulting in a duplication issue.
Can test with item id 70208
2024-05-12 07:53:42 -04:00
Chris Miles d36bc3915d [Release] 22.50.0 (#4304)
* [Release] 22.50.0

* Update CHANGELOG.md
2024-05-09 11:59:56 -05:00
Xackery d6f1bba96c [Feature] Add devcontainer support (#4294)
* Add devcontainer support

* Rename default values for eqemu_config

* Move devcontainer files to devcontainer
2024-05-09 00:54:21 -05:00
Mitch Freeman d1c7e45437 [FIX] Fix for world crash with over 1500 guilds (#4299)
* Fix for world crash with over 1500 guilds

There was an existing issue with certain clients (RoF2) if there were more than 1500 guilds.  This also enhances the loading of guilds in both world and zone for performance if there are large number of guilds as RoF2 will support 1500+ guilds.

* Safely access permissions map

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-05-09 00:53:36 -05:00
Chris Miles 257935d33a [Quests] Hot Reload Changes (#4302)
* [Quests] Hot Reload Changes

* snake_case
2024-05-09 00:51:43 -05:00
Akkadius fe136e58e4 [Hotfix] Revert GetSkill from #4234 2024-05-04 21:28:22 -05:00
Akkadius fddb91794b [Hotfix] Fix crash from #4266 2024-05-04 21:24:22 -05:00
Akkadius ad3a675222 [Hotfix] GetSkill default return 0 2024-05-04 21:07:24 -05:00
Akkadius fa733eee50 [Hotfix] Perl__send_parcel GCC compile error 2024-05-04 21:01:44 -05:00
Chris Miles f07c5901f4 [Quests] Reload Quests on Bootup, Init earlier (#4298)
* [Quests] Reload Perl quests on bootup, init earlier

* Do reload on top of init
2024-05-04 20:57:16 -04:00
Akkadius 6dd061cba2 [Hotfix] Remove food or water GM message 2024-05-04 19:43:39 -05:00
Akkadius 405d963005 [Hotfix] "GM flag" vs "GM Flag" 2024-05-04 18:44:19 -05:00
Alex King 7ad97ce168 [Database] Add Extra Haste to Bots/Character Tables (#4286)
* [Database] Add Extra Haste to Bots/Character Tables

* Remove Database::GetExtraHasteByCharacterID

* Update database.h

* Update mob.cpp

* Update database_update_manifest.cpp

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-05-04 18:21:41 -05:00
KayenEQ a71ad416b4 [Spells] Implemented SPA 122 SE_ReduceSkill (#4234)
* Implement SPA122 v1

* Implemented SPA 122 ReduceSkill

SE_ReduceSkill SPA 122	 base: skill id, limit: none, max: none, formula: % skill is reduced (positive)

* Implemented SPA 122 Reduce Skill

remove incorrect SPA addition

* Break out multiple lines

* reformatted

reformatted

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-05-04 18:11:12 -05:00
Xackery 758859eea6 [Experience] Add SetExp/SetAAExp lua mods (#4292) 2024-05-04 18:10:27 -05:00
Alex King aa0e53f5fc [Messages] Add GM Status and Invulnerability Messages (#4266)
* [Messages] Add GM Status and Invulnerability Messages

* Update zoning.cpp

* Finalize.

* Update corpse.cpp

* Update message

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-05-04 18:07:17 -05:00
Xackery 34c27ebb2a [Lua] Add UpdatePersonalFaction Lua Mod (#4279)
* Add UpdatePersonalFaction lua mod

* Fix typo

* Fix value typo
2024-05-04 17:58:58 -05:00
Alex King 943274b443 [Commands] Adjust #kill and #list Commands (#4271)
* [Commands] Adjust #kill/#list Commands

* Update list.cpp
2024-05-04 17:49:18 -05:00
Alex King c4cda66c3b [Quest API] Add Parcel Sending to Perl/Lua (#4287) 2024-05-04 17:11:59 -05:00
Xackery 46f3e50b5c [Compiling] Add profiler flag (#4293) 2024-05-04 17:04:26 -05:00
JJ f77eec83e5 [Database] Move pets query to content database (#4296) 2024-05-04 16:59:57 -05:00
JJ dfd1bfbd49 [Zone Instances] Handle routing to instances when using evac/succor (#4297) 2024-05-04 16:59:20 -05:00
Alex King b3538021cc [Feature] Add is_parcel_merchant to #npcedit (#4290) 2024-05-04 05:11:52 -04:00
JJ 7b19225e48 [Database] Break out changes to npc_types from parcels (#4295)
* [Database] Break out changes to `npc_types` from parcels

# Description

Breaking out changes to `npc_types` table to its own update since we need to alter the content schema. See #4198.

## Type of change

- [X] Bug fix (non-breaking change which fixes an issue)

# Testing

Clients tested: N/A

# Checklist

- [X] I have tested my changes
- [X] I have performed a self-review of my code. Ensuring variables, functions and methods are named in a human-readable way, comments are added only where naming of variables, functions and methods can't give enough context.
- [X] I own the changes of my code and take responsibility for the potential issues that occur
- [X] If my changes make database schema changes, I have tested the changes on a local database. Updated version.h CURRENT_BINARY_DATABASE_VERSION to the new version.

* Remove extra line
2024-05-03 01:42:49 -04:00
Paul Coene ac8cf326b2 [Hot Fix] Update database_update_manifest.cpp (#4291)
Fix typo in field check
2024-04-29 04:31:24 -04:00
Xackery 39bb7e1723 [Lua] Add IsImmuneToSpell Lua Mod (#4278)
* Add IsImmuneToSpell lua mod

* Add lua_parser.h include in spells.cpp
2024-04-28 08:20:34 -04:00
Paul Coene e268ab18f5 [Messages] Fix multiple errors in spell damage at death. (#4264)
* [Messages] Fix multiple errors in spell damage at death.

* Change iBuffTic in new code to use snake_case
2024-04-27 22:49:00 -04:00
Paul Coene 37e21d7757 [Corpses] Corpse searches for items did not search augs (#4289) 2024-04-27 02:01:08 -04:00
Paul Coene 1529c0f670 [Doors] Replace magic # in code with a field in doors table for when door closes. (#4288)
* [Doors] Move hard coded door close timer to doors table

* Fix typo in version #

* Make field unsigned and not null
2024-04-25 17:59:01 -04:00
Paul Coene 1b8922fc14 [Combat] Add rule to set stun duration. Add rule to add stun messages. (#4284)
* [Combat] Add rule to set stun duration.  Add rule to add stun messages.

* Missed a spot with hard coded constant.

* Fix spacing.
2024-04-25 01:26:44 -04:00
Mitch Freeman 1e0373a3e3 [Feature] Add Augmentation Support for Parcels (#4285)
* Add Augmentation Support for Parcels

Add Augmentation Support for Parcels

* Formatting Updates

* Move augment columns.

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-04-24 17:33:33 -04:00
Paul Coene 99612ba7b3 [Bug Fix] All NPC classes could stun with kick/only warriors could be stunned (#4273)
* [Bug Fix] All NPC classes could stun with kick/only warriors could be stunned.

* Fix default NPCKickStun value to match existing code

* Remove else and make NPC the default.

* assign stun_level in declaration.
2024-04-24 17:20:58 -04:00
Mitch Freeman 1891c9b6de Bug Fix] MariaDB 10.5.x error with parcel function GetParcelCountAndCharacterName (#4281)
MariaDB was returning inconsistent results with a JOIN for parcel function GetParcelCountAndCharacterName
2024-04-22 23:45:33 -04:00
Alex King 6b698b5f51 [Quest API] Add DescribeSpecialAbilities() to Perl/Lua (#4269) 2024-04-20 21:20:37 -05:00
Alex King 703d2cd1d8 [Quest API] Add Zone Methods to Perl/Lua (#4268)
* [Quest API] Add Zone Methods to Perl/Lua

* Update zone_store.cpp
2024-04-20 21:18:00 -05:00
Chris Miles 4215a3b9d6 [Loot] Consolidate filtering logic (#4280)
* [Loot] Consolidate filtering logic

* Log category
2024-04-20 21:17:38 -05:00
Mitch Freeman fcffc6b3d4 [Feature] Add Parcel Feature for RoF2 Clients (#4198)
* Add Parcel Feature

Add the parcel system for RoF2 client

* Fixed a duplicate define

* Reformat

reformating and review changes

* Further Formatting

* Memory Mgmt Updates

Refactored to using unique_ptr/make_unique/etc to avoid manual memory mgmt.

Other format changes

* Refactor db structure

Refactor for db structure of parcels to character_parcels
Removal of parcel_merchants
Addition of npc_types.is_parcel_merchant
Cleanup as a result

* Refactor to use item id 99990 for money transfers.  Removed the money string function as a result, though simplified the messaging related to money.  Other updates based on feedback.

* Move prune routine out of scheduler and into a world process.
Removed RuleI from #define

* Update

* Update database.cpp

* Update database_update_manifest.cpp

* Update main.cpp

* Update client_process.cpp

* Update parcels.cpp

* Remove parcel merchant content to optional sql instead of manifest.

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-04-20 21:15:56 -05:00
Mitch Freeman 64fefaebe4 [Bug Fix] GLAA fix after database.cpp updates (#4277)
* Hopefully fix glaa

* Potential Fix for GroupAA Issues

This seems to resolve the GroupAA issue.  Tested with two characters joining a group.  Functions the same as previous builds like 22.45, 22.46, etc.

* Fix for GLAA issue - For testing.

* Redo fix for GLAA

* Cleanup GLAA fix and move savng to repo

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-04-20 20:13:17 -05:00
Alex King 7b44745c67 [Bug Fix] Fix Issue With Auto Login (#4267) 2024-04-20 20:07:37 -05:00
dependabot[bot] c3295d129d Bump golang.org/x/net in /utils/scripts/build/should-release (#4272)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.17.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.17.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 20:06:43 -05:00
JJ a565e5f824 [Bug Fix] Fix Corpses "Disappearing" (#4275)
This fixes corpses "disappearing" by fixing the graveyard check. Prior to the corpse overhaul (#3938), moving corpses to graveyards was assumed successful and automatically removed from the process.

Note: Will open a separate issue for the graveyard timer handling.

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# Testing

Attach images and describe testing done to validate functionality.

Clients tested: RoF2

# Checklist

- [x] I have tested my changes
- [x] I have performed a self-review of my code. Ensuring variables, functions and methods are named in a human-readable way, comments are added only where naming of variables, functions and methods can't give enough context.
- [x] I own the changes of my code and take responsibility for the potential issues that occur
2024-04-20 19:56:58 -05:00
Alex King 5a6e0c9e3d [Cleanup] Fix Message in #find task (#4270)
* [Cleanup] Fix Message in #find task

* Update task.cpp
2024-04-19 10:00:13 -04:00
Fryguy 8fa6eab2c2 [Bug Fix] Fixes Issue 4257 - Double Taunt Message (#4258)
# Description

The client appears to generate its own taunt message, so I removed the additional server side generated message.

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)
- [ ] This change requires a documentation update

# Testing

Clients tested: RoF2

# Checklist

- [x] I have tested my changes
- [x] I have performed a self-review of my code. Ensuring variables, functions and methods are named in a human-readable way, comments are added only where naming of variables, functions and methods can't give enough context.
- [ ] I have made corresponding changes to the documentation (if applicable, if not delete this line)
- [x] I own the changes of my code and take responsibility for the potential issues that occur
2024-04-17 20:38:58 -04:00
Chris Miles 3f49a656c4 [Release] 22.49.1 (#4256) 2024-04-15 07:53:01 -05:00
Chris Miles ff3e955804 [Zoning] Fix zone routing edge case (#4255)
* [Zoning] Fix zone routing edge case

* Push
2024-04-15 07:50:38 -05:00
Chris Miles 2538ee7976 [Release] 22.49.0 (#4254) 2024-04-15 06:38:15 -05:00
Xackery a7bfc5ec92 [Performance] Change skill_cap from vector to map (#4252)
* Change skill_cap from vector to map

* Fix missed level check

* Integer based key

* Paren

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-04-15 06:32:27 -05:00
Xackery d7d99152ac [Feature] Fix ignore_default on lua mod damage (#4228)
* Fix ignore_default on lua mod damage

* Add missing init calls
2024-04-15 05:39:29 -05:00
Chris Miles 0d09edf9aa [Loot] Add content filtering to lootdrop_entries (#4229)
* [Loot] Add content filtering to lootdrop_entries

* Comment unnecessary

* We have two sections of this code for some reason

* Comments

* Fix versions
2024-04-15 05:26:38 -05:00
Alex King 0a3f1d3c41 [Feature] Add Character Auto Login (#4216)
* [Feature] Add Character Auto Login

* Add commands and finalize.

* Add methods without character name.

* Update perl_client.cpp

* Add other methods.

* Repository methods.

* Update account_repository.h

* Update command_subsettings_repository.h

* Update command_subsettings_repository.h

* Update client.cpp
2024-04-15 05:13:39 -05:00
Paul Coene ac12ba153e [Spells] Normal Group Spells (non-raid) landed twice on caster (#4240) 2024-04-15 05:07:24 -05:00
KayenEQ 989d199908 [Spells] SPA69 TotalHP can be used in Worn Slot, Fixes/Updates to Max HP related variables. (#4244)
* Allow SPA69 to work on worn effects.

Update to allow SPA69 to work on worn effects which the client accepts and calculates properly.

Updated spell effect related Max HP change variables. 1) We had stat bonuses defined that did same function. Without updating would have had to create another variable for above to work. 2) Negate bonuses spell effect end up negating item HPs. which is not intended since using same variable for items and spells.

* HP variable updates

fixes

* HP variable updates

fixes

* HP variable updates

fixes

* Update mob.cpp
2024-04-15 05:06:17 -05:00
Alex King 1bc1f71254 [Bug Fix] Fix Account Flags Loading (#4243) 2024-04-15 05:00:03 -05:00
Paul Coene 41c5369c18 [Pets] Fix errors in sync with client of sit/stand (#4245)
* [Pets] Fix errors in sync with client of sit/stand

* Forgot bot.h
2024-04-15 04:59:36 -05:00
Paul Coene d6b5a9d343 [Bug Fix] Hero forge armor bug on login and show helm toggle. (#4246)
* [Bug Fix] Hero forge armor bug on login and show helm toggle.

* Merge in KayenEQ provided revert of original work around

* Fix botched merge section.
2024-04-15 04:59:08 -05:00
Paul Coene a5e8a4c2cd [Messages] Fix bug where DoT messages stop coming out when mob dies. (#4249) 2024-04-15 04:57:55 -05:00
Alex King 9a09d820a5 [Quest API] Add GetConsiderColor() to Perl/Lua (#4253) 2024-04-15 04:53:48 -05:00
Paul Coene b1d873d1fc [Bug Fix] Using %T in channel messages on fresh corpse yields mob, not corpse name. (#4168)
* [Bug Fix] Using %T in channel messages on fresh corpse yields mob/player name, not corpse name.

* Undo changes to PC corpse.

* Use rename to fix %T usage on client for those in zone

* Fix indentation spacing

* Update to consolidate Rename as suggested.

* Fix for mobs with ` in name

* Fix to use GetName() instead of GetCleanName()
2024-04-05 09:29:48 -04:00
KayenEQ 043eeced6f [Bug Fix] Client not updating HP bar when an HP Buff with a Heal is applied. (#4237)
* [Bug Fix] HP Bar not updating when applying HP Buff with a heal.

Bug: When an HP buff with a heal effect is applied for first time, the heal portion of the effect heals the client and updates HPs currently server side, but client side the HP bar does not register it as a heal thus you display as less than full HP. However due to server thinking your healed, you are unable to correct it by healing.

Solution: You need to resend the HP update after buff completed and action packet resent.

* add SE_MaxHPChange to fix

would result in same bug
2024-04-02 01:13:29 -05:00
KayenEQ e9a0c79301 [Bug Fix] SPA214 SE_MaxHPChange calculation errors corrected. (#4238)
* [Bug Fix] HP Bar not updating when applying HP Buff with a heal.

Bug: When an HP buff with a heal effect is applied for first time, the heal portion of the effect heals the client and updates HPs currently server side, but client side the HP bar does not register it as a heal thus you display as less than full HP. However due to server thinking your healed, you are unable to correct it by healing.

Solution: You need to resend the HP update after buff completed and action packet resent.

* add SE_MaxHPChange to fix

would result in same bug

* [Bug Fix] SPA214 Percent HP change calculation fix

Fix how spell and item bonuses using SPA 214 are calculated. Will now be calculated consistent with client.

* [Bug Fix] SPA214 SE_MaxHPChange calculation errors corrected.

removed code from other PR
2024-04-02 01:12:55 -05:00
Alex King dc48c45421 [Bug Fix] Fix Bot Creation Issue (#4235)
# Notes
- Creating bots was failing because were checking for `false` on `Database::CheckUsedName()` in `BotDatabase::QueryNameAvailability`.
- `Database::CheckUsedName()` is now `Database::IsNameUsed()` and checks for both bots and character name usages.
- We were checking for `false` which was always happening when there were no entries for the supplied name, meaning we were never allowed to create a bot.
2024-04-02 01:12:08 -05:00
Chris Miles d7a8fb8691 [Fix] Fix manifest for skill caps schema type (#4231) 2024-04-02 01:08:19 -05:00
Chris Miles 3a5381d38a [Crash] Check mob pointer before trying to remove it (#4230) 2024-04-01 18:09:57 -04:00
Alex King e64f03fcc0 [Bug Fix] Fix Lua Crash with Spell Blocked Event (#4236) 2024-04-01 18:06:39 -04:00
Alex King d77966797e [Quest API] Add Spell Blocked Event to Perl/Lua (#4217)
* [Spells] Add Unblockable Spell Table and Spell Blocked Event

- Add `EVENT_SPELL_BLOCKED`, exports `$blocking_spell_id`, `$cast_spell_id`, `$blocking_spell`, and `$cast_spell`.

- Add `event_spell_blocked`, exports `e.blocking_spell_id`, `e.cast_spell_id`, `e.blocking_spell`, and `e.cast_spell`.

- Adds `spells_unblockable` table with a `spell_id` and `is_unblockable` column.
- This table will need to be populated based on known spells that should be unblockable.

- This event will allow operators to perform events when spells are blocked.

* Cleanup

* Cleanup

* Update spells.cpp

* Remove unused repositories.

* Finalize

* Update lua_parser_events.cpp
2024-03-31 22:58:30 -05:00
Akkadius 048aad437b Update pull_request_template.md 2024-03-31 22:55:27 -05:00
hg b2d9de8d96 [Quests] Avoid Player and Bot quests in unloaded zone (#4232)
If a mob has a target when a zone is shutdown it will crash while trying
to dispatch EVENT_TARGET_CHANGE when the Mob destructor cleans up hatelists
if a quest interface isn't loaded for the type (in this case no bot scripts):

 	zone.exe!fmt::v10::format<std::string const &,char const *>(fmt::v10::basic_format_string<char,std::string const &,char const *> fmt={...}, const std::string & <args_0>={...}, const char * && <args_1>=0x0000000000000000) Line 2835	C++
>	zone.exe!QuestParserCollection::GetQIByBotQuest(std::string & filename={...}) Line 1138	C++
 	zone.exe!QuestParserCollection::BotHasQuestSubLocal(QuestEventID event_id=EVENT_TARGET_CHANGE) Line 353	C++
 	zone.exe!QuestParserCollection::BotHasQuestSub(QuestEventID event_id=EVENT_TARGET_CHANGE) Line 389	C++
 	zone.exe!Mob::SetTarget(Mob * mob=0x0000000000000000) Line 5431	C++
 	zone.exe!NPC::SetTarget(Mob * mob=0x0000000000000000) Line 575	C++
 	zone.exe!Mob::RemoveFromHateList(Mob * mob=0x000001bfbdc66040) Line 4894	C++
 	zone.exe!EntityList::RemoveFromTargets(Mob * mob=0x000001bfbdc66040, bool RemoveFromXTargets=true) Line 1530	C++
 	zone.exe!Mob::~Mob() Line 547	C++
 	zone.exe!NPC::~NPC() Line 537	C++
 	zone.exe!NPC::`scalar deleting destructor'(unsigned int)	C++
 	zone.exe!EntityList::RemoveAllMobs() Line 2678	C++
 	zone.exe!EntityList::Clear() Line 3090	C++
 	zone.exe!Zone::~Zone() Line 1103	C++
 	zone.exe!Zone::`scalar deleting destructor'(unsigned int)	C++
 	zone.exe!Zone::Shutdown(bool quiet=false) Line 928	C++

This is caused by the Zone destructor deleting short_name before calling
entity_list.Clear(). With an unloaded quest interface BotHasQuestSubLocal
calls GetQIByBotQuest which gets a null zone->GetShortName() and crashes
while formatting strings.

The immediate regressing commit for this crash is because a check for
zone->IsLoaded() was removed in 74f1eac4 with others that were removed
to fix a regression by #4025. GetQIByBotQuest and GetQIByPlayerQuest
always had this check and should have remained for them.

This restores the zone->IsLoaded() checks for GetQIByBotQuest/PlayerQuest.
The other functions cannot have that check added until the other issues
mentioned in #4149 are addressed.
2024-03-31 22:49:13 -05:00
Fryguy 42bfa4bb2e [Bug Fix] Shared Tasks - charid is now character_id (#4233)
## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# Checklist:

- [x] I have performed a self-review of my code. Ensuring variables, functions and methods are named in a human-readable way, comments are added only where naming of variables, functions and methods can't give enough context.
- [x] I have tested my changes
- [x] I own the changes of my code take responsibilities for the potential issues that occur
2024-03-31 22:41:15 -05:00
Chris Miles 72ce7c8e91 Update pull_request_template.md 2024-03-31 15:52:54 -05:00
Chris Miles e306c86875 Create pull_request_template.md 2024-03-31 15:48:33 -05:00
Alex King 3ae7979a67 [Bug Fix] Fix Issue With Bot Raid Aggro (#4222)
# Notes
- Bots were reportedly being bypassed by NPCs due to not taking into consideration their raid group's damage.
- Must have been missed when bot raids were implemented.
2024-03-31 11:56:12 -05:00
Xackery b638795f9b [Feature] Add LuaMod functions for CommonDamage and HealDamage (#4227)
* Add LuaMod functions for CommonDamage and HealDamage

* Remove extra bracket
2024-03-31 11:30:16 -04:00
KayenEQ 9e3bf91374 [Spells] Implemented SPA 463 SE_SHIELD_TARGET (#4224)
SPA 463 SE_SHIELD_TARGET

Live description: "Shields your target, taking a percentage of their damage".

Only example spell on live is an NPC who uses it during a raid event "Laurion's Song" expansion. SPA 54492 'Guardian Stance' Described as 100% Melee Shielding

Example of mechanic. Base value = 70. Caster puts buff on target. Each melee hit Buff Target takes 70% less damage, Buff Caster receives 30% of the melee damage.
Added mechanic to cause buff to fade if target or caster are separated by a distance greater than the casting range of the spell. This allows similar mechanics to the /shield ability, without a range removal mechanic it would be too easy to abuse if put on a player spell. *can not confirm live does this currently

Can not be cast on self.
2024-03-30 13:34:03 -04:00
KayenEQ cd89926435 [Feature] Additive Spell Focus from Worn slot with Limit Checks (#4208)
* [Feature] Additive Spell Focus from Worn slot with limits

New rule (UseAdditiveFocusFromWornSlotWithLimits) allows you place to focus effects in worn slots which will apply the focus additively and perform normal limit checks on those focus. This differs from regular focus behavior that only takes highest value.

This is a new version of an old rule "UseAdditiveFocusFromWornSlot"
which allowed similar behavior but ignored focus limits. Thus hindering its full potential for itemization.

* Update spell_effects.cpp

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-03-30 13:23:02 -04:00
Xackery e19f72f021 [Feature] Add RegisterBug LuaMod (#4209)
* Add RegisterBug LuaMod

* Add missing header

* Add missing header to lua_mod

* Fix RegisterBug ignore_default

* Fix ignore_default

* Fix formatting
2024-03-30 11:45:37 -04:00
JJ df1dc5d1e4 [Cleanup] Avoid unnecessary copies in database functions (#4220)
Since `auto` doesn't deduce references, these will most likely create copies having unintended results.
2024-03-29 07:45:41 -04:00
Alex King e11286164f [Bug Fix] Fix Luabind Double Class Register (#4219)
* [Bug Fix] Fix Luabind Double Class Register

# Notes
- These two methods were registering to the same class as another method, causing an error seen by @neckkola and others.

# Error
```
zone: /home/eqemu/source_jas/libs/luabind/src/class_registry.cpp:151: void luabind::detail::class_registry::add_class(const luabind::type_id&, luabind::detail::class_rep*): Assertion `(m_classes.find(info) == m_classes.end()) && "you are trying to register a class twice"' failed.
```

* Update lua_general.cpp
2024-03-28 20:05:55 -04:00
JJ b946b800fb [Cleanup] Reference type in GetRaidLeaderName (#4218)
Minor cleanup from #4054
2024-03-28 19:15:16 -04:00
Alex King ab8ac81df6 [Bug Fix] Fix Group Leadership (#4214)
* [Bug Fix] Fix Group Leadership

# Notes
- We were not sending anything to `group_leaders` table if we did not already have an existing row.

# Video

* Update database.cpp
2024-03-28 15:33:49 -05:00
Alex King 109940fc0c [Quest API] Add Class/Deity/Race Methods to Perl/Lua (#4215)
# Perl
- Add `$client->GetDeityBitmask()`.
- Add `quest::get_class_bitmask(class_id)`.
- Add `quest::get_deity_bitmask(deity_id)`.
- Add `quest::get_race_bitmask(race_id)`.

# Lua
- Add `client:GetDeityBitmask()`.
- Add `eq.get_class_bitmask(class_id)`.
- Add `eq.get_deity_bitmask(deity_id)`.
- Add `eq.get_race_bitmask(race_id)`.

# Notes
- Allows operators to get the class/deity/race bitmask of a class/deity/race by ID.
- Allows operators to get a client's deity bitmask.
2024-03-28 15:32:02 -05:00
Fryguy a87496b0cf [Lua] Add Zone and Language Constants (#4211)
* [LUA] Add Zone and Language Constants

This will add Zone:

```lua
if eq.get_zone_id() == Zone.Qeynos then
   foo()
end
```

It will also add Language:

```lua
if e.language == Language.ElderElvish and e.other:GetLanguageSkill(Language.ElderElvish) >= 100 then
   e.self:Say("You know my language!", Language.ElderElvish);
end
```

These changes should help avoid magic numbers in quests and aide in readability without the need for -- comments to clarify.

* Adjust to lower case
2024-03-28 13:16:41 -04:00
Alex King f905ee70e4 [Bug Fix] Fix Auto Login Issue (#4213)
* [Bug Fix] Fix Auto Login Issue

# Notes
- We were setting `live_name` value regardless of if we were zoning, causing us to automatically log in to the last character we'd logged in to before.

* Remove &
2024-03-28 09:48:17 -04:00
JJ 52417023f8 [Cleanup] Remove unnecessary reference types (#4212)
Minor clean up from #4054 and #4181
2024-03-27 22:17:21 -04:00
KayenEQ 20d9417628 [Spells] SPA148 Stacking Fix (#4206)
Update to SPA148 which acts to block spells buffs that are of lesser value than the current buff for specific effect slots. This effected was preventing detrimental debuffs from being applied that were using same effect slot. This bug affected a very small amount of spell interactions and was fixed on live in 2018.  Example being Vishmitars Corruption (6642) being blocked by SteelOak Skin (5352)

 I confirmed the behavior on live myself. The detrimental buff  if in conflict should now be applied instead of blocked.
2024-03-27 14:39:40 -04:00
Xackery 4692799677 [Bug Fix] Fix event_consider any_cast error (#4210) 2024-03-27 14:31:38 -04:00
Chris Miles cf7f0f4321 [Skill Caps] Further improvements (#4205) 2024-03-24 13:04:26 -04:00
Chris Miles 823a5956de [Hotfix] Fix crash in SendEnterWorld (#4204) 2024-03-23 23:28:29 -05:00
JJ 6a8bd3c5d6 [Bug Fix] Fix fishing chances (#4203)
Fix regression from #4008 where the item count wasn't being incremented
Move the zone table chance to a rule
General cleanup of some initializers and variable types
2024-03-23 23:32:07 -04:00
Alex King 523ba30d81 [Repositories] Convert database.cpp to Repositories (#4054)
* [Repositories] Convert database.cpp to Repositories

- Convert all database.cpp methods to repositories where possible.

* Final push.

* Cleanup

* Cleanup

* Update database.h

* Fix crash

* Update database.cpp
2024-03-23 19:30:56 -05:00
Alex King d7ea290b6b [Skill Caps] Remove from shared memory and simplify (#4069)
* [Skill Caps] Remove from shared memory and simplify

- Removes Skill Caps loading from shared memory and puts it into zone.
- Adds `id` column to `skill_caps`.
- Remove primary keys and use `id` as primary key.
- Add unique index using `skill_id`, `class_id`, `level`, and `cap`.
- Renames `class` to `class_id` in `skill_caps` table.
- Renames `skillID` to `skill_id` in `skill_caps` table.
- Regenerates Skill Caps repository.
- Adds `#reload skill_caps` to reload skill caps in real time.

* Update groups.cpp

* Update groups.cpp
2024-03-23 18:52:40 -05:00
Alex King 036309ebec [Hot Fix] Hot Fix for Group::AddToGroup Hot Fix (#4202)
# Notes
- Typo in previous.
2024-03-23 18:51:43 -05:00
Alex King b400700d81 [Hot Fix] Fix Group::AddToGroup (#4201)
# Notes
- We were not using `r` values at any point.
2024-03-23 18:49:15 -05:00
Alex King 21cec87ac4 [Bug Fix] Fix Bot/Character ID Overlap in Groups (#4093)
* [Bug Fix] Fix Bot/Character ID Overlap in Groups

- Attempt to fix bot/character ID overlap in groups keeping bots with the same unique identifier as players from not spawning on zone.
- Adds `bot_id` to `group_id` to differentiate bots from characters and hopefully alleviate this issue.

* Update base_group_id_repository.h

* Final push
2024-03-23 17:55:03 -05:00
Alex King abdec39cdd [Quest API] Add Archetype Methods to Perl/Lua (#4181)
* [Quest API] Add Archetype Methods to Perl/Lua

- Add `$mob->GetArchetypeName()`.
- Add `$mob->IsIntelligenceCasterClass()`.
- Add `$mob->IsPureMeleeClass()`.
- Add `$mob->IsWisdomCasterClass()`.

- Add `mob:GetArchetypeName()`.
- Add `mob:IsIntelligenceCasterClass()`.
- Add `mob:IsPureMeleeClass()`.
- Add `mob:IsWisdomCasterClass()`.

- Allows operators to use mob archetypes to perform different operations.
- Add a namespace for archetypes instead of constants.
- Utilize `IsIntelligenceCasterClass()`, `IsPureMeleeClass()`, and `IsWisdomCasterClass()` where necessary.
-

* Update mob.cpp
2024-03-23 14:37:35 -05:00
Fryguy d2372de982 [Bug Fix] Radiant/Ebon Crystals should only extract to 1000 (#4195)
* [Bug] Radiant/Ebon Crystals should only extract to 1000

Creating a stack larger than 1000 can cause potential dupe issues further down the stream if other tasks are performed on the stack.

* Use stacksize instead

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-03-23 12:56:59 -05:00
Chris Miles ea9b7841d4 [Release] 22.48.0 (#4200) 2024-03-23 00:24:01 -05:00
Alex King 8826d7b927 [Rules] Add World:Rules Rule (#4194)
* [Rules] Add World:Rules Rule

# Notes
- Adds `World:Rules` rule to take the place of the variables table value.

* Update client.cpp

* Update client.cpp
2024-03-23 00:01:27 -05:00
JJ e4157f0221 [Bug Fix] Fix reusing timers (#4199)
Fixes regression from #4099 where timers that were reused were not getting changed with their updated times
2024-03-23 00:01:15 -05:00
Alex King 66cc947b2a [Quest API] Add Restore Methods for Health, Mana, and Endurance to Perl/Lua (#4179)
* [Quest API] Add Restore Methods for Health, Mana, and Endurance to Perl/Lua

- Add `$mob->RestoreEndurance()`.
- Add `$mob->RestoreHealth()`.
- Add `$mob->RestoreMana()`.

- Add `mob:RestoreEndurance()`.
- Add `mob:RestoreHealth()`.
- Add `mob:RestoreMana()`.

- Allows operators to easily restore a mob to full health, mana, or endurance.
- `RestoreHealth` is just a more verbosely named `Heal`.
- Convert spots in source to use these short hands instead of directly using `SetEndurance(GetMaxEndurance())`, `SetHP(GetMaxHP())`, or `SetMana(GetMaxMana())`.

* Update mob.h

* Update mob.h
2024-03-22 23:53:35 -05:00
hg 5bfd8f5da2 [Tradeskills] Implement learning recipes from books (#4170)
This uses the book scribe button to learn recipes in SoF+ clients. For
Titanium clients the button is not available so a workaround will need
to be added later.

Note live gives no feedback when scribing books (at least those tested).
2024-03-22 23:50:06 -05:00
Chris Miles 96830b4a19 [Loot] Fix issue with nested data being loaded multiple times (#4192)
* [Loot] Fix issue with nested data being loaded multiple times

* Update zone_loot.cpp

* Fix #lootsim printout

* Update loot.cpp
2024-03-22 23:49:23 -05:00
Alex King 4bf60a6522 [Bug Fix] Fix ScaleNPC() in Perl (#4196)
# Notes
- We were not passing `override_special_abilities` in the right parameter slot.
- Default `always_scale` to `true` when using the Perl/Lua method.
2024-03-22 23:36:30 -05:00
JJ 16cb7364e8 [Misc] Windows preprocessor define in crash.cpp (#4191) 2024-03-22 23:27:31 -05:00
Alex King f5050ab5dc [Bug Fix] Fix range_percent (#4197)
# Notes
- This was uninitialized and was getting bogus values.
2024-03-22 16:17:38 -04:00
Alex King e32cbf19ee [Bug Fix] Fix #serverrules Command (#4193)
* [Bug Fix] Fix #serverrules Command

# Notes
- This command was effectively disabled as it was not included nor was the command itself defined within a `command_add`

* Update command.cpp
2024-03-20 03:31:49 -04:00
Alex King ee12a7ad2e [Bug Fix] Fix EVENT_KILLED_MERIT firing before NPC removal (#4185)
* [Bug Fix] Fix EVENT_KILLED_MERIT firing before NPC removal

# Notes
- NPCs were parsing this event too early and anything that checked if they were still alive in `EVENT_KILLED_MERIT` would show them still alive because of this.

# Image

* Code cleanup

* Update client.h

* Add GetRaidOrGroupOrSelf() to Perl/Lua

* Update to luabind::object, fix logic per comments.

* Fix

* Fix per comments.
2024-03-17 17:32:44 -04:00
Alex King e5bdbc4f1e [Bug Fix] Fix Bot Cloning (#4186)
# Notes
- We were not setting `inventories_index` to `0` so it was trying to use the pre-existing unique identifier, causing the query to fail.
2024-03-16 23:09:57 -04:00
Alex King f829a99e6d [Quest API] Add RemoveAlternateCurrencyValue() to Perl/Lua (#4190)
# Perl
- Add `$client->RemoveAlternateCurrencyValue(currency_id, amount)`.

# Lua
- Add `client:RemoveAlternateCurrencyValue(currency_id, amount)`.

# Notes
- Allows operators to more easily remove alternate currencies, returns a `bool`, `false` if failed`, `true` if succeeded.
- Added `Zone::DoesAlternateCurrencyExist` that will reject setting, removing, or adding  to a currency that does not exist.
2024-03-16 23:09:51 -04:00
Alex King 82aa6a1587 [Bug Fix] Fix Proximity Say (#4189)
# Notes
- Without setting `HaveProximitySays` to `true` along with if `n->proximity->say` NPCs will not respond to proximity say stuff.
2024-03-14 20:26:30 -04:00
Alex King 161c13f457 [Quest API] Add Buff Support to Perl/Lua (#4182)
* [Quest API] Add Buff Support to Perl/Lua

- Add `$mob->GetCasterID()`.
- Add `$mob->GetCasterLevel()`.
- Add `$mob->GetCasterName()`.
- Add `$mob->GetCastOnX()`.
- Add `$mob->GetCastOnY()`.
- Add `$mob->GetCastOnZ()`.
- Add `$mob->GetCounters()`.
- Add `$mob->GetDOTRune()`.
- Add `$mob->GetExtraDIChance()`.
- Add `$mob->GetInstrumentModi()`.
- Add `$mob->GetMagicRune()`.
- Add `$mob->GetMeleeRune()`.
- Add `$mob->GetNumberOfHits()`.
- Add `$mob->GetRootBreakChanc()`.
- Add `$mob->GetSpellID()`.
- Add `$mob->GetTicsRemaining()`.
- Add `$mob->GetVirusSpreadTim()`.
- Add `$mob->IsCasterClient()`.
- Add `$mob->IsPersistentBuff()`.
- Add `$mob->SendsClientUpdate()`.

- Add `mob:GetCasterID()`.
- Add `mob:GetCasterLevel()`.
- Add `mob:GetCasterName()`.
- Add `mob:GetCastOnX()`.
- Add `mob:GetCastOnY()`.
- Add `mob:GetCastOnZ()`.
- Add `mob:GetCounters()`.
- Add `mob:GetDOTRune()`.
- Add `mob:GetExtraDIChance()`.
- Add `mob:GetInstrumentModi()`.
- Add `mob:GetMagicRune()`.
- Add `mob:GetMeleeRune()`.
- Add `mob:GetNumberOfHits()`.
- Add `mob:GetRootBreakChanc()`.
- Add `mob:GetSpellID()`.
- Add `mob:GetTicsRemaining()`.
- Add `mob:GetVirusSpreadTim()`.
- Add `mob:IsCasterClient()`.
- Add `mob:IsPersistentBuff()`.
- Add `mob:SendsClientUpdate()`.

- Adds support for `Buffs_Struct` to Perl/Lua.
- Allows operators to read a mob's buff data directly to determine caster, melee rune, etc.

* Fix GetCasterID() to proper data type.

* Remove Lua_Buffs, return table instead.

* Cleanup
2024-03-13 23:38:15 -04:00
Alex King b29c26becb [Bug Fix] Fix GetLeaderName() for Groups (#4184)
* [Bug Fix] Fix GetLeaderName() for Groups

# Notes
- We were getting bogus data in this.
- Made it its own method.

* Remove ExpeditionRequest::GetGroupLeaderName()
2024-03-13 21:52:02 -04:00
Alex King e48dae2392 [Quest API] Add Silent Saylink Methods to Perl/Lua (#4177)
# Perl
- Add `quest::silent_saylink(text)`.
- Add `quest::silent_saylink(text, link_name)`.

# Lua
- Add `eq.silent_say_link(text)`.
- Add `eq.silent_say_link(text, link_name)`.

# Notes
- Allows operators to more easily use silent saylinks without an optional silent parameter in the traditional saylink methods.
- Sets `silent` parameter default to `false` so we do not need to pass `false` when we are not using a a silent saylink.
- Changes all places that used `EQ::SayLinkEngine::GenerateQuestSaylink` to `Saylink::Create` where possible.
- Removed `questmgr` method that is no longer necessary.
- Cleaned up Lua methods to use the strings directly instead of building one out.
2024-03-13 20:27:44 -04:00
Alex King 4b83a96f64 [Bug Fix] Fix Empty Groups When Removing Bots (#4178)
# Notes
- We were checking for the incorrect value, meaning you could end up in an empty group.
2024-03-13 20:27:38 -04:00
Alex King 95cc22ffbb [Quest API] Add GetDeityName() to Perl/Lua (#4180)
# Perl
- Add `$mob->GetDeityName()`.

# Lua
- Add `mob:GetDeityName()`.

# Notes
- Allows operators to get a mob's deity name.
2024-03-13 20:27:31 -04:00
nytmyr 6ca11256c6 [Bots] IsValidTarget Crash Fix (#4187)
* [Bots] IsValidTarget crash fix

This addresses crashes related to IsValidTarget on multiple servers.

Unsure of the exact reason if anyone can explain why changing from const bool to bool in this situation fixes the problem.

Is it because the const is somehow crashing on a bad pointer or is it attempting to be force changed?

* Update bot.cpp

---------

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2024-03-12 12:34:27 -04:00
Alex King d94493468c [Bug Fix] Fix Mob::CalculateDistance(mob) Typo (#4183)
# Notes
- Was using `GetX()` for all parts of the calculation, meaning it would produce incorrect values.
- Part of [this](https://github.com/EQEmu/Server/pull/3455/files#diff-94a8e3b04f001e4f74ce2da8404cbce7653146d963a3b93be6536505035ce96dR602-R607).
2024-03-09 22:20:02 -05:00
Alex King 957b4f8821 [Bug Fix] Fix Crash in ClientList::GetCLEIP (#4173)
* [Bug Fix] Fix Crash in ClientList::GetCLEIP

# Notes
- We were not validating pointer when moving to next iterator.

# Crashes
https://spire.akkadius.com/dev/release/22.46.1?id=19955
https://spire.akkadius.com/dev/release/22.46.1?id=19948
https://spire.akkadius.com/dev/release/22.46.0?id=19945

* Update clientlist.cpp

* Update clientlist.cpp
2024-03-09 19:47:58 -05:00
Alex King 5013459824 [Hot Fix] Add bool return to fix Client::RemoveAAPoints (#4176)
# Notes
- Was missing the `return true;` at the bottom.
2024-03-09 10:07:13 -05:00
Alex King 94af2843e3 [Cleanup] Cleanup Zone Get Methods (#4169)
# Notes
- Utilize `GetZoneVersionWithFallback` to shorten methods and reduce duplicate code.
2024-03-08 21:22:11 -05:00
Alex King 3bfb148bdc [Quest API] Add RemoveAAPoints() and AA Loss Event to Perl/Lua (#4174)
* [Quest API] Add RemoveAAPoints() and AA Loss Event to Perl/Lua

# Perl
- Add `$client->RemoveAAPoints(points)`.
- Add `EVENT_AA_LOSS`, exports `$aa_lost`.

# Lua
- Add `client:RemoveAAPoints(points)`.
- Add `event_aa_loss`, exports `e.aa_lost`.

# Notes
- Allows operators to more easily remove AA Points.
- Has a bool return type that will return false if the player does not have enough AA Points to complete the removal.

* Update client.cpp
2024-03-08 21:20:33 -05:00
MortimerGreenwald 96370e0298 [Bug Fix] An Update to Xtarget to exclude Bot owned Temp/Swarm Pets (#4172)
* An Update to Xtarget to exclude Bot owned Temp/Swarm Pets

* Missing a parentheses

* Cleaned up logic.
2024-03-08 15:29:53 -05:00
nytmyr fef5108b0d [Bots] Move BotGroupSay to Pet Response (#4171)
* [Bots] Move BotGroupSay messages to PetResponse filter to reduce spam

* Cleanup raid checks

* Group cleanup
2024-03-08 11:46:50 -05:00
Alex King 6f883566f6 [Bug Fix] Fix Default Value in rule_values table (#4166)
# Notes
- Some versions of SQL do not allow a default value for text fields.
2024-03-07 16:41:41 -05:00
nytmyr 45b1501c8a [Quest API] Add DeleteBot() to Perl/Lua (#4167)
### Perl
- Add $bot->DeleteBot().
```
sub EVENT_SAY {
	if ($text =~/#deletebot/i && $client->Admin() >= 100) {
		my @bot_list = $entity_list->GetBotList();

		foreach $ent (@bot_list) {
			if ($ent) {
				quest::shout("Deleting " . $ent->GetCleanName());
				$ent->DeleteBot();
				$ent->Camp(0);
			}
		}
	}
}
```
### Lua
- Add bot:DeleteBot().
```
function event_say(e)
	if(e.message:findi("#deletebot")) then
		local bot_list = eq.get_entity_list():GetBotList();

		for ent in bot_list.entries do
			if (ent) then
				e.self:Message(7,"Deleting " .. ent:GetCleanName() .. "");
				ent:DeleteBot();
				ent:Camp(false);
			end
		end
	end
end
```
### Notes
- Allows operators to delete bots.
2024-03-07 06:08:17 -05:00
Akkadius 7e94f0ac72 [Release] 22.47.0 2024-03-05 22:18:16 -06:00
Chris Miles 2aa19f4cae [Release] 22.47.0 (#4164) 2024-03-05 22:04:35 -06:00
Mitch Freeman 805829f15d [Crash Fix] Added a guild_mgr check (#4163)
* CrashFix and Cleanup

* Formatting, add safe_delete

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-03-05 22:00:08 -06:00
Alex King 2c2a8cdb63 [Bug Fix] Fix Character EXP Modifiers default (#4161)
# Notes
- The `-1.0f` was causing these modifiers to be set to `0.0` and when people would enable them they would get no experience.
- We now use the zone based grabbed methods when setting which will default to a value of `1.0f` if there is not a value found.
2024-03-05 21:54:07 -06:00
Chris Miles ee3d02bac6 [Zoning] Zone routing adjustment (#4162) 2024-03-05 21:53:07 -06:00
Alex King b90139bd9a [Feature] Adjust String-based Rules Length (#4138) 2024-03-05 21:52:34 -06:00
catapultam-habeo e6a3d5e1c5 [Bug Fix] Prevent NPE when creating DZ using ad-hoc version IDs (#4141)
* initial commit

* corrected based on hgtw feedback
2024-03-05 18:21:04 -05:00
Alex King 74f1eac401 [Bug Fix] Fix Spawns Not Parsing Quest on Zone Bootup (#4149)
* Update zone.cpp

* Fix

---------

Co-authored-by: Natedog2012 <jwalters_06@yahoo.com>
2024-03-05 18:20:42 -05:00
JJ 1be9b2cdfd [Bug Fix] Fix typo when updating spawn events in spawn condition manager (#4160) 2024-03-05 05:44:38 -05:00
Mitch Freeman add0a8dddf [Bug Fix] Add id to the guild_bank table (#4155)
* Add id to guild_bank table

Add id as a primary key to guild_bank

* Remove content schema update flag
2024-03-04 19:02:35 -05:00
catapultam-habeo 8c226054e7 [Feature] Adds rules to control level requirements for Double Backstab, Assassinate, and Double Bowshot (#29) (#4159)
Co-authored-by: mute <natanx@gmail.com>
2024-03-04 18:41:25 -05:00
Mitch Freeman b4605f77e3 [Crash Fix] Goto Command could crash using Developer Tools (#4158) 2024-03-03 22:33:12 -05:00
Mitch Freeman 74a63daf7e [Crash Fix] Groundspawn Memory Corruption (#4157) 2024-03-03 22:32:29 -05:00
Alex King 8ee7910569 [Quest API] Add IsAlwaysAggro() to Perl/Lua (#4152)
- Add `$mob->IsAlwaysAggro()`.

- Add `mob:IsAlwaysAggro()`.

- Allows operators to determine if a mob is set to always aggro.
2024-03-03 20:40:20 -05:00
Alex King b766a79c11 [Quest API] Add GetHeroicStrikethrough() to Perl/Lua (#4150)
- Add `$mob->GetHeroicStrikethrough()`.

- Add `mob:GetHeroicStrikethrough()`.

- Allows operators to get a mob's Heroic Strikethrough.
2024-03-03 13:05:01 -05:00
Alex King 5e3b6d363a [Quest API] Add IsBoat()/IsControllableBoat() to Perl/Lua (#4151)
- Add `$mob->IsBoat()`.
- Add `$mob->IsControllableBoat()`.

- Add `mob:IsBoat()`.
- Add `mob:IsControllableBoat()`.

- Allows operators to determine if a mob is a boat or a controllable boat.
2024-03-03 12:34:21 -05:00
Alex King b2fc59878a [Quest API] Add IsDestructibleObject() to Perl/Lua (#4153)
# Perl
- Add `$mob-.IsDestructibleObject()`.

# Lua
- Add `mob:IsDestructibleObject()`.

# Notes
- Allows operators to determine if a mob is a destructible object.
2024-03-03 11:43:54 -05:00
JJ 4896688ac5 [Release] 22.46.1 (#4148)
### Fixes

* Change `UnburyCorpse` to use repository methods ([#4147](https://github.com/EQEmu/Server/pull/4147)) @joligario 2024-03-03
2024-03-02 19:56:29 -05:00
JJ 0385ed8526 [Bug Fix] Change UnburyCorpse to use repository methods (#4147) 2024-03-02 19:23:43 -05:00
Chris Miles 9974aaff57 [Release] 22.46.0 (#4146) 2024-03-02 15:21:32 -06:00
Chris Miles b6c3e549da [Zone] Zone Routing Improvements (#4142)
* Routing changes

* Update world_content_service.cpp

* Cleanup routing logic

* Tweaks
2024-03-02 15:19:42 -06:00
Alex King 70ee95efc0 [Quest API] Add Bot Special Attacks for Immune Aggro/Damage (#4108)
* [Quest API] Add Bot Special Attacks for Immune Aggro/Damage

# Notes
- Adds `IMMUNE_AGGRO_BOT` and `IMMUNE_DAMAGE_BOT` for uses in special abilities.

* Cleanup

* Update attack.cpp
2024-03-02 15:19:31 -06:00
Alex King 1d38e473d7 [Bug Fix] GetBotNameByID Temporary Reference Warning (#4145)
# Notes
- We were getting a warning for returning `std::string()` from this method as it's a temporary reference.
- Change from `const std::string&` to `const std::string` to avoid this.
```
/home/eqemu/source/zone/bot_database.cpp: In member function ‘const std::string& BotDatabase::GetBotNameByID(uint32)’:
/home/eqemu/source/zone/bot_database.cpp:2374:25: warning: returning reference to temporary [-Wreturn-local-addr]
 2374 |         return e.bot_id ? e.name : std::string();
```
2024-03-02 15:18:57 -06:00
Alex King 1aa3a4b11a [Bug Fix] Fix Bots/Bot Pets ending up on XTargets (#4132)
* [XTargets]

* Update eqemu_logsys.h

* Update client.cpp

* Update table column

* Undo unnecessary commit
2024-03-02 15:18:37 -06:00
Mitch Freeman 398ecbc8cf [Bug Fix] Update FreeGuildID Routine (#4143)
Updates the routine to determine a free guild id on guild creation
2024-03-02 15:17:28 -06:00
Mitch Freeman c4613e1b0f [Crash Fix] Update to location of qGlobals initialization (#4144) 2024-03-02 15:16:51 -06:00
catapultam-habeo 3003a59955 [Feature] Exempt a zone from IP-limit checks. (#4137)
* Exempt zone from IP checks

* [Feature] Add Support for String-based Rules

# Notes
- Add support for string-based rules.

# Images

* convert to comma-seperated list

* Forgot to convert the zone to a string

* Update lua_general.cpp

* fixed rule name

* use the local string methods instead

* I think this will work as desired without the extra condition

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2024-03-01 23:11:34 -05:00
Paul Coene 0c582cc4f9 [Bug Fix] Cleanup NPC Mana Tap Logic (#4134)
* [Bug Fix] Cleanup NPC Mana Tap Logic

Mana Tap rule logic was invalid - Cleaned up and simplified, either we care about npc mana or we dont.

* Updated for bypass all rule

* Change so melee targets get blocked even with requiremana rule off

---------

Co-authored-by: Trust <fryguy503@gmail.com>
2024-03-01 22:48:50 -05:00
Mitch Freeman 69c42510ca [Crash Fix] Raid::UpdateGroupAAs (#4139)
Added checks to potentially resolve a crash situation with raids and group AAs.
2024-03-01 22:46:16 -05:00
JJ 79c8858ec8 [Bug Fix] Use std::clamp for Mob::ChangeSize (#4140)
Helper template was not deducing float for lower/upper values allowing invalid sizes
Limit to sane values of 1-255 unrestricted and 3-15 for clients and pets
2024-03-01 22:46:00 -05:00
Alex King c3d8d423fe [Commands] Add #fish Command (#4136)
* [Commands] Add #fish Command

# Notes
- Adds `#fish` command.
- Allows operators to simulate fishing to see what they would get, consumes no bait.

* `use_bait`

* Update fish.cpp
2024-02-29 21:24:16 -05:00
Alex King 1cbda61891 [Bug Fix] Fix issue with NPC Secondary Textures (#4129)
* [Bug Fix] Fix issue with NPC heads

# Notes
- We were overwriting head material within this secondary loop which caused NPC's heads to show their body texture in some places or no texture if their `showhelm` was not flagged.

# Images

* Update mob.cpp

* Update mob.cpp

* Update mob.cpp
2024-02-29 20:45:54 -05:00
JJ 8d12a5b1b1 [Release] 22.45.1 (#4135)
### Character Creation

* Improved Random Name Generator ([#4081](https://github.com/EQEmu/Server/pull/4081)) @catapultam-habeo 2024-02-27

### Code

* Fix Server Rules Documentation Generation ([#4125](https://github.com/EQEmu/Server/pull/4125)) @Kinglykrab 2024-02-26
* Remove unnecessary stoptimer logs ([#4128](https://github.com/EQEmu/Server/pull/4128)) @Kinglykrab 2024-02-28

### Commands

* Add `#forage` command ([#4133](https://github.com/EQEmu/Server/pull/4133)) @joligario 2024-02-29

### Crash

* Fix crash issue during database dump ([#4127](https://github.com/EQEmu/Server/pull/4127)) @Akkadius 2024-02-29

### Crash Fix

* D20 crash if mitigation average resulted in 0 ([#4131](https://github.com/EQEmu/Server/pull/4131)) @nytmyr 2024-02-29

### Fixes

* Fix forage returning first result from table ([#4130](https://github.com/EQEmu/Server/pull/4130)) @nytmyr 2024-02-29
* Who /all displays incorrect guild name ([#4123](https://github.com/EQEmu/Server/pull/4123)) @neckkola 2024-02-25

### Quest API

* Add Pet Owner Methods to Perl/Lua ([#4115](https://github.com/EQEmu/Server/pull/4115)) @Kinglykrab 2024-02-25
2024-02-29 18:22:40 -05:00
JJ 182327b385 [Commands] Add #forage command (#4133) 2024-02-28 20:43:14 -05:00
Chris Miles aa0ca88d9d [Crash] Fix crash issue during database dump (#4127) 2024-02-28 20:36:06 -05:00
nytmyr 103a37e762 [Crash Fix] D20 crash if mitigation average resulted in 0 (#4131) 2024-02-28 20:35:56 -05:00
nytmyr 34f19489d0 [Hotfix] Fix forage returning first result from table (#4130)
Forage was not properly incrementing the total chance of items when more than one was found and would result in the final chance roll being based off the last item found rather than the total. This would cause the first item returned to be chosen in most cases when the chances are the same in the table.
2024-02-28 20:34:40 -05:00
Alex King c001060429 [Cleanup] Remove unnecessary stoptimer logs (#4128)
# Notes
- These logs were for testing and are unnecessary.
- They cause a lot of spam for servers using `Info` logs.
2024-02-27 21:35:51 -05:00
catapultam-habeo 89be55254e [Character Creation] Improved Random Name Generator (#4081)
* test against vanilla branch

* use existing methods to validate name instead of raw sql

* Revert "use existing methods to validate name instead of raw sql"

This reverts commit 43750c6f4f.

* ReserveName doesn't work like that. Oops. Well, check against Name Filter at least.

* That db access condition was wrong.

* that isn't how CheckNameFilter works, either.

* apply editorconfig w/ trivial change

* Actually apply editorconfig changes.
2024-02-26 23:15:40 -06:00
Alex King 2da6190950 [Cleanup] Fix Server Rules Documentation Generation (#4125)
# Notes
- These spaces prevented the docs server rules generator from parsing these rules.
2024-02-26 18:36:12 -05:00
Mitch Freeman d5e024cc02 [Bug Fix] Who /all displays incorrect guild name (#4123)
Issue: guild creation routine does not update world memory holding guild details until the player zones.

Between the creation of a new guild, and a guild member zones, a /who all displays 'Invalid Guild' instead of the actual guild name.
2024-02-25 18:14:28 -05:00
Alex King 35fe38cd09 [Quest API] Add Pet Owner Methods to Perl/Lua (#4115)
* [Quest API] Add Pet Owner Methods to Perl/Lua

- Add `$mob->IsPetOwnerBot()`.
- Add `$mob->IsPetOwnerClient()`.
- Add `$mob->IsPetOwnerNPC()`.

- Add `mob:IsPetOwnerBot()`.
- Add `mob:IsPetOwnerClient()`.
- Add `mob:IsPetOwnerNPC()`.

- Allows operators to use these short hands instead of doing a `GetOwner() && GetOwner()->IsClient()`.

* Update npc.cpp
2024-02-25 00:38:34 -05:00
Chris Miles eb3664a444 [Release] 22.45.0 (#4121) 2024-02-24 23:06:37 -06:00
Alex King a244509d63 [Quest API] Export Combat Record to Death Events (#4112)
# Perl
- Add `$combat_start_time`, `$combat_end_time`, `$damage_received`, and `$healing_received` to death events for NPCs.

# Lua
- Add `e.combat_start_time`, `e.combat_end_time`, `e.damage_received`, and `e.healing_received` to death events for NPCs.

# Notes
- Allows operators to hook in to the combat record logic so they can log the start and end of combat as well as the damage/healing received over the course of the fight.
2024-02-24 22:57:49 -06:00
Alex King 873c128f46 [Bug Fix] Fix Bot Weapons with No Races (#4110)
# Notes
- Bot weapons that have no races were not causing damage and saying the target was invulnerable because we were not checking the `Bots:AllowBotEquipAnyRaceGear` rule.
2024-02-24 22:55:40 -06:00
Alex King 8314f2348c [Quest API] Add Bot Methods to Perl/Lua (#4113)
* [Quest API] Add Bot Methods to Perl/Lua

# Perl
- Add `quest::GetBotClassByID(bot_id)`.
- Add `quest::GetBotGenderByID(bot_id)`.
- Add `quest::GetBotIDsByCharacterID(character_id)`.
- Add `quest::GetBotIDsByCharacterID(character_id, class_id)`.
- Add `quest::GetBotLevelByID(bot_id)`.
- Add `quest::GetBotNameByID(bot_id)`.
- Add `quest::GetBotRaceByID(bot_id)`.

# Lua
- Add `eq.get_bot_class_by_id(bot_id)`.
- Add `eq.get_bot_gender_by_id(bot_id)`.
- Add `eq.get_bot_ids_by_character_id(character_id)`.
- Add `eq.get_bot_ids_by_character_id(character_id, class_id)`.
- Add `eq.get_bot_level_by_id(bot_id)`.
- Add `eq.get_bot_name_by_id(bot_id)`.
- Add `eq.get_bot_race_by_id(bot_id)`.

# Notes
- Allows operators to get a list of a player's bot IDs, get a bot's class, gender, level, name, and race.

* Update bot_database.cpp
2024-02-24 22:53:21 -06:00
Alex King 29720f95ed [Quest API] Add GetAugmentIDs() to Perl/Lua (#4114)
# Perl
- Add `$questitem->GetAugmentIDs()`.

# Lua
- Add `iteminst:GetAugmentIDs()`.

# Notes
- Allows operators to get a list of augment IDs from an item instance directly without using the inventory method.
2024-02-24 22:52:07 -06:00
Alex King a478fd2600 [Quest API] Add GetNPCSpellsEffectsID() to Perl/Lua (#4117)
# Perl
- Add `$npc->GetNPCSpellsEffectsID()`.

# Lua
- Add `npc:GetNPCSpellsEffectsID()`.

# Notes
- Allows operator's to get an NPC's spell effects ID.
2024-02-24 22:51:37 -06:00
Alex King f57c37e9c5 [Quest API] Add Pet Methods to Perl/Lua (#4116)
* [Quest API] Add Pet Methods to Perl/Lua

# Perl
- Add `$mob->IsAnimation()`.
- Add `$mob->IsCharmed()`.
- Add `$mob->IsFamiliar()`.
- Add `$mob->IsTargetLockPet()`.

# Lua
- Add `mob:IsAnimation()`.
- Add `mob:IsCharmed()`.
- Add `mob:IsFamiliar()`.
- Add `mob:IsTargetLockPet()`.

# Notes
- These methods were not exported and could be useful for operators.

* Update perl_mob.cpp
2024-02-24 22:51:21 -06:00
Mitch Freeman b9fb4babba [Guilds] Fixes for Guild Bank (#4120)
Updates guild bank functionality
- Allows QTY 100 in guild bank
- Removes bug when deposit area is full and a UF or RoF2 client attempts to deposit another item
- Attempt to deposit a nodrop item in RoF2 creates a dupe situation
2024-02-24 22:50:14 -06:00
Mitch Freeman c2e4082045 [Bug Fix] Crash on Ubuntu 22.04 (#4119)
Ubuntu 22.04 as of Feb 25 2024 was crashing when sending guild tributes on zone in.  Issue was caused by an overrun on string copies.
Updated to use strn0cpy, crash was resolved.
2024-02-24 22:46:42 -06:00
Paul Coene e1dee55ecd [Beacon] Revert a few lines of PR #4024 that broke beacons (#4118) 2024-02-24 16:18:17 -05:00
JJ 1632ff04b0 [Repositories] Update zone base repository from #4084 (#4111) 2024-02-22 21:39:31 -05:00
Fryguy 873209dbc0 [Bug Fix] Fix hotzone string error (#4109)
The Strings entry was from a newer client. Moved text to a raw message.
2024-02-22 17:15:22 -05:00
Mitch Freeman a00b2eb382 [Bug Fix] Added additional Guild-related crash checks (#4105) 2024-02-21 19:44:05 -05:00
Alex King 67d8250b1c [Quest API] Add Hatelist Count Methods to Perl/Lua (#4106)
# Perl
- Add `$mob->GetHateListCount()`.# Perl
- Add `$mob->GetHateListCount()`.
- Add `$mob->GetHateListBotCount()`.
- Add `$mob->GetHateListClientCount()`.
- Add `$mob->GetHateListNPCCount()`.

# Lua
- Add `mob:GetHateListCount()`.
- Add `mob:GetHateListBotCount()`.
- Add `mob:GetHateListClientCount()`.
- Add `mob:GetHateListNPCCount()`.

# Notes
- Allows operators to more easily get a total entity count of a Mob's hate list, can do an overall count, or specifically bots, clients, or NPCs.
2024-02-20 22:39:57 -06:00
Alex King f505c2cfd2 [Feature] Add Augments to Starting Items for Bots/Players (#4100)
* [Feature] Add Augments to Starting Items for Bots/Players

- Adds support for augments to `bot_starting_items` and `starting_items`.
- Will allow operators to kit bots/players out with augmented gear from the start if they so choose.

* Update database_update_manifest.cpp

* Update client.cpp
2024-02-20 22:23:22 -06:00
Fryguy a221e50cc2 [Bug Fix] Add safety check to SummonAllCharacterCorpses. (#4107)
Should prevent an empty vector from being passed to the repository.
2024-02-20 22:21:56 -06:00
JJ 32c5d4d9f6 [Database] Add content_database flag for zone changes (#4104) 2024-02-20 18:03:12 -05:00
Paul Coene ce4716e9a5 [Factions] Fix issue with npcedit and cached factions (#4103)
* [Factions] Fix issue with npcedit and cached factions

* Load no matter what
2024-02-20 17:47:44 -05:00
JJ a99ce4fbdb [Bug Fix] Revert 2df7d19 (#4101)
* [Bug Fix] Revert https://github.com/EQEmu/Server/commit/2df7d19f975cb21dd4eb7d6c7d40656cf58ed138
This change breaks lich-type spells as seen in #4098. Per comment on original change, also don't see where Runes come into play.

* Revert invis change

* [Bug Fix] Correct Rune damage check location for invis break.

Correct the location of the CommonBreakInvis for runes. Appologize for the incorrect location. Thank you JJ for pointing me to the PR that caused the issue.

---------

Co-authored-by: Trust <fryguy503@gmail.com>
2024-02-19 22:35:32 -06:00
JJ dcfc54d408 [Logs] Fix log in BaseGuildManager::IsGuildLeader() (#4102)
Looks like typos created invalid escapes
2024-02-19 22:34:52 -06:00
Alex King c13ec5a06d [Repositories] Cleanup and Convert Character Creation to Repositories (#4053)
* [Repositories] Cleanup and Convert Character Creation to Repositories

# Notes
- Converts `Database::GetCharacterID()`, `Database::SaveCharacterCreate()`, and `Client::OPCharCreate` to repositories.
- Cleanup a spot we were doing a queries in a loop.

* Cleanup

* Update database.cpp

* Update database.cpp
2024-02-19 20:45:18 -06:00
Chris Miles d182fc3613 [Expansions] Zone Expansion Version Routing (#4084)
* Expansion version routing

* CheckForImproperContentFiles rule

* Update world_content_service.cpp

* Update client.cpp

* Update client.cpp

* Update CheckForImproperContentFiles

* Remove nek pok check

* Remove file checking

* Remove

* Command and dev tools menu tweaks

* Update world_content_service.cpp

* Update world_content_service.cpp

* Update version path

* Update content_filter_criteria.h

* Update content_filter_criteria.h

* Update quest_parser_collection.cpp

* Update comments

* PR feedback

* Update client_packet.cpp

* Remove notes column for display cleanliness
2024-02-19 20:35:17 -06:00
Alex King 5a89fcfb78 [Quest API] Add Entity Variable Events to Perl/Lua (#4092)
* [Quest API] Add Entity Variable Events to Perl/Lua

- Add `EVENT_ENTITY_VARIABLE_DELETE`.
- Add `EVENT_ENTITY_VARIABLE_SET`.
- Add `EVENT_ENTITY_VARIABLE_UPDATE`.
- All export `$variable_name` and `$variable_value`.

- Add `event_entity_variable_delete`.
- Add `event_entity_variable_set`.
- Add `event_entity_variable_update`.
- All export `e.variable_name` and `e.variable_value`.

- Allows operators to perform operations when entity variables are cleared, deleted, set, or updated.

* Update mob.cpp

* Cleanup.

* Cleanup

* Update mob.cpp

* Update lua_general.cpp

* Update embparser_api.cpp
2024-02-19 20:34:33 -06:00
Alex King db3601c25c [Quest API] Add Timer Events to Perl/Lua (#4099)
* [Quest API] Add Timer Events to Perl/Lua

# DRAFT

* Cleanup
2024-02-19 03:51:16 -06:00
Alex King 137a9f835a [Quest API] Add spell cast methods to Lua (#4096)
# Notes
- Add `eq.cast_spell(spell_id)` and `eq.self_cast(spell_id)` to Lua.
- Lua did not have a `quest::castspell(spell_id)` or `quest::selfcast(spell_id)` equivalent, so this adds them.
2024-02-19 02:35:30 -06:00
Alex King 4ad46b54df [Bug Fix] Fix Sympathetic Procs for Bots/Mercenariess (#4086)
# Notes
- Bots and Mercenaries were being rejected at the top of this method despite us allowing them to use this method where it's called.
2024-02-19 02:21:47 -06:00
Alex King 3f46210639 [Bots] Cleanup empty bot_commands files (#4095)
* [Bots] Cleanup empty `bot_commands` files

# Notes
- These files were part of the conversion of bot commands to individual files, these commands are part of overarching commands and therefore do not have their own files.
- These were not removed when initially committed.

* Update bot_command.cpp

* Update bot_command.cpp
2024-02-19 02:19:56 -06:00
Alex King 6ec63969bb [Bug Fix] Fix issue with IsEntOnHateList (#4097)
# Notes
- We were not validating pointer in `IsEntOnHateList()`.
2024-02-19 01:52:19 -06:00
JJ 767846f7e5 [Bug Fix] Aura effect spell id from #3964 (#4094)
Auras were trying to cast another aura spell vice the spell effect
2024-02-18 17:13:32 -05:00
Fryguy 04bb9bf39c [Feature] Hot Zone Bonus XP Notice (#4091)
When in Hotzones, a bonus XP notice will let players know the hotzone is enabled.
2024-02-18 11:24:01 -05:00
Mitch Freeman e6df5be1ed [Bug Fix] Update database_schema to add guild_permissions (#4085)
* Update database_schema to add guild_permissions

* Reordered
2024-02-16 18:09:18 -05:00
hg 6bb2f97b74 [Code] Update fmt to 10.2.1 (#4071)
This fixes MSVC compile warnings for stdext::checked_array_iterator
which were deprecated in STL for VS 2022 17.8:

https://github.com/microsoft/STL/wiki/Changelog#vs-2022-178
2024-02-16 00:29:04 -06:00
hg 86f39743fc [Quest API] Add tracebacks to Lua error messages (#4079)
This adds an error msg handler for lua calls to add a stack trace to
error messages. Lua 5.1 does not have luaL_traceback like luajit and lua
5.2+ so debug.traceback() is used directly as the msg handler.

The traceback will add more detail to errors than just logging package
and event names. Exceptions in C++ binds and luabind errors will now
show script context instead of just the error message.

e.g., for a luabind overload error:

  No matching overload found, candidates:
  void signal(int,int,int)
  void signal(int,int)
  stack traceback:
    [C]: in function 'signal'
    quests/arena/player.lua:10: in function 'somefn'
    quests/arena/player.lua:27: in function <quests/arena/player.lua:17>
2024-02-16 00:27:37 -06:00
Alex King 447fc026a8 [Repositories] Convert Zone Flags to Repositories (#4077)
# Notes
- Converts `ClearZoneFlag()`, `LoadZoneFlags()`, and `SetZoneFlag()` to repositories.
2024-02-16 00:27:08 -06:00
Chris Miles 7408df933c [Database] Remove "item_tick" from database schema per https://github.com/EQEmu/Server/pull/3985 (#4083) 2024-02-16 00:23:23 -06:00
JJ 2f59e70c6b [Bug Fix] Fix manifest check on base_data change (#4082) 2024-02-15 19:04:26 -05:00
Alex King eb8514eea8 [Bug Fix] Fix fix_z Query (#4080)
# Notes
- This query was not working properly due to using backticks instead of single quotes.
2024-02-15 11:51:07 -05:00
Alex King f498bac574 [Bug Fix] Fix ObjectContentsRepository using content_db (#4076)
# Notes
- `*this` was using content database, causing this not to work on servers using sharded databases.
2024-02-14 18:34:43 -05:00
Alex King 9a0b3a4c36 [Bug Fix] Fix #wpadd Query (#4078)
# Notes
- `GetNextWaypoint()` was getting a null value and crashing in `Strings::ToInt()`.
2024-02-14 18:28:31 -05:00
Chris Miles 34ea870717 [Opcodes] Fix opcode reloading (#4075) 2024-02-13 19:40:23 -05:00
Alex King d68c1a7a6c [Quest API] Add IsInAGuild() to Perl/Lua (#4066)
# Perl
- Add `$client->IsInAGuild()`.

# Lua
- Add `client:IsInAGuild()`.

# Notes
- Allows operators to more accurately tell if a player is in a group.
- `GuildID()` returns `uint32` max value if the player isn't in a guild so conditions using it must check for a value over a certain point, this is just a bool that simplifies that logic.
2024-02-13 19:27:43 -05:00
Akkadius c50100fcdb [Hotfix] Fix issues where we're using the wrong database pointers 2024-02-12 21:41:52 -06:00
JJ 20cdc1e63d [Release] 22.44.4 (#4074)
### Fixes

* Fix ClearSpawnTimers() ([#4073](https://github.com/EQEmu/Server/pull/4073)) @Kinglykrab 2024-02-13
2024-02-12 20:34:40 -06:00
Alex King 43c7523ee1 [Hotfix] Fix ClearSpawnTimers() (#4073)
# Notes
- This wasn't a part of my other pull request.
- We were clearing `spawn2_list` before using it in `ClearSpawnTimers()`.
2024-02-12 21:12:30 -05:00
JJ e060d97798 [Release] 22.44.3 (#4072)
### Fixes

* Fix Issue with ClearSpawnTimers() ([#4070](https://github.com/EQEmu/Server/pull/4070)) @Kinglykrab 2024-02-13
2024-02-12 19:20:04 -06:00
Alex King 435b6142b8 [Bug Fix] Fix Issue with ClearSpawnTimers() (#4070)
# Notes
- We were using the improper ID for this and not checking if the vector was empty before using.
2024-02-12 20:00:45 -05:00
Chris Miles 508b37dc93 [Release] 22.44.2 (#4068) 2024-02-12 13:43:38 -06:00
Alex King 0adca46a73 [Bots] Remove Alt Combat Functionality (#4067)
* [Bots] Remove Alt Combat Functionality

# Notes
- This functionality needlessly complicates bot targeting logic and causes crashes and unintended behavior for players when accidentally enabled or enabled by default.

* Cleanup
2024-02-12 03:00:11 -06:00
hg e920e35a5c [Cleanup] Use explicit conversions for enum formatting (#4064)
This is prep for updating to fmt 10 which removed implicit conversions
for enums.
2024-02-12 02:58:48 -06:00
Mitch Freeman 20c01ef343 [Fix] Guard against crash condition (#4062) 2024-02-11 18:32:59 -05:00
JJ 1567141c19 [Database] Fix table name in manifest (#4063) 2024-02-11 18:29:05 -05:00
JJ 6bc9bcf15a [Database] Proper default for droptime from object_contents (#4061) 2024-02-11 17:59:48 -05:00
JJ 86a2a86ba8 [Database] Fix default value for time_of_death in character_corpses (#4060)
* [Database] Fix default value for `time_of_death` in `character_corpses`

* Extra `NULL`

* Update repository

* Repositories with updated structure this time
2024-02-11 16:12:07 -05:00
JJ 3e6924d10e [Guilds] Clean up GUILD_RANK_NONE references (#4059)
Should be exhaustive for guild rank values
Cleans up redefinition of `GUILD_RANK_NONE` by including `GUILD_RANK_NONE_TI`
Fixes #4057
2024-02-11 11:58:19 -05:00
Akkadius a27a8adf1e [Release] 22.44.1 2024-02-11 02:46:47 -06:00
Chris Miles 13994fb3e4 [File] Fix File::Exists(file_name) to be resilient to Chinese characters (#4058)
* Update file.cpp

* Update file.cpp

* Update file.cpp

* Update file.cpp

* Update file.cpp

* Update file.cpp

* Update file.cpp

* Update file.cpp

* Final fix
2024-02-11 02:42:25 -06:00
396 changed files with 34041 additions and 14478 deletions
+6
View File
@@ -0,0 +1,6 @@
!Makefile
base/*.sql
base/*.zip
base/db/
base/maps/
!base/expansion/Makefile
@@ -0,0 +1,9 @@
# This is a "dev" image for running eqemu in development, also for dev containers
ARG USERNAME=user-name-goes-here
ARG USER_UID=1000
ARG USER_GID=$USER_UID
FROM --platform=linux/arm64 mcr.microsoft.com/devcontainers/base:debian
RUN sudo apt update && sudo apt install -y --no-install-recommends build-essential libtool cmake curl debconf-utils git libluabind-dev libsodium-dev liblua5.2-0 liblua5.2-dev libmariadb-dev libssl-dev minizip make mariadb-client locales nano open-vm-tools unzip uuid-dev iputils-ping wget libcurl4-openssl-dev gdb libyaml-cpp-dev ccache ninja-build pv mariadb-server libperl-dev libjson-perl libio-stringy-perl liblua5.1-dev libluabind-dev libboost-dev mariadb-server valgrind telnet libgoogle-perftools-dev google-perftools
USER $USERNAME
+9
View File
@@ -0,0 +1,9 @@
# This is a "dev" image for running eqemu in development, also for dev containers
ARG USERNAME=user-name-goes-here
ARG USER_UID=1000
ARG USER_GID=$USER_UID
FROM mcr.microsoft.com/devcontainers/base:debian
RUN sudo apt update && sudo apt install -y --no-install-recommends build-essential libtool cmake curl debconf-utils git libluabind-dev libsodium-dev liblua5.2-0 liblua5.2-dev libmariadb-dev libssl-dev minizip make mariadb-client locales nano open-vm-tools unzip uuid-dev iputils-ping wget libcurl4-openssl-dev gdb libyaml-cpp-dev ccache ninja-build pv mariadb-server libperl-dev libjson-perl libio-stringy-perl liblua5.1-dev libluabind-dev libboost-dev mariadb-server valgrind telnet libgoogle-perftools-dev google-perftools
USER $USERNAME
+284
View File
@@ -0,0 +1,284 @@
NAME := eqemu-server
.ONESHELL:
DOCKER_ARGS := --rm --name ${NAME} -v $$PWD:/src -w /src ${NAME}
DOCKER_ARM64_ARGS := --rm --platform linux/arm64 --name ${NAME}-arm64 -v $$PWD:/src -w /src ${NAME}-arm64
.PHONY: build
build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile build --no-print-directory
exit
endif
cd build$$BUILD_SUFFIX && cmake --build . --config Release --target all --
.PHONY: cmake
cmake:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile cmake --no-print-directory
exit
endif
@echo "working directory: $$PWD"
mkdir -p build$$BUILD_SUFFIX
@cd build$$BUILD_SUFFIX && cmake -DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_TESTS=ON \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja ..
clean:
ifneq (,$(findstring .devcontainer,$$PWD))
@make -C ../ -f .devcontainer/Makefile clean --no-print-directory
endif
rm -rf build
docker-cmake:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-cmake --no-print-directory
exit
endif
@echo "working directory: $$PWD"
git submodule update --init --recursive
docker run ${DOCKER_ARGS} make cmake
docker-build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-build --no-print-directory
exit
endif
docker run ${DOCKER_ARGS} make build
# Build image if it doesn't exist
docker-image-build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-image-build --no-print-directory
exit
endif
ifeq ($(shell docker images -q ${NAME} 2> /dev/null),)
@echo "Docker image not found. Building..."
docker build -f Dockerfile.debian.dev -t ${NAME} .
endif
docker-arm-cmake: docker-arm-image-build
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-arm-cmake --no-print-directory
exit
endif
git submodule update --init --recursive
docker run ${DOCKER_ARM64_ARGS} make cmake BUILD_SUFFIX=arm64
docker-arm-build: docker-arm-image-build
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-arm-build --no-print-directory
exit
endif
docker run ${DOCKER_ARM64_ARGS} make build BUILD_SUFFIX=arm64
docker-arm-image-build:
ifeq ($(shell docker images -q ${NAME}-arm64 2> /dev/null),)
@echo "Docker image not found. Building..."
docker build -f Dockerfile.debian.arm.dev -t ${NAME}-arm64 .
endif
docker-clean: clean
.PHONY: prep
prep:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile prep --no-print-directory
exit
endif
@echo "Preparing build/bin for usage..."
mkdir -p build/bin/assets/patches
cp -R -u -p .devcontainer/base/eqemu_config.json build/bin/eqemu_config.json
cp -R -u -p .devcontainer/base/login.json build/bin/login.json
cp -R -u -p loginserver/login_util/* build/bin/assets/patches/
mkdir -p build/bin/assets
cp -R -u -p utils/patches build/bin/assets/
-unlink build/bin/lua_modules
cd build/bin && ln -s quests/lua_modules lua_modules
-unlink build/bin/mods
cd build/bin && ln -s quests/mods mods
-unlink build/bin/maps
cd build/bin && ln -s ../../base/maps maps
mkdir -p build/bin/logs
mkdir -p build/bin/shared
@echo "Eqemu is prepared. Edit build/bin/eqemu_config.json to configure."
maps:
@echo "Downloading maps..."
@mkdir -p base/maps
@cd base/maps && wget -nc https://github.com/Akkadius/eqemu-maps/archive/refs/heads/master.zip
@cd base/maps && unzip -o master.zip
@cd base/maps && mv eqemu-maps-master/* .
@cd base/maps && rm -rf eqemu-maps-master
@echo "Maps downloaded."
quests:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile quests --no-print-directory
exit
endif
@cd build/bin && git clone https://github.com/ProjectEQ/projecteqquests.git quests
# Runs tests
.PHONY: test
test:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile test --no-print-directory
exit
endif
cd build/bin && ./tests
# Runs login binary
.PHONY: login
login:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile login --no-print-directory
exit
endif
cd build/bin && ./loginserver
# Runs shared_memory binary
.PHONY: shared
shared:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile shared --no-print-directory
exit
endif
cd build/bin && ./shared_memory
# Runs zone binary
.PHONY: zone
zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile zone --no-print-directory
exit
endif
@-rm build/bin/logs/zone/zone*.log
cd build/bin && ./zone
# Runs world binary
.PHONY: world
world:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile world --no-print-directory
exit
endif
@-rm build/bin/logs/world*.log
cd build/bin && ./world
# Runs ucs binary
.PHONY: ucs
ucs:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile ucs --no-print-directory
exit
endif
@-rm build/bin/logs/ucs*.log
cd build/bin && ./ucs
# Runs queryserv binary
.PHONY: queryserv
queryserv:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile queryserv --no-print-directory
exit
endif
@-rm build/bin/logs/query_server*.log
cd build/bin && ./queryserv
valgrind-%:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile valgrind --no-print-directory
exit
endif
cd build/bin && valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=logs/$*.valgrind.log ./$*
# Start mariaDB standalone
.PHONY: mariadb
mariadb:
@sudo service mariadb start
.PHONY: inject-mariadb
inject-mariadb:
-sudo service mariadb start
-mkdir -p base/db/
-sudo mariadb -e 'DROP DATABASE IF EXISTS peq;'
-sudo mariadb -e 'CREATE DATABASE peq;'
-sudo mariadb -e "CREATE USER 'peq'@'127.0.0.1' IDENTIFIED BY 'peqpass';"
-sudo mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'peq'@'127.0.0.1';"
ifeq (,$(wildcard base/db/db.sql.zip))
@echo "base/db.sql.zip not found. Downloading latest from https://db.projecteq.net/"
wget -nc https://db.projecteq.net/latest -O base/db/db.sql.zip
-cd base/db && unzip db.sql.zip
endif
@echo "Sourcing db may take a while, please wait..."
@cd base/db/peq-dump && sudo mariadb --database peq -e "source create_all_tables.sql"
@echo "MariaDB is now injected."
.PHONY: gm-%
gm-%:
sudo mariadb --database peq -e "UPDATE account SET status=255 WHERE name = '$*';"
@echo "Account $* is now a GM. /camp to have it go into effect."
depends:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile depends --no-print-directory
exit
endif
sudo apt install graphviz pip time
pip3 install graphviz
mkdir -p build/depends
@if [ ! -f "build/depends/dependency_graph.py" ]; then \
wget https://raw.githubusercontent.com/pvigier/dependency-graph/master/dependency_graph.py -O build/depends/dependency_graph.py; \
fi
@echo "Generating dependency graphs (This may take a while)..."
@echo "Login..."
time python3 build/depends/dependency_graph.py -f png login build/depends/login.dot
@echo "World..."
time python3 build/depends/dependency_graph.py -f png world build/depends/world.dot
@echo "Zone..."
time python3 build/depends/dependency_graph.py -f png zone build/depends/zone.dot
@echo "Common..."
time python3 build/depends/dependency_graph.py -f png common build/depends/common.dot
backup:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile backup --no-print-directory
exit
endif
@mkdir -p build/bin/backup
cd build/bin && ./world database:dump --compress --player-tables --state-tables --system-tables --query-serv-tables
cpu-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile cpu-zone --no-print-directory
exit
endif
@cd build/bin && mkdir -p tmp
cd build/bin && CPUPROFILE=prof.out ./zone
pprof-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-zone --no-print-directory
exit
endif
cd build/bin && google-pprof --pdf zone prof.out > prof.pdf
pprof-web-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-web-zone --no-print-directory
exit
endif
cd build/bin && google-pprof --web zone prof.out
pprof-gv-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-gv-zone --no-print-directory
exit
endif
cd build/bin && google-pprof --gv zone prof.out > prof.gv
heap-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile heap-zone --no-print-directory
exit
endif
@cd build/bin && mkdir -p tmp
cd build/bin && HEAPPROFILE=prof.out ./zone
+73
View File
@@ -0,0 +1,73 @@
{
"server": {
"zones": {
"defaultstatus": "0",
"ports": {
"low": "7000",
"high": "7400"
}
},
"qsdatabase": {
"host": "127.0.0.1",
"port": "3306",
"username": "peq",
"password": "peqpass",
"db": "peq"
},
"chatserver": {
"port": "7778",
"host": ""
},
"mailserver": {
"host": "",
"port": "7778"
},
"webinterface": {
"port": "9081"
},
"world": {
"longname": "New Devbox",
"address": "192.168.1.100",
"localaddress": "192.168.1.100",
"loginserver1": {
"account": "",
"password": "",
"legacy": 0,
"host": "login.projecteq.net",
"port": "5998"
},
"tcp": {
"ip": "127.0.0.1",
"port": "9001"
},
"telnet": {
"ip": "0.0.0.0",
"port": "9000",
"enabled": "true"
},
"key": "random-generate-here",
"http": {
"port": "9080",
"enabled": "true",
"mimefile": "mime.types"
},
"shortname": "dev"
},
"database": {
"db": "peq",
"host": "127.0.0.1",
"port": "3306",
"username": "peq",
"password": "peqpass"
},
"files": {
"opcodes": "assets/patches/opcodes.conf",
"mail_opcodes": "assets/patches/mail_opcodes.conf"
},
"directories": {
"patches": "assets/patches/",
"opcodes": "assets/patches/",
"plugins": "quests/plugins/"
}
}
}
+37
View File
@@ -0,0 +1,37 @@
{
"database": {
"host": "127.0.0.1",
"port": "3306",
"db": "peq",
"user": "peq",
"password": "peqpass"
},
"account": {
"auto_create_accounts": true
},
"worldservers": {
"unregistered_allowed": true,
"reject_duplicate_servers": false
},
"web_api": {
"enabled": true,
"port": 6000
},
"security": {
"mode": 14,
"allow_password_login": true,
"allow_token_login": true
},
"logging": {
"trace": false,
"world_trace": false,
"dump_packets_in": false,
"dump_packets_out": false
},
"client_configuration": {
"titanium_port": 5998,
"titanium_opcodes": "assets/patches/login_opcodes.conf",
"sod_port": 5999,
"sod_opcodes": "assets/patches/login_opcodes_sod.conf"
}
}
+49
View File
@@ -0,0 +1,49 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu
{
"name": "eqemu",
"build": {
"dockerfile": "Dockerfile.debian.dev"
},
"appPort": [
"5998:5998/udp",
"7000:7000/udp",
"7001:7001/udp",
"7002:7002/udp",
"7003:7003/udp",
"7004:7004/udp",
"7005:7005/udp",
"9000:9000/udp",
"9001:9001/udp"
],
"forwardPorts": [
3306
],
"remoteEnv": {
"LOCALWSF": "${localWorkspaceFolder}",
"CONTAINERWSF": "${containerWorkspaceFolder}"
},
"containerUser": "vscode",
// add ptrace
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools-extension-pack",
"vilicvane.sensitive-replace",
"maattdd.gitless",
"bibhasdn.unique-lines",
"GitHub.copilot",
"xackery.make-magic",
"Gruntfuggly.todo-tree",
"ms-vscode.cmake-tools"
]
}
},
"workspaceFolder": "/src",
"workspaceMount": "source=${localWorkspaceFolder},target=/src,type=bind,consistency=cached"
}
-3
View File
@@ -61,9 +61,6 @@ bin/
compile_flags.txt
.cache/
# vscode generated settings
.vscode/
# Build pipeline
!utils/scripts/build/
!utils/scripts/build/should-release/should-release
+23
View File
@@ -0,0 +1,23 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${default}",
"${workspaceFolder}/submodules/fmt/include",
"${workspaceFolder}/submodules/cereal/include",
"${workspaceFolder}/submodules/glm",
"${workspaceFolder}/submodules/libuv/include"
],
"defines": [
"LUA_EQEMU=1"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
+173
View File
@@ -0,0 +1,173 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) attach",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/build/bin/world",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) shared_memory",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/shared_memory",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) world",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/world",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) zone",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/zone",
"cwd": "${workspaceFolder}/build/bin",
"args": [
"",
],
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) zone neriakb",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/zone",
"cwd": "${workspaceFolder}/build/bin",
"args": [
"neriakb",
],
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) login",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/loginserver",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) ucs",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/ucs",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) queryserv",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/queryserv",
"cwd": "${workspaceFolder}/build/bin",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
+136
View File
@@ -0,0 +1,136 @@
{
"editor.detectIndentation": false,
"editor.insertSpaces": false,
"editor.tabSize": 4,
"editor.autoIndent": "full",
"editor.trimAutoWhitespace": true,
"files.trimTrailingWhitespace": true,
//"editor.formatOnSave": true,
"search.exclude": {
"dependencies": false,
},
"C_Cpp.default.includePath": [
"/usr/include/x86_64-linux-gnu",
"/usr/include/lua5.2",
"/usr/include/mariadb",
"${workspaceFolder}/dependencies/curl_x64/include",
"${workspaceFolder}/dependencies/fmt/include",
"${workspaceFolder}/dependencies/glm",
"${workspaceFolder}/dependencies/libuv/include",
"${workspaceFolder}/dependencies/sol2",
"${workspaceFolder}/dependencies/zlibng"
],
"telemetry.enableTelemetry": false,
"cmake.buildDirectory": "${workspaceFolder}/build",
"cmake.configureArgs": [
"-DEQEMU_BUILD_LOGIN=ON",
"-DEQEMU_BUILD_TESTS=ON",
"-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",
"-DEQEMU_ADD_PROFILER=ON",
"Ninja"
],
"cmake.skipConfigureIfCachePresent": true,
"cmake.configureOnOpen": false,
"files.associations": {
"*.ipp": "cpp",
"functional": "cpp",
"string": "cpp",
"iostream": "cpp",
"map": "cpp",
"fstream": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"cstring": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"strstream": "cpp",
"bit": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"coroutine": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"list": "cpp",
"set": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"source_location": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"semaphore": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cfenv": "cpp",
"cinttypes": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"csetjmp": "cpp",
"charconv": "cpp",
"format": "cpp",
"ranges": "cpp",
"span": "cpp"
},
"cmake.statusbar.advanced": {
"kit": {
"visibility": "hidden",
},
"debug": {
"visibility": "hidden",
},
"buildTarget": {
"visibility": "hidden",
},
"launch": {
"visibility": "hidden",
},
"ctest": {
"visibility": "icon",
}
}
}
+803 -13
View File
@@ -1,3 +1,793 @@
## [22.55.0] 8/26/2024
### Code
* Remove unused methods ([#4449](https://github.com/EQEmu/Server/pull/4449)) @Kinglykrab 2024-08-22
### Feature
* Add Character:DefaultGuildRank Rule ([#4438](https://github.com/EQEmu/Server/pull/4438)) @Kinglykrab 2024-08-04
* Add Optional Return to EVENT_DAMAGE_TAKEN ([#4454](https://github.com/EQEmu/Server/pull/4454)) @Kinglykrab 2024-08-27
* Extend Spell Buckets Functionality ([#4441](https://github.com/EQEmu/Server/pull/4441)) @Kinglykrab 2024-08-22
### Fixes
* Apply Race & Class restrictions to Auto-Combines ([#4452](https://github.com/EQEmu/Server/pull/4452)) @catapultam-habeo 2024-08-20
* Attune Augments when Equipped ([#4446](https://github.com/EQEmu/Server/pull/4446)) @fryguy503 2024-08-10
* Correct missed maxlevel reference in exp.cpp ([#4463](https://github.com/EQEmu/Server/pull/4463)) @N0ctrnl 2024-08-27
* Ensure close of Tribute Item search ([#4439](https://github.com/EQEmu/Server/pull/4439)) @joligario 2024-08-04
* Fix AddCrystals() in Perl/Lua ([#4445](https://github.com/EQEmu/Server/pull/4445)) @Kinglykrab 2024-08-10
* Fix Bot Spell Entries IDs Capping at 32,767 ([#4444](https://github.com/EQEmu/Server/pull/4444)) @Kinglykrab 2024-08-27
* Fix Character ID of 0 being inserted into character_stats_record ([#4458](https://github.com/EQEmu/Server/pull/4458)) @Kinglykrab 2024-08-22
* Fix Issue with Removed #setfaction Command ([#4448](https://github.com/EQEmu/Server/pull/4448)) @Kinglykrab 2024-08-11
* Fix Lua Client FilteredMessage ([#4437](https://github.com/EQEmu/Server/pull/4437)) @Kinglykrab 2024-07-31
* Fix client hotbar exchanging items when zoning ([#4460](https://github.com/EQEmu/Server/pull/4460)) @neckkola 2024-08-27
* Fix issue with killed mob coordinates ([#4457](https://github.com/EQEmu/Server/pull/4457)) @Kinglykrab 2024-08-22
* Imitate Death should also clear zone feign aggro ([#4436](https://github.com/EQEmu/Server/pull/4436)) @fryguy503 2024-07-31
* client_max_level allow leveling to end of level ([#4455](https://github.com/EQEmu/Server/pull/4455)) @fryguy503 2024-08-20
### Improvement
* Filtered Messages Extension ([#4435](https://github.com/EQEmu/Server/pull/4435)) @fryguy503 2024-07-31
### Quest API
* Add AreTasksCompleted() to Perl/Lua. ([#4456](https://github.com/EQEmu/Server/pull/4456)) @Kinglykrab 2024-08-23
* Add Area-Based Quest Methods to Perl/Lua ([#4447](https://github.com/EQEmu/Server/pull/4447)) @Kinglykrab 2024-08-27
* Add Several Door Methods to Perl/Lua ([#4451](https://github.com/EQEmu/Server/pull/4451)) @Kinglykrab 2024-08-16
### World
* Fix slow world bootup bug ([#4461](https://github.com/EQEmu/Server/pull/4461)) @Akkadius 2024-08-27
## [22.54.0] 7/30/2024
### Code
* Cleanup Client File Exporting ([#4348](https://github.com/EQEmu/Server/pull/4348)) @Kinglykrab 2024-07-31
* Cleanup Stance Code ([#4368](https://github.com/EQEmu/Server/pull/4368)) @Kinglykrab 2024-07-03
* Mask GM Show Buff message behind EntityVariable ([#4419](https://github.com/EQEmu/Server/pull/4419)) @nytmyr 2024-07-22
### Commands
* Extend #devtools Functionality ([#4425](https://github.com/EQEmu/Server/pull/4425)) @Kinglykrab 2024-07-23
### Databuckets
* Remove memory reserve from bulk load ([#4427](https://github.com/EQEmu/Server/pull/4427)) @Akkadius 2024-07-23
### Feature
* Add Barter/Buyer Features ([#4405](https://github.com/EQEmu/Server/pull/4405)) @neckkola 2024-07-30
* Add Parcel notification for online players when using the Quest API ([#4418](https://github.com/EQEmu/Server/pull/4418)) @neckkola 2024-07-22
* Implement Move Multiple Items ([#4259](https://github.com/EQEmu/Server/pull/4259)) @catapultam-habeo 2024-07-30
### Fixes
* Aegolism Spell line stacking ([#4399](https://github.com/EQEmu/Server/pull/4399)) @KayenEQ 2024-07-07
* AllowRaidTargetBlind logic backwards ([#4400](https://github.com/EQEmu/Server/pull/4400)) @fryguy503 2024-07-01
* AutoSplit unknown bug and cleanup. ([#4401](https://github.com/EQEmu/Server/pull/4401)) @fryguy503 2024-07-07
* Corpse Call removing Resurrection Effects ([#4410](https://github.com/EQEmu/Server/pull/4410)) @fryguy503 2024-07-22
* Fix #parcels add subcommand ([#4431](https://github.com/EQEmu/Server/pull/4431)) @neckkola 2024-07-29
* Fix #setlevel Allowing Skills Above Max ([#4423](https://github.com/EQEmu/Server/pull/4423)) @Kinglykrab 2024-07-23
* Fix Bot::SetBotStance ([#4426](https://github.com/EQEmu/Server/pull/4426)) @Kinglykrab 2024-07-23
* Fix Client::RemoveTitle ([#4421](https://github.com/EQEmu/Server/pull/4421)) @Kinglykrab 2024-07-23
* Fix EVENT_USE_SKILL with Sense Heading ([#4424](https://github.com/EQEmu/Server/pull/4424)) @Kinglykrab 2024-07-23
* Fix for random disconnects when a large number of guild members zone or disconnect ([#4402](https://github.com/EQEmu/Server/pull/4402)) @neckkola 2024-07-10
* Fix issue with quest::echo and quest::me ([#4433](https://github.com/EQEmu/Server/pull/4433)) @Kinglykrab 2024-07-30
* Personal tributes for bard items were not applying correctly ([#4416](https://github.com/EQEmu/Server/pull/4416)) @neckkola 2024-07-16
* Potential fix for some undesired ranged explotative behavior. ([#4413](https://github.com/EQEmu/Server/pull/4413)) @fryguy503 2024-07-22
* Proximity Aggro for Frustrated and Undead ([#4411](https://github.com/EQEmu/Server/pull/4411)) @fryguy503 2024-07-22
* Slay Adjustments ([#4389](https://github.com/EQEmu/Server/pull/4389)) @fryguy503 2024-07-07
* Stop DOSing ourselves with OP_WearChange ([#4432](https://github.com/EQEmu/Server/pull/4432)) @catapultam-habeo 2024-07-30
* [Quest API] Fix getraididbycharid and getgroupidbycharid ([#4417](https://github.com/EQEmu/Server/pull/4417)) @nytmyr 2024-07-16
### Improvement
* Flee Overhaul ([#4407](https://github.com/EQEmu/Server/pull/4407)) @fryguy503 2024-07-30
### Rules
* Add HasteCap and Hastev3Cap rules for NPCs, Bots and Mercs ([#4406](https://github.com/EQEmu/Server/pull/4406)) @nytmyr 2024-07-22
### Zone Instances
* Revert " Handle routing to instances when using evac/succor " (#4429) ([#4297](https://github.com/EQEmu/Server/pull/4297)) @Akkadius 2024-07-30
### Zoning
* Improve zone routing ([#4428](https://github.com/EQEmu/Server/pull/4428)) @Akkadius 2024-07-30
## [22.53.1] 6/16/2024
### Fixes
* Fix trader mode ([#4397](https://github.com/EQEmu/Server/pull/4397)) @joligario 2024-06-17
## [22.53.0] 6/14/2024
### Bug
* Anon players should not show in /who all ([#4392](https://github.com/EQEmu/Server/pull/4392)) @fryguy503 2024-06-14
* Escape should put player into SOS if owned. ([#4388](https://github.com/EQEmu/Server/pull/4388)) @fryguy503 2024-06-07
* Prevent Resurrection Spells from being resisted ([#4393](https://github.com/EQEmu/Server/pull/4393)) @fryguy503 2024-06-14
### Code
* Cleanup Account Status Code ([#4376](https://github.com/EQEmu/Server/pull/4376)) @Kinglykrab 2024-06-02
* Cleanup Body Type Code ([#4366](https://github.com/EQEmu/Server/pull/4366)) @Kinglykrab 2024-06-02
* Cleanup Object Type Code ([#4375](https://github.com/EQEmu/Server/pull/4375)) @Kinglykrab 2024-06-14
* Remove unused code in emu_constants.h ([#4384](https://github.com/EQEmu/Server/pull/4384)) @Kinglykrab 2024-06-14
### Fixes
* Fix #goto Target ([#4382](https://github.com/EQEmu/Server/pull/4382)) @Kinglykrab 2024-06-03
* Fix Swarm Pet Damage Messages ([#4383](https://github.com/EQEmu/Server/pull/4383)) @Kinglykrab 2024-06-04
* Fix for players having empty bazaar window dropdown list, even though trader is tagged as a trader. ([#4391](https://github.com/EQEmu/Server/pull/4391)) @neckkola 2024-06-14
* Fix potential trader crash when serialized item not found ([#4386](https://github.com/EQEmu/Server/pull/4386)) @joligario 2024-06-14
### Rules
* Add Invisible Augment Rules ([#4385](https://github.com/EQEmu/Server/pull/4385)) @Kinglykrab 2024-06-14
* Classic Harm Touch Formula ([#4394](https://github.com/EQEmu/Server/pull/4394)) @fryguy503 2024-06-14
* Mend/Sneak allow success tuning ([#4390](https://github.com/EQEmu/Server/pull/4390)) @fryguy503 2024-06-14
* Snare Override Movement Bonus ([#4381](https://github.com/EQEmu/Server/pull/4381)) @fryguy503 2024-06-02
## [22.52.0] 6/1/2024
### Code
* Cleanup Bucket Comparison Code ([#4374](https://github.com/EQEmu/Server/pull/4374)) @Kinglykrab 2024-06-02
* Cleanup Bug Category Code ([#4367](https://github.com/EQEmu/Server/pull/4367)) @Kinglykrab 2024-06-01
* Cleanup Deity Code ([#4363](https://github.com/EQEmu/Server/pull/4363)) @Kinglykrab 2024-06-01
* Cleanup Special Ability Code ([#4365](https://github.com/EQEmu/Server/pull/4365)) @Kinglykrab 2024-06-01
* Remove unused code in common/eq_constants.h ([#4364](https://github.com/EQEmu/Server/pull/4364)) @Kinglykrab 2024-06-01
### Combat
* Adjustments to Crippling Blows/Slay Undead and Confirmed Critical Code ([#4354](https://github.com/EQEmu/Server/pull/4354)) @fryguy503 2024-05-27
### Fixes
* Add protection to ensure adventure points award are only attempted on players ([#4371](https://github.com/EQEmu/Server/pull/4371)) @joligario 2024-05-31
* Adjust Kick/RoundKick Damage Lower levels ([#4355](https://github.com/EQEmu/Server/pull/4355)) @fryguy503 2024-05-28
* Bazaar Search not working correctly for Iksar, Vashir, Drakkin and Froglok races ([#4379](https://github.com/EQEmu/Server/pull/4379)) @neckkola 2024-06-02
* Fix Unescaped String in Client::GotoPlayer ([#4373](https://github.com/EQEmu/Server/pull/4373)) @Kinglykrab 2024-06-01
### NPC Spells
* Fixed an issue where the repository spell adj value was overriding the spell difficulty default value ([#4370](https://github.com/EQEmu/Server/pull/4370)) @regneq 2024-06-01
### Quest API
* Add Item Link Methods to Perl/Lua ([#4359](https://github.com/EQEmu/Server/pull/4359)) @Kinglykrab 2024-06-01
### Quests
* Fix Lua encounter double register ([#4369](https://github.com/EQEmu/Server/pull/4369)) @Akkadius 2024-05-31
* Fix issue with Lua encounters loading in certain circumstances ([#4378](https://github.com/EQEmu/Server/pull/4378)) @Akkadius 2024-06-01
### Rules
* Add Skill Base Damage Rules ([#4360](https://github.com/EQEmu/Server/pull/4360)) @Kinglykrab 2024-06-01
### Skills
* Fix caps out of bounds issue ([#4377](https://github.com/EQEmu/Server/pull/4377)) @Akkadius 2024-06-01
## [22.51.1] 5/27/2024
### Fixes
* Adjust return for perl release check @Akkadius 2024-05-26
* Corrected issue with bazaar purchase via parcels where an incorrect quantity would be calculated. ([#4352](https://github.com/EQEmu/Server/pull/4352)) @neckkola 2024-05-27
### Performance
* Improve SkillCaps::GetTrainLevel() Efficiency ([#4350](https://github.com/EQEmu/Server/pull/4350)) @Kinglykrab 2024-05-26
### Rules
* Legacy Compute Defense against modern agi based defense. ([#4349](https://github.com/EQEmu/Server/pull/4349)) @fryguy503 2024-05-27
## [22.51.0] 5/26/2024
### Commands
* #npcspawn Changes ([#4311](https://github.com/EQEmu/Server/pull/4311)) @twincannon 2024-05-16
* Cleanup #resetaa Command ([#4310](https://github.com/EQEmu/Server/pull/4310)) @Kinglykrab 2024-05-22
### Crash
* Add validation to RemoveXTarget ([#4324](https://github.com/EQEmu/Server/pull/4324)) @Akkadius 2024-05-25
* Fix Zone deconstructor crashes ([#4325](https://github.com/EQEmu/Server/pull/4325)) @Akkadius 2024-05-25
* Fix crash issue when dividing by zero in CalcHPRegen ([#4320](https://github.com/EQEmu/Server/pull/4320)) @Akkadius 2024-05-25
* Fix crash when map name is null ([#4322](https://github.com/EQEmu/Server/pull/4322)) @Akkadius 2024-05-25
* Fix player event crash in ITEM_DESTROY ([#4326](https://github.com/EQEmu/Server/pull/4326)) @Akkadius 2024-05-25
* Fix player events reload when out of bounds ([#4321](https://github.com/EQEmu/Server/pull/4321)) @Akkadius 2024-05-25
* Fix rarer crash in EntityList::MobProcess ([#4319](https://github.com/EQEmu/Server/pull/4319)) @Akkadius 2024-05-25
### Feature
* Add RoF2 Bazaar Support ([#4315](https://github.com/EQEmu/Server/pull/4315)) @neckkola 2024-05-26
* Add SE_IncreaseArchery and rules to tune archery ([#4335](https://github.com/EQEmu/Server/pull/4335)) @fryguy503 2024-05-26
* Add parcel container support ([#4305](https://github.com/EQEmu/Server/pull/4305)) @neckkola 2024-05-17
### Fixes
* Accuracy, Avoidance and Atk adjustments ([#4336](https://github.com/EQEmu/Server/pull/4336)) @fryguy503 2024-05-26
* Fix Crash with null Argument in #modifynpcstat ([#4318](https://github.com/EQEmu/Server/pull/4318)) @Kinglykrab 2024-05-24
* Fix RemoveAlternateCurrencyValue not updating Client ([#4317](https://github.com/EQEmu/Server/pull/4317)) @Kinglykrab 2024-05-23
* Fix Using Bind Wound Above 70% Health ([#4340](https://github.com/EQEmu/Server/pull/4340)) @Kinglykrab 2024-05-26
* Fix issue with #hotfix ([#4316](https://github.com/EQEmu/Server/pull/4316)) @Kinglykrab 2024-05-22
* Fix issue with #suspend ([#4314](https://github.com/EQEmu/Server/pull/4314)) @Kinglykrab 2024-05-23
* Fix issue with KeepOneRecordPerCompletedTask ([#4313](https://github.com/EQEmu/Server/pull/4313)) @Kinglykrab 2024-05-23
* Fix mistaken removed RULE_CATEGORY_END() ([#4341](https://github.com/EQEmu/Server/pull/4341)) @fryguy503 2024-05-26
* Missed a mob offense section for PR #4328 ([#4331](https://github.com/EQEmu/Server/pull/4331)) @fryguy503 2024-05-26
* Raid Targets should not be Blindable as this will break all spell casting AI. ([#4334](https://github.com/EQEmu/Server/pull/4334)) @fryguy503 2024-05-26
* When Mounts are allowed to zone, block them from zoning to disallowed zones. ([#4330](https://github.com/EQEmu/Server/pull/4330)) @fryguy503 2024-05-25
* When refreshing buffs, attempt to use the same buffslot if the buff still exists. ([#4338](https://github.com/EQEmu/Server/pull/4338)) @fryguy503 2024-05-26
### Lua Mod
* Fix issue with SetAAEXP and SetEXP firing when uninitialized ([#4345](https://github.com/EQEmu/Server/pull/4345)) @Akkadius 2024-05-26
### Merchants
* Add New Classic Greed/Faction/Charisma Prices Rule ([#4301](https://github.com/EQEmu/Server/pull/4301)) @noudess 2024-05-17
### Mobs
* Remove entity type checks from ScanCloseMobs ([#4323](https://github.com/EQEmu/Server/pull/4323)) @Akkadius 2024-05-25
### NPC Spells
* Fix an issue where procs wouldn't fire if no spell entries in list ([#4344](https://github.com/EQEmu/Server/pull/4344)) @Akkadius 2024-05-26
### Perl
* Linux /opt/eqemu-perl checks when using release binaries ([#4346](https://github.com/EQEmu/Server/pull/4346)) @Akkadius 2024-05-26
### Quest API
* Add Zone Uptime Exports to Perl/Lua ([#4339](https://github.com/EQEmu/Server/pull/4339)) @Kinglykrab 2024-05-26
### Rules
* Added MeleeMitigation Level Difference Roll Adjusted for level diffs ([#4332](https://github.com/EQEmu/Server/pull/4332)) @fryguy503 2024-05-26
* Allow maximum per kill AA amount ([#4329](https://github.com/EQEmu/Server/pull/4329)) @fryguy503 2024-05-25
* Allow servers to adjust the filtering threshold for heals from damage (e.g. Mark of Kings). ([#4327](https://github.com/EQEmu/Server/pull/4327)) @fryguy503 2024-05-25
* Backstab Haste Correction ([#4337](https://github.com/EQEmu/Server/pull/4337)) @fryguy503 2024-05-26
* Mob Offensive and Weapon Skill static tables ([#4328](https://github.com/EQEmu/Server/pull/4328)) @fryguy503 2024-05-25
* Remove hard coded initial aggro in favor or an adjustable Rule ([#4333](https://github.com/EQEmu/Server/pull/4333)) @fryguy503 2024-05-26
### Scripts
* Fix zone data load ordering issue ([#4343](https://github.com/EQEmu/Server/pull/4343)) @Akkadius 2024-05-26
### Spells
* Add content filtering to NPC spells ([#4309](https://github.com/EQEmu/Server/pull/4309)) @Akkadius 2024-05-17
## [22.50.1] 5/12/2024
### Fixes
* Clear GuildOnlineStatus on world boot ([#4306](https://github.com/EQEmu/Server/pull/4306)) @neckkola 2024-05-12
## [22.50.0] 5/9/2024
### Code
* Fix Message in #find task ([#4270](https://github.com/EQEmu/Server/pull/4270)) @Kinglykrab 2024-04-19
### Combat
* Add rule to set stun duration. Add rule to add stun messages. ([#4284](https://github.com/EQEmu/Server/pull/4284)) @noudess 2024-04-25
### Commands
* Adjust #kill and #list Commands ([#4271](https://github.com/EQEmu/Server/pull/4271)) @Kinglykrab 2024-05-04
### Compiling
* Add profiler flag ([#4293](https://github.com/EQEmu/Server/pull/4293)) @xackery 2024-05-04
### Corpses
* Corpse searches for items did not search augs ([#4289](https://github.com/EQEmu/Server/pull/4289)) @noudess 2024-04-27
### Database
* Add Extra Haste to Bots/Character Tables ([#4286](https://github.com/EQEmu/Server/pull/4286)) @Kinglykrab 2024-05-04
* Break out changes to `npc_types` from parcels ([#4295](https://github.com/EQEmu/Server/pull/4295)) @joligario 2024-05-03
* Move pets query to content database ([#4296](https://github.com/EQEmu/Server/pull/4296)) @joligario 2024-05-04
### Doors
* Replace magic # in code with a field in doors table for when door closes. ([#4288](https://github.com/EQEmu/Server/pull/4288)) @noudess 2024-04-25
### Experience
* Add SetExp/SetAAExp lua mods ([#4292](https://github.com/EQEmu/Server/pull/4292)) @xackery 2024-05-04
### Feature
* Add Augmentation Support for Parcels ([#4285](https://github.com/EQEmu/Server/pull/4285)) @neckkola 2024-04-24
* Add Character Auto Login ([#4216](https://github.com/EQEmu/Server/pull/4216)) @Kinglykrab 2024-04-15
* Add Parcel Feature for RoF2 Clients ([#4198](https://github.com/EQEmu/Server/pull/4198)) @neckkola 2024-04-21
* Add `is_parcel_merchant` to #npcedit ([#4290](https://github.com/EQEmu/Server/pull/4290)) @Kinglykrab 2024-05-04
* Add devcontainer support ([#4294](https://github.com/EQEmu/Server/pull/4294)) @xackery 2024-05-09
* Fix ignore_default on lua mod damage ([#4228](https://github.com/EQEmu/Server/pull/4228)) @xackery 2024-04-15
### Fixes
* "GM flag" vs "GM Flag" @Akkadius 2024-05-04
* All NPC classes could stun with kick/only warriors could be stunned ([#4273](https://github.com/EQEmu/Server/pull/4273)) @noudess 2024-04-24
* Fix Account Flags Loading ([#4243](https://github.com/EQEmu/Server/pull/4243)) @Kinglykrab 2024-04-15
* Fix Corpses "Disappearing" ([#4275](https://github.com/EQEmu/Server/pull/4275)) @joligario 2024-04-21
* Fix Issue With Auto Login ([#4267](https://github.com/EQEmu/Server/pull/4267)) @Kinglykrab 2024-04-21
* Fix crash from #4266 @Akkadius 2024-05-05
* Fixes Issue 4257 - Double Taunt Message ([#4258](https://github.com/EQEmu/Server/pull/4258)) @fryguy503 2024-04-18
* GLAA fix after database.cpp updates ([#4277](https://github.com/EQEmu/Server/pull/4277)) @neckkola 2024-04-21
* GetSkill default return 0 @Akkadius 2024-05-05
* Hero forge armor bug on login and show helm toggle. ([#4246](https://github.com/EQEmu/Server/pull/4246)) @noudess 2024-04-15
* Perl__send_parcel GCC compile error @Akkadius 2024-05-05
* Remove food or water GM message @Akkadius 2024-05-05
* Revert GetSkill from #4234 @Akkadius 2024-05-05
* Fix for world crash with over 1500 guilds ([#4299](https://github.com/EQEmu/Server/pull/4299)) @neckkola 2024-05-09
### Hot Fix
* Update database_update_manifest.cpp ([#4291](https://github.com/EQEmu/Server/pull/4291)) @noudess 2024-04-29
### Loot
* Add content filtering to lootdrop_entries ([#4229](https://github.com/EQEmu/Server/pull/4229)) @Akkadius 2024-04-15
* Consolidate filtering logic ([#4280](https://github.com/EQEmu/Server/pull/4280)) @Akkadius 2024-04-21
### Lua
* Add IsImmuneToSpell Lua Mod ([#4278](https://github.com/EQEmu/Server/pull/4278)) @xackery 2024-04-28
* Add UpdatePersonalFaction Lua Mod ([#4279](https://github.com/EQEmu/Server/pull/4279)) @xackery 2024-05-04
### Messages
* Add GM Status and Invulnerability Messages ([#4266](https://github.com/EQEmu/Server/pull/4266)) @Kinglykrab 2024-05-04
* Fix bug where DoT messages stop coming out when mob dies. ([#4249](https://github.com/EQEmu/Server/pull/4249)) @noudess 2024-04-15
* Fix multiple errors in spell damage at death. ([#4264](https://github.com/EQEmu/Server/pull/4264)) @noudess 2024-04-28
### Performance
* Change skill_cap from vector to map ([#4252](https://github.com/EQEmu/Server/pull/4252)) @xackery 2024-04-15
### Pets
* Fix errors in sync with client of sit/stand ([#4245](https://github.com/EQEmu/Server/pull/4245)) @noudess 2024-04-15
### Quest API
* Add DescribeSpecialAbilities() to Perl/Lua ([#4269](https://github.com/EQEmu/Server/pull/4269)) @Kinglykrab 2024-04-21
* Add GetConsiderColor() to Perl/Lua ([#4253](https://github.com/EQEmu/Server/pull/4253)) @Kinglykrab 2024-04-15
* Add Parcel Sending to Perl/Lua ([#4287](https://github.com/EQEmu/Server/pull/4287)) @Kinglykrab 2024-05-04
* Add Zone Methods to Perl/Lua ([#4268](https://github.com/EQEmu/Server/pull/4268)) @Kinglykrab 2024-04-21
### Quests
* Hot Reload Changes ([#4302](https://github.com/EQEmu/Server/pull/4302)) @Akkadius 2024-05-09
* Reload Quests on Bootup, Init earlier ([#4298](https://github.com/EQEmu/Server/pull/4298)) @Akkadius 2024-05-05
### Spells
* Implemented SPA 122 SE_ReduceSkill ([#4234](https://github.com/EQEmu/Server/pull/4234)) @KayenEQ 2024-05-04
* Normal Group Spells (non-raid) landed twice on caster ([#4240](https://github.com/EQEmu/Server/pull/4240)) @noudess 2024-04-15
* SPA69 TotalHP can be used in Worn Slot, Fixes/Updates to Max HP related variables. ([#4244](https://github.com/EQEmu/Server/pull/4244)) @KayenEQ 2024-04-15
### Zone Instances
* Handle routing to instances when using evac/succor ([#4297](https://github.com/EQEmu/Server/pull/4297)) @joligario 2024-05-04
## [22.49.1] 4/15/2024
### Zoning
* Fix zone routing edge case ([#4255](https://github.com/EQEmu/Server/pull/4255)) @Akkadius 2024-04-15
## [22.49.0] 4/15/2024
### Code
* Avoid unnecessary copies in database functions ([#4220](https://github.com/EQEmu/Server/pull/4220)) @joligario 2024-03-29
* Reference type in `GetRaidLeaderName` ([#4218](https://github.com/EQEmu/Server/pull/4218)) @joligario 2024-03-28
* Remove unnecessary reference types ([#4212](https://github.com/EQEmu/Server/pull/4212)) @joligario 2024-03-28
### Crash
* Check mob pointer before trying to remove it ([#4230](https://github.com/EQEmu/Server/pull/4230)) @Akkadius 2024-04-01
### Feature
* Add Character Auto Login ([#4216](https://github.com/EQEmu/Server/pull/4216)) @Kinglykrab 2024-04-15
* Add LuaMod functions for CommonDamage and HealDamage ([#4227](https://github.com/EQEmu/Server/pull/4227)) @xackery 2024-03-31
* Add RegisterBug LuaMod ([#4209](https://github.com/EQEmu/Server/pull/4209)) @xackery 2024-03-30
* Additive Spell Focus from Worn slot with Limit Checks ([#4208](https://github.com/EQEmu/Server/pull/4208)) @KayenEQ 2024-03-30
* Fix ignore_default on lua mod damage ([#4228](https://github.com/EQEmu/Server/pull/4228)) @xackery 2024-04-15
### Fixes
* Client not updating HP bar when an HP Buff with a Heal is applied. ([#4237](https://github.com/EQEmu/Server/pull/4237)) @KayenEQ 2024-04-02
* Fix Account Flags Loading ([#4243](https://github.com/EQEmu/Server/pull/4243)) @Kinglykrab 2024-04-15
* Fix Auto Login Issue ([#4213](https://github.com/EQEmu/Server/pull/4213)) @Kinglykrab 2024-03-28
* Fix Bot Creation Issue ([#4235](https://github.com/EQEmu/Server/pull/4235)) @Kinglykrab 2024-04-02
* Fix Bot/Character ID Overlap in Groups ([#4093](https://github.com/EQEmu/Server/pull/4093)) @Kinglykrab 2024-03-23
* Fix Group Leadership ([#4214](https://github.com/EQEmu/Server/pull/4214)) @Kinglykrab 2024-03-28
* Fix Issue With Bot Raid Aggro ([#4222](https://github.com/EQEmu/Server/pull/4222)) @Kinglykrab 2024-03-31
* Fix Lua Crash with Spell Blocked Event ([#4236](https://github.com/EQEmu/Server/pull/4236)) @Kinglykrab 2024-04-01
* Fix Luabind Double Class Register ([#4219](https://github.com/EQEmu/Server/pull/4219)) @Kinglykrab 2024-03-29
* Fix crash in SendEnterWorld ([#4204](https://github.com/EQEmu/Server/pull/4204)) @Akkadius 2024-03-24
* Fix event_consider any_cast error ([#4210](https://github.com/EQEmu/Server/pull/4210)) @xackery 2024-03-27
* Fix fishing chances ([#4203](https://github.com/EQEmu/Server/pull/4203)) @joligario 2024-03-24
* Fix manifest for skill caps schema type ([#4231](https://github.com/EQEmu/Server/pull/4231)) @Akkadius 2024-04-02
* Hero forge armor bug on login and show helm toggle. ([#4246](https://github.com/EQEmu/Server/pull/4246)) @noudess 2024-04-15
* Radiant/Ebon Crystals should only extract to 1000 ([#4195](https://github.com/EQEmu/Server/pull/4195)) @fryguy503 2024-03-23
* SPA214 SE_MaxHPChange calculation errors corrected. ([#4238](https://github.com/EQEmu/Server/pull/4238)) @KayenEQ 2024-04-02
* Shared Tasks - charid is now character_id ([#4233](https://github.com/EQEmu/Server/pull/4233)) @fryguy503 2024-04-01
* Using %T in channel messages on fresh corpse yields mob, not corpse name. ([#4168](https://github.com/EQEmu/Server/pull/4168)) @noudess 2024-04-05
### Hot Fix
* Fix Group::AddToGroup ([#4201](https://github.com/EQEmu/Server/pull/4201)) @Kinglykrab 2024-03-23
* Hot Fix for Group::AddToGroup Hot Fix ([#4202](https://github.com/EQEmu/Server/pull/4202)) @Kinglykrab 2024-03-23
### Loot
* Add content filtering to lootdrop_entries ([#4229](https://github.com/EQEmu/Server/pull/4229)) @Akkadius 2024-04-15
### Lua
* Add Zone and Language Constants ([#4211](https://github.com/EQEmu/Server/pull/4211)) @fryguy503 2024-03-28
### Messages
* Fix bug where DoT messages stop coming out when mob dies. ([#4249](https://github.com/EQEmu/Server/pull/4249)) @noudess 2024-04-15
### Performance
* Change skill_cap from vector to map ([#4252](https://github.com/EQEmu/Server/pull/4252)) @xackery 2024-04-15
### Pets
* Fix errors in sync with client of sit/stand ([#4245](https://github.com/EQEmu/Server/pull/4245)) @noudess 2024-04-15
### Quest API
* Add Archetype Methods to Perl/Lua ([#4181](https://github.com/EQEmu/Server/pull/4181)) @Kinglykrab 2024-03-23
* Add Class/Deity/Race Methods to Perl/Lua ([#4215](https://github.com/EQEmu/Server/pull/4215)) @Kinglykrab 2024-03-28
* Add GetConsiderColor() to Perl/Lua ([#4253](https://github.com/EQEmu/Server/pull/4253)) @Kinglykrab 2024-04-15
* Add Spell Blocked Event to Perl/Lua ([#4217](https://github.com/EQEmu/Server/pull/4217)) @Kinglykrab 2024-04-01
### Quests
* Avoid Player and Bot quests in unloaded zone ([#4232](https://github.com/EQEmu/Server/pull/4232)) @hgtw 2024-04-01
### Repositories
* Convert database.cpp to Repositories ([#4054](https://github.com/EQEmu/Server/pull/4054)) @Kinglykrab 2024-03-24
### Skill Caps
* Further improvements ([#4205](https://github.com/EQEmu/Server/pull/4205)) @Akkadius 2024-03-24
* Remove from shared memory and simplify ([#4069](https://github.com/EQEmu/Server/pull/4069)) @Kinglykrab 2024-03-23
### Spells
* Implemented SPA 463 SE_SHIELD_TARGET ([#4224](https://github.com/EQEmu/Server/pull/4224)) @KayenEQ 2024-03-30
* Normal Group Spells (non-raid) landed twice on caster ([#4240](https://github.com/EQEmu/Server/pull/4240)) @noudess 2024-04-15
* SPA148 Stacking Fix ([#4206](https://github.com/EQEmu/Server/pull/4206)) @KayenEQ 2024-03-27
* SPA69 TotalHP can be used in Worn Slot, Fixes/Updates to Max HP related variables. ([#4244](https://github.com/EQEmu/Server/pull/4244)) @KayenEQ 2024-04-15
## [22.48.0] 3/23/2024
### Bots
* IsValidTarget Crash Fix ([#4187](https://github.com/EQEmu/Server/pull/4187)) @nytmyr 2024-03-12
* Move BotGroupSay to Pet Response ([#4171](https://github.com/EQEmu/Server/pull/4171)) @nytmyr 2024-03-08
### Code
* Cleanup Zone Get Methods ([#4169](https://github.com/EQEmu/Server/pull/4169)) @Kinglykrab 2024-03-09
### Fixes
* An Update to Xtarget to exclude Bot owned Temp/Swarm Pets ([#4172](https://github.com/EQEmu/Server/pull/4172)) @MortimerGreenwald 2024-03-08
* Fix #serverrules Command ([#4193](https://github.com/EQEmu/Server/pull/4193)) @Kinglykrab 2024-03-20
* Fix Bot Cloning ([#4186](https://github.com/EQEmu/Server/pull/4186)) @Kinglykrab 2024-03-17
* Fix Crash in ClientList::GetCLEIP ([#4173](https://github.com/EQEmu/Server/pull/4173)) @Kinglykrab 2024-03-10
* Fix Default Value in `rule_values` table ([#4166](https://github.com/EQEmu/Server/pull/4166)) @Kinglykrab 2024-03-07
* Fix EVENT_KILLED_MERIT firing before NPC removal ([#4185](https://github.com/EQEmu/Server/pull/4185)) @Kinglykrab 2024-03-17
* Fix Empty Groups When Removing Bots ([#4178](https://github.com/EQEmu/Server/pull/4178)) @Kinglykrab 2024-03-14
* Fix GetLeaderName() for Groups ([#4184](https://github.com/EQEmu/Server/pull/4184)) @Kinglykrab 2024-03-14
* Fix Mob::CalculateDistance(mob) Typo ([#4183](https://github.com/EQEmu/Server/pull/4183)) @Kinglykrab 2024-03-10
* Fix Proximity Say ([#4189](https://github.com/EQEmu/Server/pull/4189)) @Kinglykrab 2024-03-15
* Fix ScaleNPC() in Perl ([#4196](https://github.com/EQEmu/Server/pull/4196)) @Kinglykrab 2024-03-23
* Fix range_percent ([#4197](https://github.com/EQEmu/Server/pull/4197)) @Kinglykrab 2024-03-22
* Fix reusing timers ([#4199](https://github.com/EQEmu/Server/pull/4199)) @joligario 2024-03-23
### Hot Fix
* Add bool return to fix Client::RemoveAAPoints ([#4176](https://github.com/EQEmu/Server/pull/4176)) @Kinglykrab 2024-03-09
### Loot
* Fix issue with nested data being loaded multiple times ([#4192](https://github.com/EQEmu/Server/pull/4192)) @Akkadius 2024-03-23
### Misc
* Windows preprocessor define in crash.cpp ([#4191](https://github.com/EQEmu/Server/pull/4191)) @joligario 2024-03-23
### Quest API
* Add Buff Support to Perl/Lua ([#4182](https://github.com/EQEmu/Server/pull/4182)) @Kinglykrab 2024-03-14
* Add DeleteBot() to Perl/Lua ([#4167](https://github.com/EQEmu/Server/pull/4167)) @nytmyr 2024-03-07
* Add GetDeityName() to Perl/Lua ([#4180](https://github.com/EQEmu/Server/pull/4180)) @Kinglykrab 2024-03-14
* Add RemoveAAPoints() and AA Loss Event to Perl/Lua ([#4174](https://github.com/EQEmu/Server/pull/4174)) @Kinglykrab 2024-03-09
* Add RemoveAlternateCurrencyValue() to Perl/Lua ([#4190](https://github.com/EQEmu/Server/pull/4190)) @Kinglykrab 2024-03-17
* Add Restore Methods for Health, Mana, and Endurance to Perl/Lua ([#4179](https://github.com/EQEmu/Server/pull/4179)) @Kinglykrab 2024-03-23
* Add Silent Saylink Methods to Perl/Lua ([#4177](https://github.com/EQEmu/Server/pull/4177)) @Kinglykrab 2024-03-14
### Rules
* Add World:Rules Rule ([#4194](https://github.com/EQEmu/Server/pull/4194)) @Kinglykrab 2024-03-23
### Tradeskills
* Implement learning recipes from books ([#4170](https://github.com/EQEmu/Server/pull/4170)) @hgtw 2024-03-23
## [22.47.0] 3/5/2024
### Crash Fix
* Added a guild_mgr check ([#4163](https://github.com/EQEmu/Server/pull/4163)) @neckkola 2024-03-06
* Goto Command could crash using Developer Tools ([#4158](https://github.com/EQEmu/Server/pull/4158)) @neckkola 2024-03-04
* Groundspawn Memory Corruption ([#4157](https://github.com/EQEmu/Server/pull/4157)) @neckkola 2024-03-04
* Update to location of qGlobals initialization ([#4144](https://github.com/EQEmu/Server/pull/4144)) @neckkola 2024-03-02
### Feature
* Adds rules to control level requirements for Double Backstab, Assassinate, and Double Bowshot (#4159) ([#29](https://github.com/EQEmu/Server/pull/29)) @catapultam-habeo 2024-03-04
* Adjust String-based Rules Length ([#4138](https://github.com/EQEmu/Server/pull/4138)) @Kinglykrab 2024-03-06
* Exempt a zone from IP-limit checks. ([#4137](https://github.com/EQEmu/Server/pull/4137)) @catapultam-habeo 2024-03-02
### Fixes
* Add id to the guild_bank table ([#4155](https://github.com/EQEmu/Server/pull/4155)) @neckkola 2024-03-05
* Fix Bots/Bot Pets ending up on XTargets ([#4132](https://github.com/EQEmu/Server/pull/4132)) @Kinglykrab 2024-03-02
* Fix Character EXP Modifiers default ([#4161](https://github.com/EQEmu/Server/pull/4161)) @Kinglykrab 2024-03-06
* Fix Spawns Not Parsing Quest on Zone Bootup ([#4149](https://github.com/EQEmu/Server/pull/4149)) @Kinglykrab 2024-03-05
* Fix typo when updating spawn events in spawn condition manager ([#4160](https://github.com/EQEmu/Server/pull/4160)) @joligario 2024-03-05
* GetBotNameByID Temporary Reference Warning ([#4145](https://github.com/EQEmu/Server/pull/4145)) @Kinglykrab 2024-03-02
* Prevent NPE when creating DZ using ad-hoc version IDs ([#4141](https://github.com/EQEmu/Server/pull/4141)) @catapultam-habeo 2024-03-05
* Update FreeGuildID Routine ([#4143](https://github.com/EQEmu/Server/pull/4143)) @neckkola 2024-03-02
### Quest API
* Add Bot Special Attacks for Immune Aggro/Damage ([#4108](https://github.com/EQEmu/Server/pull/4108)) @Kinglykrab 2024-03-02
* Add GetHeroicStrikethrough() to Perl/Lua ([#4150](https://github.com/EQEmu/Server/pull/4150)) @Kinglykrab 2024-03-03
* Add IsAlwaysAggro() to Perl/Lua ([#4152](https://github.com/EQEmu/Server/pull/4152)) @Kinglykrab 2024-03-04
* Add IsBoat()/IsControllableBoat() to Perl/Lua ([#4151](https://github.com/EQEmu/Server/pull/4151)) @Kinglykrab 2024-03-03
* Add IsDestructibleObject() to Perl/Lua ([#4153](https://github.com/EQEmu/Server/pull/4153)) @Kinglykrab 2024-03-03
### Zone
* Zone Routing Improvements ([#4142](https://github.com/EQEmu/Server/pull/4142)) @Akkadius 2024-03-02
### Zoning
* Zone routing adjustment ([#4162](https://github.com/EQEmu/Server/pull/4162)) @Akkadius 2024-03-06
## [22.46.1] 3/2/2024
### Fixes
* Change `UnburyCorpse` to use repository methods ([#4147](https://github.com/EQEmu/Server/pull/4147)) @joligario 2024-03-03
## [22.46.0] 3/2/2024
### Commands
* Add #fish Command ([#4136](https://github.com/EQEmu/Server/pull/4136)) @Kinglykrab 2024-03-01
### Crash Fix
* Raid::UpdateGroupAAs ([#4139](https://github.com/EQEmu/Server/pull/4139)) @neckkola 2024-03-02
* Update to location of qGlobals initialization ([#4144](https://github.com/EQEmu/Server/pull/4144)) @neckkola 2024-03-02
### Feature
* Exempt a zone from IP-limit checks. ([#4137](https://github.com/EQEmu/Server/pull/4137)) @catapultam-habeo 2024-03-02
### Fixes
* Cleanup NPC Mana Tap Logic ([#4134](https://github.com/EQEmu/Server/pull/4134)) @noudess 2024-03-02
* Fix Bots/Bot Pets ending up on XTargets ([#4132](https://github.com/EQEmu/Server/pull/4132)) @Kinglykrab 2024-03-02
* Fix issue with NPC Secondary Textures ([#4129](https://github.com/EQEmu/Server/pull/4129)) @Kinglykrab 2024-03-01
* GetBotNameByID Temporary Reference Warning ([#4145](https://github.com/EQEmu/Server/pull/4145)) @Kinglykrab 2024-03-02
* Update FreeGuildID Routine ([#4143](https://github.com/EQEmu/Server/pull/4143)) @neckkola 2024-03-02
* Use std::clamp for Mob::ChangeSize ([#4140](https://github.com/EQEmu/Server/pull/4140)) @joligario 2024-03-02
### Quest API
* Add Bot Special Attacks for Immune Aggro/Damage ([#4108](https://github.com/EQEmu/Server/pull/4108)) @Kinglykrab 2024-03-02
### Zone
* Zone Routing Improvements ([#4142](https://github.com/EQEmu/Server/pull/4142)) @Akkadius 2024-03-02
## [22.45.1] 2/29/2024
### Character Creation
* Improved Random Name Generator ([#4081](https://github.com/EQEmu/Server/pull/4081)) @catapultam-habeo 2024-02-27
### Code
* Fix Server Rules Documentation Generation ([#4125](https://github.com/EQEmu/Server/pull/4125)) @Kinglykrab 2024-02-26
* Remove unnecessary stoptimer logs ([#4128](https://github.com/EQEmu/Server/pull/4128)) @Kinglykrab 2024-02-28
### Commands
* Add `#forage` command ([#4133](https://github.com/EQEmu/Server/pull/4133)) @joligario 2024-02-29
### Crash
* Fix crash issue during database dump ([#4127](https://github.com/EQEmu/Server/pull/4127)) @Akkadius 2024-02-29
### Crash Fix
* D20 crash if mitigation average resulted in 0 ([#4131](https://github.com/EQEmu/Server/pull/4131)) @nytmyr 2024-02-29
### Fixes
* Fix forage returning first result from table ([#4130](https://github.com/EQEmu/Server/pull/4130)) @nytmyr 2024-02-29
* Who /all displays incorrect guild name ([#4123](https://github.com/EQEmu/Server/pull/4123)) @neckkola 2024-02-25
### Quest API
* Add Pet Owner Methods to Perl/Lua ([#4115](https://github.com/EQEmu/Server/pull/4115)) @Kinglykrab 2024-02-25
## [22.45.0] 2/24/2024
### Beacon
* Revert a few lines of PR #4024 that broke beacons ([#4118](https://github.com/EQEmu/Server/pull/4118)) @noudess 2024-02-24
### Bots
* Cleanup empty `bot_commands` files ([#4095](https://github.com/EQEmu/Server/pull/4095)) @Kinglykrab 2024-02-19
* Remove Alt Combat Functionality ([#4067](https://github.com/EQEmu/Server/pull/4067)) @Kinglykrab 2024-02-12
### Code
* Update fmt to 10.2.1 ([#4071](https://github.com/EQEmu/Server/pull/4071)) @hgtw 2024-02-16
* Use explicit conversions for enum formatting ([#4064](https://github.com/EQEmu/Server/pull/4064)) @hgtw 2024-02-12
### Database
* Add content_database flag for zone changes ([#4104](https://github.com/EQEmu/Server/pull/4104)) @joligario 2024-02-20
* Remove "item_tick" from database schema per https://github.com/EQEmu/Server/pull/3985 ([#4083](https://github.com/EQEmu/Server/pull/4083)) @Akkadius 2024-02-16
### Expansions
* Zone Expansion Version Routing ([#4084](https://github.com/EQEmu/Server/pull/4084)) @Akkadius 2024-02-20
### Factions
* Fix issue with npcedit and cached factions ([#4103](https://github.com/EQEmu/Server/pull/4103)) @noudess 2024-02-20
### Feature
* Add Augments to Starting Items for Bots/Players ([#4100](https://github.com/EQEmu/Server/pull/4100)) @Kinglykrab 2024-02-21
* Hot Zone Bonus XP Notice ([#4091](https://github.com/EQEmu/Server/pull/4091)) @fryguy503 2024-02-18
### Fixes
* Add safety check to SummonAllCharacterCorpses. ([#4107](https://github.com/EQEmu/Server/pull/4107)) @fryguy503 2024-02-21
* Added additional Guild-related crash checks ([#4105](https://github.com/EQEmu/Server/pull/4105)) @neckkola 2024-02-22
* Aura effect spell id from #3964 ([#4094](https://github.com/EQEmu/Server/pull/4094)) @joligario 2024-02-18
* Crash on Ubuntu 22.04 ([#4119](https://github.com/EQEmu/Server/pull/4119)) @neckkola 2024-02-25
* Fix #wpadd Query ([#4078](https://github.com/EQEmu/Server/pull/4078)) @Kinglykrab 2024-02-14
* Fix Bot Weapons with No Races ([#4110](https://github.com/EQEmu/Server/pull/4110)) @Kinglykrab 2024-02-25
* Fix ClearSpawnTimers() ([#4073](https://github.com/EQEmu/Server/pull/4073)) @Kinglykrab 2024-02-13
* Fix Issue with ClearSpawnTimers() ([#4070](https://github.com/EQEmu/Server/pull/4070)) @Kinglykrab 2024-02-13
* Fix ObjectContentsRepository using content_db ([#4076](https://github.com/EQEmu/Server/pull/4076)) @Kinglykrab 2024-02-14
* Fix Sympathetic Procs for Bots/Mercenariess ([#4086](https://github.com/EQEmu/Server/pull/4086)) @Kinglykrab 2024-02-19
* Fix fix_z Query ([#4080](https://github.com/EQEmu/Server/pull/4080)) @Kinglykrab 2024-02-15
* Fix hotzone string error ([#4109](https://github.com/EQEmu/Server/pull/4109)) @fryguy503 2024-02-22
* Fix issue with IsEntOnHateList ([#4097](https://github.com/EQEmu/Server/pull/4097)) @Kinglykrab 2024-02-19
* Fix manifest check on `base_data` change ([#4082](https://github.com/EQEmu/Server/pull/4082)) @joligario 2024-02-16
* Revert 2df7d19 ([#4101](https://github.com/EQEmu/Server/pull/4101)) @joligario 2024-02-20
* Update database_schema to add guild_permissions ([#4085](https://github.com/EQEmu/Server/pull/4085)) @neckkola 2024-02-16
### Guilds
* Fixes for Guild Bank ([#4120](https://github.com/EQEmu/Server/pull/4120)) @neckkola 2024-02-25
### Logs
* Fix log in BaseGuildManager::IsGuildLeader() ([#4102](https://github.com/EQEmu/Server/pull/4102)) @joligario 2024-02-20
### Opcodes
* Fix opcode reloading ([#4075](https://github.com/EQEmu/Server/pull/4075)) @Akkadius 2024-02-14
### Quest API
* Add Bot Methods to Perl/Lua ([#4113](https://github.com/EQEmu/Server/pull/4113)) @Kinglykrab 2024-02-25
* Add Entity Variable Events to Perl/Lua ([#4092](https://github.com/EQEmu/Server/pull/4092)) @Kinglykrab 2024-02-20
* Add GetAugmentIDs() to Perl/Lua ([#4114](https://github.com/EQEmu/Server/pull/4114)) @Kinglykrab 2024-02-25
* Add GetNPCSpellsEffectsID() to Perl/Lua ([#4117](https://github.com/EQEmu/Server/pull/4117)) @Kinglykrab 2024-02-25
* Add Hatelist Count Methods to Perl/Lua ([#4106](https://github.com/EQEmu/Server/pull/4106)) @Kinglykrab 2024-02-21
* Add IsInAGuild() to Perl/Lua ([#4066](https://github.com/EQEmu/Server/pull/4066)) @Kinglykrab 2024-02-14
* Add Pet Methods to Perl/Lua ([#4116](https://github.com/EQEmu/Server/pull/4116)) @Kinglykrab 2024-02-25
* Add Timer Events to Perl/Lua ([#4099](https://github.com/EQEmu/Server/pull/4099)) @Kinglykrab 2024-02-19
* Add spell cast methods to Lua ([#4096](https://github.com/EQEmu/Server/pull/4096)) @Kinglykrab 2024-02-19
* Add tracebacks to Lua error messages ([#4079](https://github.com/EQEmu/Server/pull/4079)) @hgtw 2024-02-16
* Export Combat Record to Death Events ([#4112](https://github.com/EQEmu/Server/pull/4112)) @Kinglykrab 2024-02-25
### Repositories
* Cleanup and Convert Character Creation to Repositories ([#4053](https://github.com/EQEmu/Server/pull/4053)) @Kinglykrab 2024-02-20
* Convert Zone Flags to Repositories ([#4077](https://github.com/EQEmu/Server/pull/4077)) @Kinglykrab 2024-02-16
* Update `zone` base repository from #4084 ([#4111](https://github.com/EQEmu/Server/pull/4111)) @joligario 2024-02-23
## [22.44.5] - 2/12/2024
### Fixes
* [Hotfix] Fix issues where we're using the wrong database pointers @Akkadius
## [22.44.4] - 2/12/2024
### Fixes
* Fix ClearSpawnTimers() ([#4073](https://github.com/EQEmu/Server/pull/4073)) @Kinglykrab 2024-02-13
## [22.44.3] - 2/12/2024
### Fixes
* Fix Issue with ClearSpawnTimers() ([#4070](https://github.com/EQEmu/Server/pull/4070)) @Kinglykrab 2024-02-13
## [22.44.2] - 2/12/2024
### Bots
* Remove Alt Combat Functionality ([#4067](https://github.com/EQEmu/Server/pull/4067)) @Kinglykrab 2024-02-12
### Code
* Use explicit conversions for enum formatting ([#4064](https://github.com/EQEmu/Server/pull/4064)) @hgtw 2024-02-12
### Database
* Fix default value for `time_of_death` in `character_corpses` ([#4060](https://github.com/EQEmu/Server/pull/4060)) @joligario 2024-02-11
* Fix table name in manifest ([#4063](https://github.com/EQEmu/Server/pull/4063)) @joligario 2024-02-11
* Proper default for `droptime` from `object_contents` ([#4061](https://github.com/EQEmu/Server/pull/4061)) @joligario 2024-02-11
### Fixes
* Guard against crash condition ([#4062](https://github.com/EQEmu/Server/pull/4062)) @neckkola 2024-02-11
### Guilds
* Clean up `GUILD_RANK_NONE` references ([#4059](https://github.com/EQEmu/Server/pull/4059)) @joligario 2024-02-11
## [22.44.1] - 2/11/2024
### Fixes
* Fix File::Exists(file_name) to be resilient to Chinese characters ([#4058](https://github.com/EQEmu/Server/pull/4058)) @Akkadius 2024-02-11
## [22.44.0] - 2/10/2024
### Base Data
@@ -770,7 +1560,7 @@
### EQTime
Hotfix for world not spamming save messages by setting to detail level logging @Akkadius 2023-11-20
Hotfix for world not spamming save messages by setting to detail level logging @Akkadius 2023-11-20
## [22.34.0] - 11/19/2023
@@ -1852,7 +2642,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Telnet encoding fix ([#3269](https://github.com/EQEmu/Server/pull/3269)) @Akkadius 2023-04-05
## [22.9.1] - 04/03/2023
## [22.9.1] - 04/03/2023
### Code
@@ -1897,7 +2687,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Change to use Pass by reference where valid. ([#3163](https://github.com/EQEmu/Server/pull/3163)) @Aeadoin 2023-04-02
## [22.9.0] - 04/01/2023
## [22.9.0] - 04/01/2023
### Bots
@@ -1921,7 +2711,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Add missing Luabind definitions to lua_general.cpp ([#3167](https://github.com/EQEmu/Server/pull/3167)) @Kinglykrab 2023-04-01
## [22.8.2] - 03/30/2023
## [22.8.2] - 03/30/2023
### Code
@@ -1945,13 +2735,13 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Remove Guild Bank Zone ID Rule ([#3156](https://github.com/EQEmu/Server/pull/3156)) @Kinglykrab 2023-03-29
## [22.8.1] - 03/27/2023
## [22.8.1] - 03/27/2023
### Fixes
* Fix for NPCs having spells interrupted. ([#3150](https://github.com/EQEmu/Server/pull/3150)) @Aeadoin 2023-03-27
## [22.8.0] - 03/25/2023
## [22.8.0] - 03/25/2023
### Code
@@ -1971,7 +2761,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Fix for Items looted from corpses. ([#3147](https://github.com/EQEmu/Server/pull/3147)) @Aeadoin 2023-03-26
* Fix for SQL Query in npc_scale_global_base ([#3144](https://github.com/EQEmu/Server/pull/3144)) @Aeadoin 2023-03-26
## [22.7.0] - 03/24/2023
## [22.7.0] - 03/24/2023
### Bots
@@ -2128,7 +2918,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Add exception handling to converters themselves ([#3029](https://github.com/EQEmu/Server/pull/3029)) @Akkadius 2023-03-05
* Add more number formatters ([#2873](https://github.com/EQEmu/Server/pull/2873)) @Kinglykrab 2023-03-04
## [22.4.5] - 03/03/2023
## [22.4.5] - 03/03/2023
### Bots
@@ -2170,7 +2960,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Add IsFindable() and IsTrackable() to Perl/Lua ([#2996](https://github.com/EQEmu/Server/pull/2996)) @Kinglykrab 2023-03-01
* Add IsUnderwaterOnly() to Perl/Lua ([#2995](https://github.com/EQEmu/Server/pull/2995)) @Kinglykrab 2023-03-01
## [22.4.4] - 02/24/2023
## [22.4.4] - 02/24/2023
### Bots
@@ -2217,7 +3007,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Fix for Lore Conflict ([#2977](https://github.com/EQEmu/Server/pull/2977)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-24
## [22.4.3] - 02/21/2023
## [22.4.3] - 02/21/2023
### Bots
@@ -2264,7 +3054,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Add date to optional Drakkin Guktan Faction Update ([#2965](https://github.com/EQEmu/Server/pull/2965)) ([joligario](https://github.com/joligario)) 2023-02-19
## [22.4.2] - 02/18/2023
## [22.4.2] - 02/18/2023
### Content
@@ -2286,7 +3076,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Fix regression caused by #2932 ([#2956](https://github.com/EQEmu/Server/pull/2956)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-18
## [22.4.1] - 02/17/2023
## [22.4.1] - 02/17/2023
### Bots
@@ -2307,7 +3097,7 @@ Revert Perl regression in #3648 causing scripts to not reliably initialize on zo
* Fix rare out of bound issue when loading event types ([#2946](https://github.com/EQEmu/Server/pull/2946)) ([Akkadius](https://github.com/Akkadius)) 2023-02-17
* Turn off KILLED_NPC (trash) off by default ([#2948](https://github.com/EQEmu/Server/pull/2948)) ([Akkadius](https://github.com/Akkadius)) 2023-02-17
## [22.4.0] - 02/17/2023
## [22.4.0] - 02/17/2023
### Bots
+7
View File
@@ -31,6 +31,13 @@ IF (EQEMU_BUILD_STATIC)
ENDIF ()
ENDIF (EQEMU_BUILD_STATIC)
# Requires libgoogle-perftools-dev google-perftools packages for linux (debian)
IF(EQEMU_ADD_PROFILER)
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed")
ENDIF(EQEMU_ADD_PROFILER)
IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-DNOMINMAX)
+51 -153
View File
@@ -29,11 +29,19 @@
#include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
#include "../../common/repositories/base_data_repository.h"
#include "../../common/repositories/db_str_repository.h"
#include "../../common/repositories/skill_caps_repository.h"
#include "../../common/repositories/spells_new_repository.h"
#include "../../common/file.h"
#include "../../common/events/player_event_logs.h"
#include "../../common/skill_caps.h"
EQEmuLogSys LogSys;
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
ZoneStore zone_store;
PathManager path;
PlayerEventLogs player_event_logs;
void ExportSpells(SharedDatabase *db);
void ExportSkillCaps(SharedDatabase *db);
@@ -94,25 +102,22 @@ int main(int argc, char **argv)
->LoadLogDatabaseSettings()
->StartFileLogs();
std::string arg_1;
std::string export_type;
if (argv[1]) {
arg_1 = argv[1];
export_type = argv[1];
}
if (arg_1 == "spells") {
if (Strings::EqualFold(export_type, "spells")) {
ExportSpells(&content_db);
return 0;
}
if (arg_1 == "skills") {
} else if (Strings::EqualFold(export_type, "skills")) {
ExportSkillCaps(&content_db);
return 0;
}
if (arg_1 == "basedata") {
} else if (Strings::EqualFold(export_type, "basedata") || Strings::EqualFold(export_type, "base_data")) {
ExportBaseData(&content_db);
return 0;
}
if (arg_1 == "dbstring") {
} else if (Strings::EqualFold(export_type, "dbstr") || Strings::EqualFold(export_type, "dbstring")) {
ExportDBStrings(&database);
return 0;
}
@@ -127,186 +132,79 @@ int main(int argc, char **argv)
return 0;
}
void ExportSpells(SharedDatabase *db)
void ExportSpells(SharedDatabase* db)
{
LogInfo("Exporting Spells");
std::string file = fmt::format("{}/export/spells_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
std::ofstream file(fmt::format("{}/export/spells_us.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/spells_us.txt to write, skipping.");
return;
}
const std::string query = "SELECT * FROM spells_new ORDER BY id";
auto results = db->QueryDatabase(query);
const auto& lines = SpellsNewRepository::GetSpellFileLines(*db);
if (results.Success()) {
for (auto row = results.begin(); row != results.end(); ++row) {
std::string line;
unsigned int fields = results.ColumnCount();
for (unsigned int i = 0; i < fields; ++i) {
if (i != 0) {
line.push_back('^');
}
const std::string& file_string = Strings::Implode("\n", lines);
if (row[i] != nullptr) {
line += row[i];
}
}
file << file_string;
fprintf(f, "%s\n", line.c_str());
}
}
else {
}
file.close();
fclose(f);
LogInfo("Exported [{}] Spell{}", lines.size(), lines.size() != 1 ? "s" : "");
}
bool SkillUsable(SharedDatabase *db, int skill_id, int class_id)
void ExportSkillCaps(SharedDatabase* db)
{
bool res = false;
std::string query = StringFormat(
"SELECT max(cap) FROM skill_caps WHERE class=%d AND skillID=%d",
class_id, skill_id
);
auto results = db->QueryDatabase(query);
if (!results.Success()) {
return false;
}
if (results.RowCount() == 0) {
return false;
}
auto row = results.begin();
if (row[0] && Strings::ToInt(row[0]) > 0) {
return true;
}
return false;
}
int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level)
{
std::string query = StringFormat(
"SELECT cap FROM skill_caps WHERE class=%d AND skillID=%d AND level=%d",
class_id, skill_id, level
);
auto results = db->QueryDatabase(query);
if (!results.Success()) {
return 0;
}
if (results.RowCount() == 0) {
return 0;
}
auto row = results.begin();
return Strings::ToInt(row[0]);
}
void ExportSkillCaps(SharedDatabase *db)
{
LogInfo("Exporting Skill Caps");
std::string file = fmt::format("{}/export/SkillCaps.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
std::ofstream file(fmt::format("{}/export/SkillCaps.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/SkillCaps.txt to write, skipping.");
return;
}
for (int cl = 1; cl <= 16; ++cl) {
for (int skill = 0; skill <= 77; ++skill) {
if (SkillUsable(db, skill, cl)) {
int previous_cap = 0;
for (int level = 1; level <= 100; ++level) {
int cap = GetSkill(db, skill, cl, level);
if (cap < previous_cap) {
cap = previous_cap;
}
const auto& lines = SkillCapsRepository::GetSkillCapFileLines(*db);
fprintf(f, "%d^%d^%d^%d^0\n", cl, skill, level, cap);
previous_cap = cap;
}
}
}
}
const std::string& file_string = Strings::Implode("\n", lines);
fclose(f);
file << file_string;
file.close();
LogInfo("Exported [{}] Skill Cap{}", lines.size(), lines.size() != 1 ? "s" : "");
}
void ExportBaseData(SharedDatabase *db)
{
LogInfo("Exporting Base Data");
std::string file = fmt::format("{}/export/BaseData.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
std::ofstream file(fmt::format("{}/export/BaseData.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/BaseData.txt to write, skipping.");
return;
}
const std::string query = "SELECT * FROM base_data ORDER BY level, class";
auto results = db->QueryDatabase(query);
if (results.Success()) {
for (auto row = results.begin(); row != results.end(); ++row) {
std::string line;
unsigned int fields = results.ColumnCount();
for (unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
if (rowIndex != 0) {
line.push_back('^');
}
const auto& lines = BaseDataRepository::GetBaseDataFileLines(*db);
if (row[rowIndex] != nullptr) {
line += row[rowIndex];
}
}
const std::string& file_string = Strings::Implode("\n", lines);
fprintf(f, "%s\n", line.c_str());
}
}
file << file_string;
fclose(f);
file.close();
LogInfo("Exported [{}] Base Data Entr{}", lines.size(), lines.size() != 1 ? "ies" : "y");
}
void ExportDBStrings(SharedDatabase *db)
{
LogInfo("Exporting DB Strings");
std::string file = fmt::format("{}/export/dbstr_us.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "w");
if (!f) {
std::ofstream file(fmt::format("{}/export/dbstr_us.txt", path.GetServerPath()));
if (!file || !file.is_open()) {
LogError("Unable to open export/dbstr_us.txt to write, skipping.");
return;
}
fprintf(f, "Major^Minor^String(New)\n");
const std::string query = "SELECT * FROM db_str ORDER BY id, type";
auto results = db->QueryDatabase(query);
if (results.Success()) {
for (auto row = results.begin(); row != results.end(); ++row) {
std::string line;
unsigned int fields = results.ColumnCount();
for (unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
if (rowIndex != 0) {
line.push_back('^');
}
const auto& lines = DbStrRepository::GetDBStrFileLines(*db);
if (row[rowIndex] != nullptr) {
line += row[rowIndex];
}
}
const std::string& file_string = Strings::Implode("\n", lines);
fprintf(f, "%s\n", line.c_str());
}
}
file << file_string;
fclose(f);
file.close();
LogInfo("Exported [{}] Database String{}", lines.size(), lines.size() != 1 ? "s" : "");
}
+5 -3
View File
@@ -29,11 +29,13 @@
#include "../../common/path_manager.h"
#include "../../common/repositories/base_data_repository.h"
#include "../../common/file.h"
#include "../../common/events/player_event_logs.h"
EQEmuLogSys LogSys;
EQEmuLogSys LogSys;
WorldContentService content_service;
ZoneStore zone_store;
PathManager path;
ZoneStore zone_store;
PathManager path;
PlayerEventLogs player_event_logs;
void ImportSpells(SharedDatabase *db);
void ImportSkillCaps(SharedDatabase *db);
+21 -10
View File
@@ -2,6 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
SET(common_sources
base_packet.cpp
bazaar.cpp
bodytypes.cpp
classes.cpp
cli/eqemu_command_handler.cpp
compression.cpp
@@ -83,6 +85,7 @@ SET(common_sources
shared_tasks.cpp
shareddb.cpp
skills.cpp
skill_caps.cpp
spdat.cpp
strings.cpp
struct_strategy.cpp
@@ -155,6 +158,7 @@ SET(repositories
repositories/base/base_bugs_repository.h
repositories/base/base_bug_reports_repository.h
repositories/base/base_buyer_repository.h
repositories/base/base_buyer_trade_items_repository.h
repositories/base/base_character_activities_repository.h
repositories/base/base_character_alternate_abilities_repository.h
repositories/base/base_character_alt_currency_repository.h
@@ -176,6 +180,8 @@ SET(repositories
repositories/base/base_character_leadership_abilities_repository.h
repositories/base/base_character_material_repository.h
repositories/base/base_character_memmed_spells_repository.h
repositories/base/base_character_parcels_repository.h
repositories/base/base_character_parcels_containers_repository.h
repositories/base/base_character_peqzone_flags_repository.h
repositories/base/base_character_pet_buffs_repository.h
repositories/base/base_character_pet_info_repository.h
@@ -334,7 +340,8 @@ SET(repositories
repositories/books_repository.h
repositories/bugs_repository.h
repositories/bug_reports_repository.h
repositories/buyer_repository.h
repositories/buyer_buy_lines_repository.h
repositories/buyer_trade_items_repository.h
repositories/character_activities_repository.h
repositories/character_alternate_abilities_repository.h
repositories/character_alt_currency_repository.h
@@ -356,6 +363,8 @@ SET(repositories
repositories/character_leadership_abilities_repository.h
repositories/character_material_repository.h
repositories/character_memmed_spells_repository.h
repositories/character_parcels_repository.h
repositories/character_parcels_containers_repository.h
repositories/character_peqzone_flags_repository.h
repositories/character_pet_buffs_repository.h
repositories/character_pet_info_repository.h
@@ -492,10 +501,11 @@ SET(repositories
repositories/zone_repository.h
repositories/zone_points_repository.h
)
)
SET(common_headers
additive_lagged_fibonacci_engine.h
bazaar.h
base_packet.h
bodytypes.h
classes.h
@@ -592,7 +602,7 @@ SET(common_headers
ptimer.h
queue.h
races.h
raid.h
raid.h
random.h
rdtsc.h
rulesys.h
@@ -606,6 +616,7 @@ SET(common_headers
shared_tasks.h
shareddb.h
skills.h
skill_caps.h
spdat.h
strings.h
struct_strategy.h
@@ -681,13 +692,13 @@ SOURCE_GROUP(Event FILES
event/event_loop.h
event/timer.h
event/task.h
)
)
SOURCE_GROUP(Json FILES
json/json.h
json/jsoncpp.cpp
json/json-forwards.h
)
)
SOURCE_GROUP(Net FILES
net/console_server.cpp
@@ -724,7 +735,7 @@ SOURCE_GROUP(Net FILES
net/websocket_server.h
net/websocket_server_connection.cpp
net/websocket_server_connection.h
)
)
SOURCE_GROUP(Patches FILES
patches/patches.h
@@ -768,12 +779,12 @@ SOURCE_GROUP(Patches FILES
patches/titanium_limits.cpp
patches/uf.cpp
patches/uf_limits.cpp
)
)
SOURCE_GROUP(StackWalker FILES
StackWalker/StackWalker.h
StackWalker/StackWalker.cpp
)
)
SOURCE_GROUP(Util FILES
util/memory_stream.h
@@ -781,7 +792,7 @@ SOURCE_GROUP(Util FILES
util/directory.h
util/uuid.cpp
util/uuid.h
)
)
INCLUDE_DIRECTORIES(Patches SocketLib StackWalker)
@@ -794,6 +805,6 @@ ENDIF (UNIX)
IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
ENDIF()
ENDIF ()
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+359
View File
@@ -0,0 +1,359 @@
#include "bazaar.h"
#include "../../common/item_instance.h"
#include "repositories/trader_repository.h"
#include <memory>
std::vector<BazaarSearchResultsFromDB_Struct>
Bazaar::GetSearchResults(
SharedDatabase &db,
BazaarSearchCriteria_Struct search,
uint32 char_zone_id
)
{
LogTrading(
"Searching for items with search criteria - item_name [{}] min_cost [{}] max_cost [{}] min_level [{}] "
"max_level [{}] max_results [{}] prestige [{}] augment [{}] trader_entity_id [{}] trader_id [{}] "
"search_scope [{}] char_zone_id [{}]",
search.item_name,
search.min_cost,
search.max_cost,
search.min_level,
search.max_level,
search.max_results,
search.prestige,
search.augment,
search.trader_entity_id,
search.trader_id,
search.search_scope,
char_zone_id
);
std::string search_criteria_trader("TRUE ");
if (search.search_scope == NonRoFBazaarSearchScope) {
search_criteria_trader.append(
fmt::format(
" AND trader.char_entity_id = {} AND trader.char_zone_id = {}",
search.trader_entity_id,
Zones::BAZAAR
)
);
}
else if (search.search_scope == Local_Scope) {
search_criteria_trader.append(fmt::format(" AND trader.char_zone_id = {}", char_zone_id));
}
else if (search.trader_id > 0) {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
}
if (search.min_cost != 0) {
search_criteria_trader.append(fmt::format(" AND trader.item_cost >= {}", search.min_cost * 1000));
}
if (search.max_cost != 0) {
search_criteria_trader.append(fmt::format(" AND trader.item_cost <= {}", (uint64) search.max_cost * 1000));
}
// not yet implemented
// if (search.prestige != 0) {
// 0xffffffff prestige only, 0xfffffffe non-prestige, 0 all
// search_criteria.append(fmt::format(" AND items.type = {} ", search.prestige));
// }
std::string query = fmt::format(
"SELECT COUNT(item_id), trader.char_id, trader.item_id, trader.item_sn, trader.item_charges, trader.item_cost, "
"trader.slot_id, SUM(trader.item_charges), trader.char_zone_id, trader.char_entity_id, character_data.name, "
"aug_slot_1, aug_slot_2, aug_slot_3, aug_slot_4, aug_slot_5, aug_slot_6 "
"FROM trader, character_data "
"WHERE {} AND trader.char_id = character_data.id "
"GROUP BY trader.item_sn, trader.item_charges, trader.char_id",
search_criteria_trader.c_str()
);
std::vector<BazaarSearchResultsFromDB_Struct> all_entries;
auto results = db.QueryDatabase(query);
if (!results.Success()) {
return all_entries;
}
struct ItemSearchType {
EQ::item::ItemType type;
bool condition;
};
struct AddititiveSearchCriteria {
bool should_check;
bool condition;
};
for (auto row: results) {
BazaarSearchResultsFromDB_Struct r{};
r.item_id = Strings::ToInt(row[2]);
r.charges = Strings::ToInt(row[4]);
auto item = db.GetItem(r.item_id);
if (!item) {
continue;
}
uint32 aug_slot_1 = Strings::ToUnsignedInt(row[11]);
uint32 aug_slot_2 = Strings::ToUnsignedInt(row[12]);
uint32 aug_slot_3 = Strings::ToUnsignedInt(row[13]);
uint32 aug_slot_4 = Strings::ToUnsignedInt(row[14]);
uint32 aug_slot_5 = Strings::ToUnsignedInt(row[15]);
uint32 aug_slot_6 = Strings::ToUnsignedInt(row[16]);
std::unique_ptr<EQ::ItemInstance> inst(
db.CreateItem(
item,
r.charges,
aug_slot_1,
aug_slot_2,
aug_slot_3,
aug_slot_4,
aug_slot_5,
aug_slot_6
)
);
if (!inst->GetItem()) {
continue;
}
r.count = Strings::ToInt(row[0]);
r.trader_id = Strings::ToInt(row[1]);
r.serial_number = Strings::ToInt(row[3]);
r.cost = Strings::ToInt(row[5]);
r.slot_id = Strings::ToInt(row[6]);
r.sum_charges = Strings::ToInt(row[7]);
r.stackable = item->Stackable;
r.icon_id = item->Icon;
r.trader_zone_id = Strings::ToInt(row[8]);
r.trader_entity_id = Strings::ToInt(row[9]);
r.serial_number_RoF = fmt::format("{:016}\0", Strings::ToInt(row[3]));
r.item_name = fmt::format("{:.63}\0", item->Name);
r.trader_name = fmt::format("{:.63}\0", std::string(row[10]).c_str());
LogTradingDetail(
"Searching against item [{}] ({}) for trader [{}]",
item->Name,
item->ID,
r.trader_name
);
// item stat searches
std::map<uint32, uint32> item_stat_searches = {
{STAT_AC, inst->GetItemArmorClass(true)},
{STAT_AGI, static_cast<uint32>(inst->GetItemAgi(true))},
{STAT_CHA, static_cast<uint32>(inst->GetItemCha(true))},
{STAT_DEX, static_cast<uint32>(inst->GetItemDex(true))},
{STAT_INT, static_cast<uint32>(inst->GetItemInt(true))},
{STAT_STA, static_cast<uint32>(inst->GetItemSta(true))},
{STAT_STR, static_cast<uint32>(inst->GetItemStr(true))},
{STAT_WIS, static_cast<uint32>(inst->GetItemWis(true))},
{STAT_COLD, static_cast<uint32>(inst->GetItemCR(true))},
{STAT_DISEASE, static_cast<uint32>(inst->GetItemDR(true))},
{STAT_FIRE, static_cast<uint32>(inst->GetItemFR(true))},
{STAT_MAGIC, static_cast<uint32>(inst->GetItemMR(true))},
{STAT_POISON, static_cast<uint32>(inst->GetItemPR(true))},
{STAT_HP, static_cast<uint32>(inst->GetItemHP(true))},
{STAT_MANA, static_cast<uint32>(inst->GetItemMana(true))},
{STAT_ENDURANCE, static_cast<uint32>(inst->GetItemEndur(true))},
{STAT_ATTACK, static_cast<uint32>(inst->GetItemAttack(true))},
{STAT_HP_REGEN, static_cast<uint32>(inst->GetItemRegen(true))},
{STAT_MANA_REGEN, static_cast<uint32>(inst->GetItemManaRegen(true))},
{STAT_HASTE, static_cast<uint32>(inst->GetItemHaste(true))},
{STAT_DAMAGE_SHIELD, static_cast<uint32>(inst->GetItemDamageShield(true))},
{STAT_DS_MITIGATION, static_cast<uint32>(inst->GetItemDSMitigation(true))},
{STAT_HEAL_AMOUNT, static_cast<uint32>(inst->GetItemHealAmt(true))},
{STAT_SPELL_DAMAGE, static_cast<uint32>(inst->GetItemSpellDamage(true))},
{STAT_CLAIRVOYANCE, static_cast<uint32>(inst->GetItemClairvoyance(true))},
{STAT_HEROIC_AGILITY, static_cast<uint32>(inst->GetItemHeroicAgi(true))},
{STAT_HEROIC_CHARISMA, static_cast<uint32>(inst->GetItemHeroicCha(true))},
{STAT_HEROIC_DEXTERITY, static_cast<uint32>(inst->GetItemHeroicDex(true))},
{STAT_HEROIC_INTELLIGENCE, static_cast<uint32>(inst->GetItemHeroicInt(true))},
{STAT_HEROIC_STAMINA, static_cast<uint32>(inst->GetItemHeroicSta(true))},
{STAT_HEROIC_STRENGTH, static_cast<uint32>(inst->GetItemHeroicStr(true))},
{STAT_HEROIC_WISDOM, static_cast<uint32>(inst->GetItemHeroicWis(true))},
{STAT_BASH, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillBash, true))},
{STAT_BACKSTAB, static_cast<uint32>(inst->GetItemBackstabDamage(true))},
{STAT_DRAGON_PUNCH, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillDragonPunch, true))},
{STAT_EAGLE_STRIKE, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillEagleStrike, true))},
{STAT_FLYING_KICK, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillFlyingKick, true))},
{STAT_KICK, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillKick, true))},
{STAT_ROUND_KICK, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillRoundKick, true))},
{STAT_TIGER_CLAW, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillTigerClaw, true))},
{STAT_FRENZY, static_cast<uint32>(inst->GetItemSkillsStat(EQ::skills::SkillFrenzy, true))},
};
r.item_stat = item_stat_searches.contains(search.item_stat) ? item_stat_searches[search.item_stat] : 0;
if (item_stat_searches.contains(search.item_stat) && item_stat_searches[search.item_stat] <= 0) {
continue;
}
static std::map<uint8, uint32> item_slot_searches = {
{EQ::invslot::slotCharm, 1},
{EQ::invslot::slotEar1, 2},
{EQ::invslot::slotHead, 4},
{EQ::invslot::slotFace, 8},
{EQ::invslot::slotEar2, 16},
{EQ::invslot::slotNeck, 32},
{EQ::invslot::slotShoulders, 64},
{EQ::invslot::slotArms, 128},
{EQ::invslot::slotBack, 256},
{EQ::invslot::slotWrist1, 512},
{EQ::invslot::slotWrist2, 1024},
{EQ::invslot::slotRange, 2048},
{EQ::invslot::slotHands, 4096},
{EQ::invslot::slotPrimary, 8192},
{EQ::invslot::slotSecondary, 16384},
{EQ::invslot::slotFinger1, 32768},
{EQ::invslot::slotFinger2, 65536},
{EQ::invslot::slotChest, 131072},
{EQ::invslot::slotLegs, 262144},
{EQ::invslot::slotFeet, 524288},
{EQ::invslot::slotWaist, 1048576},
{EQ::invslot::slotPowerSource, 2097152},
{EQ::invslot::slotAmmo, 4194304},
};
auto GetEquipmentSlotBit = [&](uint32 slot) -> uint32 {
return item_slot_searches.contains(slot) ? item_slot_searches[slot] : 0;
};
auto FindItemAugSlot = [&]() -> bool {
for (auto const &s: inst->GetItem()->AugSlotType) {
return s == search.augment;
}
return false;
};
// item type searches
std::vector<ItemSearchType> item_search_types = {
{EQ::item::ItemType::ItemTypeAll, true},
{EQ::item::ItemType::ItemTypeBook, item->ItemClass == EQ::item::ItemType::ItemTypeBook},
{EQ::item::ItemType::ItemTypeContainer, item->ItemClass == EQ::item::ItemType::ItemTypeContainer},
{EQ::item::ItemType::ItemTypeAllEffects, item->Scroll.Effect > 0 && item->Scroll.Effect < 65000},
{EQ::item::ItemType::ItemTypeUnknown9, item->Worn.Effect == 998},
{EQ::item::ItemType::ItemTypeUnknown10, item->Worn.Effect >= 1298 && item->Worn.Effect <= 1307},
{EQ::item::ItemType::ItemTypeFocusEffect, item->Focus.Effect > 0},
{EQ::item::ItemType::ItemTypeArmor, item->ItemType == EQ::item::ItemType::ItemTypeArmor},
{EQ::item::ItemType::ItemType1HBlunt, item->ItemType == EQ::item::ItemType::ItemType1HBlunt},
{EQ::item::ItemType::ItemType1HPiercing, item->ItemType == EQ::item::ItemType::ItemType1HPiercing},
{EQ::item::ItemType::ItemType1HSlash, item->ItemType == EQ::item::ItemType::ItemType1HSlash},
{EQ::item::ItemType::ItemType2HBlunt, item->ItemType == EQ::item::ItemType::ItemType2HBlunt},
{EQ::item::ItemType::ItemType2HSlash, item->ItemType == EQ::item::ItemType::ItemType2HSlash},
{EQ::item::ItemType::ItemTypeBow, item->ItemType == EQ::item::ItemType::ItemTypeBow},
{EQ::item::ItemType::ItemTypeShield, item->ItemType == EQ::item::ItemType::ItemTypeShield},
{EQ::item::ItemType::ItemTypeMisc, item->ItemType == EQ::item::ItemType::ItemTypeMisc},
{EQ::item::ItemType::ItemTypeFood, item->ItemType == EQ::item::ItemType::ItemTypeFood},
{EQ::item::ItemType::ItemTypeDrink, item->ItemType == EQ::item::ItemType::ItemTypeDrink},
{EQ::item::ItemType::ItemTypeLight, item->ItemType == EQ::item::ItemType::ItemTypeLight},
{EQ::item::ItemType::ItemTypeCombinable, item->ItemType == EQ::item::ItemType::ItemTypeCombinable},
{EQ::item::ItemType::ItemTypeBandage, item->ItemType == EQ::item::ItemType::ItemTypeBandage},
{EQ::item::ItemType::ItemTypeSmallThrowing, item->ItemType == EQ::item::ItemType::ItemTypeSmallThrowing ||
item->ItemType == EQ::item::ItemType::ItemTypeLargeThrowing},
{EQ::item::ItemType::ItemTypeSpell, item->ItemType == EQ::item::ItemType::ItemTypeSpell},
{EQ::item::ItemType::ItemTypePotion, item->ItemType == EQ::item::ItemType::ItemTypePotion},
{EQ::item::ItemType::ItemTypeBrassInstrument, item->ItemType == EQ::item::ItemType::ItemTypeBrassInstrument},
{EQ::item::ItemType::ItemTypeWindInstrument, item->ItemType == EQ::item::ItemType::ItemTypeWindInstrument},
{EQ::item::ItemType::ItemTypeStringedInstrument, item->ItemType == EQ::item::ItemType::ItemTypeStringedInstrument},
{EQ::item::ItemType::ItemTypePercussionInstrument, item->ItemType == EQ::item::ItemType::ItemTypePercussionInstrument},
{EQ::item::ItemType::ItemTypeArrow, item->ItemType == EQ::item::ItemType::ItemTypeArrow},
{EQ::item::ItemType::ItemTypeJewelry, item->ItemType == EQ::item::ItemType::ItemTypeJewelry},
{EQ::item::ItemType::ItemTypeNote, item->ItemType == EQ::item::ItemType::ItemTypeNote},
{EQ::item::ItemType::ItemTypeKey, item->ItemType == EQ::item::ItemType::ItemTypeKey},
{EQ::item::ItemType::ItemType2HPiercing, item->ItemType == EQ::item::ItemType::ItemType2HPiercing},
{EQ::item::ItemType::ItemTypeAlcohol, item->ItemType == EQ::item::ItemType::ItemTypeAlcohol},
{EQ::item::ItemType::ItemTypeMartial, item->ItemType == EQ::item::ItemType::ItemTypeMartial},
{EQ::item::ItemType::ItemTypeAugmentation, item->ItemType == EQ::item::ItemType::ItemTypeAugmentation},
{EQ::item::ItemType::ItemTypeAlternateAbility, item->ItemType == EQ::item::ItemType::ItemTypeAlternateAbility},
{EQ::item::ItemType::ItemTypeCount, item->ItemType == EQ::item::ItemType::ItemTypeCount},
{EQ::item::ItemType::ItemTypeCollectible, item->ItemType == EQ::item::ItemType::ItemTypeCollectible}
};
bool met_filter = false;
bool has_filter = false;
for (auto &i: item_search_types) {
if (i.type == search.type) {
has_filter = true;
if (i.condition) {
LogTradingDetail("Item [{}] met search criteria for type [{}]", item->Name, uint8(i.type));
met_filter = true;
break;
}
}
}
if (has_filter && !met_filter) {
continue;
}
// TODO: Add catch-all item type filter for specific item types
// item additive searches
std::vector<AddititiveSearchCriteria> item_additive_searches = {
{
.should_check = search.min_level != 1 && inst->GetItemRequiredLevel(true) > 0,
.condition = inst->GetItemRequiredLevel(true) >= search.min_level
},
{
.should_check = search.max_level != 1 && inst->GetItemRequiredLevel(true) > 0,
.condition = inst->GetItemRequiredLevel(true) <= search.max_level
},
{
.should_check = !std::string(search.item_name).empty(),
.condition = Strings::ContainsLower(item->Name, search.item_name)
},
{
.should_check = search._class != 0xFFFFFFFF,
.condition = static_cast<bool>(item->Classes & GetPlayerClassBit(search._class))
},
{
.should_check = search.race != 0xFFFFFFFF,
.condition = static_cast<bool>(item->Races & GetPlayerRaceBit(GetRaceIDFromPlayerRaceValue(search.race)))
},
{
.should_check = search.augment != 0,
.condition = FindItemAugSlot()
},
{
.should_check = search.slot != 0xFFFFFFFF,
.condition = static_cast<bool>(item->Slots & GetEquipmentSlotBit(search.slot))
},
};
bool should_add = true;
for (auto &i: item_additive_searches) {
LogTradingDetail(
"Checking item [{}] for search criteria - should_check [{}] condition [{}]",
item->Name,
i.should_check,
i.condition
);
if (i.should_check && !i.condition) {
should_add = false;
continue;
}
}
if (!should_add) {
continue;
}
LogTradingDetail("Found item [{}] meeting search criteria.", r.item_name);
all_entries.push_back(r);
}
if (all_entries.size() > search.max_results) {
all_entries.resize(search.max_results);
}
LogTrading("Returning [{}] items from search results", all_entries.size());
return all_entries;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef EQEMU_BAZAAR_H
#define EQEMU_BAZAAR_H
#include <vector>
#include "shareddb.h"
class Bazaar {
public:
static std::vector<BazaarSearchResultsFromDB_Struct>
GetSearchResults(SharedDatabase &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id);
};
#endif //EQEMU_BAZAAR_H
+12
View File
@@ -0,0 +1,12 @@
#include "../common/global_define.h"
#include "../common/bodytypes.h"
std::string BodyType::GetName(uint8 body_type_id)
{
return IsValid(body_type_id) ? body_type_names[body_type_id] : "UNKNOWN BODY TYPE";
}
bool BodyType::IsValid(uint8 body_type_id)
{
return body_type_names.find(body_type_id) != body_type_names.end();
}
+91 -45
View File
@@ -18,50 +18,96 @@
#ifndef BODYTYPES_H
#define BODYTYPES_H
typedef enum {
BT_Humanoid = 1,
BT_Lycanthrope = 2,
BT_Undead = 3,
BT_Giant = 4,
BT_Construct = 5,
BT_Extraplanar = 6,
BT_Magical = 7, //this name might be a bit off,
BT_SummonedUndead = 8,
BT_RaidGiant = 9, //Velious era Raid Giant
BT_RaidColdain = 10, //Velious era Raid Coldain
BT_NoTarget = 11, //no name, can't target this bodytype
BT_Vampire = 12,
BT_Atenha_Ra = 13,
BT_Greater_Akheva = 14,
BT_Khati_Sha = 15,
BT_Seru = 16,
BT_Grieg_Veneficus = 17,
BT_Draz_Nurakk = 18,
BT_Zek = 19, //"creatures from the Plane of War."
BT_Luggald = 20,
BT_Animal = 21,
BT_Insect = 22,
BT_Monster = 23,
BT_Summoned = 24, //Elemental?
BT_Plant = 25,
BT_Dragon = 26,
BT_Summoned2 = 27,
BT_Summoned3 = 28,
BT_Dragon2 = 29, //database data indicates this is a dragon type (kunark and DoN?)
BT_VeliousDragon = 30, //might not be a tight set
BT_Familiar = 31,
BT_Dragon3 = 32,
BT_Boxes = 33,
BT_Muramite = 34, //tribal dudes
// ...
BT_NoTarget2 = 60,
// ...
BT_SwarmPet = 63, //Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general.
BT_MonsterSummon = 64,
// 65, trap or effect related?
BT_InvisMan = 66, //no name, seen on 'InvisMan', can be /targeted
BT_Special = 67
} bodyType;
/* bodytypes above 64 make the mob not show up */
#include "types.h"
#include <map>
#include <string>
// body types above 64 make the mob invisible
namespace BodyType {
constexpr uint8 Humanoid = 1;
constexpr uint8 Lycanthrope = 2;
constexpr uint8 Undead = 3;
constexpr uint8 Giant = 4;
constexpr uint8 Construct = 5;
constexpr uint8 Extraplanar = 6;
constexpr uint8 Magical = 7; // this name might be a bit off,
constexpr uint8 SummonedUndead = 8;
constexpr uint8 RaidGiant = 9; // Velious era Raid Giant
constexpr uint8 RaidColdain = 10; // Velious era Raid Coldain
constexpr uint8 NoTarget = 11; // no name, can't target this bodytype
constexpr uint8 Vampire = 12;
constexpr uint8 AtenHaRa = 13;
constexpr uint8 GreaterAkheva = 14;
constexpr uint8 KhatiSha = 15;
constexpr uint8 Seru = 16;
constexpr uint8 GriegVeneficus = 17;
constexpr uint8 DrazNurakk = 18;
constexpr uint8 Zek = 19; //"creatures from the Plane of War."
constexpr uint8 Luggald = 20;
constexpr uint8 Animal = 21;
constexpr uint8 Insect = 22;
constexpr uint8 Monster = 23;
constexpr uint8 Summoned = 24; // Elemental?
constexpr uint8 Plant = 25;
constexpr uint8 Dragon = 26;
constexpr uint8 Summoned2 = 27;
constexpr uint8 Summoned3 = 28;
constexpr uint8 Dragon2 = 29; // database data indicates this is a dragon type (Kunark and DoN?)
constexpr uint8 VeliousDragon = 30; // might not be a tight set
constexpr uint8 Familiar = 31;
constexpr uint8 Dragon3 = 32;
constexpr uint8 Boxes = 33;
constexpr uint8 Muramite = 34; // tribal dudes
constexpr uint8 NoTarget2 = 60;
constexpr uint8 SwarmPet = 63; // Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general.
constexpr uint8 MonsterSummon = 64;
constexpr uint8 InvisibleMan = 66; // no name, seen on 'InvisMan', can be /targeted
constexpr uint8 Special = 67;
std::string GetName(uint8 body_type_id);
bool IsValid(uint8 body_type_id);
}
static std::map<uint8, std::string> body_type_names = {
{ BodyType::Humanoid, "Humanoid" },
{ BodyType::Lycanthrope, "Lycanthrope" },
{ BodyType::Undead, "Undead" },
{ BodyType::Giant, "Giant" },
{ BodyType::Construct, "Construct" },
{ BodyType::Extraplanar, "Extraplanar" },
{ BodyType::Magical, "Magical" },
{ BodyType::SummonedUndead, "Summoned Undead" },
{ BodyType::RaidGiant, "Raid Giant" },
{ BodyType::RaidColdain, "Raid Coldain" },
{ BodyType::NoTarget, "Untargetable" },
{ BodyType::Vampire, "Vampire" },
{ BodyType::AtenHaRa, "Aten Ha Ra" },
{ BodyType::GreaterAkheva, "Greater Akheva" },
{ BodyType::KhatiSha, "Khati Sha" },
{ BodyType::Seru, "Seru" },
{ BodyType::GriegVeneficus, "Grieg Veneficus" },
{ BodyType::DrazNurakk, "Draz Nurakk" },
{ BodyType::Zek, "Zek" },
{ BodyType::Luggald, "Luggald" },
{ BodyType::Animal, "Animal" },
{ BodyType::Insect, "Insect" },
{ BodyType::Monster, "Monster" },
{ BodyType::Summoned, "Summoned" },
{ BodyType::Plant, "Plant" },
{ BodyType::Dragon, "Dragon" },
{ BodyType::Summoned2, "Summoned 2" },
{ BodyType::Summoned3, "Summoned 3" },
{ BodyType::Dragon2, "Dragon 2" },
{ BodyType::VeliousDragon, "Velious Dragon" },
{ BodyType::Familiar, "Familiar" },
{ BodyType::Dragon3, "Dragon 3" },
{ BodyType::Boxes, "Boxes" },
{ BodyType::Muramite, "Muramite" },
{ BodyType::NoTarget2, "Untargetable 2" },
{ BodyType::SwarmPet, "Swarm Pet" },
{ BodyType::MonsterSummon, "Monster Summon" },
{ BodyType::InvisibleMan, "Invisible Man" },
{ BodyType::Special, "Special" },
};
#endif
+134 -25
View File
@@ -1,28 +1,12 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "world_content_service.h"
#include <utility>
#include <glm/vec3.hpp>
#include "../database.h"
#include "../rulesys.h"
#include "../eqemu_logsys.h"
#include "../repositories/content_flags_repository.h"
#include "../repositories/instance_list_repository.h"
#include "../zone_store.h"
WorldContentService::WorldContentService()
@@ -119,7 +103,7 @@ std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
/**
* @param content_flags
*/
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags)
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags> &content_flags)
{
WorldContentService::content_flags = content_flags;
}
@@ -167,14 +151,14 @@ bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f)
}
// if we don't have any enabled flag in enabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags)) {
for (const auto &flag: Strings::Split(f.content_flags)) {
if (!Strings::Contains(GetContentFlagsEnabled(), flag)) {
return false;
}
}
// if we don't have any disabled flag in disabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags_disabled)) {
for (const auto &flag: Strings::Split(f.content_flags_disabled)) {
if (!Strings::Contains(GetContentFlagsDisabled(), flag)) {
return false;
}
@@ -195,11 +179,13 @@ void WorldContentService::ReloadContentFlags()
LogInfo(
"Loaded content flag [{}] [{}]",
f.flag_name,
(f.enabled ? "Enabled" : "Disabled")
(f.enabled ? "enabled" : "disabled")
);
}
SetContentFlags(set_content_flags);
LoadStaticGlobalZoneInstances();
zone_store.LoadZones(*m_content_database);
}
Database *WorldContentService::GetDatabase() const
@@ -214,6 +200,18 @@ WorldContentService *WorldContentService::SetDatabase(Database *database)
return this;
}
Database *WorldContentService::GetContentDatabase() const
{
return m_content_database;
}
WorldContentService *WorldContentService::SetContentDatabase(Database *database)
{
WorldContentService::m_content_database = database;
return this;
}
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
{
auto flags = ContentFlagsRepository::GetWhere(
@@ -238,3 +236,114 @@ void WorldContentService::SetContentFlag(const std::string &content_flag_name, b
ReloadContentFlags();
}
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
{
auto r = FindZone(zc->zoneID, zc->instanceID);
if (r.zone_id == 0) {
return;
}
zc->instanceID = r.instance.id;
}
// LoadStaticGlobalZoneInstances loads all static global zone instances
// these are zones that are never set to expire and are global
// these are used commonly in v1/v2/v3 versions of the same zone for expansion routing
WorldContentService *WorldContentService::LoadStaticGlobalZoneInstances()
{
m_zone_static_instances = InstanceListRepository::GetWhere(
*GetDatabase(),
fmt::format("never_expires = 1 AND is_global = 1")
);
LogInfo("Loaded [{}] zone_instances", m_zone_static_instances.size());
return this;
}
// FindZone handles content and context aware zone routing (middleware)
//
// this is a middleware function that is meant to be used in the zone change process
// this hooks all core zone changes within the server and routes the player to the correct zone
// returning a zone_id of non-zero means the middleware will route the player
// returning a zone_id of 0 means the middleware will not route the player
// this is useful for handling multiple versions of the same zone
//
// implementation >
// the zoning and process spawning logic already is handled by two keys "zone_id" and "instance_id"
// we leverage static, never expires instances to handle this and client still sees it as a normal zone
//
// content awareness >
// simply use the zone_id, server content settings and the middleware will handle the rest
// you don't have to think about instances in any data tables (use instance_id 0)
// you don't have to keep track of instance ids in scripts (use instance_id 0)
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
// we decide to route the client to the correct version of the zone based on the current server side expansion
//
// example >
// we want to route players to the correct version of lavastorm based on the current server side expansion (DoesZonePassContentFiltering)
// lavastorm (pre-don) version 0 (classic)
// zone table entry for version = 0, min_expansion = 0, max_expansion = 8
// instance_list table entry for lavastorm has version = 0, is_global = 1, never_expires = 1
// lavastorm (don) version 1
// zone table entry for version = 1, min_expansion = 9, max_expansion = 99
// instance_list table entry for lavastorm has version = 1, is_global = 1, never_expires = 1
WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
{
for (const auto &z: zone_store.GetZones()) {
for (auto &i: m_zone_static_instances) {
if (
z.zoneidnumber == zone_id &&
DoesZonePassContentFiltering(z) &&
i.zone == zone_id &&
i.version == z.version) {
if (instance_id > 0 && i.id != instance_id) {
continue;
}
LogInfo(
"Routed player to public static instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
i.id,
z.short_name,
z.zoneidnumber,
z.version,
z.long_name,
i.notes
);
return WorldContentService::FindZoneResult{
.zone_id = static_cast<uint32>(z.zoneidnumber),
.instance = i,
.zone = z
};
}
}
}
return WorldContentService::FindZoneResult{.zone_id = 0};
}
bool WorldContentService::IsInPublicStaticInstance(uint32 instance_id)
{
for (auto &i: m_zone_static_instances) {
if (i.id == instance_id) {
return true;
}
}
return false;
}
bool WorldContentService::DoesZonePassContentFiltering(const ZoneRepository::Zone &z)
{
auto f = ContentFlags{
.min_expansion = z.min_expansion,
.max_expansion = z.max_expansion,
.content_flags = z.content_flags,
.content_flags_disabled = z.content_flags_disabled
};
return DoesPassContentFiltering(f);
}
+22 -20
View File
@@ -1,29 +1,11 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_WORLD_CONTENT_SERVICE_H
#define EQEMU_WORLD_CONTENT_SERVICE_H
#include <string>
#include <vector>
#include "../repositories/content_flags_repository.h"
#include "../repositories/zone_repository.h"
#include "../repositories/instance_list_repository.h"
class Database;
@@ -178,18 +160,38 @@ public:
WorldContentService * SetExpansionContext();
bool DoesPassContentFiltering(const ContentFlags& f);
bool DoesZonePassContentFiltering(const ZoneRepository::Zone& z);
WorldContentService * SetDatabase(Database *database);
Database *GetDatabase() const;
WorldContentService * SetContentDatabase(Database *database);
Database *GetContentDatabase() const;
void SetContentFlag(const std::string &content_flag_name, bool enabled);
void HandleZoneRoutingMiddleware(ZoneChange_Struct *zc);
struct FindZoneResult {
uint32 zone_id = 0;
InstanceListRepository::InstanceList instance;
ZoneRepository::Zone zone;
};
FindZoneResult FindZone(uint32 zone_id, uint32 instance_id);
bool IsInPublicStaticInstance(uint32 instance_id);
private:
int current_expansion{};
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
// reference to database
Database *m_database;
Database *m_content_database;
// holds a record of the zone table from the database
WorldContentService *LoadStaticGlobalZoneInstances();
std::vector<InstanceListRepository::InstanceList> m_zone_static_instances;
};
extern WorldContentService content_service;
+1 -1
View File
@@ -15,7 +15,7 @@
#include <cstdio>
#include <vector>
#if WINDOWS
#ifdef _WINDOWS
#define popen _popen
#endif
+1287 -1630
View File
File diff suppressed because it is too large Load Diff
+151 -139
View File
@@ -18,8 +18,8 @@
#ifndef EQEMU_DATABASE_H
#define EQEMU_DATABASE_H
#define AUTHENTICATION_TIMEOUT 60
#define INVALID_ID 0xFFFFFFFF
#define AUTHENTICATION_TIMEOUT 60
#define INVALID_ID 0xFFFFFFFF
#include "global_define.h"
#include "eqemu_logsys.h"
@@ -38,8 +38,7 @@
class MySQLRequestResult;
class Client;
namespace EQ
{
namespace EQ {
class InventoryProfile;
}
@@ -52,10 +51,11 @@ struct npcDecayTimes_Struct {
struct VarCache_Struct {
std::map<std::string, std::string> m_cache;
uint32 last_update;
uint32 last_update;
VarCache_Struct() : last_update(0) { }
void Add(const std::string &key, const std::string &value) { m_cache[key] = value; }
const std::string *Get(const std::string &key) {
void Add(const std::string& key, const std::string& value) { m_cache[key] = value; }
const std::string* Get(const std::string& key)
{
auto it = m_cache.find(key);
return (it != m_cache.end() ? &it->second : nullptr);
}
@@ -76,37 +76,33 @@ class PTimerList;
#define SQL(...) #__VA_ARGS__
class LogSettings;
class Database : public DBcore {
public:
Database();
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port, std::string connection_label = "default");
Database(
const std::string& host,
const std::string& user,
const std::string& password,
const std::string& database,
uint32 port
);
bool Connect(
const std::string& host,
const std::string& user,
const std::string& password,
const std::string& database,
uint32 port,
std::string connection_label = "default"
);
~Database();
/* Character Creation */
bool CreateCharacter(
uint32 account_id,
char *name,
uint16 gender,
uint16 race,
uint16 class_,
uint8 str,
uint8 sta,
uint8 cha,
uint8 dex,
uint8 int_,
uint8 agi,
uint8 wis,
uint8 face
);
bool DeleteCharacter(char *character_name);
bool MoveCharacterToZone(const char *charname, uint32 zone_id);
bool DeleteCharacter(const std::string& name);
bool MoveCharacterToZone(const std::string& name, uint32 zone_id);
bool MoveCharacterToZone(uint32 character_id, uint32 zone_id);
bool ReserveName(uint32 account_id, char *name);
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp);
bool UpdateName(const char *oldname, const char *newname);
bool ReserveName(uint32 account_id, const std::string& name);
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
bool UpdateName(const std::string& old_name, const std::string& new_name);
bool CopyCharacter(
const std::string& source_character_name,
const std::string& destination_character_name,
@@ -114,161 +110,177 @@ public:
);
/* General Information Queries */
bool AddBannedIP(const std::string& banned_ip, const std::string& notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(const std::string& name);
bool CheckBannedIPs(const std::string& login_ip); //Check incoming connection against banned IP table.
bool CheckGMIPs(const std::string& login_ip, uint32 account_id);
bool CheckNameFilter(const std::string& name, bool surname = false);
bool IsNameUsed(const std::string& name);
bool AddBannedIP(std::string banned_ip, std::string notes); //Add IP address to the banned_ips table.
bool AddToNameFilter(std::string name);
bool CheckBannedIPs(std::string login_ip); //Check incoming connection against banned IP table.
bool CheckGMIPs(std::string login_ip, uint32 account_id);
bool CheckNameFilter(std::string name, bool surname = false);
bool CheckUsedName(std::string name);
uint32 GetAccountIDByChar(const std::string& name, uint32* character_id = 0);
uint32 GetAccountIDByChar(uint32 character_id);
uint32 GetAccountIDByName(const std::string& account_name, const std::string& loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const std::string& name);
uint32 GetGuildIDByCharID(uint32 character_id);
uint32 GetGroupIDByCharID(uint32 character_id);
uint32 GetRaidIDByCharID(uint32 character_id);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id);
uint32 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id);
uint32 GetRaidIDByCharID(uint32 char_id);
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
void GetCharName(uint32 char_id, char* name);
std::string GetCharNameByID(uint32 char_id);
std::string GetNPCNameByID(uint32 npc_id);
std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 account_id, std::string login_ip);
const std::string GetAccountName(uint32 account_id, uint32* lsaccount_id = 0);
const std::string GetCharName(uint32 character_id);
const std::string GetCharNameByID(uint32 character_id);
const std::string GetNPCNameByID(uint32 npc_id);
const std::string GetCleanNPCNameByID(uint32 npc_id);
void LoginIP(uint32 account_id, const std::string& login_ip);
/* Instancing */
bool AddClientToInstance(uint16 instance_id, uint32 character_id);
bool CheckInstanceByCharID(uint16 instance_id, uint32 character_id);
bool CheckInstanceExists(uint16 instance_id);
bool CheckInstanceExpired(uint16 instance_id);
bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration);
bool GetUnusedInstanceID(uint16 &instance_id);
bool GetUnusedInstanceID(uint16& instance_id);
bool IsGlobalInstance(uint16 instance_id);
bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
bool RemoveClientsFromInstance(uint16 instance_id);
bool VerifyInstanceAlive(uint16 instance_id, uint32 character_id);
bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
uint16 GetInstanceID(uint32 zone, uint32 character_id, int16 version);
std::vector<uint16> GetInstanceIDs(uint32 zone_id, uint32 character_id);
uint8_t GetInstanceVersion(uint16 instance_id);
uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma);
uint32 GetTimeRemainingInstance(uint16 instance_id, bool& is_perma);
uint32 GetInstanceZoneID(uint16 instance_id);
void AssignGroupToInstance(uint32 gid, uint32 instance_id);
void AssignRaidToInstance(uint32 rid, uint32 instance_id);
void AssignGroupToInstance(uint32 group_id, uint32 instance_id);
void AssignRaidToInstance(uint32 raid_id, uint32 instance_id);
void DeleteInstance(uint16 instance_id);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 charid, uint32 group_id);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 charid, uint32 raid_id);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &character_ids);
void FlagInstanceByGroupLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 group_id);
void FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 character_id, uint32 raid_id);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32>& character_ids);
void PurgeExpiredInstances();
void SetInstanceDuration(uint16 instance_id, uint32 new_duration);
void CleanupInstanceCorpses();
/* Adventure related. */
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win = false, bool remove = false);
bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
void UpdateAdventureStatsEntry(uint32 character_id, uint8 theme_id, bool is_win = false, bool is_remove = false);
bool GetAdventureStats(uint32 character_id, AdventureStats_Struct* as);
/* Account Related */
const std::string GetLiveChar(uint32 account_id);
bool SetAccountStatus(const std::string& account_name, int16 status);
bool SetLocalPassword(uint32 account_id, const std::string& password);
bool UpdateLiveChar(const std::string& name, uint32 account_id);
int16 GetAccountStatus(uint32 account_id);
void SetAccountCRCField(uint32 account_id, const std::string& field_name, uint64 checksum);
uint32 CheckLogin(const std::string& name, const std::string& password, const std::string& loginserver, int16* status = 0);
uint32 CreateAccount(
const std::string& name,
const std::string& password,
int16 status,
const std::string& loginserver,
uint32 lsaccount_id
);
uint32 GetAccountIDFromLSID(
const std::string& in_loginserver_id,
uint32 in_loginserver_account_id,
char* in_account_name = 0,
int16* in_status = 0
);
bool DeleteAccount(const char *name, const char* loginserver);
bool GetLiveChar(uint32 account_id, char* cname);
bool SetAccountStatus(const char* name, int16 status);
bool SetAccountStatus(const std::string& account_name, int16 status);
bool SetLocalPassword(uint32 accid, const char* password);
bool UpdateLiveChar(char* charname, uint32 account_id);
uint8 GetAgreementFlag(uint32 account_id);
void SetAgreementFlag(uint32 account_id);
int16 CheckStatus(uint32 account_id);
int GetIPExemption(const std::string& account_ip);
void SetIPExemption(const std::string& account_ip, int exemption_amount);
void SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum);
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
uint8 GetAgreementFlag(uint32 account_id);
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 account_id);
int GetIPExemption(std::string account_ip);
void SetIPExemption(std::string account_ip, int exemption_amount);
int GetInstanceID(uint32 char_id, uint32 zone_id);
int GetInstanceID(uint32 character_id, uint32 zone_id);
/* Groups */
std::string GetGroupLeaderForLogin(std::string character_name);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
uint32 GetGroupID(const char* name);
void ClearGroup(uint32 gid = 0);
void ClearGroupLeader(uint32 gid = 0);
void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false);
void SetGroupLeaderName(uint32 gid, const char* name);
std::string GetGroupLeaderForLogin(const std::string& character_name);
char* GetGroupLeadershipInfo(
uint32 group_id,
char* leaderbuf,
char* maintank = nullptr,
char* assist = nullptr,
char* puller = nullptr,
char* marknpc = nullptr,
char* mentoree = nullptr,
int* mentor_percent = nullptr,
GroupLeadershipAA_Struct* GLAA = nullptr
);
std::string GetGroupLeaderName(uint32 group_id);
uint32 GetGroupID(const std::string& name);
void ClearGroup(uint32 group_id = 0);
void ClearGroupLeader(uint32 group_id = 0);
void SetGroupLeaderName(uint32 group_id, const std::string& name);
/* Raids */
const std::string GetRaidLeaderName(uint32 raid_id);
uint32 GetRaidID(const std::string& name);
void ClearRaid(uint32 raid_id = 0);
void ClearRaidDetails(uint32 raid_id = 0);
void ClearRaidLeader(uint32 group_id = std::numeric_limits<uint32>::max(), uint32 raid_id = 0);
void GetGroupLeadershipInfo(
uint32 group_id,
uint32 raid_id,
char* maintank = nullptr,
char* assist = nullptr,
char* puller = nullptr,
char* marknpc = nullptr,
char* mentoree = nullptr,
int* mentor_percent = nullptr,
GroupLeadershipAA_Struct* GLAA = nullptr
);
void GetRaidLeadershipInfo(
uint32 raid_id,
char* maintank = nullptr,
char* assist = nullptr,
char* puller = nullptr,
char* marknpc = nullptr,
RaidLeadershipAA_Struct* RLAA = nullptr
);
void SetRaidGroupLeaderInfo(uint32 group_id, uint32 raid_id);
const char *GetRaidLeaderName(uint32 rid);
uint32 GetRaidID(const char* name);
void ClearRaid(uint32 rid = 0);
void ClearRaidDetails(uint32 rid = 0);
void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0);
void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, RaidLeadershipAA_Struct* RLAA = nullptr);
void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid);
void PurgeAllDeletedDataBuckets();
void PurgeAllDeletedDataBuckets();
void ClearGuildOnlineStatus();
void ClearTraderDetails();
void ClearBuyerDetails();
/* Database Variables */
bool GetVariable(const std::string& name, std::string& value);
bool SetVariable(const std::string& name, const std::string& value);
bool LoadVariables();
bool GetVariable(std::string varname, std::string &varvalue);
bool SetVariable(const std::string& varname, const std::string &varvalue);
bool LoadVariables();
uint8 GetPEQZone(uint32 zone_id, uint32 version);
uint32 GetServerType();
void AddReport(const std::string& who, const std::string& against, const std::string& lines);
struct TimeOfDay_Struct LoadTime(time_t& realtime);
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
void ClearMerchantTemp();
void ClearPTimers(uint32 character_id);
void SetFirstLogon(uint32 character_id, uint8 first_logon);
void SetLFG(uint32 character_id, bool is_lfg);
void SetLFP(uint32 character_id, bool is_lfp);
void SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon);
/* General Queries */
int64 CountInvSnapshots();
void ClearInvSnapshots(bool from_now = false);
bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0);
bool LoadPTimers(uint32 charid, PTimerList &into);
uint8 GetPEQZone(uint32 zone_id, uint32 version);
uint8 GetMinStatus(uint32 zone_id, uint32 instance_version);
uint8 GetRaceSkill(uint8 skillid, uint8 in_race);
uint8 GetServerType();
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
void AddReport(std::string who, std::string against, std::string lines);
struct TimeOfDay_Struct LoadTime(time_t &realtime);
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
void ClearMerchantTemp();
void ClearPTimers(uint32 charid);
void SetFirstLogon(uint32 CharID, uint8 firstlogon);
void SetLFG(uint32 CharID, bool LFG);
void SetLFP(uint32 CharID, bool LFP);
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
int CountInvSnapshots();
void ClearInvSnapshots(bool from_now = false);
void SourceDatabaseTableFromUrl(std::string table_name, std::string url);
void SourceSqlFromUrl(std::string url);
void SourceDatabaseTableFromUrl(const std::string& table_name, const std::string& url);
void SourceSqlFromUrl(const std::string& url);
void PurgeCharacterParcels();
void Encode(std::string &in);
void Decode(std::string &in);
private:
Mutex Mvarcache;
Mutex Mvarcache;
VarCache_Struct varcache;
/* Groups, utility methods. */
void ClearAllGroupLeaders();
void ClearAllGroups();
void ClearAllGroupLeaders();
void ClearAllGroups();
/* Raid, utility methods. */
void ClearAllRaids();
+6 -1
View File
@@ -575,7 +575,12 @@ void DatabaseDumpService::RemoveSqlBackup()
{
std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath());
if (File::Exists(file)) {
std::filesystem::remove(file);
try {
std::filesystem::remove(file);
}
catch (std::exception &e) {
LogError("std::filesystem::remove err [{}]", e.what());
}
}
RemoveCredentialsFile();
+404 -2
View File
@@ -5247,7 +5247,7 @@ MODIFY COLUMN `name` varchar(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci
ManifestEntry{
.version = 9257,
.description = "2024_01_16_ground_spawns_fix_z.sql",
.check = "SHOW COLUMNS FROM `ground_spawns` LIKE `fix_z`",
.check = "SHOW COLUMNS FROM `ground_spawns` LIKE 'fix_z'",
.condition = "empty",
.match = "",
.sql = R"(
@@ -5259,7 +5259,7 @@ ADD COLUMN `fix_z` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 AFTER `respawn_timer`;
ManifestEntry{
.version = 9258,
.description = "2024_02_04_base_data.sql",
.check = "SHOW COLUMNS FROM `base_data` LIKE `hp_regen`",
.check = "SHOW COLUMNS FROM `base_data` LIKE 'hp_regen'",
.condition = "empty",
.match = "",
.sql = R"(
@@ -5346,6 +5346,408 @@ CREATE TABLE guild_tributes (
) ENGINE=InnoDB;
)"
},
ManifestEntry{
.version = 9261,
.description = "2024_02_11_character_corpses.sql",
.check = "SHOW COLUMNS FROM `character_corpses` LIKE 'time_of_death'",
.condition = "contains",
.match = "0000-00-00 00:00:00",
.sql = R"(
ALTER TABLE `character_corpses` MODIFY COLUMN `time_of_death` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP;
)"
},
ManifestEntry{
.version = 9262,
.description = "2024_02_11_object_contents.sql",
.check = "SHOW COLUMNS FROM `object_contents` LIKE 'droptime'",
.condition = "contains",
.match = "0000-00-00 00:00:00",
.sql = R"(
ALTER TABLE `object_contents` MODIFY COLUMN `droptime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP;
)"
},
ManifestEntry{
.version = 9263,
.description = "2024_02_16_rearrange_zone_columns.sql",
.check = "show columns from zone like 'note'",
.condition = "missing",
.match = "varchar(200)",
.sql = R"(
ALTER TABLE `zone`
MODIFY COLUMN `id` int(10) NOT NULL AUTO_INCREMENT FIRST,
MODIFY COLUMN `zoneidnumber` int(4) NOT NULL DEFAULT 0 AFTER `id`,
MODIFY COLUMN `version` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `zoneidnumber`,
MODIFY COLUMN `short_name` varchar(32) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `version`,
MODIFY COLUMN `long_name` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL AFTER `short_name`,
MODIFY COLUMN `min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `long_name`,
MODIFY COLUMN `note` varchar(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `map_file_name`,
MODIFY COLUMN `min_expansion` tinyint(4) NOT NULL DEFAULT -1 AFTER `note`,
MODIFY COLUMN `max_expansion` tinyint(4) NOT NULL DEFAULT -1 AFTER `min_expansion`,
MODIFY COLUMN `content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `max_expansion`,
MODIFY COLUMN `content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `content_flags`,
MODIFY COLUMN `expansion` tinyint(3) NOT NULL DEFAULT 0 AFTER `content_flags_disabled`,
MODIFY COLUMN `file_name` varchar(16) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `expansion`,
MODIFY COLUMN `safe_x` float NOT NULL DEFAULT 0 AFTER `file_name`,
MODIFY COLUMN `safe_y` float NOT NULL DEFAULT 0 AFTER `safe_x`,
MODIFY COLUMN `safe_z` float NOT NULL DEFAULT 0 AFTER `safe_y`,
MODIFY COLUMN `safe_heading` float NOT NULL DEFAULT 0 AFTER `safe_z`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9264,
.description = "2024_02_18_starting_items_augments.sql",
.check = "SHOW COLUMNS FROM `starting_items` LIKE 'augment_one'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `starting_items`
ADD COLUMN `augment_one` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `item_charges`,
ADD COLUMN `augment_two` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`,
ADD COLUMN `augment_three` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`,
ADD COLUMN `augment_four` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`,
ADD COLUMN `augment_five` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`,
ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9265,
.description = "2024_03_03_add_id_to_guild_bank.sql",
.check = "SHOW COLUMNS FROM `guild_bank` LIKE 'id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `guild_bank`
ADD COLUMN `id` INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
)",
},
ManifestEntry{
.version = 9266,
.description = "2024_03_02_rule_values_rule_value_length.sql",
.check = "SHOW COLUMNS FROM `rule_values` LIKE 'rule_value'",
.condition = "contains",
.match = "varchar(30)",
.sql = R"(
ALTER TABLE `rule_values`
MODIFY COLUMN `rule_value` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `rule_name`;
)"
},
ManifestEntry{
.version = 9267,
.description = "2024_02_18_group_id_bot_id.sql",
.check = "SHOW COLUMNS FROM `group_id` LIKE 'bot_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `group_id`
CHANGE COLUMN `groupid` `group_id` int(11) UNSIGNED NOT NULL DEFAULT 0 FIRST,
CHANGE COLUMN `charid` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `group_id`,
CHANGE COLUMN `ismerc` `merc_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `name`,
ADD COLUMN `bot_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `character_id`,
MODIFY COLUMN `name` varchar(64) NOT NULL DEFAULT '' AFTER `character_id`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`group_id`, `character_id`, `bot_id`, `merc_id`) USING BTREE;
ALTER TABLE `group_id`
MODIFY COLUMN `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `name`;
)"
},
ManifestEntry{
.version = 9268,
.description = "2024_03_23_skill_caps.sql",
.check = "SHOW COLUMNS FROM `skill_caps` LIKE 'skill_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `skill_caps`
CHANGE COLUMN `skillID` `skill_id` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 FIRST,
CHANGE COLUMN `class` `class_id` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `skill_id`,
ADD COLUMN `id` int(3) UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`) USING BTREE,
ADD INDEX `level_skill_cap`(`skill_id`, `class_id`, `level`, `cap`);
)",
.content_schema_update = true,
},
ManifestEntry{
.version = 9269,
.description = "2024_03_27_account_auto_login_charname.sql",
.check = "SHOW COLUMNS FROM `account` LIKE 'auto_login_charname'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `account`
ADD COLUMN `auto_login_charname` varchar(64) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `charname`;
)"
},
ManifestEntry{
.version = 9270,
.description = "2024_04_31_content_flagging_lootdrop_entries.sql",
.check = "SHOW COLUMNS FROM `lootdrop_entries` LIKE 'content_flags'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `lootdrop_entries` ADD `min_expansion` tinyint(4) NOT NULL DEFAULT -1;
ALTER TABLE `lootdrop_entries` ADD `max_expansion` tinyint(4) NOT NULL DEFAULT -1;
ALTER TABLE `lootdrop_entries` ADD `content_flags` varchar(100) NULL;
ALTER TABLE `lootdrop_entries` ADD `content_flags_disabled` varchar(100) NULL;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9271,
.description = "2024_03_10_parcel_implementation.sql",
.check = "SHOW TABLES LIKE 'character_parcels'",
.condition = "empty",
.match = "",
.sql = R"(CREATE TABLE `character_parcels` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`char_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`slot_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`quantity` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`from_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci',
`note` VARCHAR(1024) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci',
`sent_date` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `data_constraint` (`slot_id`, `char_id`) USING BTREE
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
)"
},
ManifestEntry{
.version = 9272,
.description = "2024_04_23_add_parcel_support_for_augmented_items.sql",
.check = "SHOW COLUMNS FROM `character_parcels` LIKE 'aug_slot_1'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `character_parcels`
ADD COLUMN `aug_slot_1` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `item_id`,
ADD COLUMN `aug_slot_2` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_1`,
ADD COLUMN `aug_slot_3` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_2`,
ADD COLUMN `aug_slot_4` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_3`,
ADD COLUMN `aug_slot_5` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_4`,
ADD COLUMN `aug_slot_6` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_5`;
)"
},
ManifestEntry{
.version = 9273,
.description = "2024_04_24_door_close_timer.sql",
.check = "SHOW COLUMNS FROM `doors` LIKE 'close_timer_ms'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `doors`
ADD COLUMN `close_timer_ms` smallint(8) UNSIGNED NOT NULL DEFAULT 5000 AFTER `is_ldon_door`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9274,
.description = "2024_05_02_parcel_npc_content.sql",
.check = "SHOW COLUMNS FROM `npc_types` LIKE 'is_parcel_merchant'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `npc_types`
ADD COLUMN `is_parcel_merchant` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `keeps_sold_items`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9275,
.description = "2024_04_28_character_extra_haste.sql",
.check = "SHOW COLUMNS FROM `character_data` LIKE 'extra_haste'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `character_data`
ADD COLUMN `extra_haste` int(11) NOT NULL DEFAULT 0 AFTER `wis`;
)"
},
ManifestEntry{
.version = 9276,
.description = "2024_05_12_fix_guild_bank_dup_issue.sql",
.check = "SHOW COLUMNS FROM `guild_bank` WHERE FIELD = 'qty' AND Type LIKE '%unsigned';",
.condition = "not_empty",
.match = "",
.sql = R"(
ALTER TABLE `guild_bank`
CHANGE COLUMN `qty` `qty` INT(10) NOT NULL DEFAULT '0' AFTER `itemid`;
)"
},
ManifestEntry{
.version = 9277,
.description = "2024_05_09_parcel_enable_containers.sql",
.check = "SHOW TABLES LIKE 'character_parcels_containers'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `character_parcels_containers` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`parcels_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`slot_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`aug_slot_1` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`aug_slot_2` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`aug_slot_3` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`aug_slot_4` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`aug_slot_5` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`aug_slot_6` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`quantity` INT(10) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
INDEX `fk_character_parcels_id` (`parcels_id`) USING BTREE,
CONSTRAINT `fk_character_parcels_id` FOREIGN KEY (`parcels_id`) REFERENCES `character_parcels` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1
;
)"
},
ManifestEntry{
.version = 9278,
.description = "2024_05_06_npc_greed.sql",
.check = "SHOW COLUMNS FROM `npc_types` LIKE 'greed'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `npc_types`
ADD COLUMN `greed` tinyint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `merchant_id`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9279,
.description = "2024_05_13_content_flagging_npc_spells_entries.sql",
.check = "SHOW COLUMNS FROM `npc_spells_entries` LIKE 'content_flags'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `npc_spells_entries` ADD `min_expansion` tinyint(4) NOT NULL DEFAULT -1;
ALTER TABLE `npc_spells_entries` ADD `max_expansion` tinyint(4) NOT NULL DEFAULT -1;
ALTER TABLE `npc_spells_entries` ADD `content_flags` varchar(100) NULL;
ALTER TABLE `npc_spells_entries` ADD `content_flags_disabled` varchar(100) NULL;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9280,
.description = "2024_05_11_update_trader_support.sql",
.check = "SHOW COLUMNS FROM `trader` LIKE 'aug_slot_1'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `trader`
ADD COLUMN `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
CHANGE COLUMN `char_id` `char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`,
CHANGE COLUMN `item_id` `item_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `char_id`,
ADD COLUMN `aug_slot_1` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `item_id`,
ADD COLUMN `aug_slot_2` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_1`,
ADD COLUMN `aug_slot_3` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_2`,
ADD COLUMN `aug_slot_4` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_3`,
ADD COLUMN `aug_slot_5` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_4`,
ADD COLUMN `aug_slot_6` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_5`,
CHANGE COLUMN `serialnumber` `item_sn` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `aug_slot_6`,
CHANGE COLUMN `charges` `item_charges` INT(11) NOT NULL DEFAULT '0' AFTER `item_sn`,
ADD COLUMN `char_entity_id` INT(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `slot_id`,
ADD COLUMN `char_zone_id` INT(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `char_entity_id`,
ADD COLUMN `active_transaction` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `char_zone_id`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`),
ADD INDEX `charid_slotid` (`char_id`, `slot_id`);
)"
},
ManifestEntry{
.version = 9281,
.description = "2024_06_24_update_buyer_support.sql",
.check = "SHOW COLUMNS FROM `buyer` LIKE 'id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `buyer`
ADD COLUMN `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
CHANGE COLUMN `charid` `char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`,
ADD COLUMN `char_entity_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `char_id`,
ADD COLUMN `char_name` VARCHAR(64) NULL DEFAULT NULL AFTER `char_entity_id`,
ADD COLUMN `char_zone_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `char_name`,
ADD COLUMN `char_zone_instance_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `char_zone_id`,
ADD COLUMN `transaction_date` DATETIME NULL DEFAULT NULL AFTER `char_zone_instance_id`,
ADD COLUMN `welcome_message` VARCHAR(256) NULL DEFAULT NULL AFTER `transaction_date`,
DROP COLUMN `buyslot`,
DROP COLUMN `itemid`,
DROP COLUMN `itemname`,
DROP COLUMN `quantity`,
DROP COLUMN `price`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`) USING BTREE,
ADD INDEX `charid` (`char_id`);
CREATE TABLE `buyer_buy_lines` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`buyer_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`buy_slot_id` INT(11) NOT NULL DEFAULT '0',
`item_id` INT(11) NOT NULL DEFAULT '0',
`item_qty` INT(11) NOT NULL DEFAULT '0',
`item_price` INT(11) NOT NULL DEFAULT '0',
`item_icon` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`item_name` VARCHAR(64) NOT NULL DEFAULT '' COLLATE 'latin1_swedish_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `buyerid_charid_buyslotid` (`buyer_id`, `char_id`, `buy_slot_id`) USING BTREE
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
CREATE TABLE `buyer_trade_items` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`buyer_buy_lines_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`item_id` INT(11) NOT NULL DEFAULT '0',
`item_qty` INT(11) NOT NULL DEFAULT '0',
`item_icon` INT(11) NOT NULL DEFAULT '0',
`item_name` VARCHAR(64) NOT NULL DEFAULT '0' COLLATE 'latin1_swedish_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `buyerbuylinesid` (`buyer_buy_lines_id`) USING BTREE
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
)"
},
ManifestEntry{
.version = 9282,
.description = "2024_08_02_spell_buckets_comparison.sql",
.check = "SHOW COLUMNS FROM `spell_buckets` LIKE 'bucket_comparison'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `spell_buckets`
CHANGE COLUMN `spellid` `spell_id` int UNSIGNED NOT NULL FIRST,
CHANGE COLUMN `key` `bucket_name` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `spell_id`,
CHANGE COLUMN `value` `bucket_value` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `bucket_name`,
ADD COLUMN `bucket_comparison` tinyint UNSIGNED NOT NULL DEFAULT 0 AFTER `bucket_value`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`spell_id`) USING BTREE;
)"
},
ManifestEntry{
.version = 9283,
.description = "2024_08_05_fix_client_hotbar",
.check = "SHOW COLUMNS FROM `inventory` LIKE 'guid'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `inventory`
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
ALTER TABLE `inventory_snapshots`
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
)"
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
// .version = 9228,
@@ -123,6 +123,44 @@ ALTER TABLE `bot_pets` DROP FOREIGN KEY `FK_bot_pets_1`;
ALTER TABLE `bot_pet_buffs` DROP FOREIGN KEY `FK_bot_pet_buffs_1`;
ALTER TABLE `bot_pet_inventories` DROP FOREIGN KEY `FK_bot_pet_inventories_1`;
ALTER TABLE `bot_stances` DROP FOREIGN KEY `FK_bot_stances_1`;
)"
},
ManifestEntry{
.version = 9043,
.description = "2024_02_18_bot_starting_items_augments.sql",
.check = "SHOW COLUMNS FROM `bot_starting_items` LIKE 'augment_one'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `bot_starting_items`
ADD COLUMN `augment_one` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `item_charges`,
ADD COLUMN `augment_two` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`,
ADD COLUMN `augment_three` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`,
ADD COLUMN `augment_four` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`,
ADD COLUMN `augment_five` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`,
ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`;
)"
},
ManifestEntry{
.version = 9044,
.description = "2024_04_23_bot_extra_haste.sql",
.check = "SHOW COLUMNS FROM `bot_data` LIKE 'extra_haste'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `bot_data`
ADD COLUMN `extra_haste` mediumint(8) NOT NULL DEFAULT 0 AFTER `wis`;
)"
},
ManifestEntry{
.version = 9045,
.description = "2024_08_05_bot_spells_entries_unsigned_spell_id.sql",
.check = "SHOW COLUMNS FROM `bot_spells_entries` LIKE 'spell_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `bot_spells_entries`
CHANGE COLUMN `spellid` `spell_id` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `npc_spells_id`;
)"
}
// -- template; copy/paste this when you need to create a new entry
+10 -5
View File
@@ -421,20 +421,25 @@ void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = GroupIdRepository::GetWhere(
const auto& l = GroupIdRepository::GetWhere(
*this,
fmt::format(
"groupid = {}",
"`group_id` = {}",
group_id
)
);
if (l.empty()) {
return;
}
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
if (!e.character_id) {
continue;
}
if (!GetInstanceID(zone_id, e.character_id, version)) {
AddClientToInstance(instance_id, e.character_id);
}
}
}
@@ -504,7 +509,7 @@ void Database::FlagInstanceByRaidLeader(uint32 zone_id, int16 version, uint32 ch
return;
}
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id));
auto raid_leader_id = GetCharacterID(GetRaidLeaderName(raid_id).c_str());
auto raid_leader_instance_id = GetInstanceID(zone_id, raid_leader_id, version);
if (!raid_leader_instance_id) {
+10 -2
View File
@@ -36,7 +36,6 @@ namespace DatabaseSchema {
{
return {
{"adventure_stats", "player_id"},
{"buyer", "charid"},
{"char_recipe_list", "char_id"},
{"character_activities", "charid"},
{"character_alt_currency", "char_id"},
@@ -59,6 +58,8 @@ namespace DatabaseSchema {
{"character_leadership_abilities", "id"},
{"character_material", "id"},
{"character_memmed_spells", "id"},
{"character_parcels", "char_id"},
{"character_parcels_containers", "id"},
{"character_pet_buffs", "char_id"},
{"character_pet_info", "char_id"},
{"character_pet_inventory", "char_id"},
@@ -105,6 +106,8 @@ namespace DatabaseSchema {
"adventure_details",
"adventure_stats",
"buyer",
"buyer_buy_lines",
"buyer_trade_items",
"char_recipe_list",
"character_activities",
"character_alt_currency",
@@ -128,6 +131,8 @@ namespace DatabaseSchema {
"character_leadership_abilities",
"character_material",
"character_memmed_spells",
"character_parcels",
"character_parcels_containers",
"character_pet_buffs",
"character_pet_info",
"character_pet_inventory",
@@ -146,6 +151,7 @@ namespace DatabaseSchema {
"friends",
"guild_bank",
"guild_members",
"guild_permissions",
"guild_ranks",
"guild_relations",
"guild_tributes",
@@ -320,6 +326,9 @@ namespace DatabaseSchema {
"banned_ips",
"bug_reports",
"bugs",
"buyer",
"buyer_buy_lines",
"buyer_trade_items",
"completed_shared_task_activity_state",
"completed_shared_task_members",
"completed_shared_tasks",
@@ -333,7 +342,6 @@ namespace DatabaseSchema {
"group_leaders",
"instance_list",
"ip_exemptions",
"item_tick",
"lfguild",
"merc_buffs",
"merchantlist_temp",
+6 -70
View File
@@ -19,81 +19,17 @@
#include "deity.h"
EQ::deity::DeityTypeBit EQ::deity::GetDeityBitmask(DeityType deity_type)
uint32 Deity::GetBitmask(uint32 deity_id)
{
switch (deity_type) {
case DeityBertoxxulous:
return bit_DeityBertoxxulous;
case DeityBrellSirilis:
return bit_DeityBrellSirilis;
case DeityCazicThule:
return bit_DeityCazicThule;
case DeityErollisiMarr:
return bit_DeityErollisiMarr;
case DeityBristlebane:
return bit_DeityBristlebane;
case DeityInnoruuk:
return bit_DeityInnoruuk;
case DeityKarana:
return bit_DeityKarana;
case DeityMithanielMarr:
return bit_DeityMithanielMarr;
case DeityPrexus:
return bit_DeityPrexus;
case DeityQuellious:
return bit_DeityQuellious;
case DeityRallosZek:
return bit_DeityRallosZek;
case DeityRodcetNife:
return bit_DeityRodcetNife;
case DeitySolusekRo:
return bit_DeitySolusekRo;
case DeityTheTribunal:
return bit_DeityTheTribunal;
case DeityTunare:
return bit_DeityTunare;
case DeityVeeshan:
return bit_DeityVeeshan;
case DeityAgnostic_LB:
case DeityAgnostic:
return bit_DeityAgnostic;
default:
return bit_DeityAll;
}
return IsValid(deity_id) ? deity_bitmasks[deity_id] : Deity::Bitmask::All;
}
const std::map<EQ::deity::DeityType, std::string>& EQ::deity::GetDeityMap()
std::string Deity::GetName(uint32 deity_id)
{
static const std::map<EQ::deity::DeityType, std::string> deity_map = {
{ DeityAgnostic, "Agnostic" },
{ DeityAgnostic_LB, "Agnostic" },
{ DeityBertoxxulous, "Bertoxxulous" },
{ DeityBrellSirilis, "Brell Serilis" },
{ DeityBristlebane, "Bristlebane" },
{ DeityCazicThule, "Cazic-Thule" },
{ DeityErollisiMarr, "Erollisi Marr" },
{ DeityInnoruuk, "Innoruuk" },
{ DeityKarana, "Karana" },
{ DeityMithanielMarr, "Mithaniel Marr" },
{ DeityPrexus, "Prexus" },
{ DeityQuellious, "Quellious" },
{ DeityRallosZek, "Rallos Zek" },
{ DeityRodcetNife, "Rodcet Nife" },
{ DeitySolusekRo, "Solusek Ro" },
{ DeityTheTribunal, "The Tribunal" },
{ DeityTunare, "Tunare" },
{ DeityVeeshan, "Veeshan" }
};
return deity_map;
return IsValid(deity_id) ? deity_names[deity_id] : "UNKNOWN DEITY";
}
std::string EQ::deity::GetDeityName(DeityType deity_type)
bool Deity::IsValid(uint32 deity_id)
{
if (EQ::deity::GetDeityMap().find(deity_type) != EQ::deity::GetDeityMap().end()) {
return EQ::deity::GetDeityMap().find(deity_type)->second;
}
return std::string();
return deity_names.find(deity_id) != deity_names.end();
}
+85 -50
View File
@@ -23,60 +23,95 @@
#include "types.h"
#include <map>
#include <string>
#include <limits>
namespace Deity {
constexpr uint32 Unknown = 0;
constexpr uint32 Agnostic1 = 140;
constexpr uint32 Bertoxxulous = 201;
constexpr uint32 BrellSirilis = 202;
constexpr uint32 CazicThule = 203;
constexpr uint32 ErollisiMarr = 204;
constexpr uint32 Bristlebane = 205;
constexpr uint32 Innoruuk = 206;
constexpr uint32 Karana = 207;
constexpr uint32 MithanielMarr = 208;
constexpr uint32 Prexus = 209;
constexpr uint32 Quellious = 210;
constexpr uint32 RallosZek = 211;
constexpr uint32 RodcetNife = 212;
constexpr uint32 SolusekRo = 213;
constexpr uint32 TheTribunal = 214;
constexpr uint32 Tunare = 215;
constexpr uint32 Veeshan = 216;
constexpr uint32 Agnostic2 = 396;
namespace EQ
{
namespace deity {
enum DeityType {
DeityUnknown = 0,
DeityAgnostic_LB = 140,
DeityBertoxxulous = 201,
DeityBrellSirilis,
DeityCazicThule,
DeityErollisiMarr,
DeityBristlebane,
DeityInnoruuk,
DeityKarana,
DeityMithanielMarr,
DeityPrexus,
DeityQuellious,
DeityRallosZek,
DeityRodcetNife,
DeitySolusekRo,
DeityTheTribunal,
DeityTunare,
DeityVeeshan,
DeityAgnostic = 396
};
namespace Bitmask {
constexpr uint32 Agnostic = 1;
constexpr uint32 Bertoxxulous = 2;
constexpr uint32 BrellSirilis = 4;
constexpr uint32 CazicThule = 8;
constexpr uint32 ErollisiMarr = 16;
constexpr uint32 Bristlebane = 32;
constexpr uint32 Innoruuk = 64;
constexpr uint32 Karana = 128;
constexpr uint32 MithanielMarr = 256;
constexpr uint32 Prexus = 512;
constexpr uint32 Quellious = 1024;
constexpr uint32 RallosZek = 2048;
constexpr uint32 RodcetNife = 4096;
constexpr uint32 SolusekRo = 8192;
constexpr uint32 TheTribunal = 16384;
constexpr uint32 Tunare = 32768;
constexpr uint32 Veeshan = 65536;
constexpr uint32 All = std::numeric_limits<uint32>::max();
}
enum DeityTypeBit : uint32 {
bit_DeityAgnostic = 0x00000001,
bit_DeityBertoxxulous = 0x00000002,
bit_DeityBrellSirilis = 0x00000004,
bit_DeityCazicThule = 0x00000008,
bit_DeityErollisiMarr = 0x00000010,
bit_DeityBristlebane = 0x00000020,
bit_DeityInnoruuk = 0x00000040,
bit_DeityKarana = 0x00000080,
bit_DeityMithanielMarr = 0x00000100,
bit_DeityPrexus = 0x00000200,
bit_DeityQuellious = 0x00000400,
bit_DeityRallosZek = 0x00000800,
bit_DeityRodcetNife = 0x00001000,
bit_DeitySolusekRo = 0x00002000,
bit_DeityTheTribunal = 0x00004000,
bit_DeityTunare = 0x00008000,
bit_DeityVeeshan = 0x00010000,
bit_DeityAll = UINT32_MAX
};
uint32 GetBitmask(uint32 deity_id);
std::string GetName(uint32 deity_id);
bool IsValid(uint32 deity_id);
}
extern DeityTypeBit GetDeityBitmask(DeityType deity_type);
extern std::string GetDeityName(DeityType deity_type);
extern const std::map<DeityType, std::string>& GetDeityMap();
static std::map<uint32, std::string> deity_names = {
{ Deity::Agnostic1, "Agnostic" },
{ Deity::Agnostic2, "Agnostic" },
{ Deity::Bertoxxulous, "Bertoxxulous" },
{ Deity::BrellSirilis, "Brell Serilis" },
{ Deity::Bristlebane, "Bristlebane" },
{ Deity::CazicThule, "Cazic-Thule" },
{ Deity::ErollisiMarr, "Erollisi Marr" },
{ Deity::Innoruuk, "Innoruuk" },
{ Deity::Karana, "Karana" },
{ Deity::MithanielMarr, "Mithaniel Marr" },
{ Deity::Prexus, "Prexus" },
{ Deity::Quellious, "Quellious" },
{ Deity::RallosZek, "Rallos Zek" },
{ Deity::RodcetNife, "Rodcet Nife" },
{ Deity::SolusekRo, "Solusek Ro" },
{ Deity::TheTribunal, "The Tribunal" },
{ Deity::Tunare, "Tunare" },
{ Deity::Veeshan, "Veeshan" }
};
} /*deity*/
} /*EQEmu*/
static std::map<uint32, uint32> deity_bitmasks = {
{ Deity::Agnostic1, Deity::Bitmask::Agnostic },
{ Deity::Agnostic2, Deity::Bitmask::Agnostic },
{ Deity::Bertoxxulous, Deity::Bitmask::Bertoxxulous },
{ Deity::BrellSirilis, Deity::Bitmask::BrellSirilis },
{ Deity::CazicThule, Deity::Bitmask::CazicThule },
{ Deity::ErollisiMarr, Deity::Bitmask::ErollisiMarr },
{ Deity::Bristlebane, Deity::Bitmask::Bristlebane },
{ Deity::Innoruuk, Deity::Bitmask::Innoruuk },
{ Deity::Karana, Deity::Bitmask::Karana },
{ Deity::MithanielMarr, Deity::Bitmask::MithanielMarr },
{ Deity::Prexus, Deity::Bitmask::Prexus },
{ Deity::Quellious, Deity::Bitmask::Quellious },
{ Deity::RallosZek, Deity::Bitmask::RallosZek },
{ Deity::RodcetNife, Deity::Bitmask::RodcetNife },
{ Deity::SolusekRo, Deity::Bitmask::SolusekRo },
{ Deity::TheTribunal, Deity::Bitmask::TheTribunal },
{ Deity::Tunare, Deity::Bitmask::Tunare },
{ Deity::Veeshan, Deity::Bitmask::Veeshan }
};
#endif /* COMMON_DEITY_H */
+79 -332
View File
@@ -59,103 +59,40 @@ int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
return local_array[inv_type];
}
const char* EQ::bug::CategoryIDToCategoryName(CategoryID category_id) {
switch (category_id) {
case catVideo:
return "Video";
case catAudio:
return "Audio";
case catPathing:
return "Pathing";
case catQuest:
return "Quest";
case catTradeskills:
return "Tradeskills";
case catSpellStacking:
return "Spell stacking";
case catDoorsPortals:
return "Doors/Portals";
case catItems:
return "Items";
case catNPC:
return "NPC";
case catDialogs:
return "Dialogs";
case catLoNTCG:
return "LoN - TCG";
case catMercenaries:
return "Mercenaries";
case catOther:
default:
return "Other";
}
}
EQ::bug::CategoryID EQ::bug::CategoryNameToCategoryID(const char* category_name) {
if (!category_name)
return catOther;
if (!strcmp(category_name, "Video"))
return catVideo;
if (!strcmp(category_name, "Audio"))
return catAudio;
if (!strcmp(category_name, "Pathing"))
return catPathing;
if (!strcmp(category_name, "Quest"))
return catQuest;
if (!strcmp(category_name, "Tradeskills"))
return catTradeskills;
if (!strcmp(category_name, "Spell stacking"))
return catSpellStacking;
if (!strcmp(category_name, "Doors/Portals"))
return catDoorsPortals;
if (!strcmp(category_name, "Items"))
return catItems;
if (!strcmp(category_name, "NPC"))
return catNPC;
if (!strcmp(category_name, "Dialogs"))
return catDialogs;
if (!strcmp(category_name, "LoN - TCG"))
return catLoNTCG;
if (!strcmp(category_name, "Mercenaries"))
return catMercenaries;
return catOther;
}
const char *EQ::constants::GetStanceName(StanceType stance_type) {
switch (stance_type) {
case stanceUnknown:
return "Unknown";
case stancePassive:
return "Passive";
case stanceBalanced:
return "Balanced";
case stanceEfficient:
return "Efficient";
case stanceReactive:
return "Reactive";
case stanceAggressive:
return "Aggressive";
case stanceAssist:
return "Assist";
case stanceBurn:
return "Burn";
case stanceEfficient2:
return "Efficient2";
case stanceBurnAE:
return "BurnAE";
default:
return "Invalid";
}
}
int EQ::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
if (EQ::ValueWithin(stance_type, EQ::constants::stancePassive, EQ::constants::stanceBurnAE)) {
return (stance_type - EQ::constants::stancePassive);
uint32 Bug::GetID(const std::string& category_name)
{
for (const auto& e : bug_category_names) {
if (e.second == category_name) {
return e.first;
}
}
return 0;
return Bug::Category::Other;
}
std::string Bug::GetName(uint32 category_id)
{
return IsValid(category_id) ? bug_category_names[category_id] : "UNKNOWN BUG CATEGORY";
}
bool Bug::IsValid(uint32 category_id)
{
return bug_category_names.find(category_id) != bug_category_names.end();
}
std::string Stance::GetName(uint8 stance_id)
{
return IsValid(stance_id) ? stance_names[stance_id] : "UNKNOWN STANCE";
}
bool Stance::IsValid(uint8 stance_id)
{
return stance_names.find(stance_id) != stance_names.end();
}
uint8 Stance::GetIndex(uint8 stance_id)
{
return IsValid(stance_id) ? (stance_id - Stance::Passive) : 0;
}
const std::map<uint8, std::string>& EQ::constants::GetLanguageMap()
@@ -249,102 +186,6 @@ std::string EQ::constants::GetFlyModeName(int8 flymode_id)
return EQ::constants::GetFlyModeMap().find(flymode_id)->second;
}
const std::map<bodyType, std::string>& EQ::constants::GetBodyTypeMap()
{
static const std::map<bodyType, std::string> bodytype_map = {
{ BT_Humanoid, "Humanoid" },
{ BT_Lycanthrope, "Lycanthrope" },
{ BT_Undead, "Undead" },
{ BT_Giant, "Giant" },
{ BT_Construct, "Construct" },
{ BT_Extraplanar, "Extraplanar" },
{ BT_Magical, "Magical" },
{ BT_SummonedUndead, "Summoned Undead" },
{ BT_RaidGiant, "Raid Giant" },
{ BT_RaidColdain, "Raid Coldain" },
{ BT_NoTarget, "Untargetable" },
{ BT_Vampire, "Vampire" },
{ BT_Atenha_Ra, "Aten Ha Ra" },
{ BT_Greater_Akheva, "Greater Akheva" },
{ BT_Khati_Sha, "Khati Sha" },
{ BT_Seru, "Seru" },
{ BT_Grieg_Veneficus, "Grieg Veneficus" },
{ BT_Draz_Nurakk, "Draz Nurakk" },
{ BT_Zek, "Zek" },
{ BT_Luggald, "Luggald" },
{ BT_Animal, "Animal" },
{ BT_Insect, "Insect" },
{ BT_Monster, "Monster" },
{ BT_Summoned, "Summoned" },
{ BT_Plant, "Plant" },
{ BT_Dragon, "Dragon" },
{ BT_Summoned2, "Summoned 2" },
{ BT_Summoned3, "Summoned 3" },
{ BT_Dragon2, "Dragon 2" },
{ BT_VeliousDragon, "Velious Dragon" },
{ BT_Familiar, "Familiar" },
{ BT_Dragon3, "Dragon 3" },
{ BT_Boxes, "Boxes" },
{ BT_Muramite, "Muramite" },
{ BT_NoTarget2, "Untargetable 2" },
{ BT_SwarmPet, "Swarm Pet" },
{ BT_MonsterSummon, "Monster Summon" },
{ BT_InvisMan, "Invisible Man" },
{ BT_Special, "Special" },
};
return bodytype_map;
}
std::string EQ::constants::GetBodyTypeName(bodyType bodytype_id)
{
if (EQ::constants::GetBodyTypeMap().find(bodytype_id) != EQ::constants::GetBodyTypeMap().end()) {
return EQ::constants::GetBodyTypeMap().find(bodytype_id)->second;
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetAccountStatusMap()
{
static const std::map<uint8, std::string> account_status_map = {
{ AccountStatus::Player, "Player" },
{ AccountStatus::Steward, "Steward" },
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
{ AccountStatus::Guide, "Guide" },
{ AccountStatus::QuestTroupe, "Quest Troupe" },
{ AccountStatus::SeniorGuide, "Senior Guide" },
{ AccountStatus::GMTester, "GM Tester" },
{ AccountStatus::EQSupport, "EQ Support" },
{ AccountStatus::GMStaff, "GM Staff" },
{ AccountStatus::GMAdmin, "GM Admin" },
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
{ AccountStatus::QuestMaster, "Quest Master" },
{ AccountStatus::GMAreas, "GM Areas" },
{ AccountStatus::GMCoder, "GM Coder" },
{ AccountStatus::GMMgmt, "GM Mgmt" },
{ AccountStatus::GMImpossible, "GM Impossible" },
{ AccountStatus::Max, "GM Max" }
};
return account_status_map;
}
std::string EQ::constants::GetAccountStatusName(uint8 account_status)
{
for (
auto status_level = EQ::constants::GetAccountStatusMap().rbegin();
status_level != EQ::constants::GetAccountStatusMap().rend();
++status_level
) {
if (account_status >= status_level->first) {
return status_level->second;
}
}
return std::string();
}
const std::map<uint8, std::string>& EQ::constants::GetConsiderLevelMap()
{
static const std::map<uint8, std::string> consider_level_map = {
@@ -435,84 +276,6 @@ std::string EQ::constants::GetSpawnAnimationName(uint8 animation_id)
return EQ::constants::GetSpawnAnimationMap().find(animation_id)->second;
}
const std::map<int, std::string>& EQ::constants::GetObjectTypeMap()
{
static const std::map<int, std::string> object_type_map = {
{ ObjectTypes::SmallBag, "Small Bag" },
{ ObjectTypes::LargeBag, "Large Bag" },
{ ObjectTypes::Quiver, "Quiver" },
{ ObjectTypes::BeltPouch, "Belt Pouch" },
{ ObjectTypes::WristPouch, "Wrist Pouch" },
{ ObjectTypes::Backpack, "Backpack" },
{ ObjectTypes::SmallChest, "Small Chest" },
{ ObjectTypes::LargeChest, "Large Chest" },
{ ObjectTypes::Bandolier, "Bandolier" },
{ ObjectTypes::Medicine, "Medicine" },
{ ObjectTypes::Tinkering, "Tinkering" },
{ ObjectTypes::Lexicon, "Lexicon" },
{ ObjectTypes::PoisonMaking, "Mortar and Pestle" },
{ ObjectTypes::Quest, "Quest" },
{ ObjectTypes::MixingBowl, "Mixing Bowl" },
{ ObjectTypes::Baking, "Baking" },
{ ObjectTypes::Tailoring, "Tailoring" },
{ ObjectTypes::Blacksmithing, "Blacksmithing" },
{ ObjectTypes::Fletching, "Fletching" },
{ ObjectTypes::Brewing, "Brewing" },
{ ObjectTypes::JewelryMaking, "Jewelry Making" },
{ ObjectTypes::Pottery, "Pottery" },
{ ObjectTypes::Kiln, "Kiln" },
{ ObjectTypes::KeyMaker, "Key Maker" },
{ ObjectTypes::ResearchWIZ, "Lexicon" },
{ ObjectTypes::ResearchMAG, "Lexicon" },
{ ObjectTypes::ResearchNEC, "Lexicon" },
{ ObjectTypes::ResearchENC, "Lexicon" },
{ ObjectTypes::Unknown, "Unknown" },
{ ObjectTypes::ResearchPractice, "Lexicon" },
{ ObjectTypes::Alchemy, "Alchemy" },
{ ObjectTypes::HighElfForge, "High Elf Forge" },
{ ObjectTypes::DarkElfForge, "Dark Elf Forge" },
{ ObjectTypes::OgreForge, "Ogre Forge" },
{ ObjectTypes::DwarfForge, "Dwarf Forge" },
{ ObjectTypes::GnomeForge, "Gnome Forge" },
{ ObjectTypes::BarbarianForge, "Barbarian Forge" },
{ ObjectTypes::IksarForge, "Iksar Forge" },
{ ObjectTypes::HumanForgeOne, "Human Forge" },
{ ObjectTypes::HumanForgeTwo, "Human Forge" },
{ ObjectTypes::HalflingTailoringOne, "Halfling Tailoring" },
{ ObjectTypes::HalflingTailoringTwo, "Halfling Tailoring" },
{ ObjectTypes::EruditeTailoring, "Erudite Tailoring" },
{ ObjectTypes::WoodElfTailoring, "Wood Elf Tailoring" },
{ ObjectTypes::WoodElfFletching, "Wood Elf Fletching" },
{ ObjectTypes::IksarPottery, "Iksar Pottery" },
{ ObjectTypes::Fishing, "Fishing" },
{ ObjectTypes::TrollForge, "Troll Forge" },
{ ObjectTypes::WoodElfForge, "Wood Elf Forge" },
{ ObjectTypes::HalflingForge, "Halfling Forge" },
{ ObjectTypes::EruditeForge, "Erudite Forge" },
{ ObjectTypes::Merchant, "Merchant" },
{ ObjectTypes::FroglokForge, "Froglok Forge" },
{ ObjectTypes::Augmenter, "Augmenter" },
{ ObjectTypes::Churn, "Churn" },
{ ObjectTypes::TransformationMold, "Transformation Mold" },
{ ObjectTypes::DetransformationMold, "Detransformation Mold" },
{ ObjectTypes::Unattuner, "Unattuner" },
{ ObjectTypes::TradeskillBag, "Tradeskill Bag" },
{ ObjectTypes::CollectibleBag, "Collectible Bag" },
{ ObjectTypes::NoDeposit, "No Deposit" }
};
return object_type_map;
}
std::string EQ::constants::GetObjectTypeName(int object_type)
{
if (!EQ::ValueWithin(object_type, ObjectTypes::SmallBag, ObjectTypes::NoDeposit)) {
return std::string();
}
return EQ::constants::GetObjectTypeMap().find(object_type)->second;
}
const std::map<uint8, std::string> &EQ::constants::GetWeatherTypeMap()
{
static const std::map<uint8, std::string> weather_type_map = {
@@ -640,75 +403,59 @@ std::string EQ::constants::GetAppearanceTypeName(uint32 appearance_type)
return std::string();
}
const std::map<uint32, std::string>& EQ::constants::GetSpecialAbilityMap()
std::string SpecialAbility::GetName(int ability_id)
{
static const std::map<uint32, std::string> special_ability_map = {
{ SPECATK_SUMMON, "Summon" },
{ SPECATK_ENRAGE, "Enrage" },
{ SPECATK_RAMPAGE, "Rampage" },
{ SPECATK_AREA_RAMPAGE, "Area Rampage" },
{ SPECATK_FLURRY, "Flurry" },
{ SPECATK_TRIPLE, "Triple Attack" },
{ SPECATK_QUAD, "Quadruple Attack" },
{ SPECATK_INNATE_DW, "Dual Wield" },
{ SPECATK_BANE, "Bane Attack" },
{ SPECATK_MAGICAL, "Magical Attack" },
{ SPECATK_RANGED_ATK, "Ranged Attack" },
{ UNSLOWABLE, "Immune to Slow" },
{ UNMEZABLE, "Immune to Mesmerize" },
{ UNCHARMABLE, "Immune to Charm" },
{ UNSTUNABLE, "Immune to Stun" },
{ UNSNAREABLE, "Immune to Snare" },
{ UNFEARABLE, "Immune to Fear" },
{ UNDISPELLABLE, "Immune to Dispell" },
{ IMMUNE_MELEE, "Immune to Melee" },
{ IMMUNE_MAGIC, "Immune to Magic" },
{ IMMUNE_FLEEING, "Immune to Fleeing" },
{ IMMUNE_MELEE_EXCEPT_BANE, "Immune to Melee except Bane" },
{ IMMUNE_MELEE_NONMAGICAL, "Immune to Non-Magical Melee" },
{ IMMUNE_AGGRO, "Immune to Aggro" },
{ IMMUNE_AGGRO_ON, "Immune to Being Aggro" },
{ IMMUNE_CASTING_FROM_RANGE, "Immune to Ranged Spells" },
{ IMMUNE_FEIGN_DEATH, "Immune to Feign Death" },
{ IMMUNE_TAUNT, "Immune to Taunt" },
{ NPC_TUNNELVISION, "Tunnel Vision" },
{ NPC_NO_BUFFHEAL_FRIENDS, "Does Not Heal of Buff Allies" },
{ IMMUNE_PACIFY, "Immune to Pacify" },
{ LEASH, "Leashed" },
{ TETHER, "Tethered" },
{ DESTRUCTIBLE_OBJECT, "Destructible Object" },
{ NO_HARM_FROM_CLIENT, "Immune to Harm from Client" },
{ ALWAYS_FLEE, "Always Flees" },
{ FLEE_PERCENT, "Flee Percentage" },
{ ALLOW_BENEFICIAL, "Allows Beneficial Spells" },
{ DISABLE_MELEE, "Melee is Disabled" },
{ NPC_CHASE_DISTANCE, "Chase Distance" },
{ ALLOW_TO_TANK, "Allowed to Tank" },
{ IGNORE_ROOT_AGGRO_RULES, "Ignores Root Aggro" },
{ CASTING_RESIST_DIFF, "Casting Resist Difficulty" },
{ COUNTER_AVOID_DAMAGE, "Counter Damage Avoidance" },
{ PROX_AGGRO, "Proximity Aggro" },
{ IMMUNE_RANGED_ATTACKS, "Immune to Ranged Attacks" },
{ IMMUNE_DAMAGE_CLIENT, "Immune to Client Damage" },
{ IMMUNE_DAMAGE_NPC, "Immune to NPC Damage" },
{ IMMUNE_AGGRO_CLIENT, "Immune to Client Aggro" },
{ IMMUNE_AGGRO_NPC, "Immune to NPC Aggro" },
{ MODIFY_AVOID_DAMAGE, "Modify Damage Avoidance" },
{ IMMUNE_FADING_MEMORIES, "Immune to Memory Fades" },
{ IMMUNE_OPEN, "Immune to Open" },
{ IMMUNE_ASSASSINATE, "Immune to Assassinate" },
{ IMMUNE_HEADSHOT, "Immune to Headshot" },
return IsValid(ability_id) ? special_ability_names[ability_id] : "UNKNOWN SPECIAL ABILITY";
}
bool SpecialAbility::IsValid(int ability_id)
{
return special_ability_names.find(ability_id) != special_ability_names.end();
}
const std::map<uint32, std::string>& EQ::constants::GetConsiderColorMap()
{
static const std::map<uint32, std::string> consider_color_map = {
{ ConsiderColor::Green, "Green" },
{ ConsiderColor::DarkBlue, "Dark Blue" },
{ ConsiderColor::Gray, "Gray" },
{ ConsiderColor::White, "White" },
{ ConsiderColor::Red, "Red" },
{ ConsiderColor::Yellow, "Yellow" },
{ ConsiderColor::LightBlue, "Light Blue" },
{ ConsiderColor::WhiteTitanium, "White" },
};
return special_ability_map;
return consider_color_map;
}
std::string EQ::constants::GetSpecialAbilityName(uint32 ability_id)
std::string EQ::constants::GetConsiderColorName(uint32 consider_color)
{
const auto& a = EQ::constants::GetSpecialAbilityMap().find(ability_id);
if (a != EQ::constants::GetSpecialAbilityMap().end()) {
return a->second;
const auto& c = EQ::constants::GetConsiderColorMap().find(consider_color);
return c != EQ::constants::GetConsiderColorMap().end() ? c->second : std::string();
}
std::string AccountStatus::GetName(uint8 account_status)
{
for (
auto e = account_status_names.rbegin();
e != account_status_names.rend();
++e
) {
if (account_status >= e->first) {
return e->second;
}
}
return std::string();
return "UNKNOWN ACCOUNT STATUS";
}
std::string ComparisonType::GetName(uint8 type)
{
return IsValid(type) ? comparison_types[type] : "UNKNOWN COMPARISON TYPE";
}
bool ComparisonType::IsValid(uint8 type)
{
return comparison_types.find(type) != comparison_types.end();
}
+290 -218
View File
@@ -26,6 +26,76 @@
#include <string.h>
namespace AccountStatus {
constexpr uint8 Player = 0;
constexpr uint8 Steward = 10;
constexpr uint8 ApprenticeGuide = 20;
constexpr uint8 Guide = 50;
constexpr uint8 QuestTroupe = 80;
constexpr uint8 SeniorGuide = 81;
constexpr uint8 GMTester = 85;
constexpr uint8 EQSupport = 90;
constexpr uint8 GMStaff = 95;
constexpr uint8 GMAdmin = 100;
constexpr uint8 GMLeadAdmin = 150;
constexpr uint8 QuestMaster = 160;
constexpr uint8 GMAreas = 170;
constexpr uint8 GMCoder = 180;
constexpr uint8 GMMgmt = 200;
constexpr uint8 GMImpossible = 250;
constexpr uint8 Max = 255;
std::string GetName(uint8 account_status);
}
static std::map<uint8, std::string> account_status_names = {
{ AccountStatus::Player, "Player" },
{ AccountStatus::Steward, "Steward" },
{ AccountStatus::ApprenticeGuide, "Apprentice Guide" },
{ AccountStatus::Guide, "Guide" },
{ AccountStatus::QuestTroupe, "Quest Troupe" },
{ AccountStatus::SeniorGuide, "Senior Guide" },
{ AccountStatus::GMTester, "GM Tester" },
{ AccountStatus::EQSupport, "EQ Support" },
{ AccountStatus::GMStaff, "GM Staff" },
{ AccountStatus::GMAdmin, "GM Admin" },
{ AccountStatus::GMLeadAdmin, "GM Lead Admin" },
{ AccountStatus::QuestMaster, "Quest Master" },
{ AccountStatus::GMAreas, "GM Areas" },
{ AccountStatus::GMCoder, "GM Coder" },
{ AccountStatus::GMMgmt, "GM Mgmt" },
{ AccountStatus::GMImpossible, "GM Impossible" },
{ AccountStatus::Max, "GM Max" }
};
namespace ComparisonType {
constexpr uint8 Equal = 0;
constexpr uint8 NotEqual = 1;
constexpr uint8 GreaterOrEqual = 2;
constexpr uint8 LesserOrEqual = 3;
constexpr uint8 Greater = 4;
constexpr uint8 Lesser = 5;
constexpr uint8 Any = 6;
constexpr uint8 NotAny = 7;
constexpr uint8 Between = 8;
constexpr uint8 NotBetween = 9;
std::string GetName(uint8 type);
bool IsValid(uint8 type);
}
static std::map<uint8, std::string> comparison_types = {
{ ComparisonType::Equal, "Equal" },
{ ComparisonType::NotEqual, "Not Equal" },
{ ComparisonType::GreaterOrEqual, "Greater or Equal" },
{ ComparisonType::LesserOrEqual, "Lesser or Equal" },
{ ComparisonType::Greater, "Greater" },
{ ComparisonType::Lesser, "Lesser" },
{ ComparisonType::Any, "Any" },
{ ComparisonType::NotAny, "Not Any" },
{ ComparisonType::Between, "Between" },
{ ComparisonType::NotBetween, "Not Between" },
};
// local definitions are the result of using hybrid-client or server-only values and methods
namespace EQ
@@ -204,19 +274,6 @@ namespace EQ
const size_t SAY_LINK_CLOSER_SIZE = 1;
const size_t SAY_LINK_MAXIMUM_SIZE = (SAY_LINK_OPENER_SIZE + SAY_LINK_BODY_SIZE + SAY_LINK_TEXT_SIZE + SAY_LINK_CLOSER_SIZE);
enum StanceType : int {
stanceUnknown = 0,
stancePassive,
stanceBalanced,
stanceEfficient,
stanceReactive,
stanceAggressive,
stanceAssist,
stanceBurn,
stanceEfficient2,
stanceBurnAE
};
enum BotSpellIDs : int {
Warrior = 3001,
Cleric,
@@ -267,70 +324,6 @@ namespace EQ
Looting
};
enum ObjectTypes : int {
SmallBag,
LargeBag,
Quiver,
BeltPouch,
WristPouch,
Backpack,
SmallChest,
LargeChest,
Bandolier,
Medicine,
Tinkering,
Lexicon,
PoisonMaking,
Quest,
MixingBowl,
Baking,
Tailoring,
Blacksmithing,
Fletching,
Brewing,
JewelryMaking,
Pottery,
Kiln,
KeyMaker,
ResearchWIZ,
ResearchMAG,
ResearchNEC,
ResearchENC,
Unknown,
ResearchPractice,
Alchemy,
HighElfForge,
DarkElfForge,
OgreForge,
DwarfForge,
GnomeForge,
BarbarianForge,
IksarForge,
HumanForgeOne,
HumanForgeTwo,
HalflingTailoringOne,
HalflingTailoringTwo,
EruditeTailoring,
WoodElfTailoring,
WoodElfFletching,
IksarPottery,
Fishing,
TrollForge,
WoodElfForge,
HalflingForge,
EruditeForge,
Merchant,
FroglokForge,
Augmenter,
Churn,
TransformationMold,
DetransformationMold,
Unattuner,
TradeskillBag,
CollectibleBag,
NoDeposit
};
enum WeatherTypes : uint8 {
None,
Raining,
@@ -356,9 +349,6 @@ namespace EQ
Proximity
};
const char *GetStanceName(StanceType stance_type);
int ConvertStanceTypeToIndex(StanceType stance_type);
extern const std::map<uint8, std::string>& GetLanguageMap();
std::string GetLanguageName(uint8 language_id);
@@ -368,12 +358,6 @@ namespace EQ
extern const std::map<int8, std::string>& GetFlyModeMap();
std::string GetFlyModeName(int8 flymode_id);
extern const std::map<bodyType, std::string>& GetBodyTypeMap();
std::string GetBodyTypeName(bodyType bodytype_id);
extern const std::map<uint8, std::string>& GetAccountStatusMap();
std::string GetAccountStatusName(uint8 account_status);
extern const std::map<uint8, std::string>& GetConsiderLevelMap();
std::string GetConsiderLevelName(uint8 consider_level);
@@ -386,9 +370,6 @@ namespace EQ
extern const std::map<uint8, std::string>& GetSpawnAnimationMap();
std::string GetSpawnAnimationName(uint8 animation_id);
extern const std::map<int, std::string>& GetObjectTypeMap();
std::string GetObjectTypeName(int object_type);
extern const std::map<uint8, std::string>& GetWeatherTypeMap();
std::string GetWeatherTypeName(uint8 weather_type);
@@ -401,12 +382,8 @@ namespace EQ
extern const std::map<uint32, std::string>& GetAppearanceTypeMap();
std::string GetAppearanceTypeName(uint32 animation_type);
extern const std::map<uint32, std::string>& GetSpecialAbilityMap();
std::string GetSpecialAbilityName(uint32 ability_id);
const int STANCE_TYPE_FIRST = stancePassive;
const int STANCE_TYPE_LAST = stanceBurnAE;
const int STANCE_TYPE_COUNT = stanceBurnAE;
extern const std::map<uint32, std::string>& GetConsiderColorMap();
std::string GetConsiderColorName(uint32 consider_color);
} /*constants*/
@@ -461,37 +438,6 @@ namespace EQ
} // namespace spells
namespace bug {
enum CategoryID : uint32 {
catOther = 0,
catVideo,
catAudio,
catPathing,
catQuest,
catTradeskills,
catSpellStacking,
catDoorsPortals,
catItems,
catNPC,
catDialogs,
catLoNTCG,
catMercenaries
};
enum OptionalInfoFlag : uint32 {
infoNoOptionalInfo = 0x0,
infoCanDuplicate = 0x1,
infoCrashBug = 0x2,
infoTargetInfo = 0x4,
infoCharacterFlags = 0x8,
infoUnknownValue = 0xFFFFFFF0
};
const char* CategoryIDToCategoryName(CategoryID category_id);
CategoryID CategoryNameToCategoryID(const char* category_name);
} // namespace bug
enum WaypointStatus : int {
RoamBoxPauseInProgress = -3,
QuestControlNoGrid = -2,
@@ -505,7 +451,7 @@ namespace EQ
Raid,
Guild
};
}; // namespace consent
};
} /*EQEmu*/
enum ServerLockType : int {
@@ -514,26 +460,6 @@ enum ServerLockType : int {
Unlock
};
enum AccountStatus : uint8 {
Player = 0,
Steward = 10,
ApprenticeGuide = 20,
Guide = 50,
QuestTroupe = 80,
SeniorGuide = 81,
GMTester = 85,
EQSupport = 90,
GMStaff = 95,
GMAdmin = 100,
GMLeadAdmin = 150,
QuestMaster = 160,
GMAreas = 170,
GMCoder = 180,
GMMgmt = 200,
GMImpossible = 250,
Max = 255
};
enum Invisibility : uint8 {
Visible,
Invisible,
@@ -559,6 +485,17 @@ enum ConsiderLevel : uint8 {
Scowls
};
namespace ConsiderColor {
constexpr uint32 Green = 2;
constexpr uint32 DarkBlue = 4;
constexpr uint32 Gray = 6;
constexpr uint32 White = 10;
constexpr uint32 Red = 13;
constexpr uint32 Yellow = 15;
constexpr uint32 LightBlue = 18;
constexpr uint32 WhiteTitanium = 20;
};
enum TargetDescriptionType : uint8 {
LCSelf,
UCSelf,
@@ -574,19 +511,6 @@ enum ReloadWorld : uint8 {
ForceRepop
};
enum BucketComparison : uint8 {
BucketEqualTo = 0,
BucketNotEqualTo,
BucketGreaterThanOrEqualTo,
BucketLesserThanOrEqualTo,
BucketGreaterThan,
BucketLesserThan,
BucketIsAny,
BucketIsNotAny,
BucketIsBetween,
BucketIsNotBetween
};
enum class EntityFilterType {
All,
Bots,
@@ -600,65 +524,131 @@ enum class ApplySpellType {
Raid
};
enum {
SPECATK_SUMMON = 1,
SPECATK_ENRAGE = 2,
SPECATK_RAMPAGE = 3,
SPECATK_AREA_RAMPAGE = 4,
SPECATK_FLURRY = 5,
SPECATK_TRIPLE = 6,
SPECATK_QUAD = 7,
SPECATK_INNATE_DW = 8,
SPECATK_BANE = 9,
SPECATK_MAGICAL = 10,
SPECATK_RANGED_ATK = 11,
UNSLOWABLE = 12,
UNMEZABLE = 13,
UNCHARMABLE = 14,
UNSTUNABLE = 15,
UNSNAREABLE = 16,
UNFEARABLE = 17,
UNDISPELLABLE = 18,
IMMUNE_MELEE = 19,
IMMUNE_MAGIC = 20,
IMMUNE_FLEEING = 21,
IMMUNE_MELEE_EXCEPT_BANE = 22,
IMMUNE_MELEE_NONMAGICAL = 23,
IMMUNE_AGGRO = 24,
IMMUNE_AGGRO_ON = 25,
IMMUNE_CASTING_FROM_RANGE = 26,
IMMUNE_FEIGN_DEATH = 27,
IMMUNE_TAUNT = 28,
NPC_TUNNELVISION = 29,
NPC_NO_BUFFHEAL_FRIENDS = 30,
IMMUNE_PACIFY = 31,
LEASH = 32,
TETHER = 33,
DESTRUCTIBLE_OBJECT = 34,
NO_HARM_FROM_CLIENT = 35,
ALWAYS_FLEE = 36,
FLEE_PERCENT = 37,
ALLOW_BENEFICIAL = 38,
DISABLE_MELEE = 39,
NPC_CHASE_DISTANCE = 40,
ALLOW_TO_TANK = 41,
IGNORE_ROOT_AGGRO_RULES = 42,
CASTING_RESIST_DIFF = 43,
COUNTER_AVOID_DAMAGE = 44, // Modify by percent NPC's opponents chance to riposte, block, parry or dodge individually, or for all skills
PROX_AGGRO = 45,
IMMUNE_RANGED_ATTACKS = 46,
IMMUNE_DAMAGE_CLIENT = 47,
IMMUNE_DAMAGE_NPC = 48,
IMMUNE_AGGRO_CLIENT = 49,
IMMUNE_AGGRO_NPC = 50,
MODIFY_AVOID_DAMAGE = 51, // Modify by percent the NPCs chance to riposte, block, parry or dodge individually, or for all skills
IMMUNE_FADING_MEMORIES = 52,
IMMUNE_OPEN = 53,
IMMUNE_ASSASSINATE = 54,
IMMUNE_HEADSHOT = 55,
MAX_SPECIAL_ATTACK = 56
};
namespace SpecialAbility {
constexpr int Summon = 1;
constexpr int Enrage = 2;
constexpr int Rampage = 3;
constexpr int AreaRampage = 4;
constexpr int Flurry = 5;
constexpr int TripleAttack = 6;
constexpr int QuadrupleAttack = 7;
constexpr int DualWield = 8;
constexpr int BaneAttack = 9;
constexpr int MagicalAttack = 10;
constexpr int RangedAttack = 11;
constexpr int SlowImmunity = 12;
constexpr int MesmerizeImmunity = 13;
constexpr int CharmImmunity = 14;
constexpr int StunImmunity = 15;
constexpr int SnareImmunity = 16;
constexpr int FearImmunity = 17;
constexpr int DispellImmunity = 18;
constexpr int MeleeImmunity = 19;
constexpr int MagicImmunity = 20;
constexpr int FleeingImmunity = 21;
constexpr int MeleeImmunityExceptBane = 22;
constexpr int MeleeImmunityExceptMagical = 23;
constexpr int AggroImmunity = 24;
constexpr int BeingAggroImmunity = 25;
constexpr int CastingFromRangeImmunity = 26;
constexpr int FeignDeathImmunity = 27;
constexpr int TauntImmunity = 28;
constexpr int TunnelVision = 29;
constexpr int NoBuffHealFriends = 30;
constexpr int PacifyImmunity = 31;
constexpr int Leash = 32;
constexpr int Tether = 33;
constexpr int DestructibleObject = 34;
constexpr int HarmFromClientImmunity = 35;
constexpr int AlwaysFlee = 36;
constexpr int FleePercent = 37;
constexpr int AllowBeneficial = 38;
constexpr int DisableMelee = 39;
constexpr int NPCChaseDistance = 40;
constexpr int AllowedToTank = 41;
constexpr int IgnoreRootAggroRules = 42;
constexpr int CastingResistDifficulty = 43;
constexpr int CounterAvoidDamage = 44;
constexpr int ProximityAggro = 45;
constexpr int RangedAttackImmunity = 46;
constexpr int ClientDamageImmunity = 47;
constexpr int NPCDamageImmunity = 48;
constexpr int ClientAggroImmunity = 49;
constexpr int NPCAggroImmunity = 50;
constexpr int ModifyAvoidDamage = 51;
constexpr int MemoryFadeImmunity = 52;
constexpr int OpenImmunity = 53;
constexpr int AssassinateImmunity = 54;
constexpr int HeadshotImmunity = 55;
constexpr int BotAggroImmunity = 56;
constexpr int BotDamageImmunity = 57;
constexpr int Max = 58;
constexpr int MaxParameters = 9;
std::string GetName(int ability_id);
bool IsValid(int ability_id);
}
static std::map<int, std::string> special_ability_names = {
{ SpecialAbility::Summon, "Summon" },
{ SpecialAbility::Enrage, "Enrage" },
{ SpecialAbility::Rampage, "Rampage" },
{ SpecialAbility::AreaRampage, "Area Rampage" },
{ SpecialAbility::Flurry, "Flurry" },
{ SpecialAbility::TripleAttack, "Triple Attack" },
{ SpecialAbility::QuadrupleAttack, "Quadruple Attack" },
{ SpecialAbility::DualWield, "Dual Wield" },
{ SpecialAbility::BaneAttack, "Bane Attack" },
{ SpecialAbility::MagicalAttack, "Magical Attack" },
{ SpecialAbility::RangedAttack, "Ranged Attack" },
{ SpecialAbility::SlowImmunity, "Immune to Slow" },
{ SpecialAbility::MesmerizeImmunity, "Immune to Mesmerize" },
{ SpecialAbility::CharmImmunity, "Immune to Charm" },
{ SpecialAbility::StunImmunity, "Immune to Stun" },
{ SpecialAbility::SnareImmunity, "Immune to Snare" },
{ SpecialAbility::FearImmunity, "Immune to Fear" },
{ SpecialAbility::DispellImmunity, "Immune to Dispell" },
{ SpecialAbility::MeleeImmunity, "Immune to Melee" },
{ SpecialAbility::MagicImmunity, "Immune to Magic" },
{ SpecialAbility::FleeingImmunity, "Immune to Fleeing" },
{ SpecialAbility::MeleeImmunityExceptBane, "Immune to Melee except Bane" },
{ SpecialAbility::MeleeImmunityExceptMagical, "Immune to Non-Magical Melee" },
{ SpecialAbility::AggroImmunity, "Immune to Aggro" },
{ SpecialAbility::BeingAggroImmunity, "Immune to Being Aggro" },
{ SpecialAbility::CastingFromRangeImmunity, "Immune to Ranged Spells" },
{ SpecialAbility::FeignDeathImmunity, "Immune to Feign Death" },
{ SpecialAbility::TauntImmunity, "Immune to Taunt" },
{ SpecialAbility::TunnelVision, "Tunnel Vision" },
{ SpecialAbility::NoBuffHealFriends, "Does Not Heal or Buff Allies" },
{ SpecialAbility::PacifyImmunity, "Immune to Pacify" },
{ SpecialAbility::Leash, "Leashed" },
{ SpecialAbility::Tether, "Tethered" },
{ SpecialAbility::DestructibleObject, "Destructible Object" },
{ SpecialAbility::HarmFromClientImmunity, "Immune to Harm from Client" },
{ SpecialAbility::AlwaysFlee, "Always Flees" },
{ SpecialAbility::FleePercent, "Flee Percentage" },
{ SpecialAbility::AllowBeneficial, "Allows Beneficial Spells" },
{ SpecialAbility::DisableMelee, "Melee is Disabled" },
{ SpecialAbility::NPCChaseDistance, "Chase Distance" },
{ SpecialAbility::AllowedToTank, "Allowed to Tank" },
{ SpecialAbility::IgnoreRootAggroRules, "Ignores Root Aggro" },
{ SpecialAbility::CastingResistDifficulty, "Casting Resist Difficulty" },
{ SpecialAbility::CounterAvoidDamage, "Counter Damage Avoidance" },
{ SpecialAbility::ProximityAggro, "Proximity Aggro" },
{ SpecialAbility::RangedAttackImmunity, "Immune to Ranged Attacks" },
{ SpecialAbility::ClientDamageImmunity, "Immune to Client Damage" },
{ SpecialAbility::NPCDamageImmunity, "Immune to NPC Damage" },
{ SpecialAbility::ClientAggroImmunity, "Immune to Client Aggro" },
{ SpecialAbility::NPCAggroImmunity, "Immune to NPC Aggro" },
{ SpecialAbility::ModifyAvoidDamage, "Modify Damage Avoidance" },
{ SpecialAbility::MemoryFadeImmunity, "Immune to Memory Fades" },
{ SpecialAbility::OpenImmunity, "Immune to Open" },
{ SpecialAbility::AssassinateImmunity, "Immune to Assassinate" },
{ SpecialAbility::HeadshotImmunity, "Immune to Headshot" },
{ SpecialAbility::BotAggroImmunity, "Immune to Bot Aggro" },
{ SpecialAbility::BotDamageImmunity, "Immune to Bot Damage" },
};
namespace HeroicBonusBucket
{
@@ -684,4 +674,86 @@ namespace HeroicBonusBucket
const std::string DexEnduranceRegen = "HDEX-EnduranceRegen";
}
namespace Bug {
namespace Category {
constexpr uint32 Other = 0;
constexpr uint32 Video = 1;
constexpr uint32 Audio = 2;
constexpr uint32 Pathing = 3;
constexpr uint32 Quest = 4;
constexpr uint32 Tradeskills = 5;
constexpr uint32 SpellStacking = 6;
constexpr uint32 DoorsPortals = 7;
constexpr uint32 Items = 8;
constexpr uint32 NPC = 9;
constexpr uint32 Dialogs = 10;
constexpr uint32 LoNTCG = 11;
constexpr uint32 Mercenaries = 12;
}
namespace InformationFlag {
constexpr uint32 None = 0;
constexpr uint32 Repeatable = 1;
constexpr uint32 Crash = 2;
constexpr uint32 TargetInfo = 4;
constexpr uint32 CharacterFlags = 8;
constexpr uint32 Unknown = 4294967280;
}
uint32 GetID(const std::string& category_name);
std::string GetName(uint32 category_id);
bool IsValid(uint32 category_id);
}
static std::map<uint32, std::string> bug_category_names = {
{ Bug::Category::Other, "Other" },
{ Bug::Category::Video, "Video" },
{ Bug::Category::Audio, "Audio" },
{ Bug::Category::Pathing, "Pathing" },
{ Bug::Category::Quest, "Quest" },
{ Bug::Category::Tradeskills, "Tradeskills" },
{ Bug::Category::SpellStacking, "Spell Stacking" },
{ Bug::Category::DoorsPortals, "Doors and Portals" },
{ Bug::Category::Items, "Items" },
{ Bug::Category::NPC, "NPC" },
{ Bug::Category::Dialogs, "Dialogs" },
{ Bug::Category::LoNTCG, "LoN - TCG" },
{ Bug::Category::Mercenaries, "Mercenaries" }
};
namespace Stance {
constexpr uint32 Unknown = 0;
constexpr uint32 Passive = 1;
constexpr uint32 Balanced = 2;
constexpr uint32 Efficient = 3;
constexpr uint32 Reactive = 4;
constexpr uint32 Aggressive = 5;
constexpr uint32 Assist = 6;
constexpr uint32 Burn = 7;
constexpr uint32 Efficient2 = 8;
constexpr uint32 AEBurn = 9;
std::string GetName(uint8 stance_id);
uint8 GetIndex(uint8 stance_id);
bool IsValid(uint8 stance_id);
}
static std::map<uint32, std::string> stance_names = {
{ Stance::Unknown, "Unknown" },
{ Stance::Passive, "Passive" },
{ Stance::Balanced, "Balanced" },
{ Stance::Efficient, "Efficient" },
{ Stance::Reactive, "Reactive" },
{ Stance::Aggressive, "Aggressive" },
{ Stance::Assist, "Assist" },
{ Stance::Burn, "Burn" },
{ Stance::Efficient2, "Efficient" },
{ Stance::AEBurn, "AE Burn" }
};
namespace PCNPCOnlyFlagType {
constexpr int PC = 1;
constexpr int NPC = 2;
}
#endif /*COMMON_EMU_CONSTANTS_H*/
+1
View File
@@ -45,6 +45,7 @@ typedef enum { //EQEmu internal opcodes list
_maxEmuOpcode
} EmuOpcode;
constexpr int format_as(EmuOpcode opcode) { return static_cast<int>(opcode); }
extern const char *OpcodeNames[_maxEmuOpcode+1];
#endif
+7
View File
@@ -67,6 +67,7 @@ N(OP_Buff),
N(OP_BuffCreate),
N(OP_BuffRemoveRequest),
N(OP_Bug),
N(OP_BuyerItems),
N(OP_CameraEffect),
N(OP_Camp),
N(OP_CancelSneakHide),
@@ -510,6 +511,11 @@ N(OP_ShopEndConfirm),
N(OP_ShopItem),
N(OP_ShopPlayerBuy),
N(OP_ShopPlayerSell),
N(OP_ShopSendParcel),
N(OP_ShopDeleteParcel),
N(OP_ShopRespondParcel),
N(OP_ShopRetrieveParcel),
N(OP_ShopParcelIcon),
N(OP_ShopRequest),
N(OP_SimpleMessage),
N(OP_SkillUpdate),
@@ -552,6 +558,7 @@ N(OP_TradeBusy),
N(OP_TradeCoins),
N(OP_TradeMoneyUpdate),
N(OP_Trader),
N(OP_TraderBulkSend),
N(OP_TraderBuy),
N(OP_TraderDelItem),
N(OP_TradeRequest),
+70 -65
View File
@@ -758,10 +758,10 @@ typedef enum {
FilterFocusEffects = 22, //0=show, 1=hide
FilterPetSpells = 23, //0=show, 1=hide
FilterHealOverTime = 24, //0=show, 1=mine only, 2=hide
FilterUnknown25 = 25,
FilterUnknown26 = 26,
FilterUnknown27 = 27,
FilterUnknown28 = 28,
FilterItemSpeech = 25, //0=show, 1=hide // RoF2 Confirmed
FilterStrikethrough = 26, //0=show, 1=hide // RoF2 Confirmed
FilterStuns = 27, //0=show, 1=hide // RoF2 Confirmed
FilterBardSongsOnPets = 28, //0=show, 1=hide // RoF2 Confirmed
_FilterCount
} eqFilterType;
@@ -772,67 +772,47 @@ typedef enum {
FilterShowSelfOnly
} eqFilterMode;
#define STAT_STR 0
#define STAT_STA 1
#define STAT_AGI 2
#define STAT_DEX 3
#define STAT_INT 4
#define STAT_WIS 5
#define STAT_CHA 6
#define STAT_MAGIC 7
#define STAT_COLD 8
#define STAT_FIRE 9
#define STAT_POISON 10
#define STAT_DISEASE 11
#define STAT_MANA 12
#define STAT_HP 13
#define STAT_AC 14
#define STAT_ENDURANCE 15
#define STAT_ATTACK 16
#define STAT_HP_REGEN 17
#define STAT_MANA_REGEN 18
#define STAT_HASTE 19
#define STAT_DAMAGE_SHIELD 20
/*
** Recast timer types. Used as an off set to charProfileStruct timers.
**
** (Another orphaned enumeration...)
*/
enum RecastTimerTypes
{
RecTimer_0 = 0,
RecTimer_1,
RecTimer_WeaponHealClick, // 2
RecTimer_MuramiteBaneNukeClick, // 3
RecTimer_4,
RecTimer_DispellClick, // 5 (also click heal orbs?)
RecTimer_Epic, // 6
RecTimer_OoWBPClick, // 7
RecTimer_VishQuestClassItem, // 8
RecTimer_HealPotion, // 9
RecTimer_10,
RecTimer_11,
RecTimer_12,
RecTimer_13,
RecTimer_14,
RecTimer_15,
RecTimer_16,
RecTimer_17,
RecTimer_18,
RecTimer_ModRod, // 19
_RecTimerCount
};
enum GroupUpdateAction
{
GUA_Joined = 0,
GUA_Left = 1,
GUA_LastLeft = 6,
GUA_FullGroupInfo = 7,
GUA_MakeLeader = 8,
GUA_Started = 9
};
#define STAT_STR 0
#define STAT_STA 1
#define STAT_AGI 2
#define STAT_DEX 3
#define STAT_INT 4
#define STAT_WIS 5
#define STAT_CHA 6
#define STAT_MAGIC 7
#define STAT_COLD 8
#define STAT_FIRE 9
#define STAT_POISON 10
#define STAT_DISEASE 11
#define STAT_MANA 12
#define STAT_HP 13
#define STAT_AC 14
#define STAT_ENDURANCE 15
#define STAT_ATTACK 16
#define STAT_HP_REGEN 17
#define STAT_MANA_REGEN 18
#define STAT_HASTE 19
#define STAT_DAMAGE_SHIELD 20
#define STAT_DS_MITIGATION 22
#define STAT_HEAL_AMOUNT 23
#define STAT_SPELL_DAMAGE 24
#define STAT_CLAIRVOYANCE 25
#define STAT_HEROIC_AGILITY 26
#define STAT_HEROIC_CHARISMA 27
#define STAT_HEROIC_DEXTERITY 28
#define STAT_HEROIC_INTELLIGENCE 29
#define STAT_HEROIC_STAMINA 30
#define STAT_HEROIC_STRENGTH 31
#define STAT_HEROIC_WISDOM 32
#define STAT_BASH 33
#define STAT_BACKSTAB 34
#define STAT_DRAGON_PUNCH 35
#define STAT_EAGLE_STRIKE 36
#define STAT_FLYING_KICK 37
#define STAT_KICK 38
#define STAT_ROUND_KICK 39
#define STAT_TIGER_CLAW 40
#define STAT_FRENZY 41
static const uint8 DamageTypeSomething = 0x1C; //0x1c is something...
static const uint8 DamageTypeFalling = 0xFC;
@@ -1127,4 +1107,29 @@ namespace RaidLootType {
constexpr uint32 EntireRaid = 4;
}
namespace LeadershipAbilitySlot {
constexpr uint16 HealthOfTargetsTarget = 14;
}
enum ExpSource
{
Quest,
GM,
Kill,
Death,
Resurrection,
LDoNChest,
Task,
Sacrifice
};
#define PARCEL_SEND_ITEMS 0
#define PARCEL_SEND_MONEY 1
#define PARCEL_MONEY_ITEM_ID 99990 // item id of money
#define PARCEL_LIMIT 5
#define PARCEL_BEGIN_SLOT 1
namespace DoorType {
constexpr uint32 BuyerStall = 155;
}
#endif /*COMMON_EQ_CONSTANTS_H*/
+713 -154
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -141,6 +141,7 @@ namespace Logs {
Zoning,
EqTime,
Corpses,
XTargets,
MaxCategoryID /* Don't Remove this */
};
@@ -241,6 +242,7 @@ namespace Logs {
"Zoning",
"EqTime",
"Corpses",
"XTargets"
};
}
+10
View File
@@ -834,6 +834,16 @@
OutF(LogSys, Logs::Detail, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogXTargets(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::XTargets))\
OutF(LogSys, Logs::General, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogXTargetsDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::XTargets))\
OutF(LogSys, Logs::Detail, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.IsLogEnabled(debug_level, log_category))\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
+10 -2
View File
@@ -642,6 +642,10 @@ void PlayerEventLogs::ProcessRetentionTruncation()
void PlayerEventLogs::ReloadSettings()
{
for (auto &e: PlayerEventLogSettingsRepository::All(*m_database)) {
if (e.id >= PlayerEvent::MAX || e.id < 0) {
continue;
}
m_settings[e.id] = e;
}
}
@@ -697,8 +701,12 @@ void PlayerEventLogs::SetSettingsDefaults()
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::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;
m_settings[PlayerEvent::PARCEL_RETRIEVE].event_enabled = 1;
m_settings[PlayerEvent::PARCEL_DELETE].event_enabled = 1;
m_settings[PlayerEvent::BARTER_TRANSACTION].event_enabled = 1;
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
m_settings[i].retention_days = RETENTION_DAYS_DEFAULT;
+135 -2
View File
@@ -58,6 +58,10 @@ namespace PlayerEvent {
ITEM_CREATION,
GUILD_TRIBUTE_DONATE_ITEM,
GUILD_TRIBUTE_DONATE_PLAT,
PARCEL_SEND,
PARCEL_RETRIEVE,
PARCEL_DELETE,
BARTER_TRANSACTION,
MAX // dont remove
};
@@ -66,7 +70,7 @@ namespace PlayerEvent {
// If event is unimplemented just tag (Unimplemented) in the name
// Events don't get saved to the database if unimplemented or deprecated
// Events tagged as deprecated will get automatically removed
static const char *EventName[PlayerEvent::MAX] = {
static const char *EventName[EventType::MAX] = {
"None",
"GM Command",
"Zoning",
@@ -116,7 +120,11 @@ namespace PlayerEvent {
"Killed Raid NPC",
"Item Creation",
"Guild Tribute Donate Item",
"Guild Tribute Donate Platinum"
"Guild Tribute Donate Platinum",
"Parcel Item Sent",
"Parcel Item Retrieved",
"Parcel Prune Routine",
"Barter Transaction"
};
// Generic struct used by all events
@@ -976,6 +984,131 @@ namespace PlayerEvent {
);
}
};
struct ParcelRetrieve {
uint32 item_id;
uint32 quantity;
std::string from_player_name;
uint32 sent_date;
uint32 aug_slot_1;
uint32 aug_slot_2;
uint32 aug_slot_3;
uint32 aug_slot_4;
uint32 aug_slot_5;
uint32 aug_slot_6;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(quantity),
CEREAL_NVP(from_player_name),
CEREAL_NVP(sent_date),
CEREAL_NVP(aug_slot_1),
CEREAL_NVP(aug_slot_2),
CEREAL_NVP(aug_slot_3),
CEREAL_NVP(aug_slot_4),
CEREAL_NVP(aug_slot_5),
CEREAL_NVP(aug_slot_6)
);
}
};
struct ParcelSend {
uint32 item_id;
uint32 quantity;
std::string from_player_name;
std::string to_player_name;
uint32 sent_date;
uint32 aug_slot_1;
uint32 aug_slot_2;
uint32 aug_slot_3;
uint32 aug_slot_4;
uint32 aug_slot_5;
uint32 aug_slot_6;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(quantity),
CEREAL_NVP(from_player_name),
CEREAL_NVP(to_player_name),
CEREAL_NVP(sent_date),
CEREAL_NVP(aug_slot_1),
CEREAL_NVP(aug_slot_2),
CEREAL_NVP(aug_slot_3),
CEREAL_NVP(aug_slot_4),
CEREAL_NVP(aug_slot_5),
CEREAL_NVP(aug_slot_6)
);
}
};
struct ParcelDelete {
uint32 item_id;
uint32 quantity;
uint32 char_id;
std::string from_name;
std::string note;
uint32 sent_date;
uint32 aug_slot_1;
uint32 aug_slot_2;
uint32 aug_slot_3;
uint32 aug_slot_4;
uint32 aug_slot_5;
uint32 aug_slot_6;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(item_id),
CEREAL_NVP(quantity),
CEREAL_NVP(char_id),
CEREAL_NVP(from_name),
CEREAL_NVP(note),
CEREAL_NVP(sent_date),
CEREAL_NVP(aug_slot_1),
CEREAL_NVP(aug_slot_2),
CEREAL_NVP(aug_slot_3),
CEREAL_NVP(aug_slot_4),
CEREAL_NVP(aug_slot_5),
CEREAL_NVP(aug_slot_6)
);
}
};
struct BarterTransaction {
std::string status;
uint32 item_id;
uint32 item_quantity;
std::string item_name;
std::vector<BuyerLineTradeItems_Struct> trade_items;
std::string buyer_name;
std::string seller_name;
uint64 total_cost;
// cereal
template<class Archive>
void serialize(Archive &ar)
{
ar(
CEREAL_NVP(status),
CEREAL_NVP(item_id),
CEREAL_NVP(item_quantity),
CEREAL_NVP(item_name),
CEREAL_NVP(trade_items),
CEREAL_NVP(buyer_name),
CEREAL_NVP(seller_name),
CEREAL_NVP(total_cost)
);
}
};
}
#endif //EQEMU_PLAYER_EVENTS_H
+8 -8
View File
@@ -38,21 +38,21 @@
#include <fmt/format.h>
#include <filesystem>
#include <iostream>
#include <sys/stat.h>
namespace fs = std::filesystem;
/**
* @param name
* @return
*/
bool File::Exists(const std::string &name)
{
return fs::exists(fs::path{name});
struct stat sb{};
if (stat(name.c_str(), &sb) == 0) {
return true;
}
return false;
}
/**
* @param directory_name
*/
void File::Makedir(const std::string &directory_name)
{
try {
+46 -67
View File
@@ -92,10 +92,20 @@ BaseGuildManager::~BaseGuildManager()
bool BaseGuildManager::LoadGuilds()
{
ClearGuilds();
auto guilds = GuildsRepository::All(*m_db);
auto guilds_ranks = GuildRanksRepository::All(*m_db);
auto guilds_permissions = GuildPermissionsRepository::All(*m_db);
auto guilds_tributes = GuildTributesRepository::All(*m_db);
auto guilds = GuildsRepository::GetWhere(
*m_db,
fmt::format("`id` < '{}'", RoF2::constants::MAX_GUILD_ID)
);
auto guilds_ranks = GuildRanksRepository::LoadAll(*m_db);
auto guilds_permissions = GuildPermissionsRepository::LoadAll(*m_db);
auto guilds_tributes = GuildTributesRepository::GetWhere(
*m_db,
fmt::format(
"`guild_id` < '{}'",
RoF2::constants::MAX_GUILD_ID
)
);
if (guilds.empty()) {
LogGuilds("No Guilds found in database.");
@@ -108,22 +118,27 @@ bool BaseGuildManager::LoadGuilds()
_CreateGuild(g.id, g.name, g.leader, g.minstatus, g.motd, g.motd_setter, g.channel, g.url, g.favor);
for (auto const &r: guilds_ranks) {
if (r.guild_id == g.id) {
m_guilds[g.id]->rank_names[r.rank_] = r.title;
for (int i = 1; i <= GUILD_MAX_RANK; i++) {
auto key = fmt::format("{}-{}", g.id, i);
if (guilds_ranks.contains(key)) {
m_guilds[g.id]->rank_names[i] = guilds_ranks.find(key)->second;
}
}
auto count = 0;
for (auto const &p: guilds_permissions) {
if (p.guild_id == g.id) {
for (int i = 1; i <= GUILD_MAX_FUNCTIONS; i++) {
auto key = fmt::format("{}-{}", g.id, i);
if (guilds_permissions.contains(key)) {
auto p = guilds_permissions.find(key)->second;
m_guilds[g.id]->functions[p.perm_id].id = p.id;
m_guilds[g.id]->functions[p.perm_id].guild_id = p.guild_id;
m_guilds[g.id]->functions[p.perm_id].perm_id = p.perm_id;
m_guilds[g.id]->functions[p.perm_id].perm_value = p.permission;
count++;
}
count++;
}
if (count < GUILD_MAX_FUNCTIONS) {
@@ -342,41 +357,14 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id)
return true;
}
uint32 BaseGuildManager::_GetFreeGuildID()
{
GuildsRepository::DeleteWhere(*m_db, "`name` = ''");
GuildsRepository::Guilds out;
out.id = 0;
out.leader = 0;
out.minstatus = 0;
out.tribute = 0;
out.name = "";
out.motd = "";
out.motd_setter = "";
out.url = "";
out.channel = "";
auto last_insert_id = GuildsRepository::InsertOne(*m_db, out);
if (last_insert_id.id > 0) {
LogGuilds("Located a free guild ID [{}] in the database", last_insert_id.id);
return last_insert_id.id;
}
LogGuilds("Unable to find a free guild ID in the database");
return GUILD_NONE;
}
uint32 BaseGuildManager::CreateGuild(std::string name, uint32 leader_char_id)
{
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
if (guild_id == GUILD_NONE) {
return (GUILD_NONE);
}
//RefreshGuild(guild_id);
//SendGuildRefresh(guild_id, true, false, false, false);
//SendCharRefresh(GUILD_NONE, guild_id, leader_char_id);
uint32 guild_id = UpdateDbCreateGuild(name, leader_char_id);
if (guild_id == GUILD_NONE) {
return (GUILD_NONE);
}
return guild_id;
return guild_id;
}
bool BaseGuildManager::DeleteGuild(uint32 guild_id)
@@ -539,8 +527,8 @@ bool BaseGuildManager::SetPublicNote(uint32 charid, std::string public_note)
uint32 BaseGuildManager::UpdateDbCreateGuild(std::string name, uint32 leader)
{
auto new_id = _GetFreeGuildID();
if (new_id == GUILD_NONE) {
auto new_id = GuildsRepository::GetMaxId(*m_db) + 1;
if (!new_id) {
return GUILD_NONE;
}
@@ -881,7 +869,7 @@ static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into)
if (into.guild_id == 0) {
into.guild_id = GUILD_NONE;
}
if (into.rank > GUILD_MAX_RANK) {
if (into.rank > GUILD_MAX_RANK + 1) {
into.rank = GUILD_RANK_NONE;
}
}
@@ -956,33 +944,24 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into)
}
//returns ownership of the buffer.
uint8 *BaseGuildManager::MakeGuildList(const char *head_name, uint32 &length) const
GuildsListMessaging_Struct BaseGuildManager::MakeGuildList()
{
//dynamic structs will make this a lot less painful.
GuildsListMessaging_Struct guild_list_messaging{};
uint32 string_length = 0;
length = sizeof(GuildsList_Struct);
auto buffer = new uint8[length];
for (auto const &g: m_guilds) {
GuildsListMessagingEntry_Struct guild_entry{};
//a bit little better than memsetting the whole thing...
uint32 r, pos;
for (r = 0, pos = 0; r <= MAX_NUMBER_GUILDS; r++, pos += 64) {
//strcpy((char *) buffer+pos, "BAD GUILD");
// These 'BAD GUILD' entries were showing in the drop-downs for selecting guilds in the LFP window,
// so just fill unused entries with an empty string instead.
buffer[pos] = '\0';
guild_entry.guild_id = g.first;
guild_entry.guild_name = g.second->name;
string_length += g.second->name.length() + 1;
guild_list_messaging.guild_detail.push_back(guild_entry);
}
strn0cpy((char *) buffer, head_name, 64);
guild_list_messaging.no_of_guilds = m_guilds.size();
guild_list_messaging.string_length = string_length;
std::map<uint32, GuildInfo *>::const_iterator cur, end;
cur = m_guilds.begin();
end = m_guilds.end();
for (; cur != end; ++cur) {
pos = 64 + (64 * cur->first);
strn0cpy((char *) buffer + pos, cur->second->name.c_str(), 64);
}
return (buffer);
return guild_list_messaging;
}
const char *BaseGuildManager::GetRankName(uint32 guild_id, uint8 rank) const
@@ -1090,7 +1069,7 @@ bool BaseGuildManager::IsGuildLeader(uint32 guild_id, uint32 char_id) const
LogGuilds("Check leader for char [{}]: invalid guild", char_id);
return (false); //invalid guild
}
LogGuilds("Check leader for guild [{}]\, char [{}]\: leader id=[{}]", guild_id, char_id, res->second->leader);
LogGuilds("Check leader for guild [{}], char [{}]: leader id=[{}]", guild_id, char_id, res->second->leader);
return (char_id == res->second->leader);
}
+13 -4
View File
@@ -75,9 +75,18 @@ class BaseGuildManager
virtual ~BaseGuildManager();
//this must be called before doing anything else with this object
void SetDatabase(Database *db)
BaseGuildManager * SetDatabase(Database *db)
{
m_db = db;
return this;
}
BaseGuildManager * SetContentDatabase(Database *db)
{
m_content_db = db;
return this;
}
bool LoadGuilds();
@@ -125,7 +134,7 @@ class BaseGuildManager
bool CheckGMStatus(uint32 guild_id, uint8 status) const;
bool CheckPermission(uint32 guild_id, uint8 rank, GuildAction act) const;
bool UpdateDbBankerFlag(uint32 charid, bool is_banker);
uint8* MakeGuildList(const char* head_name, uint32& length) const; //make a guild list packet, returns ownership of the buffer.
GuildsListMessaging_Struct MakeGuildList();
uint8 GetDisplayedRank(uint32 guild_id, uint8 rank, uint32 char_id) const;
uint32 GetGuildIDByName(const char *GuildName);
uint32 GetGuildIDByCharacterID(uint32 character_id);
@@ -194,11 +203,11 @@ class BaseGuildManager
std::map<uint32, GuildInfo *> m_guilds; //we own the pointers in this map
void ClearGuilds(); //clears internal structure
Database *m_db; //we do not own this
Database *m_db;
Database *m_content_db;
bool _StoreGuildDB(uint32 guild_id);
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
uint32 _GetFreeGuildID();
GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in);
};
#endif /*GUILD_BASE_H_*/
+2 -1
View File
@@ -35,7 +35,7 @@
#define GUILD_MEMBER_TI 0
#define GUILD_OFFICER_TI 1
#define GUILD_LEADER_TI 2
#define GUILD_RANK_NONE (GUILD_MAX_RANK+1)
#define GUILD_RANK_NONE_TI (GUILD_MAX_RANK + 1)
//defines for standard ranks base on RoF2 definitions
#define GUILD_RANK_NONE 0
@@ -81,5 +81,6 @@ typedef enum {
GUILD_ACTION_MEMBERS_DEMOTE_SELF = 30,
} GuildAction;
constexpr int format_as(GuildAction action) { return static_cast<int>(action); }
#endif
+68 -3
View File
@@ -276,7 +276,7 @@ bool EQ::InventoryProfile::SwapItem(
SwapItemFailState &fail_state,
uint16 race_id,
uint8 class_id,
uint16 deity_id,
uint32 deity_id,
uint8 level
) {
fail_state = swapInvalid;
@@ -354,7 +354,7 @@ bool EQ::InventoryProfile::SwapItem(
fail_state = swapRaceClass;
return false;
}
if (deity_id && source_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & source_item->Deity)) {
if (deity_id && source_item->Deity && !(Deity::GetBitmask(deity_id) & source_item->Deity)) {
fail_state = swapDeity;
return false;
}
@@ -380,7 +380,7 @@ bool EQ::InventoryProfile::SwapItem(
fail_state = swapRaceClass;
return false;
}
if (deity_id && destination_item->Deity && !(deity::GetDeityBitmask((deity::DeityType)deity_id) & destination_item->Deity)) {
if (deity_id && destination_item->Deity && !(Deity::GetBitmask(deity_id) & destination_item->Deity)) {
fail_state = swapDeity;
return false;
}
@@ -1743,3 +1743,68 @@ std::vector<uint32> EQ::InventoryProfile::GetAugmentIDsBySlotID(int16 slot_id)
return augments;
}
std::vector<int16> EQ::InventoryProfile::FindAllFreeSlotsThatFitItem(const EQ::ItemData *item_data)
{
std::vector<int16> free_slots{};
for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) {
if ((((uint64) 1 << i) & GetLookup()->PossessionsBitmask) == 0) {
continue;
}
EQ::ItemInstance *inv_item = GetItem(i);
if (!inv_item) {
// Found available slot in personal inventory
free_slots.push_back(i);
}
if (inv_item->IsClassBag() &&
EQ::InventoryProfile::CanItemFitInContainer(item_data, inv_item->GetItem())) {
int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(i, EQ::invbag::SLOT_BEGIN);
uint8 bag_size = inv_item->GetItem()->BagSlots;
for (uint8 bag_slot = EQ::invbag::SLOT_BEGIN; bag_slot < bag_size; bag_slot++) {
auto bag_item = GetItem(base_slot_id + bag_slot);
if (!bag_item) {
// Found available slot within bag
free_slots.push_back(i);
}
}
}
}
return free_slots;
}
int16 EQ::InventoryProfile::FindFirstFreeSlotThatFitsItem(const EQ::ItemData *item_data)
{
for (int16 i = EQ::invslot::GENERAL_BEGIN; i <= EQ::invslot::GENERAL_END; i++) {
if ((((uint64) 1 << i) & GetLookup()->PossessionsBitmask) == 0) {
continue;
}
EQ::ItemInstance *inv_item = GetItem(i);
if (!inv_item) {
// Found available slot in personal inventory
return i;
}
if (inv_item->IsClassBag() &&
EQ::InventoryProfile::CanItemFitInContainer(item_data, inv_item->GetItem())) {
int16 base_slot_id = EQ::InventoryProfile::CalcSlotId(i, EQ::invbag::SLOT_BEGIN);
uint8 bag_size = inv_item->GetItem()->BagSlots;
for (uint8 bag_slot = EQ::invbag::SLOT_BEGIN; bag_slot < bag_size; bag_slot++) {
auto bag_item = GetItem(base_slot_id + bag_slot);
if (!bag_item) {
// Found available slot within bag
return base_slot_id + bag_slot;
}
}
}
}
return 0;
}
+3 -1
View File
@@ -132,7 +132,7 @@ namespace EQ
// Swap items in inventory
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint32 deity_id = Deity::Unknown, uint8 level = 0);
// Remove item from inventory
bool DeleteItem(int16 slot_id, int16 quantity = 0);
@@ -176,6 +176,8 @@ namespace EQ
// Locate an available inventory slot
int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false);
int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = invslot::GENERAL_BEGIN, uint8 bag_start = invbag::SLOT_BEGIN);
std::vector<int16> FindAllFreeSlotsThatFitItem(const EQ::ItemData *inst);
int16 FindFirstFreeSlotThatFitsItem(const EQ::ItemData *inst);
// Calculate slot_id for an item within a bag
static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id
+55 -21
View File
@@ -81,45 +81,79 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
);
}
/**
* Gets local address - pings google to inspect what interface was used locally
* @return
*/
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include <iostream>
#include <string>
#include <cstring>
std::string IpUtil::GetLocalIPAddress()
{
char my_ip_address[16];
unsigned int my_port;
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
return "";
}
#endif
char my_ip_address[INET_ADDRSTRLEN];
struct sockaddr_in server_address{};
struct sockaddr_in my_address{};
int sockfd;
int sockfd;
// Connect to server
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
// Create a UDP socket
#ifdef _WIN32
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == INVALID_SOCKET) {
WSACleanup();
return "";
}
#else
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
return "";
}
#endif
// Set server_addr
// Set server_addr (dummy address)
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("172.217.160.99");
server_address.sin_port = htons(80);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("8.8.8.8"); // Google DNS
server_address.sin_port = htons(53); // DNS port
// Connect to server
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
close(sockfd);
return "";
}
// Perform a dummy connection to the server (UDP)
connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
// Get my ip address and port
// Get my IP address
memset(&my_address, 0, sizeof(my_address));
socklen_t len = sizeof(my_address);
getsockname(sockfd, (struct sockaddr *) &my_address, &len);
inet_ntop(AF_INET, &my_address.sin_addr, my_ip_address, sizeof(my_ip_address));
my_port = ntohs(my_address.sin_port);
return fmt::format("{}", my_ip_address);
#ifdef _WIN32
closesocket(sockfd);
WSACleanup();
#else
close(sockfd);
#endif
LogInfo("Local IP Address [{}]", my_ip_address);
return std::string(my_ip_address);
}
/**
* Gets public address
* Uses various websites as options to return raw public IP back to the client
+69 -66
View File
@@ -58,72 +58,75 @@ namespace EQ
};
enum ItemType : uint8 {
/*9138*/ ItemType1HSlash = 0,
/*9141*/ ItemType2HSlash,
/*9140*/ ItemType1HPiercing,
/*9139*/ ItemType1HBlunt,
/*9142*/ ItemType2HBlunt,
/*5504*/ ItemTypeBow, // 5
/*----*/ ItemTypeUnknown1,
/*----*/ ItemTypeLargeThrowing,
/*5505*/ ItemTypeShield,
/*5506*/ ItemTypeScroll,
/*5507*/ ItemTypeArmor, // 10
/*5508*/ ItemTypeMisc, // a lot of random crap has this item use.
/*7564*/ ItemTypeLockPick,
/*----*/ ItemTypeUnknown2,
/*5509*/ ItemTypeFood,
/*5510*/ ItemTypeDrink, // 15
/*5511*/ ItemTypeLight,
/*5512*/ ItemTypeCombinable, // not all stackable items are this use...
/*5513*/ ItemTypeBandage,
/*----*/ ItemTypeSmallThrowing,
/*----*/ ItemTypeSpell, // 20 // spells and tomes
/*5514*/ ItemTypePotion,
/*----*/ ItemTypeUnknown3,
/*0406*/ ItemTypeWindInstrument,
/*0407*/ ItemTypeStringedInstrument,
/*0408*/ ItemTypeBrassInstrument, // 25
/*0405*/ ItemTypePercussionInstrument,
/*5515*/ ItemTypeArrow,
/*----*/ ItemTypeUnknown4,
/*5521*/ ItemTypeJewelry,
/*----*/ ItemTypeSkull, // 30
/*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...)
/*5517*/ ItemTypeNote,
/*5518*/ ItemTypeKey,
/*----*/ ItemTypeCoin,
/*5520*/ ItemType2HPiercing, // 35
/*----*/ ItemTypeFishingPole,
/*----*/ ItemTypeFishingBait,
/*5519*/ ItemTypeAlcohol,
/*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?)
/*----*/ ItemTypeCompass, // 40
/*----*/ ItemTypeUnknown5,
/*----*/ ItemTypePoison, // might be wrong, but includes poisons
/*----*/ ItemTypeUnknown6,
/*----*/ ItemTypeUnknown7,
/*5522*/ ItemTypeMartial, // 45
/*----*/ ItemTypeUnknown8,
/*----*/ ItemTypeUnknown9,
/*----*/ ItemTypeUnknown10,
/*----*/ ItemTypeUnknown11,
/*----*/ ItemTypeSinging, // 50
/*5750*/ ItemTypeAllInstrumentTypes,
/*5776*/ ItemTypeCharm,
/*----*/ ItemTypeDye,
/*----*/ ItemTypeAugmentation,
/*----*/ ItemTypeAugmentationSolvent, // 55
/*----*/ ItemTypeAugmentationDistiller,
/*----*/ ItemTypeUnknown12,
/*----*/ ItemTypeFellowshipKit,
/*----*/ ItemTypeUnknown13,
/*----*/ ItemTypeRecipe, // 60
/*----*/ ItemTypeAdvancedRecipe,
/*----*/ ItemTypeJournal, // only one(1) database entry
/*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage)
/*5881*/ ItemTypePerfectedAugmentationDistiller,
/*----*/ ItemTypeCount
/*9138*/ ItemType1HSlash = 0,
/*9141*/ ItemType2HSlash,
/*9140*/ ItemType1HPiercing,
/*9139*/ ItemType1HBlunt,
/*9142*/ ItemType2HBlunt,
/*5504*/ ItemTypeBow, // 5
/*----*/ ItemTypeUnknown1,
/*----*/ ItemTypeLargeThrowing,
/*5505*/ ItemTypeShield,
/*5506*/ ItemTypeScroll,
/*5507*/ ItemTypeArmor, // 10
/*5508*/ ItemTypeMisc, // a lot of random crap has this item use.
/*7564*/ ItemTypeLockPick,
/*----*/ ItemTypeUnknown2,
/*5509*/ ItemTypeFood,
/*5510*/ ItemTypeDrink, // 15
/*5511*/ ItemTypeLight,
/*5512*/ ItemTypeCombinable, // not all stackable items are this use...
/*5513*/ ItemTypeBandage,
/*----*/ ItemTypeSmallThrowing,
/*----*/ ItemTypeSpell, // 20 // spells and tomes
/*5514*/ ItemTypePotion,
/*----*/ ItemTypeUnknown3,
/*0406*/ ItemTypeWindInstrument,
/*0407*/ ItemTypeStringedInstrument,
/*0408*/ ItemTypeBrassInstrument, // 25
/*0405*/ ItemTypePercussionInstrument,
/*5515*/ ItemTypeArrow,
/*----*/ ItemTypeUnknown4,
/*5521*/ ItemTypeJewelry,
/*----*/ ItemTypeSkull, // 30
/*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...)
/*5517*/ ItemTypeNote,
/*5518*/ ItemTypeKey,
/*----*/ ItemTypeCoin,
/*5520*/ ItemType2HPiercing, // 35
/*----*/ ItemTypeFishingPole,
/*----*/ ItemTypeFishingBait,
/*5519*/ ItemTypeAlcohol,
/*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?)
/*----*/ ItemTypeCompass, // 40
/*----*/ ItemTypeUnknown5,
/*----*/ ItemTypePoison, // might be wrong, but includes poisons
/*----*/ ItemTypeUnknown6,
/*----*/ ItemTypeUnknown7,
/*5522*/ ItemTypeMartial, // 45
/*----*/ ItemTypeAllEffects,
/*----*/ ItemTypeUnknown9,
/*----*/ ItemTypeUnknown10,
/*----*/ ItemTypeFocusEffect,
/*----*/ ItemTypeSinging, // 50
/*5750*/ ItemTypeAllInstrumentTypes,
/*5776*/ ItemTypeCharm,
/*----*/ ItemTypeDye,
/*----*/ ItemTypeAugmentation,
/*----*/ ItemTypeAugmentationSolvent, // 55
/*----*/ ItemTypeAugmentationDistiller,
/*----*/ ItemTypeAlternateAbility,
/*----*/ ItemTypeFellowshipKit,
/*----*/ ItemTypeUnknown13,
/*----*/ ItemTypeRecipe, // 60
/*----*/ ItemTypeAdvancedRecipe,
/*----*/ ItemTypeJournal, // only one(1) database entry
/*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage)
/*5881*/ ItemTypePerfectedAugmentationDistiller,
/*----*/ ItemTypeCount,
/*----*/ ItemTypeCollectible,
/*----*/ ItemTypeContainer,
/*----*/ ItemTypeAll = 0xFF
/*
Unknowns:
+186 -36
View File
@@ -32,10 +32,11 @@
//#include <iostream>
int32 NextItemInstSerialNumber = 1;
static inline int32 GetNextItemInstSerialNumber() {
int32 next_item_serial_number = 1;
std::unordered_set<uint64> guids{};
static inline int32 GetNextItemInstSerialNumber()
{
// The Bazaar relies on each item a client has up for Trade having a unique
// identifier. This 'SerialNumber' is sent in Serialized item packets and
// is used in Bazaar packets to identify the item a player is buying or inspecting.
@@ -46,12 +47,18 @@ static inline int32 GetNextItemInstSerialNumber() {
// NextItemInstSerialNumber is the next one to hand out.
//
// It is very unlikely to reach 2,147,483,647. Maybe we should call abort(), rather than wrapping back to 1.
if(NextItemInstSerialNumber >= INT_MAX)
NextItemInstSerialNumber = 1;
else
NextItemInstSerialNumber++;
if (next_item_serial_number >= INT32_MAX) {
next_item_serial_number = 1;
}
else {
next_item_serial_number++;
}
return NextItemInstSerialNumber;
while (guids.contains(next_item_serial_number)) {
next_item_serial_number++;
}
return next_item_serial_number;
}
//
@@ -303,47 +310,34 @@ int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
return INVALID_INDEX;
}
auto i = invaug::SOCKET_BEGIN;
for (; i <= invaug::SOCKET_END; ++i) {
if (GetItem(i)) {
continue;
}
if (
augment_type == -1 ||
(
m_item->AugSlotType[i] &&
((1 << (m_item->AugSlotType[i] - 1)) & augment_type)
)
) {
break;
for (int16 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; ++slot_id) {
if (IsAugmentSlotAvailable(augment_type, slot_id)) {
return slot_id;
}
}
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
return INVALID_INDEX;
}
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const
{
if (!m_item || !m_item->IsClassCommon()) {
if (!m_item || !m_item->IsClassCommon() || GetItem(slot)) {
return false;
}
if (
return (
(
!GetItem(slot) &&
m_item->AugSlotVisible[slot]
augment_type == -1 ||
(
m_item->AugSlotType[slot] &&
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
)
) &&
augment_type == -1 ||
(
m_item->AugSlotType[slot] &&
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
RuleB(Items, AugmentItemAllowInvisibleAugments) ||
m_item->AugSlotVisible[slot]
)
) {
return true;
}
return false;
);
}
// Retrieve item inside container
@@ -1292,7 +1286,7 @@ int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
return race;
}
int EQ::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const
int EQ::ItemInstance::GetItemBaneDamageBody(uint8 against, bool augments) const
{
int64 damage = 0;
const auto item = GetItem();
@@ -1801,6 +1795,162 @@ uint32 EQ::ItemInstance::GetItemGuildFavor() const
return 0;
}
std::vector<uint32> EQ::ItemInstance::GetAugmentIDs() const
{
std::vector<uint32> augments;
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; slot_id++) {
augments.push_back(GetAugment(slot_id) ? GetAugmentItemID(slot_id) : 0);
}
return augments;
}
int EQ::ItemInstance::GetItemRegen(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->Regen;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemRegen();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemManaRegen(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->ManaRegen;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemManaRegen();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemDamageShield(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->DamageShield;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemDamageShield();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemDSMitigation(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->DSMitigation;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemDSMitigation();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemHealAmt(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->HealAmt;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemHealAmt();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemSpellDamage(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->SpellDmg;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemSpellDamage();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemClairvoyance(bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->Clairvoyance;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemClairvoyance();
}
}
}
}
return stat;
}
int EQ::ItemInstance::GetItemSkillsStat(EQ::skills::SkillType skill, bool augments) const
{
int stat = 0;
const auto item = GetItem();
if (item) {
stat = item->ExtraDmgSkill == skill ? item->ExtraDmgAmt : 0;
if (augments) {
for (int i = invaug::SOCKET_BEGIN; i <= invaug::SOCKET_END; ++i) {
if (GetAugment(i)) {
stat += GetAugment(i)->GetItemSkillsStat(skill);
}
}
}
}
return stat;
}
void EQ::ItemInstance::AddGUIDToMap(uint64 existing_serial_number)
{
guids.emplace(existing_serial_number);
}
void EQ::ItemInstance::ClearGUIDMap()
{
guids.clear();
}
//
// class EvolveInfo
//
+12 -1
View File
@@ -265,11 +265,12 @@ namespace EQ
// these two are just quick checks
int GetItemBaneDamageBody(bool augments = false) const;
int GetItemBaneDamageRace(bool augments = false) const;
int GetItemBaneDamageBody(bodyType against, bool augments = false) const;
int GetItemBaneDamageBody(uint8 against, bool augments = false) const;
int GetItemBaneDamageRace(uint16 against, bool augments = false) const;
int GetItemMagical(bool augments = false) const;
int GetItemHP(bool augments = false) const;
int GetItemMana(bool augments = false) const;
int GetItemManaRegen(bool augments = false) const;
int GetItemEndur(bool augments = false) const;
int GetItemAttack(bool augments = false) const;
int GetItemStr(bool augments = false) const;
@@ -299,7 +300,17 @@ namespace EQ
int GetItemHeroicDR(bool augments = false) const;
int GetItemHeroicCorrup(bool augments = false) const;
int GetItemHaste(bool augments = false) const;
int GetItemRegen(bool augments = false) const;
int GetItemDamageShield(bool augments = false) const;
int GetItemDSMitigation(bool augments = false) const;
int GetItemHealAmt(bool augments = false) const;
int GetItemSpellDamage(bool augments = false) const;
int GetItemClairvoyance(bool augments = false) const;
int GetItemSkillsStat(EQ::skills::SkillType skill, bool augments = false) const;
uint32 GetItemGuildFavor() const;
std::vector<uint32> GetAugmentIDs() const;
static void AddGUIDToMap(uint64 existing_serial_number);
static void ClearGUIDMap();
protected:
//////////////////////////
+24 -54
View File
@@ -3089,21 +3089,6 @@ namespace RoF
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(Merchant_Click_Struct);
SETUP_DIRECT_ENCODE(Merchant_Click_Struct, structs::Merchant_Click_Struct);
OUT(npcid);
OUT(playerid);
OUT(command);
OUT(rate);
eq->unknown01 = 3; // Not sure what these values do yet, but list won't display without them
eq->unknown02 = 2592000;
FINISH_ENCODE();
}
ENCODE(OP_SkillUpdate)
{
ENCODE_LENGTH_EXACT(SkillUpdate_Struct);
@@ -3509,14 +3494,13 @@ namespace RoF
ENCODE_LENGTH_EXACT(ClickTrader_Struct);
SETUP_DIRECT_ENCODE(ClickTrader_Struct, structs::ClickTrader_Struct);
eq->Code = emu->Code;
// Live actually has 200 items now, but 80 is the most our internal struct supports
for (uint32 i = 0; i < 200; i++)
eq->Code = emu->action;
for (uint32 i = 0; i < RoF::invtype::BAZAAR_SIZE; i++)
{
strncpy(eq->items[i].SerialNumber, "0000000000000000", sizeof(eq->items[i].SerialNumber));
eq->items[i].Unknown18 = 0;
if (i < 80) {
eq->ItemCost[i] = emu->ItemCost[i];
eq->ItemCost[i] = emu->item_cost[i];
}
else {
eq->ItemCost[i] = 0;
@@ -3530,9 +3514,9 @@ namespace RoF
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
eq->Code = emu->Code;
eq->Code = emu->action;
strncpy(eq->SerialNumber, "0000000000000000", sizeof(eq->SerialNumber));
eq->TraderID = emu->TraderID;
eq->TraderID = emu->entity_id;
eq->Stacksize = 0;
eq->Price = 0;
@@ -3558,13 +3542,13 @@ namespace RoF
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
OUT(action);
OUT(price);
OUT(trader_id);
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
OUT(item_id);
OUT(quantity);
OUT(already_sold);
FINISH_ENCODE();
}
@@ -5047,19 +5031,6 @@ namespace RoF
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::Merchant_Click_Struct);
SETUP_DIRECT_DECODE(Merchant_Click_Struct, structs::Merchant_Click_Struct);
IN(npcid);
IN(playerid);
IN(command);
IN(rate);
FINISH_DIRECT_DECODE();
}
DECODE(OP_Trader)
{
uint32 psize = __packet->size;
@@ -5069,12 +5040,11 @@ namespace RoF
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::ClickTrader_Struct);
MEMSET_IN(ClickTrader_Struct);
emu->Code = eq->Code;
// Live actually has 200 items now, but 80 is the most our internal struct supports
for (uint32 i = 0; i < 80; i++)
emu->action = eq->Code;
for (uint32 i = 0; i < RoF::invtype::BAZAAR_SIZE; i++)
{
emu->SerialNumber[i] = 0; // eq->SerialNumber[i];
emu->ItemCost[i] = eq->ItemCost[i];
emu->serial_number[i] = 0; // eq->SerialNumber[i];
emu->item_cost[i] = eq->ItemCost[i];
}
FINISH_DIRECT_DECODE();
@@ -5085,8 +5055,8 @@ namespace RoF
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
MEMSET_IN(Trader_ShowItems_Struct);
emu->Code = eq->Code;
emu->TraderID = eq->TraderID;
emu->action = eq->Code;
emu->entity_id = eq->TraderID;
FINISH_DIRECT_DECODE();
}
@@ -5108,12 +5078,12 @@ namespace RoF
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
FINISH_DIRECT_DECODE();
}
+1199 -370
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -158,6 +158,7 @@ namespace RoF2
slotCursor
};
constexpr int16 format_as(InventorySlots slot) { return static_cast<int16>(slot); }
} // namespace enum_
using namespace enum_;
@@ -270,6 +271,7 @@ namespace RoF2
const size_t CHARACTER_CREATION_LIMIT = 12;
const size_t SAY_LINK_BODY_SIZE = 56;
const uint32 MAX_GUILD_ID = 50000;
} /*constants*/
+5 -2
View File
@@ -43,10 +43,12 @@ E(OP_ApplyPoison)
E(OP_AugmentInfo)
E(OP_Barter)
E(OP_BazaarSearch)
E(OP_BecomeTrader)
E(OP_BeginCast)
E(OP_BlockedBuffs)
E(OP_Buff)
E(OP_BuffCreate)
E(OP_BuyerItems)
E(OP_CancelTrade)
E(OP_CastSpell)
E(OP_ChannelMessage)
@@ -116,7 +118,6 @@ E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SkillUpdate)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnAppearance)
@@ -149,11 +150,13 @@ D(OP_Animation)
D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_Barter)
D(OP_BazaarSearch)
D(OP_BlockedBuffs)
D(OP_BookButton)
D(OP_Buff)
D(OP_BuffRemoveRequest)
D(OP_BuyerItems)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)
@@ -200,7 +203,7 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_ShopSendParcel)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
+312 -148
View File
@@ -354,15 +354,15 @@ struct Spawn_Struct_Bitfields
/*29*/ unsigned showname:1;
/*30*/ unsigned idleanimationsoff:1; // what we called statue?
/*31*/ unsigned untargetable:1; // bClickThrough
/* do these later
32 unsigned buyer:1;
33 unsigned offline:1;
34 unsigned interactiveobject:1;
35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
36 unsigned title:1;
37 unsigned suffix:1;
38 unsigned padding1:1;
39 unsigned padding2:1;
// byte 5
/*32 unsigned buyer:1;
/*33 unsigned offline:1;
/*34 unsigned interactiveobject:1;
/*35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
/*36 unsigned title:1;
/*37 unsigned suffix:1;
/*38 unsigned padding1:1;
/*39 unsigned padding2:1;
40 unsinged padding3:1;
*/
/*
@@ -2247,15 +2247,17 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 unknown01; // Seen 3 from Server or -1 from Client
/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client
/*024*/
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client
/*024*/
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -3104,28 +3106,163 @@ struct EnvDamage2_Struct {
};
//Bazaar Stuff
enum RoF2BazaarTraderBuyerActions {
Zero = 0,
BeginTraderMode = 1,
EndTraderMode = 2,
PriceUpdate = 3,
EndTransaction = 4,
BazaarSearch = 7,
WelcomeMessage = 9,
BuyTraderItem = 10,
ListTraderItems = 11,
BazaarInspect = 18,
ClickTrader = 28,
ItemMove = 19,
ReconcileItems = 20
};
enum RoF2BuyerActions {
BuyerSearchResults = 0x00,
BuyerBuyLine = 0x06,
BuyerModifyBuyLine = 0x07,
BuyerRemoveItem = 0x08,
BuyerSellItem = 0x09,
BuyerBuyItem = 0x0a,
BuyerInspectBegin = 0x0b,
BuyerInspectEnd = 0x0c,
BuyerAppearance = 0x0d,
BuyerSendBuyLine = 0x0e,
BuyerItemInspect = 0x0f,
BuyerBrowsingBuyLine = 0x10,
BarterWelcomeMessage = 0x11,
BuyerWelcomeMessage = 0x13,
BuyerGreeting = 0x14,
BuyerInventoryFull = 0x16
};
struct BarterItemSearchLinkRequest_Struct {
uint32 action;
uint32 unknown_004;
uint32 seller_id;
uint32 buyer_id;
uint32 unknown_016;
uint32 slot_id; // 0xffffffff main buy line 0x0 trade_item_1, 0x1 trade_item_2
uint32 item_id;
uint32 unknown_028;
};
struct BuyerWelcomeMessageUpdate_Struct {
uint32 action;
char unknown_004[64];
uint32 unknown_068;
char welcome_message[256];
};
struct Buyer_SetAppearance_Struct {
uint32 action;
uint32 entity_id;
char unknown[64];
uint32 enabled;
};
struct BuyerRemoveItem_Struct {
uint32 action;
uint32 unknown004;
uint32 slot_id;
uint32 toggle;
};
struct BuyerLineSellItem_Struct {
uint32 action;
uint32 purchase_method; // 0 direct merchant, 1 via /barter window
uint32 unknown008;
uint32 buyer_entity_id;
uint32 seller_entity_id;
char unknown[15];
uint32 slot;
uint8 enabled;
uint32 item_id;
char item_name[64];
uint32 item_icon;
uint32 item_quantity;
uint8 item_toggle;
uint32 item_cost;
uint32 no_trade_items;
BuyerLineTradeItems_Struct trade_items[10];
char unknown2[13];
uint32 seller_quantity;
};
struct BuyerLineItemsSearch_Struct {
uint32 slot;
uint8 enabled;
uint32 item_id;
char item_name[64];
uint32 item_icon;
uint32 item_quantity;
uint8 item_toggle;
uint32 item_cost;
uint32 buyer_id;
BuyerLineTradeItems_Struct trade_items[MAX_BUYER_COMPENSATION_ITEMS];
};
struct BuyerLineSearch_Struct {
uint32 action;
uint32 no_items;
std::vector<BuyerLineItemsSearch_Struct> buy_line;
};
struct BuyerStart_Struct {
uint32 action;
uint16 no_buyer_lines;
uint32 slot;
uint8 enabled;
uint32 item_id;
char item_name[1]; // vary length
uint32 item_icon;
uint32 item_quantity;
uint8 toggle;
uint32 item_cost;
uint32 no_trade_items;
BuyerLineTradeItems_Struct trade_items[1]; // size is actually no_trade_items. If 0, then this is not in packet
char unknown[13];
};
struct BuyerItemSearchResultEntry_Struct {
char item_name[64];
uint32 item_id;
uint32 item_icon;
uint32 unknown_072;
};
struct BuyerItemSearchResults_Struct {
uint32 action;
uint32 result_count;
BuyerItemSearchResultEntry_Struct results[];
};
enum {
BazaarTrader_StartTraderMode = 1,
BazaarTrader_EndTraderMode = 2,
BazaarTrader_UpdatePrice = 3,
BazaarTrader_EndTransaction = 4,
BazaarSearchResults = 7,
BazaarWelcome = 9,
BazaarBuyItem = 10,
BazaarTrader_ShowItems = 11,
BazaarSearchDone = 12,
BazaarTrader_StartTraderMode = 1,
BazaarTrader_EndTraderMode = 2,
BazaarTrader_UpdatePrice = 3,
BazaarTrader_EndTransaction = 4,
BazaarSearchResults = 7,
BazaarWelcome = 9,
BazaarBuyItem = 10,
BazaarTrader_ShowItems = 11,
BazaarSearchDone = 12,
BazaarTrader_CustomerBrowsing = 13,
BazaarInspectItem = 18,
BazaarSearchDone2 = 19,
BazaarInspectItem = 18,
BazaarSearchDone2 = 19,
BazaarTrader_StartTraderMode2 = 22
};
enum {
BazaarPriceChange_Fail = 0,
BazaarPriceChange_Fail = 0,
BazaarPriceChange_UpdatePrice = 1,
BazaarPriceChange_RemoveItem = 2,
BazaarPriceChange_AddItem = 3
BazaarPriceChange_RemoveItem = 2,
BazaarPriceChange_AddItem = 3
};
struct BazaarWindowStart_Struct {
@@ -3134,34 +3271,51 @@ struct BazaarWindowStart_Struct {
uint16 Unknown002;
};
struct BazaarDeliveryCost_Struct {
uint32 action;
uint32 voucher_delivery_cost;
float parcel_deliver_cost; //percentage of item cost
uint32 unknown_010;
};
struct BazaarWelcome_Struct {
uint32 Code;
uint32 EntityID;
uint32 Traders;
uint32 Items;
uint32 Traders2;
uint32 Items2;
uint32 action;
uint32 unknown_004;
uint32 num_of_traders;
uint32 num_of_items;
};
struct BazaarSearch_Struct {
BazaarWindowStart_Struct Beginning;
uint32 TraderID;
uint32 Class_;
uint32 Race;
uint32 ItemStat;
uint32 Slot;
uint32 Type;
char Name[64];
uint32 MinPrice;
uint32 MaxPrice;
uint32 Minlevel;
uint32 MaxLlevel;
/*000*/ uint32 action;
/*004*/ uint8 search_scope;//1 all traders 0 local traders
/*005*/ uint8 unknown_005{0};
/*006*/ uint16 unknown_006{0};
/*008*/ uint32 unknown_008{0};
/*012*/ uint32 unknown_012{0};
/*016*/ uint32 trader_id;
/*020*/ uint32 _class;
/*024*/ uint32 race;
/*028*/ uint32 item_stat;
/*032*/ uint32 slot;
/*036*/ uint32 type;
/*040*/ char item_name[64];
/*104*/ uint32 min_cost;
/*108*/ uint32 max_cost;
/*112*/ uint32 min_level;
/*116*/ uint32 max_level;
/*120*/ uint32 max_results;
/*124*/ uint32 prestige;
/*128*/ uint32 augment;
};
struct BazaarInspect_Struct{
uint32 ItemID;
uint32 Unknown004;
char Name[64];
struct BazaarInspect_Struct {
uint32 action;
uint32 unknown_004;
uint32 trader_id;
char serial_number[17];
char unknown_029[3];
uint32 item_id;
uint32 unknown_036;
};
struct NewBazaarInspect_Struct {
@@ -3182,18 +3336,23 @@ struct BazaarReturnDone_Struct{
uint32 Unknown016;
};
struct BazaarSearchResults_Struct {
/*000*/ BazaarWindowStart_Struct Beginning;
/*004*/ uint32 SellerID;
/*008*/ char SellerName[64];
/*072*/ uint32 NumItems;
/*076*/ uint32 ItemID;
/*080*/ uint32 SerialNumber;
/*084*/ uint32 Unknown084;
/*088*/ char ItemName[64];
/*152*/ uint32 Cost;
/*156*/ uint32 ItemStat;
/*160*/
struct BazaarSearchDetails_Struct { //24+name+17
/*014*/ uint32 trader_id;
/*018*/ char serial_num[17];
/*022*/ uint32 cost;
/*026*/ uint32 quanity;
/*030*/ uint32 id;
/*034*/ uint32 icon;
/*038*/ char name[1];
/*039*/ uint32 stat;
};
struct BazaarSearchResults_Struct { //14
/*000*/ uint32 unknown000;
/*004*/ uint16 zone_id;
/*006*/ uint32 entity_id;
/*010*/ uint32 num_items;
/*014*/ BazaarSearchDetails_Struct items[];
};
struct ServerSideFilters_Struct {
@@ -3396,21 +3555,26 @@ struct WhoAllPlayerPart4 {
};
struct TraderItemSerial_Struct {
char SerialNumber[17];
uint8 Unknown18;
char serial_number[17];
uint8 unknown_018;
void operator=(uint32 a) {
auto _tmp = fmt::format("{:016}", a);
strn0cpy(this->serial_number, _tmp.c_str(), sizeof(this->serial_number));
}
};
struct Trader_Struct {
/*0000*/ uint32 Code;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 ItemCost[200];
struct BeginTrader_Struct {
/*0000*/ uint32 action;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 item_cost[200];
/*4404*/
};
struct ClickTrader_Struct {
/*0000*/ uint32 Code;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 ItemCost[200];
/*0000*/ uint32 action;
/*0004*/ TraderItemSerial_Struct items[200];
/*3604*/ uint32 item_cost[200];
/*4404*/
};
@@ -3419,67 +3583,55 @@ struct GetItems_Struct {
};
struct BecomeTrader_Struct {
uint32 id;
uint32 code;
uint32 entity_id;
uint32 action;
};
struct BazaarWindowRemoveTrader_Struct {
uint32 action;
uint32 trader_id;
};
struct TraderPriceUpdate_Struct {
uint32 action;
char serial_number[17];
char unknown_021[3];
uint32 unknown_024;
uint32 new_price;
};
struct Trader_ShowItems_Struct {
/*000*/ uint32 Code;
/*004*/ uint16 TraderID;
/*008*/ uint32 Unknown08;
/*012*/
};
struct Trader_ShowItems_Struct_WIP {
/*000*/ uint32 Code;
/*004*/ char SerialNumber[17];
/*021*/ uint8 Unknown21;
/*022*/ uint16 TraderID;
/*026*/ uint32 Stacksize;
/*030*/ uint32 Price;
/*032*/
/*000*/ uint32 action;
/*004*/ uint32 entity_id;
/*008*/ uint32 unknown_008;
/*012*/
};
struct TraderStatus_Struct {
/*000*/ uint32 Code;
/*004*/ uint32 Uknown04;
/*008*/ uint32 Uknown08;
/*000*/ uint32 action;
/*004*/ uint32 sub_action;
/*008*/ uint32 uknown_008;
/*012*/
};
struct TraderBuy_Struct {
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown008;
/*012*/ uint32 Unknown012;
/*016*/ uint32 TraderID;
/*020*/ char BuyerName[64];
/*084*/ char SellerName[64];
/*148*/ char Unknown148[32];
/*180*/ char ItemName[64];
/*244*/ char SerialNumber[16];
/*260*/ uint32 Unknown076;
/*264*/ uint32 ItemID;
/*268*/ uint32 Price;
/*272*/ uint32 AlreadySold;
/*276*/ uint32 Unknown276;
/*280*/ uint32 Quantity;
/*284*/
};
struct TraderBuy_Struct_OLD {
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Price;
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 TraderID;
/*020*/ char ItemName[64];
/*084*/ uint32 Unknown076;
/*088*/ uint32 ItemID;
/*092*/ uint32 AlreadySold;
/*096*/ uint32 Quantity;
/*100*/ uint32 Unknown092;
/*104*/
/*000*/ uint32 action;
/*004*/ uint32 method;
/*008*/ uint32 sub_action;
/*012*/ uint32 unknown_012;
/*016*/ uint32 trader_id;
/*020*/ char buyer_name[64];
/*084*/ char seller_name[64];
/*148*/ char unknown_148[32];
/*180*/ char item_name[64];
/*244*/ char serial_number[17];
/*261*/ char unknown_261[3];
/*264*/ uint32 item_id;
/*268*/ uint32 price;
/*272*/ uint32 already_sold;
/*276*/ uint32 unknown_276;
/*280*/ uint32 quantity;
/*284*/
};
struct TraderItemUpdate_Struct{
@@ -3500,15 +3652,15 @@ struct MoneyUpdate_Struct{
struct TraderDelItem_Struct{
/*000*/ uint32 Unknown000;
/*004*/ uint32 TraderID;
/*008*/ char SerialNumber[16];
/*008*/ char SerialNumber[17];
/*024*/ uint32 Unknown012;
/*028*/
};
struct TraderClick_Struct{
/*000*/ uint32 Code;
/*004*/ uint32 TraderID;
/*008*/ uint32 Approval;
/*000*/ uint32 action;
/*004*/ uint32 trader_id;
/*008*/ uint32 unknown_008;
/*012*/
};
@@ -4572,25 +4724,25 @@ struct RoF2SlotStruct
struct ItemSerializationHeader
{
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
/*017*/ uint32 stacksize;
/*021*/ uint32 unknown004;
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
/*026*/ uint16 main_slot;
/*028*/ uint16 sub_slot;
/*030*/ uint16 aug_slot; // 0xffff
/*032*/ uint32 price;
/*036*/ uint32 merchant_slot; //1 if not a merchant item
/*040*/ uint32 scaled_value; //0
/*044*/ uint32 instance_id; //unique instance id if not merchant item, else is merchant slot
/*048*/ uint32 unknown028; //0
/*052*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0
/*056*/ uint32 charges; //Total Charges an item has (-1 for unlimited)
/*060*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items)
/*064*/ uint32 unknown044; // 0
/*068*/ uint32 unknown048; // 0
/*072*/ uint32 unknown052; // 0
uint8 isEvolving;
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
/*017*/ uint32 stacksize;
/*021*/ uint32 unknown004;
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
/*026*/ uint16 main_slot;
/*028*/ uint16 sub_slot;
/*030*/ uint16 aug_slot; // 0xffff
/*032*/ uint32 price;
/*036*/ uint32 merchant_slot; // 1 if not a merchant item
/*040*/ uint32 scaled_value; // 0
/*044*/ uint32 instance_id; // unique instance id if not merchant item, else is merchant slot
/*048*/ uint32 parcel_item_id;
/*052*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0
/*056*/ uint32 charges; // Total Charges an item has (-1 for unlimited)
/*060*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items)
/*064*/ uint32 unknown044; // 0
/*068*/ uint32 unknown048; // 0
/*072*/ uint32 unknown052; // 0
uint8 isEvolving;
};
struct EvolvingItem {
@@ -5261,6 +5413,18 @@ struct Checksum_Struct {
uint8_t data[2048];
};
struct Parcel_Struct
{
/*000*/ uint32 npc_id;
/*004*/ TypelessInventorySlot_Struct inventory_slot;
/*012*/ uint32 quantity;
/*016*/ uint32 money_flag;
/*020*/ char send_to[64];
/*084*/ char note[128];
/*212*/ uint32 unknown_212;
/*216*/ uint32 unknown_216;
/*220*/ uint32 unknown_220;
};
}; /*structs*/
}; /*RoF2*/
-2
View File
@@ -101,7 +101,6 @@ E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SkillUpdate)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnAppearance)
@@ -183,7 +182,6 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
+21 -19
View File
@@ -2200,15 +2200,17 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 unknown01; // Seen 3 from Server or -1 from Client
/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client
/*024*/
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown020; // Seen 2592000 from Server or -1 from Client
/*024*/
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -3374,17 +3376,17 @@ struct TraderStatus_Struct {
};
struct TraderBuy_Struct {
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Price;
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 TraderID;
/*020*/ char ItemName[64];
/*084*/ uint32 Unknown076;
/*088*/ uint32 ItemID;
/*092*/ uint32 AlreadySold;
/*096*/ uint32 Quantity;
/*100*/ uint32 Unknown092;
/*000*/ uint32 action;
/*004*/ uint32 unknown_004;
/*008*/ uint32 price;
/*012*/ uint32 unknown_008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 trader_id;
/*020*/ char item_name[64];
/*084*/ uint32 unknown_076;
/*088*/ uint32 item_id;
/*092*/ uint32 already_sold;
/*096*/ uint32 quantity;
/*100*/ uint32 unknown_092;
/*104*/
};
+41 -13
View File
@@ -2026,6 +2026,19 @@ namespace SoD
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
FINISH_ENCODE();
}
ENCODE(OP_SomeItemPacketMaybe)
{
// This Opcode is not named very well. It is used for the animation of arrows leaving the player's bow
@@ -2273,13 +2286,13 @@ namespace SoD
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
OUT(action);
OUT(price);
OUT(trader_id);
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
OUT(item_id);
OUT(quantity);
OUT(already_sold);
FINISH_ENCODE();
}
@@ -3483,18 +3496,33 @@ namespace SoD
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
emu->tab_display = 0;
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_TraderBuy)
{
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
FINISH_DIRECT_DECODE();
}
+2
View File
@@ -78,6 +78,7 @@ E(OP_SendCharInfo)
E(OP_SendZonepoints)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnDoor)
E(OP_SpecialMesg)
@@ -141,6 +142,7 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
+21 -16
View File
@@ -1845,12 +1845,16 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; //1=open, 0=cancel/close
/*012*/ float rate; //cost multiplier, dosent work anymore
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown020; // Seen 2592000 from Server or -1 from Client
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -2875,20 +2879,21 @@ struct Trader_ShowItems_Struct{
};
struct TraderBuy_Struct {
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Price;
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 TraderID;
/*020*/ char ItemName[64];
/*084*/ uint32 Unknown076;
/*088*/ uint32 ItemID;
/*092*/ uint32 AlreadySold;
/*096*/ uint32 Quantity;
/*100*/ uint32 Unknown092;
/*000*/ uint32 action;
/*004*/ uint32 unknown_004;
/*008*/ uint32 price;
/*012*/ uint32 unknown_008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 trader_id;
/*020*/ char item_name[64];
/*084*/ uint32 unknown_076;
/*088*/ uint32 item_id;
/*092*/ uint32 already_sold;
/*096*/ uint32 quantity;
/*100*/ uint32 unknown_092;
/*104*/
};
struct TraderItemUpdate_Struct{
uint32 unknown0;
uint32 traderid;
+44 -16
View File
@@ -270,8 +270,8 @@ namespace SoF
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
OUT(ID);
OUT(Code);
OUT(trader_id);
OUT(action);
FINISH_ENCODE();
}
@@ -1683,6 +1683,19 @@ namespace SoF
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
FINISH_ENCODE();
}
ENCODE(OP_SomeItemPacketMaybe)
{
// This Opcode is not named very well. It is used for the animation of arrows leaving the player's bow
@@ -1889,13 +1902,13 @@ namespace SoF
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
OUT(action);
OUT(price);
OUT(trader_id);
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
OUT(item_id);
OUT(quantity);
OUT(already_sold);
FINISH_ENCODE();
}
@@ -2336,7 +2349,7 @@ namespace SoF
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
emu->category_id = Bug::GetID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
@@ -2874,18 +2887,33 @@ namespace SoF
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
emu->tab_display = 0;
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_TraderBuy)
{
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
FINISH_DIRECT_DECODE();
}
+2
View File
@@ -72,6 +72,7 @@ E(OP_SendAATable)
E(OP_SendCharInfo)
E(OP_SendZonepoints)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnDoor)
E(OP_SpecialMesg)
@@ -128,6 +129,7 @@ D(OP_ReadBook)
D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
+20 -16
View File
@@ -1859,12 +1859,16 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
/*008*/ uint32 command; //1=open, 0=cancel/close
/*012*/ float rate; //cost multiplier, dosent work anymore
struct MerchantClick_Struct
{
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; // 1=open, 0=cancel/close
/*012*/ float rate; // cost multiplier, dosent work anymore
/*016*/ int32 tab_display; // bitmask b000 none, b001 Purchase/Sell, b010 Recover, b100 Parcels
/*020*/ int32 unknown020; // Seen 2592000 from Server or -1 from Client
};
/*
Unknowns:
0 is e7 from 01 to // MAYBE SLOT IN PURCHASE
@@ -2767,8 +2771,8 @@ struct GetItems_Struct{
};
struct BecomeTrader_Struct{
uint32 ID;
uint32 Code;
uint32 trader_id;
uint32 action;
};
struct Trader_ShowItems_Struct{
@@ -2778,15 +2782,15 @@ struct Trader_ShowItems_Struct{
};
struct TraderBuy_Struct {
/*000*/ uint32 Action;
/*004*/ uint32 Price;
/*008*/ uint32 TraderID;
/*012*/ char ItemName[64];
/*076*/ uint32 Unknown076;
/*080*/ uint32 ItemID;
/*084*/ uint32 AlreadySold;
/*088*/ uint32 Quantity;
/*092*/ uint32 Unknown092;
/*000*/ uint32 action;
/*004*/ uint32 price;
/*008*/ uint32 trader_id;
/*012*/ char item_name[64];
/*076*/ uint32 unknown_076;
/*080*/ uint32 item_id;
/*084*/ uint32 already_sold;
/*088*/ uint32 quantity;
/*092*/ uint32 unknown_092;
};
struct TraderItemUpdate_Struct{
+3 -3
View File
@@ -60,7 +60,7 @@
eq_struct *eq = (eq_struct *) __packet->pBuffer; \
#define ALLOC_LEN_ENCODE(len) \
__packet->pBuffer = new unsigned char[len]; \
__packet->pBuffer = new unsigned char[len] {}; \
__packet->size = len; \
memset(__packet->pBuffer, 0, len); \
@@ -124,7 +124,7 @@
#define SETUP_DIRECT_DECODE(emu_struct, eq_struct) \
unsigned char *__eq_buffer = __packet->pBuffer; \
__packet->size = sizeof(emu_struct); \
__packet->pBuffer = new unsigned char[__packet->size]; \
__packet->pBuffer = new unsigned char[__packet->size] {}; \
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
eq_struct *eq = (eq_struct *) __eq_buffer;
@@ -133,7 +133,7 @@
eq_struct* in = (eq_struct*)__packet->pBuffer; \
auto size = strlen(in->var_field); \
__packet->size = sizeof(emu_struct) + size + 1; \
__packet->pBuffer = new unsigned char[__packet->size]; \
__packet->pBuffer = new unsigned char[__packet->size] {}; \
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
eq_struct *eq = (eq_struct *) __eq_buffer;
+454 -70
View File
@@ -32,6 +32,7 @@
#include "../strings.h"
#include "../item_instance.h"
#include "titanium_structs.h"
#include "../rulesys.h"
#include "../path_manager.h"
#include "../raid.h"
#include "../guilds.h"
@@ -197,64 +198,135 @@ namespace Titanium
ENCODE(OP_BazaarSearch)
{
if (((*p)->size == sizeof(BazaarReturnDone_Struct)) || ((*p)->size == sizeof(BazaarWelcome_Struct))) {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
return;
}
//consume the packet
EQApplicationPacket *in = *p;
*p = nullptr;
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer;
uint32 action = *(uint32 *)in->pBuffer;
//determine and verify length
int entrycount = in->size / sizeof(BazaarSearchResults_Struct);
if (entrycount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0) {
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
delete in;
return;
switch (action) {
case BazaarSearch: {
LogTrading(
"Encode OP_BazaarSearch(Ti) BazaarSearch action <green>[{}]",
action
);
std::vector<BazaarSearchResultsFromDB_Struct> results {};
auto bsms = (BazaarSearchMessaging_Struct *)in->pBuffer;
EQ::Util::MemoryStreamReader ss(
reinterpret_cast<char *>(bsms->payload),
in->size - sizeof(BazaarSearchMessaging_Struct)
);
cereal::BinaryInputArchive ar(ss);
ar(results);
auto size = results.size() * sizeof(structs::BazaarSearchResults_Struct);
auto buffer = new uchar[size];
uchar *bufptr = buffer;
memset(buffer, 0, size);
for (auto row = results.begin(); row != results.end(); ++row) {
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, structs::TiBazaarTraderBuyerActions::BazaarSearch);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->trader_entity_id);
bufptr += 4;
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->item_id);
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number);
bufptr += 4;
if (row->stackable) {
strn0cpy(
reinterpret_cast<char *>(bufptr),
fmt::format("{}({})", row->item_name.c_str(), row->charges).c_str(),
64
);
}
else {
strn0cpy(
reinterpret_cast<char *>(bufptr),
fmt::format("{}({})", row->item_name.c_str(), row->count).c_str(),
64
);
}
bufptr += 64;
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->cost);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->item_stat);
}
auto outapp = new EQApplicationPacket(OP_BazaarSearch, size);
memcpy(outapp->pBuffer, buffer, size);
dest->FastQueuePacket(&outapp);
safe_delete(outapp);
safe_delete_array(buffer);
safe_delete(in);
break;
}
case BazaarInspect:
case WelcomeMessage: {
LogTrading(
"Encode OP_BazaarSearch(Ti) BazaarInspect/WelcomeMessage action <green>[{}]",
action
);
dest->FastQueuePacket(&in, ack_req);
break;
}
default: {
LogTrading(
"Encode OP_BazaarSearch(Ti) unhandled action <red>[{}]",
action
);
dest->FastQueuePacket(&in, ack_req);
}
}
//make the EQ struct.
in->size = sizeof(structs::BazaarSearchResults_Struct)*entrycount;
in->pBuffer = new unsigned char[in->size];
structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *) in->pBuffer;
//zero out the packet. We could avoid this memset by setting all fields (including unknowns) in the loop.
memset(in->pBuffer, 0, in->size);
for (int i = 0; i < entrycount; i++, eq++, emu++) {
eq->Beginning.Action = emu->Beginning.Action;
eq->Beginning.Unknown001 = emu->Beginning.Unknown001;
eq->Beginning.Unknown002 = emu->Beginning.Unknown002;
eq->NumItems = emu->NumItems;
eq->SerialNumber = emu->SerialNumber;
eq->SellerID = emu->SellerID;
eq->Cost = emu->Cost;
eq->ItemStat = emu->ItemStat;
strcpy(eq->ItemName, emu->ItemName);
}
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_BecomeTrader)
{
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
uint32 action = *(uint32 *)(*p)->pBuffer;
OUT(ID);
OUT(Code);
FINISH_ENCODE();
switch (action)
{
case TraderOff:
{
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
LogTrading(
"Encode OP_BecomeTrader(Ti) TraderOff action <green>[{}] entity_id <green>[{}] trader_name "
"<green>[{}]",
emu->action,
emu->entity_id,
emu->trader_name
);
eq->action = structs::TiBazaarTraderBuyerActions::Zero;
eq->entity_id = emu->entity_id;
FINISH_ENCODE();
break;
}
case TraderOn:
{
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
LogTrading(
"Encode OP_BecomeTrader(Ti) TraderOn action <green>[{}] entity_id <green>[{}] trader_name "
"<green>[{}]",
emu->action,
emu->entity_id,
emu->trader_name
);
eq->action = structs::TiBazaarTraderBuyerActions::BeginTraderMode;
eq->entity_id = emu->entity_id;
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
FINISH_ENCODE();
break;
}
default:
{
LogTrading(
"Encode OP_BecomeTrader(Ti) unhandled action <red>[{}] Sending packet as is.",
action
);
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
}
}
}
ENCODE(OP_Buff)
@@ -692,6 +764,10 @@ namespace Titanium
eq->rank = GUILD_LEADER_TI;
break;
}
default: {
eq->rank = GUILD_RANK_NONE_TI;
break;
}
}
memcpy(eq->member_name, emu->member_name, sizeof(eq->member_name));
@@ -730,7 +806,7 @@ namespace Titanium
break;
}
}
break;
break;
}
case AppearanceType::GuildShow: {
FAIL_ENCODE();
@@ -744,6 +820,28 @@ namespace Titanium
FINISH_ENCODE();
}
ENCODE(OP_GuildsList)
{
EQApplicationPacket* in = *p;
*p = nullptr;
GuildsListMessaging_Struct glms{};
EQ::Util::MemoryStreamReader ss(reinterpret_cast<char *>(in->pBuffer), in->size);
cereal::BinaryInputArchive ar(ss);
ar(glms);
auto outapp = new EQApplicationPacket(OP_GuildsList, sizeof(structs::GuildsList_Struct));
auto out = (structs::GuildsList_Struct *) outapp->pBuffer;
for (auto const& g : glms.guild_detail) {
if (g.guild_id < Titanium::constants::MAX_GUILD_ID) {
strn0cpy(out->Guilds[g.guild_id].name, g.guild_name.c_str(), sizeof(out->Guilds[g.guild_id].name));
}
}
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberAdd)
{
ENCODE_LENGTH_EXACT(GuildMemberAdd_Struct)
@@ -1417,6 +1515,7 @@ namespace Titanium
break;
}
default: {
eq->guildrank = GUILD_RANK_NONE_TI;
break;
}
}
@@ -1853,6 +1952,19 @@ namespace Titanium
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
FINISH_ENCODE();
}
ENCODE(OP_SpecialMesg)
{
EQApplicationPacket *in = *p;
@@ -1970,32 +2082,170 @@ namespace Titanium
ENCODE(OP_Trader)
{
if ((*p)->size != sizeof(TraderBuy_Struct)) {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
return;
}
auto action = *(uint32 *) (*p)->pBuffer;
ENCODE_FORWARD(OP_TraderBuy);
switch (action) {
case TraderOn: {
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Encode OP_Trader BeginTraderMode action <green>[{}]",
action
);
eq->action = structs::TiBazaarTraderBuyerActions::BeginTraderMode;
OUT(entity_id);
FINISH_ENCODE();
break;
}
case TraderOff: {
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Encode OP_Trader EndTraderMode action <green>[{}]",
action
);
eq->action = structs::TiBazaarTraderBuyerActions::EndTraderMode;
OUT(entity_id);
FINISH_ENCODE();
break;
}
case ListTraderItems: {
ENCODE_LENGTH_EXACT(Trader_Struct);
SETUP_DIRECT_ENCODE(Trader_Struct, structs::Trader_Struct);
LogTrading(
"Encode OP_Trader ListTraderItems action <green>[{}]",
action
);
eq->action = structs::TiBazaarTraderBuyerActions::ListTraderItems;
std::copy_n(emu->items, UF::invtype::BAZAAR_SIZE, eq->item_id);
std::copy_n(emu->item_cost, UF::invtype::BAZAAR_SIZE, eq->item_cost);
FINISH_ENCODE();
break;
}
case BuyTraderItem: {
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_Trader item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
eq->item_id,
eq->price,
eq->quantity,
eq->trader_id
);
eq->action = structs::TiBazaarTraderBuyerActions::BuyTraderItem;
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
FINISH_ENCODE();
break;
}
case ItemMove: {
LogTrading(
"Encode OP_Trader ItemMove action <green>[{}]",
action
);
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
break;
}
default: {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
LogError("Unknown Encode OP_Trader action <red>{} received. Unhandled.", action);
}
}
}
ENCODE(OP_TraderBuy)
{
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_TraderBuy item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
emu->item_id,
emu->price,
emu->quantity,
emu->trader_id
);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
OUT(action);
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
OUT_str(item_name);
FINISH_ENCODE();
}
ENCODE(OP_TraderShop)
{
auto action = *(uint32 *)(*p)->pBuffer;
switch (action) {
case ClickTrader: {
ENCODE_LENGTH_EXACT(TraderClick_Struct);
SETUP_DIRECT_ENCODE(TraderClick_Struct, structs::TraderClick_Struct);
LogTrading(
"ClickTrader action <green>[{}] trader_id <green>[{}]",
action,
emu->TraderID
);
eq->action = 0;
eq->trader_id = emu->TraderID;
eq->approval = emu->Approval;
FINISH_ENCODE();
break;
}
case BuyTraderItem: {
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_TraderShop item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
eq->item_id,
eq->price,
eq->quantity,
eq->trader_id
);
eq->action = structs::TiBazaarTraderBuyerActions::BuyTraderItem;
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
FINISH_ENCODE();
break;
}
default: {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
LogError("Unknown Encode OP_TraderShop action <red>[{}] received. Unhandled.", action);
}
}
}
ENCODE(OP_TributeItem)
{
ENCODE_LENGTH_EXACT(TributeItem_Struct);
@@ -2246,6 +2496,53 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_BazaarSearch)
{
uint32 action = *(uint32 *) __packet->pBuffer;
switch (action) {
case structs::TiBazaarTraderBuyerActions::BazaarSearch: {
DECODE_LENGTH_EXACT(structs::BazaarSearch_Struct);
SETUP_DIRECT_DECODE(BazaarSearchCriteria_Struct, structs::BazaarSearch_Struct);
emu->action = eq->Beginning.Action;
emu->item_stat = eq->ItemStat;
emu->max_cost = eq->MaxPrice;
emu->min_cost = eq->MinPrice;
emu->max_level = eq->MaxLlevel;
emu->min_level = eq->Minlevel;
emu->race = eq->Race;
emu->slot = eq->Slot;
emu->type = eq->Type == UINT32_MAX ? UINT8_MAX : eq->Type;
emu->trader_entity_id = eq->TraderID;
emu->trader_id = 0;
emu->_class = eq->Class_;
emu->search_scope = eq->TraderID > 0 ? NonRoFBazaarSearchScope : Local_Scope;
emu->max_results = RuleI(Bazaar, MaxSearchResults);
strn0cpy(emu->item_name, eq->Name, sizeof(emu->item_name));
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::BazaarInspect: {
SETUP_DIRECT_DECODE(BazaarInspect_Struct, structs::BazaarInspect_Struct);
IN(action);
memcpy(emu->player_name, eq->player_name, sizeof(emu->player_name));
IN(serial_number);
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::WelcomeMessage: {
break;
}
default: {
LogTrading("(Ti) Unhandled action <red>[{}]", action);
}
}
}
DECODE(OP_Buff)
{
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
@@ -2270,7 +2567,7 @@ namespace Titanium
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = EQ::bug::CategoryNameToCategoryID(eq->category_name);
emu->category_id = Bug::GetID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
@@ -2870,18 +3167,105 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
emu->tab_display = 0;
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_Trader)
{
auto action = (uint32) __packet->pBuffer[0];
switch (action) {
case structs::TiBazaarTraderBuyerActions::BeginTraderMode: {
DECODE_LENGTH_EXACT(structs::BeginTrader_Struct);
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::BeginTrader_Struct);
LogTrading(
"Decode OP_Trader BeginTraderMode action <red>[{}]",
action
);
emu->action = TraderOn;
emu->unknown_004 = 0;
std::copy_n(eq->serial_number, Titanium::invtype::BAZAAR_SIZE, emu->serial_number);
std::copy_n(eq->cost, Titanium::invtype::BAZAAR_SIZE, emu->item_cost);
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::EndTraderMode: {
DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct);
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Decode OP_Trader(Ti) EndTraderMode action <red>[{}]",
action
);
emu->action = TraderOff;
IN(entity_id);
FINISH_DIRECT_DECODE();
break;
}
case structs::TiBazaarTraderBuyerActions::PriceUpdate:
case structs::TiBazaarTraderBuyerActions::ItemMove:
case structs::TiBazaarTraderBuyerActions::EndTransaction:
case structs::TiBazaarTraderBuyerActions::ListTraderItems: {
LogTrading(
"Decode OP_Trader(Ti) Price/ItemMove/EndTransaction/ListTraderItems action <red>[{}]",
action
);
break;
}
case structs::TiBazaarTraderBuyerActions::ReconcileItems: {
break;
}
default: {
LogError("Unhandled(Ti) action <red>[{}] received.", action);
}
}
}
DECODE(OP_TraderBuy)
{
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
IN(action);
IN(price);
IN(trader_id);
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
IN(item_id);
IN(quantity);
FINISH_DIRECT_DECODE();
}
DECODE(OP_TraderShop)
{
DECODE_LENGTH_EXACT(structs::TraderClick_Struct);
SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct);
LogTrading(
"(Ti) action <green>[{}] trader_id <green>[{}] approval <green>[{}]",
eq->action,
eq->trader_id,
eq->approval
);
emu->Code = ClickTrader;
emu->TraderID = eq->trader_id;
emu->Approval = eq->approval;
FINISH_DIRECT_DECODE();
}
+1
View File
@@ -287,6 +287,7 @@ namespace Titanium
const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER
const size_t SAY_LINK_BODY_SIZE = 45;
const uint32 MAX_GUILD_ID = 1500;
} /*constants*/
+7
View File
@@ -45,6 +45,7 @@ E(OP_Emote)
E(OP_FormattedMessage)
E(OP_GroundSpawn)
E(OP_SetGuildRank)
E(OP_GuildsList)
E(OP_GuildMemberLevelUpdate)
E(OP_GuildMemberList)
E(OP_GuildMemberAdd)
@@ -74,12 +75,14 @@ E(OP_SendCharInfo)
E(OP_SendAATable)
E(OP_SetFace)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SpawnAppearance)
E(OP_SpecialMesg)
E(OP_TaskDescription)
E(OP_Track)
E(OP_Trader)
E(OP_TraderBuy)
E(OP_TraderShop)
E(OP_TributeItem)
E(OP_VetRewardsAvaliable)
E(OP_WearChange)
@@ -90,6 +93,7 @@ E(OP_ZoneSpawns)
D(OP_AdventureMerchantSell)
D(OP_ApplyPoison)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
@@ -120,7 +124,10 @@ D(OP_RaidInvite)
D(OP_ReadBook)
D(OP_SetServerFilter)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TraderShop)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
D(OP_WearChange)
+76 -46
View File
@@ -1669,9 +1669,9 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
struct MerchantClick_Struct {
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; //1=open, 0=cancel/close
/*012*/ float rate; //cost multiplier, dosent work anymore
};
@@ -2273,24 +2273,29 @@ struct BazaarWelcome_Struct {
};
struct BazaarSearch_Struct {
BazaarWindowStart_Struct beginning;
uint32 traderid;
uint32 class_;
uint32 race;
uint32 stat;
uint32 slot;
uint32 type;
char name[64];
uint32 minprice;
uint32 maxprice;
uint32 minlevel;
uint32 maxlevel;
BazaarWindowStart_Struct Beginning;
uint32 TraderID;
uint32 Class_;
uint32 Race;
uint32 ItemStat;
uint32 Slot;
uint32 Type;
char Name[64];
uint32 MinPrice;
uint32 MaxPrice;
uint32 Minlevel;
uint32 MaxLlevel;
};
struct BazaarInspect_Struct{
struct BazaarInspect_Struct {
uint32 action;
char player_name[64];
uint32 unknown_068;
uint32 serial_number;
uint32 unknown_076;
uint32 item_id;
uint32 unknown;
char name[64];
};
struct BazaarReturnDone_Struct{
uint32 type;
uint32 traderid;
@@ -2298,16 +2303,17 @@ struct BazaarReturnDone_Struct{
uint32 unknown12;
uint32 unknown16;
};
struct BazaarSearchResults_Struct {
BazaarWindowStart_Struct Beginning;
uint32 SellerID;
uint32 NumItems; // Don't know. Don't know the significance of this field.
uint32 SerialNumber;
uint32 Unknown016;
uint32 Unknown020; // Something to do with stats as well
char ItemName[64];
uint32 Cost;
uint32 ItemStat;
uint32 entity_id;
uint32 unknown_008;
uint32 item_id;
uint32 serial_number;
uint32 unknown_020;
char item_name[64];
uint32 item_cost;
uint32 item_stat;
};
struct ServerSideFilters_Struct {
@@ -2454,11 +2460,18 @@ struct WhoAllReturnStruct {
struct WhoAllPlayer player[0];
};
struct BeginTrader_Struct {
uint32 action;
uint32 unknown04;
uint64 serial_number[80];
uint32 cost[80];
};
struct Trader_Struct {
uint32 code;
uint32 itemid[160];
uint32 unknown;
uint32 itemcost[80];
uint32 action;
uint32 unknown004;
uint64 item_id[80];
uint32 item_cost[80];
};
struct ClickTrader_Struct {
@@ -2471,27 +2484,28 @@ struct GetItems_Struct{
uint32 items[80];
};
struct BecomeTrader_Struct{
uint32 ID;
uint32 Code;
struct BecomeTrader_Struct {
uint32 entity_id;
uint32 action;
char trader_name[64];
};
struct Trader_ShowItems_Struct{
uint32 code;
uint32 traderid;
uint32 action;
uint32 entity_id;
uint32 unknown08[3];
};
struct TraderBuy_Struct {
/*000*/ uint32 Action;
/*004*/ uint32 Price;
/*008*/ uint32 TraderID;
/*012*/ char ItemName[64];
/*076*/ uint32 Unknown076;
/*080*/ uint32 ItemID;
/*084*/ uint32 AlreadySold;
/*088*/ uint32 Quantity;
/*092*/ uint32 Unknown092;
/*000*/ uint32 action;
/*004*/ uint32 price;
/*008*/ uint32 trader_id;
/*012*/ char item_name[64];
/*076*/ uint32 unknown_076;
/*080*/ uint32 item_id;
/*084*/ uint32 already_sold;
/*088*/ uint32 quantity;
/*092*/ uint32 unknown_092;
};
@@ -2517,8 +2531,9 @@ struct TraderDelItem_Struct{
};
struct TraderClick_Struct{
uint32 traderid;
uint32 unknown4[2];
uint32 trader_id;
uint32 action;
uint32 unknown_004;
uint32 approval;
};
@@ -3744,6 +3759,21 @@ struct GuildMemberRank_Struct {
/*076*/ uint32 alt_banker; //Banker/Alt bit 00 - none 10 - Alt 11 - Alt and Banker 01 - Banker. Banker not functional for RoF2+
};
enum TiBazaarTraderBuyerActions {
Zero = 0,
BeginTraderMode = 1,
EndTraderMode = 2,
PriceUpdate = 3,
EndTransaction = 4,
BazaarSearch = 7,
WelcomeMessage = 9,
BuyTraderItem = 10,
ListTraderItems = 11,
BazaarInspect = 18,
ItemMove = 19,
ReconcileItems = 20
};
}; /*structs*/
}; /*Titanium*/
+467 -107
View File
@@ -37,6 +37,8 @@
#include "../races.h"
#include "../raid.h"
#include "../guilds.h"
//#include "../repositories/trader_repository.h"
#include "../cereal/include/cereal/types/vector.hpp"
#include <iostream>
#include <sstream>
@@ -307,50 +309,134 @@ namespace UF
EQApplicationPacket *in = *p;
*p = nullptr;
char *Buffer = (char *)in->pBuffer;
uint32 action = *(uint32 *)in->pBuffer;
uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer);
switch (action) {
case BazaarSearch: {
LogTrading(
"Encode OP_BazaarSearch(UF) BazaarSearch action <green>[{}]",
action
);
std::vector<BazaarSearchResultsFromDB_Struct> results {};
auto bsms = (BazaarSearchMessaging_Struct *)in->pBuffer;
EQ::Util::MemoryStreamReader ss(
reinterpret_cast<char *>(bsms->payload),
in->size - sizeof(BazaarSearchMessaging_Struct)
);
cereal::BinaryInputArchive ar(ss);
ar(results);
if (SubAction != BazaarSearchResults)
{
dest->FastQueuePacket(&in, ack_req);
return;
auto size = results.size() * sizeof(BazaarSearchResults_Struct);
auto buffer = new uchar[size];
uchar *bufptr = buffer;
memset(buffer, 0, size);
for (auto row = results.begin(); row != results.end(); ++row) {
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, structs::UFBazaarTraderBuyerActions::BazaarSearch);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->trader_entity_id);
strn0cpy(reinterpret_cast<char *>(bufptr), row->trader_name.c_str(), 64);
bufptr += 64;
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 1);
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->item_id);
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number);
bufptr += 4;
if (row->stackable) {
strn0cpy(
reinterpret_cast<char *>(bufptr),
fmt::format("{}({})", row->item_name.c_str(), row->charges).c_str(),
64
);
}
else {
strn0cpy(
reinterpret_cast<char *>(bufptr),
fmt::format("{}({})", row->item_name.c_str(), row->count).c_str(),
64
);
}
bufptr += 64;
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->cost);
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->item_stat);
}
auto outapp = new EQApplicationPacket(OP_BazaarSearch, size);
memcpy(outapp->pBuffer, buffer, size);
dest->FastQueuePacket(&outapp);
safe_delete(outapp);
safe_delete_array(buffer);
safe_delete(in);
break;
}
case BazaarInspect:
case WelcomeMessage: {
LogTrading(
"Encode OP_BazaarSearch(UF) BazaarInspect/WelcomeMessage action <green>[{}]",
action
);
dest->FastQueuePacket(&in, ack_req);
break;
}
default: {
LogTrading(
"Encode OP_BazaarSearch(UF) unhandled action <red>[{}]",
action
);
dest->FastQueuePacket(&in, ack_req);
}
}
}
unsigned char *__emu_buffer = in->pBuffer;
ENCODE(OP_BecomeTrader)
{
uint32 action = *(uint32 *)(*p)->pBuffer;
BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer;
int EntryCount = in->size / sizeof(BazaarSearchResults_Struct);
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
switch (action)
{
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
delete in;
return;
case TraderOff:
{
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
LogTrading(
"Encode OP_BecomeTrader(UF) TraderOff action <green>[{}] entity_id <green>[{}] trader_name "
"<green>[{}]",
emu->action,
emu->entity_id,
emu->trader_name
);
eq->action = structs::UFBazaarTraderBuyerActions::Zero;
eq->entity_id = emu->entity_id;
FINISH_ENCODE();
break;
}
case TraderOn:
{
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
LogTrading(
"Encode OP_BecomeTrader(UF) TraderOn action <green>[{}] entity_id <green>[{}] trader_name "
"<green>[{}]",
emu->action,
emu->entity_id,
emu->trader_name
);
eq->action = structs::UFBazaarTraderBuyerActions::BeginTraderMode;
eq->entity_id = emu->entity_id;
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
FINISH_ENCODE();
break;
}
default:
{
LogTrading(
"Encode OP_BecomeTrader(UF) unhandled action <red>[{}] Sending packet as is.",
action
);
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
}
}
in->size = EntryCount * sizeof(structs::BazaarSearchResults_Struct);
in->pBuffer = new unsigned char[in->size];
memset(in->pBuffer, 0, in->size);
structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *)in->pBuffer;
for (int i = 0; i < EntryCount; ++i, ++emu, ++eq)
{
OUT(Beginning.Action);
OUT(SellerID);
memcpy(eq->SellerName, emu->SellerName, sizeof(eq->SellerName));
OUT(NumItems);
OUT(ItemID);
OUT(SerialNumber);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(Cost);
OUT(ItemStat);
}
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_Buff)
@@ -1155,6 +1241,7 @@ namespace UF
break;
}
default: {
emu_e->rank = GUILD_RANK_NONE_TI;
break;
}
}
@@ -1181,53 +1268,37 @@ namespace UF
ENCODE(OP_GuildsList)
{
EQApplicationPacket *in = *p;
EQApplicationPacket* in = *p;
*p = nullptr;
uint32 NumberOfGuilds = in->size / 64;
uint32 PacketSize = 68; // 64 x 0x00 + a uint32 that I am guessing is the highest guild ID in use.
GuildsListMessaging_Struct glms{};
EQ::Util::MemoryStreamReader ss(reinterpret_cast<char *>(in->pBuffer), in->size);
cereal::BinaryInputArchive ar(ss);
ar(glms);
unsigned char *__emu_buffer = in->pBuffer;
char *InBuffer = (char *)__emu_buffer;
uint32 actual_no_guilds = 0;
auto packet_size = 64 + 4 + glms.guild_detail.size() * 4 + glms.string_length;
auto buffer = new uchar[packet_size];
auto buf_pos = buffer;
for (unsigned int i = 0; i < NumberOfGuilds; ++i)
{
if (InBuffer[0])
{
PacketSize += (5 + strlen(InBuffer));
actual_no_guilds++;
memset(buf_pos, 0, 64);
buf_pos += 64;
VARSTRUCT_ENCODE_TYPE(uint32, buf_pos, glms.no_of_guilds);
for (auto const& g : glms.guild_detail) {
if (g.guild_id < UF::constants::MAX_GUILD_ID) {
VARSTRUCT_ENCODE_TYPE(uint32, buf_pos, g.guild_id);
strn0cpy((char *) buf_pos, g.guild_name.c_str(), g.guild_name.length() + 1);
buf_pos += g.guild_name.length() + 1;
}
InBuffer += 64;
}
PacketSize++; // Appears to be an extra 0x00 at the very end.
in->size = PacketSize;
in->pBuffer = new unsigned char[in->size];
InBuffer = (char *)__emu_buffer;
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_GuildsList);
// Init the first 64 bytes to zero, as per live.
//
memset(OutBuffer, 0, 64);
OutBuffer += 64;
outapp->size = packet_size;
outapp->pBuffer = buffer;
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, actual_no_guilds);
for (unsigned int i = 0; i < NumberOfGuilds; ++i)
{
if (InBuffer[0])
{
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, i - 1);
VARSTRUCT_ENCODE_STRING(OutBuffer, InBuffer);
}
InBuffer += 64;
}
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0x00);
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberAdd)
@@ -1256,6 +1327,10 @@ namespace UF
eq->rank_ = GUILD_LEADER_TI;
break;
}
default: {
eq->rank_ = GUILD_RANK_NONE_TI;
break;
}
}
OUT(zone_id)
OUT(last_on)
@@ -1291,6 +1366,10 @@ namespace UF
eq->rank_ = GUILD_LEADER_TI;
break;
}
default: {
eq->rank_ = GUILD_RANK_NONE_TI;
break;
}
}
FINISH_ENCODE()
}
@@ -1970,6 +2049,7 @@ namespace UF
break;
}
default: {
emu->guildrank = GUILD_RANK_NONE_TI;
break;
}
}
@@ -2444,6 +2524,19 @@ namespace UF
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
FINISH_ENCODE();
}
ENCODE(OP_SomeItemPacketMaybe)
{
// This Opcode is not named very well. It is used for the animation of arrows leaving the player's bow
@@ -2503,6 +2596,10 @@ namespace UF
eq->parameter = GUILD_LEADER_TI;
break;
}
default: {
eq->parameter = GUILD_RANK_NONE_TI;
break;
}
}
break;
}
@@ -2545,6 +2642,7 @@ namespace UF
break;
}
default: {
emu->rank = GUILD_RANK_NONE_TI;
break;
}
}
@@ -2731,32 +2829,170 @@ namespace UF
ENCODE(OP_Trader)
{
if ((*p)->size != sizeof(TraderBuy_Struct)) {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
return;
}
auto action = *(uint32 *) (*p)->pBuffer;
ENCODE_FORWARD(OP_TraderBuy);
switch (action) {
case TraderOn: {
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Encode OP_Trader BeginTraderMode action <green>[{}]",
action
);
eq->action = structs::UFBazaarTraderBuyerActions::BeginTraderMode;
OUT(entity_id);
FINISH_ENCODE();
break;
}
case TraderOff: {
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Encode OP_Trader EndTraderMode action <green>[{}]",
action
);
eq->action = structs::UFBazaarTraderBuyerActions::EndTraderMode;
OUT(entity_id);
FINISH_ENCODE();
break;
}
case ListTraderItems: {
ENCODE_LENGTH_EXACT(Trader_Struct);
SETUP_DIRECT_ENCODE(Trader_Struct, structs::Trader_Struct);
LogTrading(
"Encode OP_Trader ListTraderItems action <green>[{}]",
action
);
eq->action = structs::UFBazaarTraderBuyerActions::ListTraderItems;
std::copy_n(emu->items, UF::invtype::BAZAAR_SIZE, eq->item_id);
std::copy_n(emu->item_cost, UF::invtype::BAZAAR_SIZE, eq->item_cost);
FINISH_ENCODE();
break;
}
case BuyTraderItem: {
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_Trader item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
eq->item_id,
eq->price,
eq->quantity,
eq->trader_id
);
eq->action = structs::UFBazaarTraderBuyerActions::BuyTraderItem;
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
FINISH_ENCODE();
break;
}
case ItemMove: {
LogTrading(
"Encode OP_Trader ItemMove action <green>[{}]",
action
);
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
break;
}
default: {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
LogError("Unknown Encode OP_Trader action <red>{} received. Unhandled.", action);
}
}
}
ENCODE(OP_TraderBuy)
{
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_TraderBuy item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
emu->item_id,
emu->price,
emu->quantity,
emu->trader_id
);
OUT(Action);
OUT(Price);
OUT(TraderID);
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
OUT(ItemID);
OUT(Quantity);
OUT(AlreadySold);
OUT(action);
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
OUT_str(item_name);
FINISH_ENCODE();
}
ENCODE(OP_TraderShop)
{
auto action = *(uint32 *)(*p)->pBuffer;
switch (action) {
case ClickTrader: {
ENCODE_LENGTH_EXACT(TraderClick_Struct);
SETUP_DIRECT_ENCODE(TraderClick_Struct, structs::TraderClick_Struct);
LogTrading(
"ClickTrader action <green>[{}] trader_id <green>[{}]",
action,
emu->TraderID
);
eq->action = 0;
eq->trader_id = emu->TraderID;
eq->approval = emu->Approval;
FINISH_ENCODE();
break;
}
case BuyTraderItem: {
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
LogTrading(
"Encode OP_TraderShop item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
eq->item_id,
eq->price,
eq->quantity,
eq->trader_id
);
eq->action = structs::UFBazaarTraderBuyerActions::BuyTraderItem;
OUT(price);
OUT(trader_id);
OUT(item_id);
OUT(already_sold);
OUT(quantity);
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
FINISH_ENCODE();
break;
}
default: {
EQApplicationPacket *in = *p;
*p = nullptr;
dest->FastQueuePacket(&in, ack_req);
LogError("Unknown Encode OP_TraderShop action <red>[{}] received. Unhandled.", action);
}
}
}
ENCODE(OP_TributeItem)
{
ENCODE_LENGTH_EXACT(TributeItem_Struct);
@@ -3028,7 +3264,7 @@ namespace UF
Bitfields->targetable = 1;
Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0;
Bitfields->statue = 0;
Bitfields->trader = 0;
Bitfields->trader = emu->trader ? 1 : 0;
Bitfields->buyer = 0;
Bitfields->showname = ShowName;
@@ -3163,6 +3399,7 @@ namespace UF
break;
}
default: {
emu->guildrank = GUILD_RANK_NONE_TI;
break;
}
}
@@ -3350,20 +3587,49 @@ namespace UF
DECODE(OP_BazaarSearch)
{
char *Buffer = (char *)__packet->pBuffer;
uint32 action = *(uint32 *) __packet->pBuffer;
uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer);
switch (action) {
case structs::UFBazaarTraderBuyerActions::BazaarSearch: {
DECODE_LENGTH_EXACT(structs::BazaarSearch_Struct);
SETUP_DIRECT_DECODE(BazaarSearchCriteria_Struct, structs::BazaarSearch_Struct);
if ((SubAction != BazaarInspectItem) || (__packet->size != sizeof(structs::NewBazaarInspect_Struct)))
return;
emu->action = eq->Beginning.Action;
emu->item_stat = eq->ItemStat;
emu->max_cost = eq->MaxPrice;
emu->min_cost = eq->MinPrice;
emu->max_level = eq->MaxLlevel;
emu->min_level = eq->Minlevel;
emu->race = eq->Race;
emu->slot = eq->Slot;
emu->type = eq->Type == UINT32_MAX ? UINT8_MAX : eq->Type;
emu->trader_entity_id = eq->TraderID;
emu->trader_id = 0;
emu->_class = eq->Class_;
emu->search_scope = eq->TraderID > 0 ? NonRoFBazaarSearchScope : Local_Scope;
emu->max_results = RuleI(Bazaar, MaxSearchResults);
strn0cpy(emu->item_name, eq->Name, sizeof(emu->item_name));
SETUP_DIRECT_DECODE(NewBazaarInspect_Struct, structs::NewBazaarInspect_Struct);
MEMSET_IN(structs::NewBazaarInspect_Struct);
IN(Beginning.Action);
memcpy(emu->Name, eq->Name, sizeof(emu->Name));
IN(SerialNumber);
FINISH_DIRECT_DECODE();
break;
}
case structs::UFBazaarTraderBuyerActions::BazaarInspect: {
SETUP_DIRECT_DECODE(BazaarInspect_Struct, structs::BazaarInspect_Struct);
FINISH_DIRECT_DECODE();
IN(action);
memcpy(emu->player_name, eq->player_name, sizeof(emu->player_name));
IN(serial_number);
FINISH_DIRECT_DECODE();
break;
}
case structs::UFBazaarTraderBuyerActions::WelcomeMessage: {
break;
}
default: {
LogTrading("(UF) Unhandled action <red>[{}]", action);
}
}
}
DECODE(OP_BookButton)
@@ -4031,18 +4297,112 @@ namespace UF
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
emu->tab_display = 0;
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_Trader)
{
auto action = (uint32) __packet->pBuffer[0];
switch (action) {
case structs::UFBazaarTraderBuyerActions::BeginTraderMode: {
DECODE_LENGTH_EXACT(structs::BeginTrader_Struct);
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::BeginTrader_Struct);
LogTrading(
"Decode OP_Trader BeginTraderMode action <red>[{}]",
action
);
emu->action = TraderOn;
emu->unknown_004 = 0;
std::copy_n(eq->serial_number, UF::invtype::BAZAAR_SIZE, emu->serial_number);
std::copy_n(eq->cost, UF::invtype::BAZAAR_SIZE, emu->item_cost);
FINISH_DIRECT_DECODE();
break;
}
case structs::UFBazaarTraderBuyerActions::EndTraderMode: {
DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct);
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
LogTrading(
"Decode OP_Trader(UF) EndTraderMode action <red>[{}]",
action
);
emu->action = TraderOff;
IN(entity_id);
FINISH_DIRECT_DECODE();
break;
}
case structs::UFBazaarTraderBuyerActions::PriceUpdate:
case structs::UFBazaarTraderBuyerActions::ItemMove:
case structs::UFBazaarTraderBuyerActions::EndTransaction:
case structs::UFBazaarTraderBuyerActions::ListTraderItems: {
LogTrading(
"Decode OP_Trader(UF) Price/ItemMove/EndTransaction/ListTraderItems action <red>[{}]",
action
);
break;
}
case structs::UFBazaarTraderBuyerActions::ReconcileItems: {
break;
}
default: {
LogError("Unhandled(UF) action <red>[{}] received.", action);
}
}
}
DECODE(OP_TraderBuy)
{
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
MEMSET_IN(TraderBuy_Struct);
LogTrading(
"Decode OP_TraderBuy(UF) item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
eq->item_id,
eq->price,
eq->quantity,
eq->trader_id
);
IN(Action);
IN(Price);
IN(TraderID);
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
IN(ItemID);
IN(Quantity);
emu->action = BuyTraderItem;
IN(price);
IN(trader_id);
IN(item_id);
IN(quantity);
IN(already_sold);
strn0cpy(emu->item_name, eq->item_name, sizeof(eq->item_name));
FINISH_DIRECT_DECODE();
}
DECODE(OP_TraderShop)
{
DECODE_LENGTH_EXACT(structs::TraderClick_Struct);
SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct);
LogTrading(
"(UF) action <green>[{}] trader_id <green>[{}] approval <green>[{}]",
eq->action,
eq->trader_id,
eq->approval
);
emu->Code = ClickTrader;
emu->TraderID = eq->trader_id;
emu->Approval = eq->approval;
FINISH_DIRECT_DECODE();
}
+1
View File
@@ -289,6 +289,7 @@ namespace UF
const size_t CHARACTER_CREATION_LIMIT = 12;
const size_t SAY_LINK_BODY_SIZE = 50;
const uint32 MAX_GUILD_ID = 50000;
} /*constants*/
+6
View File
@@ -27,6 +27,7 @@ E(OP_ApplyPoison)
E(OP_AugmentInfo)
E(OP_Barter)
E(OP_BazaarSearch)
E(OP_BecomeTrader)
E(OP_Buff)
E(OP_BuffCreate)
E(OP_CancelTrade)
@@ -89,6 +90,7 @@ E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnAppearance)
E(OP_SpawnDoor)
@@ -99,6 +101,7 @@ E(OP_TaskDescription)
E(OP_Track)
E(OP_Trader)
E(OP_TraderBuy)
E(OP_TraderShop)
E(OP_TributeItem)
E(OP_VetRewardsAvaliable)
E(OP_WearChange)
@@ -158,7 +161,10 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TraderShop)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
D(OP_WearChange)
+78 -42
View File
@@ -1916,9 +1916,9 @@ struct TimeOfDay_Struct {
};
// Darvik: shopkeeper structs
struct Merchant_Click_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid;
struct MerchantClick_Struct {
/*000*/ uint32 npc_id; // Merchant NPC's entity id
/*004*/ uint32 player_id;
/*008*/ uint32 command; //1=open, 0=cancel/close
/*012*/ float rate; //cost multiplier, dosent work anymore
};
@@ -2640,23 +2640,23 @@ struct EnvDamage2_Struct {
//Bazaar Stuff
enum {
BazaarTrader_StartTraderMode = 1,
BazaarTrader_EndTraderMode = 2,
BazaarTrader_UpdatePrice = 3,
BazaarTrader_EndTransaction = 4,
BazaarSearchResults = 7,
BazaarWelcome = 9,
BazaarBuyItem = 10,
BazaarTrader_ShowItems = 11,
BazaarSearchDone = 12,
BazaarTrader_StartTraderMode = 1,
BazaarTrader_EndTraderMode = 2,
BazaarTrader_UpdatePrice = 3,
BazaarTrader_EndTransaction = 4,
BazaarSearchResults = 7,
BazaarWelcome = 9,
BazaarBuyItem = 10,
BazaarTrader_ShowItems = 11,
BazaarSearchDone = 12,
BazaarTrader_CustomerBrowsing = 13
};
enum {
BazaarPriceChange_Fail = 0,
BazaarPriceChange_Fail = 0,
BazaarPriceChange_UpdatePrice = 1,
BazaarPriceChange_RemoveItem = 2,
BazaarPriceChange_AddItem = 3
BazaarPriceChange_RemoveItem = 2,
BazaarPriceChange_AddItem = 3
};
struct BazaarWindowStart_Struct {
@@ -2687,10 +2687,14 @@ struct BazaarSearch_Struct {
uint32 Minlevel;
uint32 MaxLlevel;
};
struct BazaarInspect_Struct{
uint32 ItemID;
uint32 Unknown004;
char Name[64];
struct BazaarInspect_Struct {
uint32 action;
char player_name[64];
uint32 unknown_068;
uint32 serial_number;
uint32 unknown_076;
uint32 item_id;
};
struct NewBazaarInspect_Struct {
@@ -2929,10 +2933,17 @@ struct WhoAllPlayerPart4 {
};
struct Trader_Struct {
uint32 code;
uint32 itemid[160];
uint32 unknown;
uint32 itemcost[80];
uint32 action;
uint32 unknown004;
uint64 item_id[80];
uint32 item_cost[80];
};
struct BeginTrader_Struct {
uint32 action;
uint32 unknown04;
uint64 serial_number[80];
uint32 cost[80];
};
struct ClickTrader_Struct {
@@ -2945,30 +2956,30 @@ struct GetItems_Struct{
uint32 items[80];
};
struct BecomeTrader_Struct{
uint32 id;
uint32 code;
struct BecomeTrader_Struct {
uint32 entity_id;
uint32 action;
char trader_name[64];
};
struct Trader_ShowItems_Struct{
uint32 code;
uint32 traderid;
uint32 action;
uint32 entity_id;
uint32 unknown08[3];
};
struct TraderBuy_Struct {
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Price;
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
/*016*/ uint32 TraderID;
/*020*/ char ItemName[64];
/*084*/ uint32 Unknown076;
/*088*/ uint32 ItemID;
/*092*/ uint32 AlreadySold;
/*096*/ uint32 Quantity;
/*100*/ uint32 Unknown092;
/*104*/
uint32 action;
uint32 unknown_004;
uint32 price;
uint32 unknown_008; // Probably high order bits of a 64 bit price.
uint32 trader_id;
char item_name[64];
uint32 unknown_076;
uint32 item_id;
uint32 already_sold;
uint32 quantity;
uint32 unknown_092;
};
struct TraderItemUpdate_Struct{
@@ -3002,8 +3013,9 @@ struct TraderDelItem_Struct{
};
struct TraderClick_Struct{
uint32 traderid;
uint32 unknown4[2];
uint32 trader_id;
uint32 action;
uint32 unknown_004;
uint32 approval;
};
@@ -4674,6 +4686,30 @@ struct SayLinkBodyFrame_Struct {
/*050*/
};
struct TraderPriceUpdate_Struct {
/*000*/ uint32 action;
/*004*/ uint32 sub_action;
/*008*/ int32 serial_number;
/*012*/ uint32 unknown_012;
/*016*/ uint32 new_price;
/*020*/ uint32 unknown_016;
};
enum UFBazaarTraderBuyerActions {
Zero = 0,
BeginTraderMode = 1,
EndTraderMode = 2,
PriceUpdate = 3,
EndTransaction = 4,
BazaarSearch = 7,
WelcomeMessage = 9,
BuyTraderItem = 10,
ListTraderItems = 11,
BazaarInspect = 18,
ItemMove = 19,
ReconcileItems = 20
};
}; /*structs*/
}; /*UF*/
+1 -1
View File
@@ -1379,7 +1379,7 @@ uint32 GetPlayerRaceValue(uint16 race_id) {
}
}
uint32 GetPlayerRaceBit(uint16 race_id) {
uint16 GetPlayerRaceBit(uint16 race_id) {
switch (race_id) {
case HUMAN:
return PLAYER_RACE_HUMAN_BIT;
+1 -1
View File
@@ -124,7 +124,7 @@ bool IsPlayerRace(uint16 race_id);
const std::string GetPlayerRaceAbbreviation(uint16 race_id);
uint32 GetPlayerRaceValue(uint16 race_id);
uint32 GetPlayerRaceBit(uint16 race_id);
uint16 GetPlayerRaceBit(uint16 race_id);
uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value);
uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit);
+62
View File
@@ -44,7 +44,69 @@ public:
*/
// Custom extended repository methods here
static int16 GetAccountStatus(Database& db, const uint32 account_id)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `{}` WHERE `{}` = {}",
TableName(),
PrimaryKey(),
account_id
)
);
if (!results.Success() || !results.RowCount()) {
return 0;
}
auto row = results.begin();
int16 status = static_cast<int16>(Strings::ToInt(row[0]));
int date_diff = 0;
if (row[1]) {
date_diff = Strings::ToInt(row[1]);
}
if (date_diff > 0) {
status = -1;
}
return status;
}
static bool UpdatePassword(Database& db, const uint32 account_id, const std::string& password)
{
auto results = db.QueryDatabase(
fmt::format(
"UPDATE `{}` SET `password` = MD5('{}') WHERE `{}` = {}",
TableName(),
password,
PrimaryKey(),
account_id
)
);
return results.Success();
}
static std::string GetAutoLoginCharacterNameByAccountID(Database& db, const uint32 account_id)
{
return AccountRepository::FindOne(db, account_id).auto_login_charname;
}
static bool SetAutoLoginCharacterNameByAccountID(Database& db, const uint32 account_id, const std::string& character_name)
{
auto e = AccountRepository::FindOne(db, account_id);
if (!e.id) {
return false;
}
e.auto_login_charname = character_name;
return AccountRepository::UpdateOne(db, e);
}
};
#endif //EQEMU_ACCOUNT_REPOSITORY_H
@@ -44,7 +44,65 @@ public:
*/
// Custom extended repository methods here
static void UpdateAdventureStatsEntry(Database& db, uint32 character_id, uint8 theme_id, bool is_win, bool is_remove)
{
std::string field;
switch (theme_id) {
case LDoNThemes::GUK: {
field = "guk_";
break;
}
case LDoNThemes::MIR: {
field = "mir_";
break;
}
case LDoNThemes::MMC: {
field = "mmc_";
break;
}
case LDoNThemes::RUJ: {
field = "ruj_";
break;
}
case LDoNThemes::TAK: {
field = "tak_";
break;
}
}
field += is_win ? "wins" : "losses";
auto e = FindOne(db, character_id);
if (!e.player_id && !is_remove) {
const std::string& query = fmt::format(
"INSERT INTO `{}` SET `{}` = 1, `{}` = {}",
TableName(),
field,
PrimaryKey(),
character_id
);
db.QueryDatabase(query);
return;
}
const std::string& field_operation = is_remove ? "-" : "+";
const std::string& query = fmt::format(
"UPDATE `{}` SET `{}` = {} {} 1 WHERE `{}` = {}",
TableName(),
field,
field,
field_operation,
PrimaryKey(),
character_id
);
db.QueryDatabase(query);
}
};
#endif //EQEMU_ADVENTURE_STATS_REPOSITORY_H
@@ -22,7 +22,7 @@ public:
int32_t accid;
std::string ip;
int32_t count;
std::string lastused;
time_t lastused;
};
static std::string PrimaryKey()
@@ -46,7 +46,7 @@ public:
"accid",
"ip",
"count",
"lastused",
"UNIX_TIMESTAMP(lastused)",
};
}
@@ -130,7 +130,7 @@ public:
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.ip = row[1] ? row[1] : "";
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
e.lastused = row[3] ? row[3] : std::time(nullptr);
e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
return e;
}
@@ -167,7 +167,7 @@ public:
v.push_back(columns[0] + " = " + std::to_string(e.accid));
v.push_back(columns[1] + " = '" + Strings::Escape(e.ip) + "'");
v.push_back(columns[2] + " = " + std::to_string(e.count));
v.push_back(columns[3] + " = '" + Strings::Escape(e.lastused) + "'");
v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
@@ -192,7 +192,7 @@ public:
v.push_back(std::to_string(e.accid));
v.push_back("'" + Strings::Escape(e.ip) + "'");
v.push_back(std::to_string(e.count));
v.push_back("'" + Strings::Escape(e.lastused) + "'");
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
@@ -225,7 +225,7 @@ public:
v.push_back(std::to_string(e.accid));
v.push_back("'" + Strings::Escape(e.ip) + "'");
v.push_back(std::to_string(e.count));
v.push_back("'" + Strings::Escape(e.lastused) + "'");
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -262,7 +262,7 @@ public:
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.ip = row[1] ? row[1] : "";
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
e.lastused = row[3] ? row[3] : std::time(nullptr);
e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@@ -290,7 +290,7 @@ public:
e.accid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.ip = row[1] ? row[1] : "";
e.count = row[2] ? static_cast<int32_t>(atoi(row[2])) : 1;
e.lastused = row[3] ? row[3] : std::time(nullptr);
e.lastused = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@@ -368,7 +368,7 @@ public:
v.push_back(std::to_string(e.accid));
v.push_back("'" + Strings::Escape(e.ip) + "'");
v.push_back(std::to_string(e.count));
v.push_back("'" + Strings::Escape(e.lastused) + "'");
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
@@ -394,7 +394,7 @@ public:
v.push_back(std::to_string(e.accid));
v.push_back("'" + Strings::Escape(e.ip) + "'");
v.push_back(std::to_string(e.count));
v.push_back("'" + Strings::Escape(e.lastused) + "'");
v.push_back("FROM_UNIXTIME(" + (e.lastused > 0 ? std::to_string(e.lastused) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
+129 -117
View File
@@ -22,6 +22,7 @@ public:
int32_t id;
std::string name;
std::string charname;
std::string auto_login_charname;
uint32_t sharedplat;
std::string password;
int32_t status;
@@ -56,6 +57,7 @@ public:
"id",
"name",
"charname",
"auto_login_charname",
"sharedplat",
"password",
"status",
@@ -86,6 +88,7 @@ public:
"id",
"name",
"charname",
"auto_login_charname",
"sharedplat",
"password",
"status",
@@ -147,30 +150,31 @@ public:
{
Account e{};
e.id = 0;
e.name = "";
e.charname = "";
e.sharedplat = 0;
e.password = "";
e.status = 0;
e.ls_id = "eqemu";
e.lsaccount_id = 0;
e.gmspeed = 0;
e.invulnerable = 0;
e.flymode = 0;
e.ignore_tells = 0;
e.revoked = 0;
e.karma = 0;
e.minilogin_ip = "";
e.hideme = 0;
e.rulesflag = 0;
e.suspendeduntil = 0;
e.time_creation = 0;
e.ban_reason = "";
e.suspend_reason = "";
e.crc_eqgame = "";
e.crc_skillcaps = "";
e.crc_basedata = "";
e.id = 0;
e.name = "";
e.charname = "";
e.auto_login_charname = "";
e.sharedplat = 0;
e.password = "";
e.status = 0;
e.ls_id = "eqemu";
e.lsaccount_id = 0;
e.gmspeed = 0;
e.invulnerable = 0;
e.flymode = 0;
e.ignore_tells = 0;
e.revoked = 0;
e.karma = 0;
e.minilogin_ip = "";
e.hideme = 0;
e.rulesflag = 0;
e.suspendeduntil = 0;
e.time_creation = 0;
e.ban_reason = "";
e.suspend_reason = "";
e.crc_eqgame = "";
e.crc_skillcaps = "";
e.crc_basedata = "";
return e;
}
@@ -207,30 +211,31 @@ public:
if (results.RowCount() == 1) {
Account e{};
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.name = row[1] ? row[1] : "";
e.charname = row[2] ? row[2] : "";
e.sharedplat = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.password = row[4] ? row[4] : "";
e.status = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.ls_id = row[6] ? row[6] : "eqemu";
e.lsaccount_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.gmspeed = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 0;
e.invulnerable = row[9] ? static_cast<int8_t>(atoi(row[9])) : 0;
e.flymode = row[10] ? static_cast<int8_t>(atoi(row[10])) : 0;
e.ignore_tells = row[11] ? static_cast<int8_t>(atoi(row[11])) : 0;
e.revoked = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.karma = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.minilogin_ip = row[14] ? row[14] : "";
e.hideme = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
e.rulesflag = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10);
e.time_creation = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
e.ban_reason = row[19] ? row[19] : "";
e.suspend_reason = row[20] ? row[20] : "";
e.crc_eqgame = row[21] ? row[21] : "";
e.crc_skillcaps = row[22] ? row[22] : "";
e.crc_basedata = row[23] ? row[23] : "";
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.name = row[1] ? row[1] : "";
e.charname = row[2] ? row[2] : "";
e.auto_login_charname = row[3] ? row[3] : "";
e.sharedplat = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.password = row[5] ? row[5] : "";
e.status = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.ls_id = row[7] ? row[7] : "eqemu";
e.lsaccount_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.gmspeed = row[9] ? static_cast<uint8_t>(strtoul(row[9], nullptr, 10)) : 0;
e.invulnerable = row[10] ? static_cast<int8_t>(atoi(row[10])) : 0;
e.flymode = row[11] ? static_cast<int8_t>(atoi(row[11])) : 0;
e.ignore_tells = row[12] ? static_cast<int8_t>(atoi(row[12])) : 0;
e.revoked = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
e.karma = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.minilogin_ip = row[15] ? row[15] : "";
e.hideme = row[16] ? static_cast<int8_t>(atoi(row[16])) : 0;
e.rulesflag = row[17] ? static_cast<uint8_t>(strtoul(row[17], nullptr, 10)) : 0;
e.suspendeduntil = strtoll(row[18] ? row[18] : "-1", nullptr, 10);
e.time_creation = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
e.ban_reason = row[20] ? row[20] : "";
e.suspend_reason = row[21] ? row[21] : "";
e.crc_eqgame = row[22] ? row[22] : "";
e.crc_skillcaps = row[23] ? row[23] : "";
e.crc_basedata = row[24] ? row[24] : "";
return e;
}
@@ -266,27 +271,28 @@ public:
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[2] + " = '" + Strings::Escape(e.charname) + "'");
v.push_back(columns[3] + " = " + std::to_string(e.sharedplat));
v.push_back(columns[4] + " = '" + Strings::Escape(e.password) + "'");
v.push_back(columns[5] + " = " + std::to_string(e.status));
v.push_back(columns[6] + " = '" + Strings::Escape(e.ls_id) + "'");
v.push_back(columns[7] + " = " + std::to_string(e.lsaccount_id));
v.push_back(columns[8] + " = " + std::to_string(e.gmspeed));
v.push_back(columns[9] + " = " + std::to_string(e.invulnerable));
v.push_back(columns[10] + " = " + std::to_string(e.flymode));
v.push_back(columns[11] + " = " + std::to_string(e.ignore_tells));
v.push_back(columns[12] + " = " + std::to_string(e.revoked));
v.push_back(columns[13] + " = " + std::to_string(e.karma));
v.push_back(columns[14] + " = '" + Strings::Escape(e.minilogin_ip) + "'");
v.push_back(columns[15] + " = " + std::to_string(e.hideme));
v.push_back(columns[16] + " = " + std::to_string(e.rulesflag));
v.push_back(columns[17] + " = FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")");
v.push_back(columns[18] + " = " + std::to_string(e.time_creation));
v.push_back(columns[19] + " = '" + Strings::Escape(e.ban_reason) + "'");
v.push_back(columns[20] + " = '" + Strings::Escape(e.suspend_reason) + "'");
v.push_back(columns[21] + " = '" + Strings::Escape(e.crc_eqgame) + "'");
v.push_back(columns[22] + " = '" + Strings::Escape(e.crc_skillcaps) + "'");
v.push_back(columns[23] + " = '" + Strings::Escape(e.crc_basedata) + "'");
v.push_back(columns[3] + " = '" + Strings::Escape(e.auto_login_charname) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.sharedplat));
v.push_back(columns[5] + " = '" + Strings::Escape(e.password) + "'");
v.push_back(columns[6] + " = " + std::to_string(e.status));
v.push_back(columns[7] + " = '" + Strings::Escape(e.ls_id) + "'");
v.push_back(columns[8] + " = " + std::to_string(e.lsaccount_id));
v.push_back(columns[9] + " = " + std::to_string(e.gmspeed));
v.push_back(columns[10] + " = " + std::to_string(e.invulnerable));
v.push_back(columns[11] + " = " + std::to_string(e.flymode));
v.push_back(columns[12] + " = " + std::to_string(e.ignore_tells));
v.push_back(columns[13] + " = " + std::to_string(e.revoked));
v.push_back(columns[14] + " = " + std::to_string(e.karma));
v.push_back(columns[15] + " = '" + Strings::Escape(e.minilogin_ip) + "'");
v.push_back(columns[16] + " = " + std::to_string(e.hideme));
v.push_back(columns[17] + " = " + std::to_string(e.rulesflag));
v.push_back(columns[18] + " = FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")");
v.push_back(columns[19] + " = " + std::to_string(e.time_creation));
v.push_back(columns[20] + " = '" + Strings::Escape(e.ban_reason) + "'");
v.push_back(columns[21] + " = '" + Strings::Escape(e.suspend_reason) + "'");
v.push_back(columns[22] + " = '" + Strings::Escape(e.crc_eqgame) + "'");
v.push_back(columns[23] + " = '" + Strings::Escape(e.crc_skillcaps) + "'");
v.push_back(columns[24] + " = '" + Strings::Escape(e.crc_basedata) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -311,6 +317,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back("'" + Strings::Escape(e.charname) + "'");
v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'");
v.push_back(std::to_string(e.sharedplat));
v.push_back("'" + Strings::Escape(e.password) + "'");
v.push_back(std::to_string(e.status));
@@ -364,6 +371,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back("'" + Strings::Escape(e.charname) + "'");
v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'");
v.push_back(std::to_string(e.sharedplat));
v.push_back("'" + Strings::Escape(e.password) + "'");
v.push_back(std::to_string(e.status));
@@ -418,30 +426,31 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Account e{};
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.name = row[1] ? row[1] : "";
e.charname = row[2] ? row[2] : "";
e.sharedplat = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.password = row[4] ? row[4] : "";
e.status = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.ls_id = row[6] ? row[6] : "eqemu";
e.lsaccount_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.gmspeed = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 0;
e.invulnerable = row[9] ? static_cast<int8_t>(atoi(row[9])) : 0;
e.flymode = row[10] ? static_cast<int8_t>(atoi(row[10])) : 0;
e.ignore_tells = row[11] ? static_cast<int8_t>(atoi(row[11])) : 0;
e.revoked = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.karma = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.minilogin_ip = row[14] ? row[14] : "";
e.hideme = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
e.rulesflag = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10);
e.time_creation = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
e.ban_reason = row[19] ? row[19] : "";
e.suspend_reason = row[20] ? row[20] : "";
e.crc_eqgame = row[21] ? row[21] : "";
e.crc_skillcaps = row[22] ? row[22] : "";
e.crc_basedata = row[23] ? row[23] : "";
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.name = row[1] ? row[1] : "";
e.charname = row[2] ? row[2] : "";
e.auto_login_charname = row[3] ? row[3] : "";
e.sharedplat = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.password = row[5] ? row[5] : "";
e.status = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.ls_id = row[7] ? row[7] : "eqemu";
e.lsaccount_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.gmspeed = row[9] ? static_cast<uint8_t>(strtoul(row[9], nullptr, 10)) : 0;
e.invulnerable = row[10] ? static_cast<int8_t>(atoi(row[10])) : 0;
e.flymode = row[11] ? static_cast<int8_t>(atoi(row[11])) : 0;
e.ignore_tells = row[12] ? static_cast<int8_t>(atoi(row[12])) : 0;
e.revoked = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
e.karma = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.minilogin_ip = row[15] ? row[15] : "";
e.hideme = row[16] ? static_cast<int8_t>(atoi(row[16])) : 0;
e.rulesflag = row[17] ? static_cast<uint8_t>(strtoul(row[17], nullptr, 10)) : 0;
e.suspendeduntil = strtoll(row[18] ? row[18] : "-1", nullptr, 10);
e.time_creation = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
e.ban_reason = row[20] ? row[20] : "";
e.suspend_reason = row[21] ? row[21] : "";
e.crc_eqgame = row[22] ? row[22] : "";
e.crc_skillcaps = row[23] ? row[23] : "";
e.crc_basedata = row[24] ? row[24] : "";
all_entries.push_back(e);
}
@@ -466,30 +475,31 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Account e{};
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.name = row[1] ? row[1] : "";
e.charname = row[2] ? row[2] : "";
e.sharedplat = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.password = row[4] ? row[4] : "";
e.status = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.ls_id = row[6] ? row[6] : "eqemu";
e.lsaccount_id = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.gmspeed = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 0;
e.invulnerable = row[9] ? static_cast<int8_t>(atoi(row[9])) : 0;
e.flymode = row[10] ? static_cast<int8_t>(atoi(row[10])) : 0;
e.ignore_tells = row[11] ? static_cast<int8_t>(atoi(row[11])) : 0;
e.revoked = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.karma = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.minilogin_ip = row[14] ? row[14] : "";
e.hideme = row[15] ? static_cast<int8_t>(atoi(row[15])) : 0;
e.rulesflag = row[16] ? static_cast<uint8_t>(strtoul(row[16], nullptr, 10)) : 0;
e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10);
e.time_creation = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
e.ban_reason = row[19] ? row[19] : "";
e.suspend_reason = row[20] ? row[20] : "";
e.crc_eqgame = row[21] ? row[21] : "";
e.crc_skillcaps = row[22] ? row[22] : "";
e.crc_basedata = row[23] ? row[23] : "";
e.id = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.name = row[1] ? row[1] : "";
e.charname = row[2] ? row[2] : "";
e.auto_login_charname = row[3] ? row[3] : "";
e.sharedplat = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.password = row[5] ? row[5] : "";
e.status = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.ls_id = row[7] ? row[7] : "eqemu";
e.lsaccount_id = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.gmspeed = row[9] ? static_cast<uint8_t>(strtoul(row[9], nullptr, 10)) : 0;
e.invulnerable = row[10] ? static_cast<int8_t>(atoi(row[10])) : 0;
e.flymode = row[11] ? static_cast<int8_t>(atoi(row[11])) : 0;
e.ignore_tells = row[12] ? static_cast<int8_t>(atoi(row[12])) : 0;
e.revoked = row[13] ? static_cast<uint8_t>(strtoul(row[13], nullptr, 10)) : 0;
e.karma = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.minilogin_ip = row[15] ? row[15] : "";
e.hideme = row[16] ? static_cast<int8_t>(atoi(row[16])) : 0;
e.rulesflag = row[17] ? static_cast<uint8_t>(strtoul(row[17], nullptr, 10)) : 0;
e.suspendeduntil = strtoll(row[18] ? row[18] : "-1", nullptr, 10);
e.time_creation = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
e.ban_reason = row[20] ? row[20] : "";
e.suspend_reason = row[21] ? row[21] : "";
e.crc_eqgame = row[22] ? row[22] : "";
e.crc_skillcaps = row[23] ? row[23] : "";
e.crc_basedata = row[24] ? row[24] : "";
all_entries.push_back(e);
}
@@ -567,6 +577,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back("'" + Strings::Escape(e.charname) + "'");
v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'");
v.push_back(std::to_string(e.sharedplat));
v.push_back("'" + Strings::Escape(e.password) + "'");
v.push_back(std::to_string(e.status));
@@ -613,6 +624,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back("'" + Strings::Escape(e.charname) + "'");
v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'");
v.push_back(std::to_string(e.sharedplat));
v.push_back("'" + Strings::Escape(e.password) + "'");
v.push_back(std::to_string(e.status));
@@ -57,6 +57,7 @@ public:
int32_t int_;
int32_t agi;
int32_t wis;
int32_t extra_haste;
int16_t fire;
int16_t cold;
int16_t magic;
@@ -118,6 +119,7 @@ public:
"`int`",
"agi",
"wis",
"extra_haste",
"fire",
"cold",
"magic",
@@ -175,6 +177,7 @@ public:
"`int`",
"agi",
"wis",
"extra_haste",
"fire",
"cold",
"magic",
@@ -266,6 +269,7 @@ public:
e.int_ = 75;
e.agi = 75;
e.wis = 75;
e.extra_haste = 0;
e.fire = 0;
e.cold = 0;
e.magic = 0;
@@ -353,19 +357,20 @@ public:
e.int_ = row[35] ? static_cast<int32_t>(atoi(row[35])) : 75;
e.agi = row[36] ? static_cast<int32_t>(atoi(row[36])) : 75;
e.wis = row[37] ? static_cast<int32_t>(atoi(row[37])) : 75;
e.fire = row[38] ? static_cast<int16_t>(atoi(row[38])) : 0;
e.cold = row[39] ? static_cast<int16_t>(atoi(row[39])) : 0;
e.magic = row[40] ? static_cast<int16_t>(atoi(row[40])) : 0;
e.poison = row[41] ? static_cast<int16_t>(atoi(row[41])) : 0;
e.disease = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
e.corruption = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
e.show_helm = row[44] ? static_cast<uint32_t>(strtoul(row[44], nullptr, 10)) : 0;
e.follow_distance = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 200;
e.stop_melee_level = row[46] ? static_cast<uint8_t>(strtoul(row[46], nullptr, 10)) : 255;
e.expansion_bitmask = row[47] ? static_cast<int32_t>(atoi(row[47])) : -1;
e.enforce_spell_settings = row[48] ? static_cast<uint8_t>(strtoul(row[48], nullptr, 10)) : 0;
e.archery_setting = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
e.caster_range = row[50] ? static_cast<uint32_t>(strtoul(row[50], nullptr, 10)) : 300;
e.extra_haste = row[38] ? static_cast<int32_t>(atoi(row[38])) : 0;
e.fire = row[39] ? static_cast<int16_t>(atoi(row[39])) : 0;
e.cold = row[40] ? static_cast<int16_t>(atoi(row[40])) : 0;
e.magic = row[41] ? static_cast<int16_t>(atoi(row[41])) : 0;
e.poison = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
e.disease = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
e.corruption = row[44] ? static_cast<int16_t>(atoi(row[44])) : 0;
e.show_helm = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 0;
e.follow_distance = row[46] ? static_cast<uint32_t>(strtoul(row[46], nullptr, 10)) : 200;
e.stop_melee_level = row[47] ? static_cast<uint8_t>(strtoul(row[47], nullptr, 10)) : 255;
e.expansion_bitmask = row[48] ? static_cast<int32_t>(atoi(row[48])) : -1;
e.enforce_spell_settings = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
e.archery_setting = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
e.caster_range = row[51] ? static_cast<uint32_t>(strtoul(row[51], nullptr, 10)) : 300;
return e;
}
@@ -436,19 +441,20 @@ public:
v.push_back(columns[35] + " = " + std::to_string(e.int_));
v.push_back(columns[36] + " = " + std::to_string(e.agi));
v.push_back(columns[37] + " = " + std::to_string(e.wis));
v.push_back(columns[38] + " = " + std::to_string(e.fire));
v.push_back(columns[39] + " = " + std::to_string(e.cold));
v.push_back(columns[40] + " = " + std::to_string(e.magic));
v.push_back(columns[41] + " = " + std::to_string(e.poison));
v.push_back(columns[42] + " = " + std::to_string(e.disease));
v.push_back(columns[43] + " = " + std::to_string(e.corruption));
v.push_back(columns[44] + " = " + std::to_string(e.show_helm));
v.push_back(columns[45] + " = " + std::to_string(e.follow_distance));
v.push_back(columns[46] + " = " + std::to_string(e.stop_melee_level));
v.push_back(columns[47] + " = " + std::to_string(e.expansion_bitmask));
v.push_back(columns[48] + " = " + std::to_string(e.enforce_spell_settings));
v.push_back(columns[49] + " = " + std::to_string(e.archery_setting));
v.push_back(columns[50] + " = " + std::to_string(e.caster_range));
v.push_back(columns[38] + " = " + std::to_string(e.extra_haste));
v.push_back(columns[39] + " = " + std::to_string(e.fire));
v.push_back(columns[40] + " = " + std::to_string(e.cold));
v.push_back(columns[41] + " = " + std::to_string(e.magic));
v.push_back(columns[42] + " = " + std::to_string(e.poison));
v.push_back(columns[43] + " = " + std::to_string(e.disease));
v.push_back(columns[44] + " = " + std::to_string(e.corruption));
v.push_back(columns[45] + " = " + std::to_string(e.show_helm));
v.push_back(columns[46] + " = " + std::to_string(e.follow_distance));
v.push_back(columns[47] + " = " + std::to_string(e.stop_melee_level));
v.push_back(columns[48] + " = " + std::to_string(e.expansion_bitmask));
v.push_back(columns[49] + " = " + std::to_string(e.enforce_spell_settings));
v.push_back(columns[50] + " = " + std::to_string(e.archery_setting));
v.push_back(columns[51] + " = " + std::to_string(e.caster_range));
auto results = db.QueryDatabase(
fmt::format(
@@ -508,6 +514,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.fire));
v.push_back(std::to_string(e.cold));
v.push_back(std::to_string(e.magic));
@@ -588,6 +595,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.fire));
v.push_back(std::to_string(e.cold));
v.push_back(std::to_string(e.magic));
@@ -672,19 +680,20 @@ public:
e.int_ = row[35] ? static_cast<int32_t>(atoi(row[35])) : 75;
e.agi = row[36] ? static_cast<int32_t>(atoi(row[36])) : 75;
e.wis = row[37] ? static_cast<int32_t>(atoi(row[37])) : 75;
e.fire = row[38] ? static_cast<int16_t>(atoi(row[38])) : 0;
e.cold = row[39] ? static_cast<int16_t>(atoi(row[39])) : 0;
e.magic = row[40] ? static_cast<int16_t>(atoi(row[40])) : 0;
e.poison = row[41] ? static_cast<int16_t>(atoi(row[41])) : 0;
e.disease = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
e.corruption = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
e.show_helm = row[44] ? static_cast<uint32_t>(strtoul(row[44], nullptr, 10)) : 0;
e.follow_distance = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 200;
e.stop_melee_level = row[46] ? static_cast<uint8_t>(strtoul(row[46], nullptr, 10)) : 255;
e.expansion_bitmask = row[47] ? static_cast<int32_t>(atoi(row[47])) : -1;
e.enforce_spell_settings = row[48] ? static_cast<uint8_t>(strtoul(row[48], nullptr, 10)) : 0;
e.archery_setting = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
e.caster_range = row[50] ? static_cast<uint32_t>(strtoul(row[50], nullptr, 10)) : 300;
e.extra_haste = row[38] ? static_cast<int32_t>(atoi(row[38])) : 0;
e.fire = row[39] ? static_cast<int16_t>(atoi(row[39])) : 0;
e.cold = row[40] ? static_cast<int16_t>(atoi(row[40])) : 0;
e.magic = row[41] ? static_cast<int16_t>(atoi(row[41])) : 0;
e.poison = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
e.disease = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
e.corruption = row[44] ? static_cast<int16_t>(atoi(row[44])) : 0;
e.show_helm = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 0;
e.follow_distance = row[46] ? static_cast<uint32_t>(strtoul(row[46], nullptr, 10)) : 200;
e.stop_melee_level = row[47] ? static_cast<uint8_t>(strtoul(row[47], nullptr, 10)) : 255;
e.expansion_bitmask = row[48] ? static_cast<int32_t>(atoi(row[48])) : -1;
e.enforce_spell_settings = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
e.archery_setting = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
e.caster_range = row[51] ? static_cast<uint32_t>(strtoul(row[51], nullptr, 10)) : 300;
all_entries.push_back(e);
}
@@ -747,19 +756,20 @@ public:
e.int_ = row[35] ? static_cast<int32_t>(atoi(row[35])) : 75;
e.agi = row[36] ? static_cast<int32_t>(atoi(row[36])) : 75;
e.wis = row[37] ? static_cast<int32_t>(atoi(row[37])) : 75;
e.fire = row[38] ? static_cast<int16_t>(atoi(row[38])) : 0;
e.cold = row[39] ? static_cast<int16_t>(atoi(row[39])) : 0;
e.magic = row[40] ? static_cast<int16_t>(atoi(row[40])) : 0;
e.poison = row[41] ? static_cast<int16_t>(atoi(row[41])) : 0;
e.disease = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
e.corruption = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
e.show_helm = row[44] ? static_cast<uint32_t>(strtoul(row[44], nullptr, 10)) : 0;
e.follow_distance = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 200;
e.stop_melee_level = row[46] ? static_cast<uint8_t>(strtoul(row[46], nullptr, 10)) : 255;
e.expansion_bitmask = row[47] ? static_cast<int32_t>(atoi(row[47])) : -1;
e.enforce_spell_settings = row[48] ? static_cast<uint8_t>(strtoul(row[48], nullptr, 10)) : 0;
e.archery_setting = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
e.caster_range = row[50] ? static_cast<uint32_t>(strtoul(row[50], nullptr, 10)) : 300;
e.extra_haste = row[38] ? static_cast<int32_t>(atoi(row[38])) : 0;
e.fire = row[39] ? static_cast<int16_t>(atoi(row[39])) : 0;
e.cold = row[40] ? static_cast<int16_t>(atoi(row[40])) : 0;
e.magic = row[41] ? static_cast<int16_t>(atoi(row[41])) : 0;
e.poison = row[42] ? static_cast<int16_t>(atoi(row[42])) : 0;
e.disease = row[43] ? static_cast<int16_t>(atoi(row[43])) : 0;
e.corruption = row[44] ? static_cast<int16_t>(atoi(row[44])) : 0;
e.show_helm = row[45] ? static_cast<uint32_t>(strtoul(row[45], nullptr, 10)) : 0;
e.follow_distance = row[46] ? static_cast<uint32_t>(strtoul(row[46], nullptr, 10)) : 200;
e.stop_melee_level = row[47] ? static_cast<uint8_t>(strtoul(row[47], nullptr, 10)) : 255;
e.expansion_bitmask = row[48] ? static_cast<int32_t>(atoi(row[48])) : -1;
e.enforce_spell_settings = row[49] ? static_cast<uint8_t>(strtoul(row[49], nullptr, 10)) : 0;
e.archery_setting = row[50] ? static_cast<uint8_t>(strtoul(row[50], nullptr, 10)) : 0;
e.caster_range = row[51] ? static_cast<uint32_t>(strtoul(row[51], nullptr, 10)) : 300;
all_entries.push_back(e);
}
@@ -872,6 +882,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.fire));
v.push_back(std::to_string(e.cold));
v.push_back(std::to_string(e.magic));
@@ -945,6 +956,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.fire));
v.push_back(std::to_string(e.cold));
v.push_back(std::to_string(e.magic));
@@ -21,7 +21,7 @@ public:
struct BotSpellsEntries {
uint32_t id;
int32_t npc_spells_id;
int16_t spellid;
uint16_t spell_id;
uint32_t type;
uint8_t minlevel;
uint8_t maxlevel;
@@ -46,7 +46,7 @@ public:
return {
"id",
"npc_spells_id",
"spellid",
"spell_id",
"type",
"minlevel",
"maxlevel",
@@ -67,7 +67,7 @@ public:
return {
"id",
"npc_spells_id",
"spellid",
"spell_id",
"type",
"minlevel",
"maxlevel",
@@ -122,7 +122,7 @@ public:
e.id = 0;
e.npc_spells_id = 0;
e.spellid = 0;
e.spell_id = 0;
e.type = 0;
e.minlevel = 0;
e.maxlevel = 255;
@@ -173,7 +173,7 @@ public:
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
@@ -220,7 +220,7 @@ public:
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.npc_spells_id));
v.push_back(columns[2] + " = " + std::to_string(e.spellid));
v.push_back(columns[2] + " = " + std::to_string(e.spell_id));
v.push_back(columns[3] + " = " + std::to_string(e.type));
v.push_back(columns[4] + " = " + std::to_string(e.minlevel));
v.push_back(columns[5] + " = " + std::to_string(e.maxlevel));
@@ -256,7 +256,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.npc_spells_id));
v.push_back(std::to_string(e.spellid));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
@@ -300,7 +300,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.npc_spells_id));
v.push_back(std::to_string(e.spellid));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
@@ -348,7 +348,7 @@ public:
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
@@ -387,7 +387,7 @@ public:
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<int16_t>(atoi(row[2])) : 0;
e.spell_id = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
@@ -476,7 +476,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.npc_spells_id));
v.push_back(std::to_string(e.spellid));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
@@ -513,7 +513,7 @@ public:
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.npc_spells_id));
v.push_back(std::to_string(e.spellid));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.minlevel));
v.push_back(std::to_string(e.maxlevel));
@@ -24,6 +24,12 @@ public:
uint32_t classes;
uint32_t item_id;
uint8_t item_charges;
uint32_t augment_one;
uint32_t augment_two;
uint32_t augment_three;
uint32_t augment_four;
uint32_t augment_five;
uint32_t augment_six;
uint8_t min_status;
int32_t slot_id;
int8_t min_expansion;
@@ -45,6 +51,12 @@ public:
"classes",
"item_id",
"item_charges",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"min_status",
"slot_id",
"min_expansion",
@@ -62,6 +74,12 @@ public:
"classes",
"item_id",
"item_charges",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"min_status",
"slot_id",
"min_expansion",
@@ -113,6 +131,12 @@ public:
e.classes = 0;
e.item_id = 0;
e.item_charges = 1;
e.augment_one = 0;
e.augment_two = 0;
e.augment_three = 0;
e.augment_four = 0;
e.augment_five = 0;
e.augment_six = 0;
e.min_status = 0;
e.slot_id = -1;
e.min_expansion = -1;
@@ -160,12 +184,18 @@ public:
e.classes = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.item_charges = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 1;
e.min_status = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
e.slot_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : -1;
e.min_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -1;
e.max_expansion = row[8] ? static_cast<int8_t>(atoi(row[8])) : -1;
e.content_flags = row[9] ? row[9] : "";
e.content_flags_disabled = row[10] ? row[10] : "";
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_status = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<int32_t>(atoi(row[12])) : -1;
e.min_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.max_expansion = row[14] ? static_cast<int8_t>(atoi(row[14])) : -1;
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
return e;
}
@@ -203,12 +233,18 @@ public:
v.push_back(columns[2] + " = " + std::to_string(e.classes));
v.push_back(columns[3] + " = " + std::to_string(e.item_id));
v.push_back(columns[4] + " = " + std::to_string(e.item_charges));
v.push_back(columns[5] + " = " + std::to_string(e.min_status));
v.push_back(columns[6] + " = " + std::to_string(e.slot_id));
v.push_back(columns[7] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[8] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[10] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[5] + " = " + std::to_string(e.augment_one));
v.push_back(columns[6] + " = " + std::to_string(e.augment_two));
v.push_back(columns[7] + " = " + std::to_string(e.augment_three));
v.push_back(columns[8] + " = " + std::to_string(e.augment_four));
v.push_back(columns[9] + " = " + std::to_string(e.augment_five));
v.push_back(columns[10] + " = " + std::to_string(e.augment_six));
v.push_back(columns[11] + " = " + std::to_string(e.min_status));
v.push_back(columns[12] + " = " + std::to_string(e.slot_id));
v.push_back(columns[13] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[14] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[16] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -235,6 +271,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -275,6 +317,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -319,12 +367,18 @@ public:
e.classes = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.item_charges = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 1;
e.min_status = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
e.slot_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : -1;
e.min_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -1;
e.max_expansion = row[8] ? static_cast<int8_t>(atoi(row[8])) : -1;
e.content_flags = row[9] ? row[9] : "";
e.content_flags_disabled = row[10] ? row[10] : "";
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_status = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<int32_t>(atoi(row[12])) : -1;
e.min_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.max_expansion = row[14] ? static_cast<int8_t>(atoi(row[14])) : -1;
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
all_entries.push_back(e);
}
@@ -354,12 +408,18 @@ public:
e.classes = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.item_charges = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 1;
e.min_status = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
e.slot_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : -1;
e.min_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -1;
e.max_expansion = row[8] ? static_cast<int8_t>(atoi(row[8])) : -1;
e.content_flags = row[9] ? row[9] : "";
e.content_flags_disabled = row[10] ? row[10] : "";
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_status = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<int32_t>(atoi(row[12])) : -1;
e.min_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.max_expansion = row[14] ? static_cast<int8_t>(atoi(row[14])) : -1;
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
all_entries.push_back(e);
}
@@ -439,6 +499,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -472,6 +538,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -0,0 +1,475 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H
#define EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBuyerBuyLinesRepository {
public:
struct BuyerBuyLines {
uint64_t id;
uint64_t buyer_id;
uint32_t char_id;
int32_t buy_slot_id;
int32_t item_id;
int32_t item_qty;
int32_t item_price;
uint32_t item_icon;
std::string item_name;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"buyer_id",
"char_id",
"buy_slot_id",
"item_id",
"item_qty",
"item_price",
"item_icon",
"item_name",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"buyer_id",
"char_id",
"buy_slot_id",
"item_id",
"item_qty",
"item_price",
"item_icon",
"item_name",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("buyer_buy_lines");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BuyerBuyLines NewEntity()
{
BuyerBuyLines e{};
e.id = 0;
e.buyer_id = 0;
e.char_id = 0;
e.buy_slot_id = 0;
e.item_id = 0;
e.item_qty = 0;
e.item_price = 0;
e.item_icon = 0;
e.item_name = "";
return e;
}
static BuyerBuyLines GetBuyerBuyLines(
const std::vector<BuyerBuyLines> &buyer_buy_liness,
int buyer_buy_lines_id
)
{
for (auto &buyer_buy_lines : buyer_buy_liness) {
if (buyer_buy_lines.id == buyer_buy_lines_id) {
return buyer_buy_lines;
}
}
return NewEntity();
}
static BuyerBuyLines FindOne(
Database& db,
int buyer_buy_lines_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
buyer_buy_lines_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BuyerBuyLines e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.buyer_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
e.char_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.buy_slot_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.item_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.item_qty = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.item_price = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.item_icon = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.item_name = row[8] ? row[8] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int buyer_buy_lines_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
buyer_buy_lines_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BuyerBuyLines &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.buyer_id));
v.push_back(columns[2] + " = " + std::to_string(e.char_id));
v.push_back(columns[3] + " = " + std::to_string(e.buy_slot_id));
v.push_back(columns[4] + " = " + std::to_string(e.item_id));
v.push_back(columns[5] + " = " + std::to_string(e.item_qty));
v.push_back(columns[6] + " = " + std::to_string(e.item_price));
v.push_back(columns[7] + " = " + std::to_string(e.item_icon));
v.push_back(columns[8] + " = '" + Strings::Escape(e.item_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BuyerBuyLines InsertOne(
Database& db,
BuyerBuyLines e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.buy_slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_price));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BuyerBuyLines> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.buy_slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_price));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<BuyerBuyLines> All(Database& db)
{
std::vector<BuyerBuyLines> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BuyerBuyLines e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.buyer_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
e.char_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.buy_slot_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.item_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.item_qty = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.item_price = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.item_icon = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.item_name = row[8] ? row[8] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BuyerBuyLines> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BuyerBuyLines> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BuyerBuyLines e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.buyer_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
e.char_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.buy_slot_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.item_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.item_qty = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.item_price = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.item_icon = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.item_name = row[8] ? row[8] : "";
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const BuyerBuyLines &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.buy_slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_price));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<BuyerBuyLines> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.buy_slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_price));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H
@@ -19,40 +19,46 @@
class BaseBuyerRepository {
public:
struct Buyer {
int32_t charid;
int32_t buyslot;
int32_t itemid;
std::string itemname;
int32_t quantity;
int32_t price;
uint64_t id;
uint32_t char_id;
uint32_t char_entity_id;
std::string char_name;
uint32_t char_zone_id;
uint32_t char_zone_instance_id;
time_t transaction_date;
std::string welcome_message;
};
static std::string PrimaryKey()
{
return std::string("charid");
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"charid",
"buyslot",
"itemid",
"itemname",
"quantity",
"price",
"id",
"char_id",
"char_entity_id",
"char_name",
"char_zone_id",
"char_zone_instance_id",
"transaction_date",
"welcome_message",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"charid",
"buyslot",
"itemid",
"itemname",
"quantity",
"price",
"id",
"char_id",
"char_entity_id",
"char_name",
"char_zone_id",
"char_zone_instance_id",
"UNIX_TIMESTAMP(transaction_date)",
"welcome_message",
};
}
@@ -93,12 +99,14 @@ public:
{
Buyer e{};
e.charid = 0;
e.buyslot = 0;
e.itemid = 0;
e.itemname = "";
e.quantity = 0;
e.price = 0;
e.id = 0;
e.char_id = 0;
e.char_entity_id = 0;
e.char_name = "";
e.char_zone_id = 0;
e.char_zone_instance_id = 0;
e.transaction_date = 0;
e.welcome_message = "";
return e;
}
@@ -109,7 +117,7 @@ public:
)
{
for (auto &buyer : buyers) {
if (buyer.charid == buyer_id) {
if (buyer.id == buyer_id) {
return buyer;
}
}
@@ -135,12 +143,14 @@ public:
if (results.RowCount() == 1) {
Buyer e{};
e.charid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.buyslot = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.itemid = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.itemname = row[3] ? row[3] : "";
e.quantity = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.price = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.char_entity_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.char_name = row[3] ? row[3] : "";
e.char_zone_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.char_zone_instance_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.transaction_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10);
e.welcome_message = row[7] ? row[7] : "";
return e;
}
@@ -174,12 +184,13 @@ public:
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.charid));
v.push_back(columns[1] + " = " + std::to_string(e.buyslot));
v.push_back(columns[2] + " = " + std::to_string(e.itemid));
v.push_back(columns[3] + " = '" + Strings::Escape(e.itemname) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.quantity));
v.push_back(columns[5] + " = " + std::to_string(e.price));
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
v.push_back(columns[2] + " = " + std::to_string(e.char_entity_id));
v.push_back(columns[3] + " = '" + Strings::Escape(e.char_name) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.char_zone_id));
v.push_back(columns[5] + " = " + std::to_string(e.char_zone_instance_id));
v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
v.push_back(columns[7] + " = '" + Strings::Escape(e.welcome_message) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -187,7 +198,7 @@ public:
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.charid
e.id
)
);
@@ -201,12 +212,14 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.buyslot));
v.push_back(std::to_string(e.itemid));
v.push_back("'" + Strings::Escape(e.itemname) + "'");
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.price));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back("'" + Strings::Escape(e.char_name) + "'");
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -217,7 +230,7 @@ public:
);
if (results.Success()) {
e.charid = results.LastInsertedID();
e.id = results.LastInsertedID();
return e;
}
@@ -236,12 +249,14 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.buyslot));
v.push_back(std::to_string(e.itemid));
v.push_back("'" + Strings::Escape(e.itemname) + "'");
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.price));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back("'" + Strings::Escape(e.char_name) + "'");
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -275,12 +290,14 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Buyer e{};
e.charid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.buyslot = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.itemid = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.itemname = row[3] ? row[3] : "";
e.quantity = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.price = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.char_entity_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.char_name = row[3] ? row[3] : "";
e.char_zone_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.char_zone_instance_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.transaction_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10);
e.welcome_message = row[7] ? row[7] : "";
all_entries.push_back(e);
}
@@ -305,12 +322,14 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
Buyer e{};
e.charid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.buyslot = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.itemid = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.itemname = row[3] ? row[3] : "";
e.quantity = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.price = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.char_entity_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.char_name = row[3] ? row[3] : "";
e.char_zone_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.char_zone_instance_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.transaction_date = strtoll(row[6] ? row[6] : "-1", nullptr, 10);
e.welcome_message = row[7] ? row[7] : "";
all_entries.push_back(e);
}
@@ -385,12 +404,14 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.buyslot));
v.push_back(std::to_string(e.itemid));
v.push_back("'" + Strings::Escape(e.itemname) + "'");
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.price));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back("'" + Strings::Escape(e.char_name) + "'");
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -413,12 +434,14 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.buyslot));
v.push_back(std::to_string(e.itemid));
v.push_back("'" + Strings::Escape(e.itemname) + "'");
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.price));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.char_entity_id));
v.push_back("'" + Strings::Escape(e.char_name) + "'");
v.push_back(std::to_string(e.char_zone_id));
v.push_back(std::to_string(e.char_zone_instance_id));
v.push_back("FROM_UNIXTIME(" + (e.transaction_date > 0 ? std::to_string(e.transaction_date) : "null") + ")");
v.push_back("'" + Strings::Escape(e.welcome_message) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -0,0 +1,439 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H
#define EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseBuyerTradeItemsRepository {
public:
struct BuyerTradeItems {
uint64_t id;
uint64_t buyer_buy_lines_id;
int32_t item_id;
int32_t item_qty;
int32_t item_icon;
std::string item_name;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"buyer_buy_lines_id",
"item_id",
"item_qty",
"item_icon",
"item_name",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"buyer_buy_lines_id",
"item_id",
"item_qty",
"item_icon",
"item_name",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("buyer_trade_items");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static BuyerTradeItems NewEntity()
{
BuyerTradeItems e{};
e.id = 0;
e.buyer_buy_lines_id = 0;
e.item_id = 0;
e.item_qty = 0;
e.item_icon = 0;
e.item_name = "0";
return e;
}
static BuyerTradeItems GetBuyerTradeItems(
const std::vector<BuyerTradeItems> &buyer_trade_itemss,
int buyer_trade_items_id
)
{
for (auto &buyer_trade_items : buyer_trade_itemss) {
if (buyer_trade_items.id == buyer_trade_items_id) {
return buyer_trade_items;
}
}
return NewEntity();
}
static BuyerTradeItems FindOne(
Database& db,
int buyer_trade_items_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
buyer_trade_items_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
BuyerTradeItems e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.buyer_buy_lines_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
e.item_id = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.item_qty = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.item_icon = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.item_name = row[5] ? row[5] : "0";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int buyer_trade_items_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
buyer_trade_items_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const BuyerTradeItems &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.buyer_buy_lines_id));
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
v.push_back(columns[3] + " = " + std::to_string(e.item_qty));
v.push_back(columns[4] + " = " + std::to_string(e.item_icon));
v.push_back(columns[5] + " = '" + Strings::Escape(e.item_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static BuyerTradeItems InsertOne(
Database& db,
BuyerTradeItems e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_buy_lines_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<BuyerTradeItems> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_buy_lines_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<BuyerTradeItems> All(Database& db)
{
std::vector<BuyerTradeItems> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BuyerTradeItems e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.buyer_buy_lines_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
e.item_id = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.item_qty = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.item_icon = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.item_name = row[5] ? row[5] : "0";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<BuyerTradeItems> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<BuyerTradeItems> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
BuyerTradeItems e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.buyer_buy_lines_id = row[1] ? strtoull(row[1], nullptr, 10) : 0;
e.item_id = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.item_qty = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.item_icon = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.item_name = row[5] ? row[5] : "0";
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const BuyerTradeItems &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_buy_lines_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<BuyerTradeItems> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.buyer_buy_lines_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_qty));
v.push_back(std::to_string(e.item_icon));
v.push_back("'" + Strings::Escape(e.item_name) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H
@@ -237,7 +237,7 @@ public:
e.y = 0;
e.z = 0;
e.heading = 0;
e.time_of_death = 0;
e.time_of_death = std::time(nullptr);
e.guild_consent_id = 0;
e.is_rezzed = 0;
e.is_buried = 0;
@@ -77,6 +77,7 @@ public:
uint32_t int_;
uint32_t agi;
uint32_t wis;
int32_t extra_haste;
uint32_t zone_change_count;
uint32_t toxicity;
uint32_t hunger_level;
@@ -190,6 +191,7 @@ public:
"`int`",
"agi",
"wis",
"extra_haste",
"zone_change_count",
"toxicity",
"hunger_level",
@@ -299,6 +301,7 @@ public:
"`int`",
"agi",
"wis",
"extra_haste",
"zone_change_count",
"toxicity",
"hunger_level",
@@ -442,6 +445,7 @@ public:
e.int_ = 0;
e.agi = 0;
e.wis = 0;
e.extra_haste = 0;
e.zone_change_count = 0;
e.toxicity = 0;
e.hunger_level = 0;
@@ -581,51 +585,52 @@ public:
e.int_ = row[55] ? static_cast<uint32_t>(strtoul(row[55], nullptr, 10)) : 0;
e.agi = row[56] ? static_cast<uint32_t>(strtoul(row[56], nullptr, 10)) : 0;
e.wis = row[57] ? static_cast<uint32_t>(strtoul(row[57], nullptr, 10)) : 0;
e.zone_change_count = row[58] ? static_cast<uint32_t>(strtoul(row[58], nullptr, 10)) : 0;
e.toxicity = row[59] ? static_cast<uint32_t>(strtoul(row[59], nullptr, 10)) : 0;
e.hunger_level = row[60] ? static_cast<uint32_t>(strtoul(row[60], nullptr, 10)) : 0;
e.thirst_level = row[61] ? static_cast<uint32_t>(strtoul(row[61], nullptr, 10)) : 0;
e.ability_up = row[62] ? static_cast<uint32_t>(strtoul(row[62], nullptr, 10)) : 0;
e.ldon_points_guk = row[63] ? static_cast<uint32_t>(strtoul(row[63], nullptr, 10)) : 0;
e.ldon_points_mir = row[64] ? static_cast<uint32_t>(strtoul(row[64], nullptr, 10)) : 0;
e.ldon_points_mmc = row[65] ? static_cast<uint32_t>(strtoul(row[65], nullptr, 10)) : 0;
e.ldon_points_ruj = row[66] ? static_cast<uint32_t>(strtoul(row[66], nullptr, 10)) : 0;
e.ldon_points_tak = row[67] ? static_cast<uint32_t>(strtoul(row[67], nullptr, 10)) : 0;
e.ldon_points_available = row[68] ? static_cast<uint32_t>(strtoul(row[68], nullptr, 10)) : 0;
e.tribute_time_remaining = row[69] ? static_cast<uint32_t>(strtoul(row[69], nullptr, 10)) : 0;
e.career_tribute_points = row[70] ? static_cast<uint32_t>(strtoul(row[70], nullptr, 10)) : 0;
e.tribute_points = row[71] ? static_cast<uint32_t>(strtoul(row[71], nullptr, 10)) : 0;
e.tribute_active = row[72] ? static_cast<uint32_t>(strtoul(row[72], nullptr, 10)) : 0;
e.pvp_status = row[73] ? static_cast<uint8_t>(strtoul(row[73], nullptr, 10)) : 0;
e.pvp_kills = row[74] ? static_cast<uint32_t>(strtoul(row[74], nullptr, 10)) : 0;
e.pvp_deaths = row[75] ? static_cast<uint32_t>(strtoul(row[75], nullptr, 10)) : 0;
e.pvp_current_points = row[76] ? static_cast<uint32_t>(strtoul(row[76], nullptr, 10)) : 0;
e.pvp_career_points = row[77] ? static_cast<uint32_t>(strtoul(row[77], nullptr, 10)) : 0;
e.pvp_best_kill_streak = row[78] ? static_cast<uint32_t>(strtoul(row[78], nullptr, 10)) : 0;
e.pvp_worst_death_streak = row[79] ? static_cast<uint32_t>(strtoul(row[79], nullptr, 10)) : 0;
e.pvp_current_kill_streak = row[80] ? static_cast<uint32_t>(strtoul(row[80], nullptr, 10)) : 0;
e.pvp2 = row[81] ? static_cast<uint32_t>(strtoul(row[81], nullptr, 10)) : 0;
e.pvp_type = row[82] ? static_cast<uint32_t>(strtoul(row[82], nullptr, 10)) : 0;
e.show_helm = row[83] ? static_cast<uint32_t>(strtoul(row[83], nullptr, 10)) : 0;
e.group_auto_consent = row[84] ? static_cast<uint8_t>(strtoul(row[84], nullptr, 10)) : 0;
e.raid_auto_consent = row[85] ? static_cast<uint8_t>(strtoul(row[85], nullptr, 10)) : 0;
e.guild_auto_consent = row[86] ? static_cast<uint8_t>(strtoul(row[86], nullptr, 10)) : 0;
e.leadership_exp_on = row[87] ? static_cast<uint8_t>(strtoul(row[87], nullptr, 10)) : 0;
e.RestTimer = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 0;
e.air_remaining = row[89] ? static_cast<uint32_t>(strtoul(row[89], nullptr, 10)) : 0;
e.autosplit_enabled = row[90] ? static_cast<uint32_t>(strtoul(row[90], nullptr, 10)) : 0;
e.lfp = row[91] ? static_cast<uint8_t>(strtoul(row[91], nullptr, 10)) : 0;
e.lfg = row[92] ? static_cast<uint8_t>(strtoul(row[92], nullptr, 10)) : 0;
e.mailkey = row[93] ? row[93] : "";
e.xtargets = row[94] ? static_cast<uint8_t>(strtoul(row[94], nullptr, 10)) : 5;
e.firstlogon = row[95] ? static_cast<int8_t>(atoi(row[95])) : 0;
e.e_aa_effects = row[96] ? static_cast<uint32_t>(strtoul(row[96], nullptr, 10)) : 0;
e.e_percent_to_aa = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
e.e_expended_aa_spent = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
e.aa_points_spent_old = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
e.aa_points_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
e.e_last_invsnapshot = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10);
e.extra_haste = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.zone_change_count = row[59] ? static_cast<uint32_t>(strtoul(row[59], nullptr, 10)) : 0;
e.toxicity = row[60] ? static_cast<uint32_t>(strtoul(row[60], nullptr, 10)) : 0;
e.hunger_level = row[61] ? static_cast<uint32_t>(strtoul(row[61], nullptr, 10)) : 0;
e.thirst_level = row[62] ? static_cast<uint32_t>(strtoul(row[62], nullptr, 10)) : 0;
e.ability_up = row[63] ? static_cast<uint32_t>(strtoul(row[63], nullptr, 10)) : 0;
e.ldon_points_guk = row[64] ? static_cast<uint32_t>(strtoul(row[64], nullptr, 10)) : 0;
e.ldon_points_mir = row[65] ? static_cast<uint32_t>(strtoul(row[65], nullptr, 10)) : 0;
e.ldon_points_mmc = row[66] ? static_cast<uint32_t>(strtoul(row[66], nullptr, 10)) : 0;
e.ldon_points_ruj = row[67] ? static_cast<uint32_t>(strtoul(row[67], nullptr, 10)) : 0;
e.ldon_points_tak = row[68] ? static_cast<uint32_t>(strtoul(row[68], nullptr, 10)) : 0;
e.ldon_points_available = row[69] ? static_cast<uint32_t>(strtoul(row[69], nullptr, 10)) : 0;
e.tribute_time_remaining = row[70] ? static_cast<uint32_t>(strtoul(row[70], nullptr, 10)) : 0;
e.career_tribute_points = row[71] ? static_cast<uint32_t>(strtoul(row[71], nullptr, 10)) : 0;
e.tribute_points = row[72] ? static_cast<uint32_t>(strtoul(row[72], nullptr, 10)) : 0;
e.tribute_active = row[73] ? static_cast<uint32_t>(strtoul(row[73], nullptr, 10)) : 0;
e.pvp_status = row[74] ? static_cast<uint8_t>(strtoul(row[74], nullptr, 10)) : 0;
e.pvp_kills = row[75] ? static_cast<uint32_t>(strtoul(row[75], nullptr, 10)) : 0;
e.pvp_deaths = row[76] ? static_cast<uint32_t>(strtoul(row[76], nullptr, 10)) : 0;
e.pvp_current_points = row[77] ? static_cast<uint32_t>(strtoul(row[77], nullptr, 10)) : 0;
e.pvp_career_points = row[78] ? static_cast<uint32_t>(strtoul(row[78], nullptr, 10)) : 0;
e.pvp_best_kill_streak = row[79] ? static_cast<uint32_t>(strtoul(row[79], nullptr, 10)) : 0;
e.pvp_worst_death_streak = row[80] ? static_cast<uint32_t>(strtoul(row[80], nullptr, 10)) : 0;
e.pvp_current_kill_streak = row[81] ? static_cast<uint32_t>(strtoul(row[81], nullptr, 10)) : 0;
e.pvp2 = row[82] ? static_cast<uint32_t>(strtoul(row[82], nullptr, 10)) : 0;
e.pvp_type = row[83] ? static_cast<uint32_t>(strtoul(row[83], nullptr, 10)) : 0;
e.show_helm = row[84] ? static_cast<uint32_t>(strtoul(row[84], nullptr, 10)) : 0;
e.group_auto_consent = row[85] ? static_cast<uint8_t>(strtoul(row[85], nullptr, 10)) : 0;
e.raid_auto_consent = row[86] ? static_cast<uint8_t>(strtoul(row[86], nullptr, 10)) : 0;
e.guild_auto_consent = row[87] ? static_cast<uint8_t>(strtoul(row[87], nullptr, 10)) : 0;
e.leadership_exp_on = row[88] ? static_cast<uint8_t>(strtoul(row[88], nullptr, 10)) : 0;
e.RestTimer = row[89] ? static_cast<uint32_t>(strtoul(row[89], nullptr, 10)) : 0;
e.air_remaining = row[90] ? static_cast<uint32_t>(strtoul(row[90], nullptr, 10)) : 0;
e.autosplit_enabled = row[91] ? static_cast<uint32_t>(strtoul(row[91], nullptr, 10)) : 0;
e.lfp = row[92] ? static_cast<uint8_t>(strtoul(row[92], nullptr, 10)) : 0;
e.lfg = row[93] ? static_cast<uint8_t>(strtoul(row[93], nullptr, 10)) : 0;
e.mailkey = row[94] ? row[94] : "";
e.xtargets = row[95] ? static_cast<uint8_t>(strtoul(row[95], nullptr, 10)) : 5;
e.firstlogon = row[96] ? static_cast<int8_t>(atoi(row[96])) : 0;
e.e_aa_effects = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
e.e_percent_to_aa = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
e.e_expended_aa_spent = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
e.aa_points_spent_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
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);
return e;
}
@@ -716,51 +721,52 @@ public:
v.push_back(columns[55] + " = " + std::to_string(e.int_));
v.push_back(columns[56] + " = " + std::to_string(e.agi));
v.push_back(columns[57] + " = " + std::to_string(e.wis));
v.push_back(columns[58] + " = " + std::to_string(e.zone_change_count));
v.push_back(columns[59] + " = " + std::to_string(e.toxicity));
v.push_back(columns[60] + " = " + std::to_string(e.hunger_level));
v.push_back(columns[61] + " = " + std::to_string(e.thirst_level));
v.push_back(columns[62] + " = " + std::to_string(e.ability_up));
v.push_back(columns[63] + " = " + std::to_string(e.ldon_points_guk));
v.push_back(columns[64] + " = " + std::to_string(e.ldon_points_mir));
v.push_back(columns[65] + " = " + std::to_string(e.ldon_points_mmc));
v.push_back(columns[66] + " = " + std::to_string(e.ldon_points_ruj));
v.push_back(columns[67] + " = " + std::to_string(e.ldon_points_tak));
v.push_back(columns[68] + " = " + std::to_string(e.ldon_points_available));
v.push_back(columns[69] + " = " + std::to_string(e.tribute_time_remaining));
v.push_back(columns[70] + " = " + std::to_string(e.career_tribute_points));
v.push_back(columns[71] + " = " + std::to_string(e.tribute_points));
v.push_back(columns[72] + " = " + std::to_string(e.tribute_active));
v.push_back(columns[73] + " = " + std::to_string(e.pvp_status));
v.push_back(columns[74] + " = " + std::to_string(e.pvp_kills));
v.push_back(columns[75] + " = " + std::to_string(e.pvp_deaths));
v.push_back(columns[76] + " = " + std::to_string(e.pvp_current_points));
v.push_back(columns[77] + " = " + std::to_string(e.pvp_career_points));
v.push_back(columns[78] + " = " + std::to_string(e.pvp_best_kill_streak));
v.push_back(columns[79] + " = " + std::to_string(e.pvp_worst_death_streak));
v.push_back(columns[80] + " = " + std::to_string(e.pvp_current_kill_streak));
v.push_back(columns[81] + " = " + std::to_string(e.pvp2));
v.push_back(columns[82] + " = " + std::to_string(e.pvp_type));
v.push_back(columns[83] + " = " + std::to_string(e.show_helm));
v.push_back(columns[84] + " = " + std::to_string(e.group_auto_consent));
v.push_back(columns[85] + " = " + std::to_string(e.raid_auto_consent));
v.push_back(columns[86] + " = " + std::to_string(e.guild_auto_consent));
v.push_back(columns[87] + " = " + std::to_string(e.leadership_exp_on));
v.push_back(columns[88] + " = " + std::to_string(e.RestTimer));
v.push_back(columns[89] + " = " + std::to_string(e.air_remaining));
v.push_back(columns[90] + " = " + std::to_string(e.autosplit_enabled));
v.push_back(columns[91] + " = " + std::to_string(e.lfp));
v.push_back(columns[92] + " = " + std::to_string(e.lfg));
v.push_back(columns[93] + " = '" + Strings::Escape(e.mailkey) + "'");
v.push_back(columns[94] + " = " + std::to_string(e.xtargets));
v.push_back(columns[95] + " = " + std::to_string(e.firstlogon));
v.push_back(columns[96] + " = " + std::to_string(e.e_aa_effects));
v.push_back(columns[97] + " = " + std::to_string(e.e_percent_to_aa));
v.push_back(columns[98] + " = " + std::to_string(e.e_expended_aa_spent));
v.push_back(columns[99] + " = " + std::to_string(e.aa_points_spent_old));
v.push_back(columns[100] + " = " + std::to_string(e.aa_points_old));
v.push_back(columns[101] + " = " + std::to_string(e.e_last_invsnapshot));
v.push_back(columns[102] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
v.push_back(columns[58] + " = " + std::to_string(e.extra_haste));
v.push_back(columns[59] + " = " + std::to_string(e.zone_change_count));
v.push_back(columns[60] + " = " + std::to_string(e.toxicity));
v.push_back(columns[61] + " = " + std::to_string(e.hunger_level));
v.push_back(columns[62] + " = " + std::to_string(e.thirst_level));
v.push_back(columns[63] + " = " + std::to_string(e.ability_up));
v.push_back(columns[64] + " = " + std::to_string(e.ldon_points_guk));
v.push_back(columns[65] + " = " + std::to_string(e.ldon_points_mir));
v.push_back(columns[66] + " = " + std::to_string(e.ldon_points_mmc));
v.push_back(columns[67] + " = " + std::to_string(e.ldon_points_ruj));
v.push_back(columns[68] + " = " + std::to_string(e.ldon_points_tak));
v.push_back(columns[69] + " = " + std::to_string(e.ldon_points_available));
v.push_back(columns[70] + " = " + std::to_string(e.tribute_time_remaining));
v.push_back(columns[71] + " = " + std::to_string(e.career_tribute_points));
v.push_back(columns[72] + " = " + std::to_string(e.tribute_points));
v.push_back(columns[73] + " = " + std::to_string(e.tribute_active));
v.push_back(columns[74] + " = " + std::to_string(e.pvp_status));
v.push_back(columns[75] + " = " + std::to_string(e.pvp_kills));
v.push_back(columns[76] + " = " + std::to_string(e.pvp_deaths));
v.push_back(columns[77] + " = " + std::to_string(e.pvp_current_points));
v.push_back(columns[78] + " = " + std::to_string(e.pvp_career_points));
v.push_back(columns[79] + " = " + std::to_string(e.pvp_best_kill_streak));
v.push_back(columns[80] + " = " + std::to_string(e.pvp_worst_death_streak));
v.push_back(columns[81] + " = " + std::to_string(e.pvp_current_kill_streak));
v.push_back(columns[82] + " = " + std::to_string(e.pvp2));
v.push_back(columns[83] + " = " + std::to_string(e.pvp_type));
v.push_back(columns[84] + " = " + std::to_string(e.show_helm));
v.push_back(columns[85] + " = " + std::to_string(e.group_auto_consent));
v.push_back(columns[86] + " = " + std::to_string(e.raid_auto_consent));
v.push_back(columns[87] + " = " + std::to_string(e.guild_auto_consent));
v.push_back(columns[88] + " = " + std::to_string(e.leadership_exp_on));
v.push_back(columns[89] + " = " + std::to_string(e.RestTimer));
v.push_back(columns[90] + " = " + std::to_string(e.air_remaining));
v.push_back(columns[91] + " = " + std::to_string(e.autosplit_enabled));
v.push_back(columns[92] + " = " + std::to_string(e.lfp));
v.push_back(columns[93] + " = " + std::to_string(e.lfg));
v.push_back(columns[94] + " = '" + Strings::Escape(e.mailkey) + "'");
v.push_back(columns[95] + " = " + std::to_string(e.xtargets));
v.push_back(columns[96] + " = " + std::to_string(e.firstlogon));
v.push_back(columns[97] + " = " + std::to_string(e.e_aa_effects));
v.push_back(columns[98] + " = " + std::to_string(e.e_percent_to_aa));
v.push_back(columns[99] + " = " + std::to_string(e.e_expended_aa_spent));
v.push_back(columns[100] + " = " + std::to_string(e.aa_points_spent_old));
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") + ")");
auto results = db.QueryDatabase(
fmt::format(
@@ -840,6 +846,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.zone_change_count));
v.push_back(std::to_string(e.toxicity));
v.push_back(std::to_string(e.hunger_level));
@@ -972,6 +979,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.zone_change_count));
v.push_back(std::to_string(e.toxicity));
v.push_back(std::to_string(e.hunger_level));
@@ -1108,51 +1116,52 @@ public:
e.int_ = row[55] ? static_cast<uint32_t>(strtoul(row[55], nullptr, 10)) : 0;
e.agi = row[56] ? static_cast<uint32_t>(strtoul(row[56], nullptr, 10)) : 0;
e.wis = row[57] ? static_cast<uint32_t>(strtoul(row[57], nullptr, 10)) : 0;
e.zone_change_count = row[58] ? static_cast<uint32_t>(strtoul(row[58], nullptr, 10)) : 0;
e.toxicity = row[59] ? static_cast<uint32_t>(strtoul(row[59], nullptr, 10)) : 0;
e.hunger_level = row[60] ? static_cast<uint32_t>(strtoul(row[60], nullptr, 10)) : 0;
e.thirst_level = row[61] ? static_cast<uint32_t>(strtoul(row[61], nullptr, 10)) : 0;
e.ability_up = row[62] ? static_cast<uint32_t>(strtoul(row[62], nullptr, 10)) : 0;
e.ldon_points_guk = row[63] ? static_cast<uint32_t>(strtoul(row[63], nullptr, 10)) : 0;
e.ldon_points_mir = row[64] ? static_cast<uint32_t>(strtoul(row[64], nullptr, 10)) : 0;
e.ldon_points_mmc = row[65] ? static_cast<uint32_t>(strtoul(row[65], nullptr, 10)) : 0;
e.ldon_points_ruj = row[66] ? static_cast<uint32_t>(strtoul(row[66], nullptr, 10)) : 0;
e.ldon_points_tak = row[67] ? static_cast<uint32_t>(strtoul(row[67], nullptr, 10)) : 0;
e.ldon_points_available = row[68] ? static_cast<uint32_t>(strtoul(row[68], nullptr, 10)) : 0;
e.tribute_time_remaining = row[69] ? static_cast<uint32_t>(strtoul(row[69], nullptr, 10)) : 0;
e.career_tribute_points = row[70] ? static_cast<uint32_t>(strtoul(row[70], nullptr, 10)) : 0;
e.tribute_points = row[71] ? static_cast<uint32_t>(strtoul(row[71], nullptr, 10)) : 0;
e.tribute_active = row[72] ? static_cast<uint32_t>(strtoul(row[72], nullptr, 10)) : 0;
e.pvp_status = row[73] ? static_cast<uint8_t>(strtoul(row[73], nullptr, 10)) : 0;
e.pvp_kills = row[74] ? static_cast<uint32_t>(strtoul(row[74], nullptr, 10)) : 0;
e.pvp_deaths = row[75] ? static_cast<uint32_t>(strtoul(row[75], nullptr, 10)) : 0;
e.pvp_current_points = row[76] ? static_cast<uint32_t>(strtoul(row[76], nullptr, 10)) : 0;
e.pvp_career_points = row[77] ? static_cast<uint32_t>(strtoul(row[77], nullptr, 10)) : 0;
e.pvp_best_kill_streak = row[78] ? static_cast<uint32_t>(strtoul(row[78], nullptr, 10)) : 0;
e.pvp_worst_death_streak = row[79] ? static_cast<uint32_t>(strtoul(row[79], nullptr, 10)) : 0;
e.pvp_current_kill_streak = row[80] ? static_cast<uint32_t>(strtoul(row[80], nullptr, 10)) : 0;
e.pvp2 = row[81] ? static_cast<uint32_t>(strtoul(row[81], nullptr, 10)) : 0;
e.pvp_type = row[82] ? static_cast<uint32_t>(strtoul(row[82], nullptr, 10)) : 0;
e.show_helm = row[83] ? static_cast<uint32_t>(strtoul(row[83], nullptr, 10)) : 0;
e.group_auto_consent = row[84] ? static_cast<uint8_t>(strtoul(row[84], nullptr, 10)) : 0;
e.raid_auto_consent = row[85] ? static_cast<uint8_t>(strtoul(row[85], nullptr, 10)) : 0;
e.guild_auto_consent = row[86] ? static_cast<uint8_t>(strtoul(row[86], nullptr, 10)) : 0;
e.leadership_exp_on = row[87] ? static_cast<uint8_t>(strtoul(row[87], nullptr, 10)) : 0;
e.RestTimer = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 0;
e.air_remaining = row[89] ? static_cast<uint32_t>(strtoul(row[89], nullptr, 10)) : 0;
e.autosplit_enabled = row[90] ? static_cast<uint32_t>(strtoul(row[90], nullptr, 10)) : 0;
e.lfp = row[91] ? static_cast<uint8_t>(strtoul(row[91], nullptr, 10)) : 0;
e.lfg = row[92] ? static_cast<uint8_t>(strtoul(row[92], nullptr, 10)) : 0;
e.mailkey = row[93] ? row[93] : "";
e.xtargets = row[94] ? static_cast<uint8_t>(strtoul(row[94], nullptr, 10)) : 5;
e.firstlogon = row[95] ? static_cast<int8_t>(atoi(row[95])) : 0;
e.e_aa_effects = row[96] ? static_cast<uint32_t>(strtoul(row[96], nullptr, 10)) : 0;
e.e_percent_to_aa = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
e.e_expended_aa_spent = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
e.aa_points_spent_old = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
e.aa_points_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
e.e_last_invsnapshot = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10);
e.extra_haste = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.zone_change_count = row[59] ? static_cast<uint32_t>(strtoul(row[59], nullptr, 10)) : 0;
e.toxicity = row[60] ? static_cast<uint32_t>(strtoul(row[60], nullptr, 10)) : 0;
e.hunger_level = row[61] ? static_cast<uint32_t>(strtoul(row[61], nullptr, 10)) : 0;
e.thirst_level = row[62] ? static_cast<uint32_t>(strtoul(row[62], nullptr, 10)) : 0;
e.ability_up = row[63] ? static_cast<uint32_t>(strtoul(row[63], nullptr, 10)) : 0;
e.ldon_points_guk = row[64] ? static_cast<uint32_t>(strtoul(row[64], nullptr, 10)) : 0;
e.ldon_points_mir = row[65] ? static_cast<uint32_t>(strtoul(row[65], nullptr, 10)) : 0;
e.ldon_points_mmc = row[66] ? static_cast<uint32_t>(strtoul(row[66], nullptr, 10)) : 0;
e.ldon_points_ruj = row[67] ? static_cast<uint32_t>(strtoul(row[67], nullptr, 10)) : 0;
e.ldon_points_tak = row[68] ? static_cast<uint32_t>(strtoul(row[68], nullptr, 10)) : 0;
e.ldon_points_available = row[69] ? static_cast<uint32_t>(strtoul(row[69], nullptr, 10)) : 0;
e.tribute_time_remaining = row[70] ? static_cast<uint32_t>(strtoul(row[70], nullptr, 10)) : 0;
e.career_tribute_points = row[71] ? static_cast<uint32_t>(strtoul(row[71], nullptr, 10)) : 0;
e.tribute_points = row[72] ? static_cast<uint32_t>(strtoul(row[72], nullptr, 10)) : 0;
e.tribute_active = row[73] ? static_cast<uint32_t>(strtoul(row[73], nullptr, 10)) : 0;
e.pvp_status = row[74] ? static_cast<uint8_t>(strtoul(row[74], nullptr, 10)) : 0;
e.pvp_kills = row[75] ? static_cast<uint32_t>(strtoul(row[75], nullptr, 10)) : 0;
e.pvp_deaths = row[76] ? static_cast<uint32_t>(strtoul(row[76], nullptr, 10)) : 0;
e.pvp_current_points = row[77] ? static_cast<uint32_t>(strtoul(row[77], nullptr, 10)) : 0;
e.pvp_career_points = row[78] ? static_cast<uint32_t>(strtoul(row[78], nullptr, 10)) : 0;
e.pvp_best_kill_streak = row[79] ? static_cast<uint32_t>(strtoul(row[79], nullptr, 10)) : 0;
e.pvp_worst_death_streak = row[80] ? static_cast<uint32_t>(strtoul(row[80], nullptr, 10)) : 0;
e.pvp_current_kill_streak = row[81] ? static_cast<uint32_t>(strtoul(row[81], nullptr, 10)) : 0;
e.pvp2 = row[82] ? static_cast<uint32_t>(strtoul(row[82], nullptr, 10)) : 0;
e.pvp_type = row[83] ? static_cast<uint32_t>(strtoul(row[83], nullptr, 10)) : 0;
e.show_helm = row[84] ? static_cast<uint32_t>(strtoul(row[84], nullptr, 10)) : 0;
e.group_auto_consent = row[85] ? static_cast<uint8_t>(strtoul(row[85], nullptr, 10)) : 0;
e.raid_auto_consent = row[86] ? static_cast<uint8_t>(strtoul(row[86], nullptr, 10)) : 0;
e.guild_auto_consent = row[87] ? static_cast<uint8_t>(strtoul(row[87], nullptr, 10)) : 0;
e.leadership_exp_on = row[88] ? static_cast<uint8_t>(strtoul(row[88], nullptr, 10)) : 0;
e.RestTimer = row[89] ? static_cast<uint32_t>(strtoul(row[89], nullptr, 10)) : 0;
e.air_remaining = row[90] ? static_cast<uint32_t>(strtoul(row[90], nullptr, 10)) : 0;
e.autosplit_enabled = row[91] ? static_cast<uint32_t>(strtoul(row[91], nullptr, 10)) : 0;
e.lfp = row[92] ? static_cast<uint8_t>(strtoul(row[92], nullptr, 10)) : 0;
e.lfg = row[93] ? static_cast<uint8_t>(strtoul(row[93], nullptr, 10)) : 0;
e.mailkey = row[94] ? row[94] : "";
e.xtargets = row[95] ? static_cast<uint8_t>(strtoul(row[95], nullptr, 10)) : 5;
e.firstlogon = row[96] ? static_cast<int8_t>(atoi(row[96])) : 0;
e.e_aa_effects = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
e.e_percent_to_aa = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
e.e_expended_aa_spent = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
e.aa_points_spent_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
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);
all_entries.push_back(e);
}
@@ -1235,51 +1244,52 @@ public:
e.int_ = row[55] ? static_cast<uint32_t>(strtoul(row[55], nullptr, 10)) : 0;
e.agi = row[56] ? static_cast<uint32_t>(strtoul(row[56], nullptr, 10)) : 0;
e.wis = row[57] ? static_cast<uint32_t>(strtoul(row[57], nullptr, 10)) : 0;
e.zone_change_count = row[58] ? static_cast<uint32_t>(strtoul(row[58], nullptr, 10)) : 0;
e.toxicity = row[59] ? static_cast<uint32_t>(strtoul(row[59], nullptr, 10)) : 0;
e.hunger_level = row[60] ? static_cast<uint32_t>(strtoul(row[60], nullptr, 10)) : 0;
e.thirst_level = row[61] ? static_cast<uint32_t>(strtoul(row[61], nullptr, 10)) : 0;
e.ability_up = row[62] ? static_cast<uint32_t>(strtoul(row[62], nullptr, 10)) : 0;
e.ldon_points_guk = row[63] ? static_cast<uint32_t>(strtoul(row[63], nullptr, 10)) : 0;
e.ldon_points_mir = row[64] ? static_cast<uint32_t>(strtoul(row[64], nullptr, 10)) : 0;
e.ldon_points_mmc = row[65] ? static_cast<uint32_t>(strtoul(row[65], nullptr, 10)) : 0;
e.ldon_points_ruj = row[66] ? static_cast<uint32_t>(strtoul(row[66], nullptr, 10)) : 0;
e.ldon_points_tak = row[67] ? static_cast<uint32_t>(strtoul(row[67], nullptr, 10)) : 0;
e.ldon_points_available = row[68] ? static_cast<uint32_t>(strtoul(row[68], nullptr, 10)) : 0;
e.tribute_time_remaining = row[69] ? static_cast<uint32_t>(strtoul(row[69], nullptr, 10)) : 0;
e.career_tribute_points = row[70] ? static_cast<uint32_t>(strtoul(row[70], nullptr, 10)) : 0;
e.tribute_points = row[71] ? static_cast<uint32_t>(strtoul(row[71], nullptr, 10)) : 0;
e.tribute_active = row[72] ? static_cast<uint32_t>(strtoul(row[72], nullptr, 10)) : 0;
e.pvp_status = row[73] ? static_cast<uint8_t>(strtoul(row[73], nullptr, 10)) : 0;
e.pvp_kills = row[74] ? static_cast<uint32_t>(strtoul(row[74], nullptr, 10)) : 0;
e.pvp_deaths = row[75] ? static_cast<uint32_t>(strtoul(row[75], nullptr, 10)) : 0;
e.pvp_current_points = row[76] ? static_cast<uint32_t>(strtoul(row[76], nullptr, 10)) : 0;
e.pvp_career_points = row[77] ? static_cast<uint32_t>(strtoul(row[77], nullptr, 10)) : 0;
e.pvp_best_kill_streak = row[78] ? static_cast<uint32_t>(strtoul(row[78], nullptr, 10)) : 0;
e.pvp_worst_death_streak = row[79] ? static_cast<uint32_t>(strtoul(row[79], nullptr, 10)) : 0;
e.pvp_current_kill_streak = row[80] ? static_cast<uint32_t>(strtoul(row[80], nullptr, 10)) : 0;
e.pvp2 = row[81] ? static_cast<uint32_t>(strtoul(row[81], nullptr, 10)) : 0;
e.pvp_type = row[82] ? static_cast<uint32_t>(strtoul(row[82], nullptr, 10)) : 0;
e.show_helm = row[83] ? static_cast<uint32_t>(strtoul(row[83], nullptr, 10)) : 0;
e.group_auto_consent = row[84] ? static_cast<uint8_t>(strtoul(row[84], nullptr, 10)) : 0;
e.raid_auto_consent = row[85] ? static_cast<uint8_t>(strtoul(row[85], nullptr, 10)) : 0;
e.guild_auto_consent = row[86] ? static_cast<uint8_t>(strtoul(row[86], nullptr, 10)) : 0;
e.leadership_exp_on = row[87] ? static_cast<uint8_t>(strtoul(row[87], nullptr, 10)) : 0;
e.RestTimer = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 0;
e.air_remaining = row[89] ? static_cast<uint32_t>(strtoul(row[89], nullptr, 10)) : 0;
e.autosplit_enabled = row[90] ? static_cast<uint32_t>(strtoul(row[90], nullptr, 10)) : 0;
e.lfp = row[91] ? static_cast<uint8_t>(strtoul(row[91], nullptr, 10)) : 0;
e.lfg = row[92] ? static_cast<uint8_t>(strtoul(row[92], nullptr, 10)) : 0;
e.mailkey = row[93] ? row[93] : "";
e.xtargets = row[94] ? static_cast<uint8_t>(strtoul(row[94], nullptr, 10)) : 5;
e.firstlogon = row[95] ? static_cast<int8_t>(atoi(row[95])) : 0;
e.e_aa_effects = row[96] ? static_cast<uint32_t>(strtoul(row[96], nullptr, 10)) : 0;
e.e_percent_to_aa = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
e.e_expended_aa_spent = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
e.aa_points_spent_old = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
e.aa_points_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
e.e_last_invsnapshot = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
e.deleted_at = strtoll(row[102] ? row[102] : "-1", nullptr, 10);
e.extra_haste = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.zone_change_count = row[59] ? static_cast<uint32_t>(strtoul(row[59], nullptr, 10)) : 0;
e.toxicity = row[60] ? static_cast<uint32_t>(strtoul(row[60], nullptr, 10)) : 0;
e.hunger_level = row[61] ? static_cast<uint32_t>(strtoul(row[61], nullptr, 10)) : 0;
e.thirst_level = row[62] ? static_cast<uint32_t>(strtoul(row[62], nullptr, 10)) : 0;
e.ability_up = row[63] ? static_cast<uint32_t>(strtoul(row[63], nullptr, 10)) : 0;
e.ldon_points_guk = row[64] ? static_cast<uint32_t>(strtoul(row[64], nullptr, 10)) : 0;
e.ldon_points_mir = row[65] ? static_cast<uint32_t>(strtoul(row[65], nullptr, 10)) : 0;
e.ldon_points_mmc = row[66] ? static_cast<uint32_t>(strtoul(row[66], nullptr, 10)) : 0;
e.ldon_points_ruj = row[67] ? static_cast<uint32_t>(strtoul(row[67], nullptr, 10)) : 0;
e.ldon_points_tak = row[68] ? static_cast<uint32_t>(strtoul(row[68], nullptr, 10)) : 0;
e.ldon_points_available = row[69] ? static_cast<uint32_t>(strtoul(row[69], nullptr, 10)) : 0;
e.tribute_time_remaining = row[70] ? static_cast<uint32_t>(strtoul(row[70], nullptr, 10)) : 0;
e.career_tribute_points = row[71] ? static_cast<uint32_t>(strtoul(row[71], nullptr, 10)) : 0;
e.tribute_points = row[72] ? static_cast<uint32_t>(strtoul(row[72], nullptr, 10)) : 0;
e.tribute_active = row[73] ? static_cast<uint32_t>(strtoul(row[73], nullptr, 10)) : 0;
e.pvp_status = row[74] ? static_cast<uint8_t>(strtoul(row[74], nullptr, 10)) : 0;
e.pvp_kills = row[75] ? static_cast<uint32_t>(strtoul(row[75], nullptr, 10)) : 0;
e.pvp_deaths = row[76] ? static_cast<uint32_t>(strtoul(row[76], nullptr, 10)) : 0;
e.pvp_current_points = row[77] ? static_cast<uint32_t>(strtoul(row[77], nullptr, 10)) : 0;
e.pvp_career_points = row[78] ? static_cast<uint32_t>(strtoul(row[78], nullptr, 10)) : 0;
e.pvp_best_kill_streak = row[79] ? static_cast<uint32_t>(strtoul(row[79], nullptr, 10)) : 0;
e.pvp_worst_death_streak = row[80] ? static_cast<uint32_t>(strtoul(row[80], nullptr, 10)) : 0;
e.pvp_current_kill_streak = row[81] ? static_cast<uint32_t>(strtoul(row[81], nullptr, 10)) : 0;
e.pvp2 = row[82] ? static_cast<uint32_t>(strtoul(row[82], nullptr, 10)) : 0;
e.pvp_type = row[83] ? static_cast<uint32_t>(strtoul(row[83], nullptr, 10)) : 0;
e.show_helm = row[84] ? static_cast<uint32_t>(strtoul(row[84], nullptr, 10)) : 0;
e.group_auto_consent = row[85] ? static_cast<uint8_t>(strtoul(row[85], nullptr, 10)) : 0;
e.raid_auto_consent = row[86] ? static_cast<uint8_t>(strtoul(row[86], nullptr, 10)) : 0;
e.guild_auto_consent = row[87] ? static_cast<uint8_t>(strtoul(row[87], nullptr, 10)) : 0;
e.leadership_exp_on = row[88] ? static_cast<uint8_t>(strtoul(row[88], nullptr, 10)) : 0;
e.RestTimer = row[89] ? static_cast<uint32_t>(strtoul(row[89], nullptr, 10)) : 0;
e.air_remaining = row[90] ? static_cast<uint32_t>(strtoul(row[90], nullptr, 10)) : 0;
e.autosplit_enabled = row[91] ? static_cast<uint32_t>(strtoul(row[91], nullptr, 10)) : 0;
e.lfp = row[92] ? static_cast<uint8_t>(strtoul(row[92], nullptr, 10)) : 0;
e.lfg = row[93] ? static_cast<uint8_t>(strtoul(row[93], nullptr, 10)) : 0;
e.mailkey = row[94] ? row[94] : "";
e.xtargets = row[95] ? static_cast<uint8_t>(strtoul(row[95], nullptr, 10)) : 5;
e.firstlogon = row[96] ? static_cast<int8_t>(atoi(row[96])) : 0;
e.e_aa_effects = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 0;
e.e_percent_to_aa = row[98] ? static_cast<uint32_t>(strtoul(row[98], nullptr, 10)) : 0;
e.e_expended_aa_spent = row[99] ? static_cast<uint32_t>(strtoul(row[99], nullptr, 10)) : 0;
e.aa_points_spent_old = row[100] ? static_cast<uint32_t>(strtoul(row[100], nullptr, 10)) : 0;
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);
all_entries.push_back(e);
}
@@ -1412,6 +1422,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.zone_change_count));
v.push_back(std::to_string(e.toxicity));
v.push_back(std::to_string(e.hunger_level));
@@ -1537,6 +1548,7 @@ public:
v.push_back(std::to_string(e.int_));
v.push_back(std::to_string(e.agi));
v.push_back(std::to_string(e.wis));
v.push_back(std::to_string(e.extra_haste));
v.push_back(std::to_string(e.zone_change_count));
v.push_back(std::to_string(e.toxicity));
v.push_back(std::to_string(e.hunger_level));
@@ -0,0 +1,499 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H
#define EQEMU_BASE_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseCharacterParcelsContainersRepository {
public:
struct CharacterParcelsContainers {
uint32_t id;
uint32_t parcels_id;
uint32_t slot_id;
uint32_t item_id;
uint32_t aug_slot_1;
uint32_t aug_slot_2;
uint32_t aug_slot_3;
uint32_t aug_slot_4;
uint32_t aug_slot_5;
uint32_t aug_slot_6;
uint32_t quantity;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"parcels_id",
"slot_id",
"item_id",
"aug_slot_1",
"aug_slot_2",
"aug_slot_3",
"aug_slot_4",
"aug_slot_5",
"aug_slot_6",
"quantity",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"parcels_id",
"slot_id",
"item_id",
"aug_slot_1",
"aug_slot_2",
"aug_slot_3",
"aug_slot_4",
"aug_slot_5",
"aug_slot_6",
"quantity",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("character_parcels_containers");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static CharacterParcelsContainers NewEntity()
{
CharacterParcelsContainers e{};
e.id = 0;
e.parcels_id = 0;
e.slot_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.quantity = 0;
return e;
}
static CharacterParcelsContainers GetCharacterParcelsContainers(
const std::vector<CharacterParcelsContainers> &character_parcels_containerss,
int character_parcels_containers_id
)
{
for (auto &character_parcels_containers : character_parcels_containerss) {
if (character_parcels_containers.id == character_parcels_containers_id) {
return character_parcels_containers;
}
}
return NewEntity();
}
static CharacterParcelsContainers FindOne(
Database& db,
int character_parcels_containers_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
character_parcels_containers_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
CharacterParcelsContainers e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int character_parcels_containers_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
character_parcels_containers_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const CharacterParcelsContainers &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.parcels_id));
v.push_back(columns[2] + " = " + std::to_string(e.slot_id));
v.push_back(columns[3] + " = " + std::to_string(e.item_id));
v.push_back(columns[4] + " = " + std::to_string(e.aug_slot_1));
v.push_back(columns[5] + " = " + std::to_string(e.aug_slot_2));
v.push_back(columns[6] + " = " + std::to_string(e.aug_slot_3));
v.push_back(columns[7] + " = " + std::to_string(e.aug_slot_4));
v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_5));
v.push_back(columns[9] + " = " + std::to_string(e.aug_slot_6));
v.push_back(columns[10] + " = " + std::to_string(e.quantity));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static CharacterParcelsContainers InsertOne(
Database& db,
CharacterParcelsContainers e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.parcels_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<CharacterParcelsContainers> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.parcels_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<CharacterParcelsContainers> All(Database& db)
{
std::vector<CharacterParcelsContainers> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcelsContainers e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<CharacterParcelsContainers> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<CharacterParcelsContainers> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcelsContainers e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const CharacterParcelsContainers &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.parcels_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<CharacterParcelsContainers> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.parcels_id));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H
@@ -0,0 +1,535 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_CHARACTER_PARCELS_REPOSITORY_H
#define EQEMU_BASE_CHARACTER_PARCELS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseCharacterParcelsRepository {
public:
struct CharacterParcels {
uint32_t id;
uint32_t char_id;
uint32_t item_id;
uint32_t aug_slot_1;
uint32_t aug_slot_2;
uint32_t aug_slot_3;
uint32_t aug_slot_4;
uint32_t aug_slot_5;
uint32_t aug_slot_6;
uint32_t slot_id;
uint32_t quantity;
std::string from_name;
std::string note;
time_t sent_date;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"char_id",
"item_id",
"aug_slot_1",
"aug_slot_2",
"aug_slot_3",
"aug_slot_4",
"aug_slot_5",
"aug_slot_6",
"slot_id",
"quantity",
"from_name",
"note",
"sent_date",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"char_id",
"item_id",
"aug_slot_1",
"aug_slot_2",
"aug_slot_3",
"aug_slot_4",
"aug_slot_5",
"aug_slot_6",
"slot_id",
"quantity",
"from_name",
"note",
"UNIX_TIMESTAMP(sent_date)",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("character_parcels");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static CharacterParcels NewEntity()
{
CharacterParcels e{};
e.id = 0;
e.char_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.slot_id = 0;
e.quantity = 0;
e.from_name = "";
e.note = "";
e.sent_date = 0;
return e;
}
static CharacterParcels GetCharacterParcels(
const std::vector<CharacterParcels> &character_parcelss,
int character_parcels_id
)
{
for (auto &character_parcels : character_parcelss) {
if (character_parcels.id == character_parcels_id) {
return character_parcels;
}
}
return NewEntity();
}
static CharacterParcels FindOne(
Database& db,
int character_parcels_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
character_parcels_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
CharacterParcels e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.from_name = row[11] ? row[11] : "";
e.note = row[12] ? row[12] : "";
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int character_parcels_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
character_parcels_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const CharacterParcels &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
v.push_back(columns[3] + " = " + std::to_string(e.aug_slot_1));
v.push_back(columns[4] + " = " + std::to_string(e.aug_slot_2));
v.push_back(columns[5] + " = " + std::to_string(e.aug_slot_3));
v.push_back(columns[6] + " = " + std::to_string(e.aug_slot_4));
v.push_back(columns[7] + " = " + std::to_string(e.aug_slot_5));
v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_6));
v.push_back(columns[9] + " = " + std::to_string(e.slot_id));
v.push_back(columns[10] + " = " + std::to_string(e.quantity));
v.push_back(columns[11] + " = '" + Strings::Escape(e.from_name) + "'");
v.push_back(columns[12] + " = '" + Strings::Escape(e.note) + "'");
v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static CharacterParcels InsertOne(
Database& db,
CharacterParcels e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<CharacterParcels> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<CharacterParcels> All(Database& db)
{
std::vector<CharacterParcels> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcels e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.from_name = row[11] ? row[11] : "";
e.note = row[12] ? row[12] : "";
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<CharacterParcels> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<CharacterParcels> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcels e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.from_name = row[11] ? row[11] : "";
e.note = row[12] ? row[12] : "";
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const CharacterParcels &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<CharacterParcels> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_CHARACTER_PARCELS_REPOSITORY_H
@@ -50,6 +50,7 @@ public:
float buffer;
uint32_t client_version_mask;
int16_t is_ldon_door;
int16_t close_timer_ms;
int32_t dz_switch_id;
int8_t min_expansion;
int8_t max_expansion;
@@ -96,6 +97,7 @@ public:
"buffer",
"client_version_mask",
"is_ldon_door",
"close_timer_ms",
"dz_switch_id",
"min_expansion",
"max_expansion",
@@ -138,6 +140,7 @@ public:
"buffer",
"client_version_mask",
"is_ldon_door",
"close_timer_ms",
"dz_switch_id",
"min_expansion",
"max_expansion",
@@ -214,6 +217,7 @@ public:
e.buffer = 0;
e.client_version_mask = 4294967295;
e.is_ldon_door = 0;
e.close_timer_ms = 5000;
e.dz_switch_id = 0;
e.min_expansion = -1;
e.max_expansion = -1;
@@ -286,11 +290,12 @@ public:
e.buffer = row[28] ? strtof(row[28], nullptr) : 0;
e.client_version_mask = row[29] ? static_cast<uint32_t>(strtoul(row[29], nullptr, 10)) : 4294967295;
e.is_ldon_door = row[30] ? static_cast<int16_t>(atoi(row[30])) : 0;
e.dz_switch_id = row[31] ? static_cast<int32_t>(atoi(row[31])) : 0;
e.min_expansion = row[32] ? static_cast<int8_t>(atoi(row[32])) : -1;
e.max_expansion = row[33] ? static_cast<int8_t>(atoi(row[33])) : -1;
e.content_flags = row[34] ? row[34] : "";
e.content_flags_disabled = row[35] ? row[35] : "";
e.close_timer_ms = row[31] ? static_cast<int16_t>(atoi(row[31])) : 5000;
e.dz_switch_id = row[32] ? static_cast<int32_t>(atoi(row[32])) : 0;
e.min_expansion = row[33] ? static_cast<int8_t>(atoi(row[33])) : -1;
e.max_expansion = row[34] ? static_cast<int8_t>(atoi(row[34])) : -1;
e.content_flags = row[35] ? row[35] : "";
e.content_flags_disabled = row[36] ? row[36] : "";
return e;
}
@@ -354,11 +359,12 @@ public:
v.push_back(columns[28] + " = " + std::to_string(e.buffer));
v.push_back(columns[29] + " = " + std::to_string(e.client_version_mask));
v.push_back(columns[30] + " = " + std::to_string(e.is_ldon_door));
v.push_back(columns[31] + " = " + std::to_string(e.dz_switch_id));
v.push_back(columns[32] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[33] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[34] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[35] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[31] + " = " + std::to_string(e.close_timer_ms));
v.push_back(columns[32] + " = " + std::to_string(e.dz_switch_id));
v.push_back(columns[33] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[34] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[35] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[36] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -411,6 +417,7 @@ public:
v.push_back(std::to_string(e.buffer));
v.push_back(std::to_string(e.client_version_mask));
v.push_back(std::to_string(e.is_ldon_door));
v.push_back(std::to_string(e.close_timer_ms));
v.push_back(std::to_string(e.dz_switch_id));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
@@ -476,6 +483,7 @@ public:
v.push_back(std::to_string(e.buffer));
v.push_back(std::to_string(e.client_version_mask));
v.push_back(std::to_string(e.is_ldon_door));
v.push_back(std::to_string(e.close_timer_ms));
v.push_back(std::to_string(e.dz_switch_id));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
@@ -545,11 +553,12 @@ public:
e.buffer = row[28] ? strtof(row[28], nullptr) : 0;
e.client_version_mask = row[29] ? static_cast<uint32_t>(strtoul(row[29], nullptr, 10)) : 4294967295;
e.is_ldon_door = row[30] ? static_cast<int16_t>(atoi(row[30])) : 0;
e.dz_switch_id = row[31] ? static_cast<int32_t>(atoi(row[31])) : 0;
e.min_expansion = row[32] ? static_cast<int8_t>(atoi(row[32])) : -1;
e.max_expansion = row[33] ? static_cast<int8_t>(atoi(row[33])) : -1;
e.content_flags = row[34] ? row[34] : "";
e.content_flags_disabled = row[35] ? row[35] : "";
e.close_timer_ms = row[31] ? static_cast<int16_t>(atoi(row[31])) : 5000;
e.dz_switch_id = row[32] ? static_cast<int32_t>(atoi(row[32])) : 0;
e.min_expansion = row[33] ? static_cast<int8_t>(atoi(row[33])) : -1;
e.max_expansion = row[34] ? static_cast<int8_t>(atoi(row[34])) : -1;
e.content_flags = row[35] ? row[35] : "";
e.content_flags_disabled = row[36] ? row[36] : "";
all_entries.push_back(e);
}
@@ -605,11 +614,12 @@ public:
e.buffer = row[28] ? strtof(row[28], nullptr) : 0;
e.client_version_mask = row[29] ? static_cast<uint32_t>(strtoul(row[29], nullptr, 10)) : 4294967295;
e.is_ldon_door = row[30] ? static_cast<int16_t>(atoi(row[30])) : 0;
e.dz_switch_id = row[31] ? static_cast<int32_t>(atoi(row[31])) : 0;
e.min_expansion = row[32] ? static_cast<int8_t>(atoi(row[32])) : -1;
e.max_expansion = row[33] ? static_cast<int8_t>(atoi(row[33])) : -1;
e.content_flags = row[34] ? row[34] : "";
e.content_flags_disabled = row[35] ? row[35] : "";
e.close_timer_ms = row[31] ? static_cast<int16_t>(atoi(row[31])) : 5000;
e.dz_switch_id = row[32] ? static_cast<int32_t>(atoi(row[32])) : 0;
e.min_expansion = row[33] ? static_cast<int8_t>(atoi(row[33])) : -1;
e.max_expansion = row[34] ? static_cast<int8_t>(atoi(row[34])) : -1;
e.content_flags = row[35] ? row[35] : "";
e.content_flags_disabled = row[36] ? row[36] : "";
all_entries.push_back(e);
}
@@ -715,6 +725,7 @@ public:
v.push_back(std::to_string(e.buffer));
v.push_back(std::to_string(e.client_version_mask));
v.push_back(std::to_string(e.is_ldon_door));
v.push_back(std::to_string(e.close_timer_ms));
v.push_back(std::to_string(e.dz_switch_id));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
@@ -773,6 +784,7 @@ public:
v.push_back(std::to_string(e.buffer));
v.push_back(std::to_string(e.client_version_mask));
v.push_back(std::to_string(e.is_ldon_door));
v.push_back(std::to_string(e.close_timer_ms));
v.push_back(std::to_string(e.dz_switch_id));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
@@ -19,34 +19,37 @@
class BaseGroupIdRepository {
public:
struct GroupId {
int32_t groupid;
int32_t charid;
uint32_t group_id;
std::string name;
int8_t ismerc;
uint32_t character_id;
uint32_t bot_id;
uint32_t merc_id;
};
static std::string PrimaryKey()
{
return std::string("groupid");
return std::string("group_id");
}
static std::vector<std::string> Columns()
{
return {
"groupid",
"charid",
"group_id",
"name",
"ismerc",
"character_id",
"bot_id",
"merc_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"groupid",
"charid",
"group_id",
"name",
"ismerc",
"character_id",
"bot_id",
"merc_id",
};
}
@@ -87,10 +90,11 @@ public:
{
GroupId e{};
e.groupid = 0;
e.charid = 0;
e.name = "";
e.ismerc = 0;
e.group_id = 0;
e.name = "";
e.character_id = 0;
e.bot_id = 0;
e.merc_id = 0;
return e;
}
@@ -101,7 +105,7 @@ public:
)
{
for (auto &group_id : group_ids) {
if (group_id.groupid == group_id_id) {
if (group_id.group_id == group_id_id) {
return group_id;
}
}
@@ -127,10 +131,11 @@ public:
if (results.RowCount() == 1) {
GroupId e{};
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.name = row[2] ? row[2] : "";
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.name = row[1] ? row[1] : "";
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
return e;
}
@@ -164,10 +169,11 @@ public:
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.groupid));
v.push_back(columns[1] + " = " + std::to_string(e.charid));
v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[3] + " = " + std::to_string(e.ismerc));
v.push_back(columns[0] + " = " + std::to_string(e.group_id));
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[2] + " = " + std::to_string(e.character_id));
v.push_back(columns[3] + " = " + std::to_string(e.bot_id));
v.push_back(columns[4] + " = " + std::to_string(e.merc_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -175,7 +181,7 @@ public:
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.groupid
e.group_id
)
);
@@ -189,10 +195,11 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -203,7 +210,7 @@ public:
);
if (results.Success()) {
e.groupid = results.LastInsertedID();
e.group_id = results.LastInsertedID();
return e;
}
@@ -222,10 +229,11 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -259,10 +267,11 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
GroupId e{};
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.name = row[2] ? row[2] : "";
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.name = row[1] ? row[1] : "";
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -287,10 +296,11 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
GroupId e{};
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.name = row[2] ? row[2] : "";
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.name = row[1] ? row[1] : "";
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -365,10 +375,11 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -391,10 +402,11 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -105,7 +105,7 @@ public:
e.gid = 0;
e.leadername = "";
e.marknpc = "";
e.leadershipaa = 0;
e.leadershipaa = "";
e.maintank = "";
e.assist = "";
e.puller = "";
@@ -150,7 +150,7 @@ public:
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.leadername = row[1] ? row[1] : "";
e.marknpc = row[2] ? row[2] : "";
e.leadershipaa = row[3] ? row[3] : 0;
e.leadershipaa = row[3] ? row[3] : "";
e.maintank = row[4] ? row[4] : "";
e.assist = row[5] ? row[5] : "";
e.puller = row[6] ? row[6] : "";
@@ -192,7 +192,7 @@ public:
v.push_back(columns[0] + " = " + std::to_string(e.gid));
v.push_back(columns[1] + " = '" + Strings::Escape(e.leadername) + "'");
v.push_back(columns[2] + " = '" + Strings::Escape(e.marknpc) + "'");
v.push_back(columns[3] + " = '" + Strings::Escape(e.leadershipaa) + "'");
v.push_back(columns[3] + " = '" + e.leadershipaa + "'");
v.push_back(columns[4] + " = '" + Strings::Escape(e.maintank) + "'");
v.push_back(columns[5] + " = '" + Strings::Escape(e.assist) + "'");
v.push_back(columns[6] + " = '" + Strings::Escape(e.puller) + "'");
@@ -222,7 +222,7 @@ public:
v.push_back(std::to_string(e.gid));
v.push_back("'" + Strings::Escape(e.leadername) + "'");
v.push_back("'" + Strings::Escape(e.marknpc) + "'");
v.push_back("'" + Strings::Escape(e.leadershipaa) + "'");
v.push_back("'" + e.leadershipaa + "'");
v.push_back("'" + Strings::Escape(e.maintank) + "'");
v.push_back("'" + Strings::Escape(e.assist) + "'");
v.push_back("'" + Strings::Escape(e.puller) + "'");
@@ -260,7 +260,7 @@ public:
v.push_back(std::to_string(e.gid));
v.push_back("'" + Strings::Escape(e.leadername) + "'");
v.push_back("'" + Strings::Escape(e.marknpc) + "'");
v.push_back("'" + Strings::Escape(e.leadershipaa) + "'");
v.push_back("'" + e.leadershipaa + "'");
v.push_back("'" + Strings::Escape(e.maintank) + "'");
v.push_back("'" + Strings::Escape(e.assist) + "'");
v.push_back("'" + Strings::Escape(e.puller) + "'");
@@ -302,7 +302,7 @@ public:
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.leadername = row[1] ? row[1] : "";
e.marknpc = row[2] ? row[2] : "";
e.leadershipaa = row[3] ? row[3] : 0;
e.leadershipaa = row[3] ? row[3] : "";
e.maintank = row[4] ? row[4] : "";
e.assist = row[5] ? row[5] : "";
e.puller = row[6] ? row[6] : "";
@@ -335,7 +335,7 @@ public:
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.leadername = row[1] ? row[1] : "";
e.marknpc = row[2] ? row[2] : "";
e.leadershipaa = row[3] ? row[3] : 0;
e.leadershipaa = row[3] ? row[3] : "";
e.maintank = row[4] ? row[4] : "";
e.assist = row[5] ? row[5] : "";
e.puller = row[6] ? row[6] : "";
@@ -418,7 +418,7 @@ public:
v.push_back(std::to_string(e.gid));
v.push_back("'" + Strings::Escape(e.leadername) + "'");
v.push_back("'" + Strings::Escape(e.marknpc) + "'");
v.push_back("'" + Strings::Escape(e.leadershipaa) + "'");
v.push_back("'" + e.leadershipaa + "'");
v.push_back("'" + Strings::Escape(e.maintank) + "'");
v.push_back("'" + Strings::Escape(e.assist) + "'");
v.push_back("'" + Strings::Escape(e.puller) + "'");
@@ -449,7 +449,7 @@ public:
v.push_back(std::to_string(e.gid));
v.push_back("'" + Strings::Escape(e.leadername) + "'");
v.push_back("'" + Strings::Escape(e.marknpc) + "'");
v.push_back("'" + Strings::Escape(e.leadershipaa) + "'");
v.push_back("'" + e.leadershipaa + "'");
v.push_back("'" + Strings::Escape(e.maintank) + "'");
v.push_back("'" + Strings::Escape(e.assist) + "'");
v.push_back("'" + Strings::Escape(e.puller) + "'");
@@ -35,6 +35,7 @@ public:
uint32_t ornamenticon;
uint32_t ornamentidfile;
int32_t ornament_hero_model;
uint64_t guid;
};
static std::string PrimaryKey()
@@ -61,6 +62,7 @@ public:
"ornamenticon",
"ornamentidfile",
"ornament_hero_model",
"guid",
};
}
@@ -83,6 +85,7 @@ public:
"ornamenticon",
"ornamentidfile",
"ornament_hero_model",
"guid",
};
}
@@ -139,6 +142,7 @@ public:
e.ornamenticon = 0;
e.ornamentidfile = 0;
e.ornament_hero_model = 0;
e.guid = 0;
return e;
}
@@ -191,6 +195,7 @@ public:
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
return e;
}
@@ -240,6 +245,7 @@ public:
v.push_back(columns[13] + " = " + std::to_string(e.ornamenticon));
v.push_back(columns[14] + " = " + std::to_string(e.ornamentidfile));
v.push_back(columns[15] + " = " + std::to_string(e.ornament_hero_model));
v.push_back(columns[16] + " = " + std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
@@ -277,6 +283,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
@@ -322,6 +329,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -371,6 +379,7 @@ public:
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
all_entries.push_back(e);
}
@@ -411,6 +420,7 @@ public:
e.ornamenticon = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.ornamentidfile = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornament_hero_model = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.guid = row[16] ? strtoull(row[16], nullptr, 10) : 0;
all_entries.push_back(e);
}
@@ -501,6 +511,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
@@ -539,6 +550,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -36,6 +36,7 @@ public:
uint32_t ornamenticon;
uint32_t ornamentidfile;
int32_t ornament_hero_model;
uint64_t guid;
};
static std::string PrimaryKey()
@@ -63,6 +64,7 @@ public:
"ornamenticon",
"ornamentidfile",
"ornament_hero_model",
"guid",
};
}
@@ -86,6 +88,7 @@ public:
"ornamenticon",
"ornamentidfile",
"ornament_hero_model",
"guid",
};
}
@@ -143,6 +146,7 @@ public:
e.ornamenticon = 0;
e.ornamentidfile = 0;
e.ornament_hero_model = 0;
e.guid = 0;
return e;
}
@@ -196,6 +200,7 @@ public:
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
return e;
}
@@ -246,6 +251,7 @@ public:
v.push_back(columns[14] + " = " + std::to_string(e.ornamenticon));
v.push_back(columns[15] + " = " + std::to_string(e.ornamentidfile));
v.push_back(columns[16] + " = " + std::to_string(e.ornament_hero_model));
v.push_back(columns[17] + " = " + std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
@@ -284,6 +290,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
@@ -330,6 +337,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -380,6 +388,7 @@ public:
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
all_entries.push_back(e);
}
@@ -421,6 +430,7 @@ public:
e.ornamenticon = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.ornamentidfile = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
e.ornament_hero_model = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
e.guid = row[17] ? strtoull(row[17], nullptr, 10) : 0;
all_entries.push_back(e);
}
@@ -512,6 +522,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
auto results = db.QueryDatabase(
fmt::format(
@@ -551,6 +562,7 @@ public:
v.push_back(std::to_string(e.ornamenticon));
v.push_back(std::to_string(e.ornamentidfile));
v.push_back(std::to_string(e.ornament_hero_model));
v.push_back(std::to_string(e.guid));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -19,17 +19,21 @@
class BaseLootdropEntriesRepository {
public:
struct LootdropEntries {
uint32_t lootdrop_id;
int32_t item_id;
uint16_t item_charges;
uint8_t equip_item;
float chance;
float disabled_chance;
uint16_t trivial_min_level;
uint16_t trivial_max_level;
uint8_t multiplier;
uint16_t npc_min_level;
uint16_t npc_max_level;
uint32_t lootdrop_id;
int32_t item_id;
uint16_t item_charges;
uint8_t equip_item;
float chance;
float disabled_chance;
uint16_t trivial_min_level;
uint16_t trivial_max_level;
uint8_t multiplier;
uint16_t npc_min_level;
uint16_t npc_max_level;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
std::string content_flags_disabled;
};
static std::string PrimaryKey()
@@ -51,6 +55,10 @@ public:
"multiplier",
"npc_min_level",
"npc_max_level",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
@@ -68,6 +76,10 @@ public:
"multiplier",
"npc_min_level",
"npc_max_level",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
@@ -108,17 +120,21 @@ public:
{
LootdropEntries e{};
e.lootdrop_id = 0;
e.item_id = 0;
e.item_charges = 1;
e.equip_item = 0;
e.chance = 1;
e.disabled_chance = 0;
e.trivial_min_level = 0;
e.trivial_max_level = 0;
e.multiplier = 1;
e.npc_min_level = 0;
e.npc_max_level = 0;
e.lootdrop_id = 0;
e.item_id = 0;
e.item_charges = 1;
e.equip_item = 0;
e.chance = 1;
e.disabled_chance = 0;
e.trivial_min_level = 0;
e.trivial_max_level = 0;
e.multiplier = 1;
e.npc_min_level = 0;
e.npc_max_level = 0;
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
e.content_flags_disabled = "";
return e;
}
@@ -155,17 +171,21 @@ public:
if (results.RowCount() == 1) {
LootdropEntries e{};
e.lootdrop_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.item_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.item_charges = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 1;
e.equip_item = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.chance = row[4] ? strtof(row[4], nullptr) : 1;
e.disabled_chance = row[5] ? strtof(row[5], nullptr) : 0;
e.trivial_min_level = row[6] ? static_cast<uint16_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trivial_max_level = row[7] ? static_cast<uint16_t>(strtoul(row[7], nullptr, 10)) : 0;
e.multiplier = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 1;
e.npc_min_level = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
e.npc_max_level = row[10] ? static_cast<uint16_t>(strtoul(row[10], nullptr, 10)) : 0;
e.lootdrop_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.item_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.item_charges = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 1;
e.equip_item = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.chance = row[4] ? strtof(row[4], nullptr) : 1;
e.disabled_chance = row[5] ? strtof(row[5], nullptr) : 0;
e.trivial_min_level = row[6] ? static_cast<uint16_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trivial_max_level = row[7] ? static_cast<uint16_t>(strtoul(row[7], nullptr, 10)) : 0;
e.multiplier = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 1;
e.npc_min_level = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
e.npc_max_level = row[10] ? static_cast<uint16_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
return e;
}
@@ -210,6 +230,10 @@ public:
v.push_back(columns[8] + " = " + std::to_string(e.multiplier));
v.push_back(columns[9] + " = " + std::to_string(e.npc_min_level));
v.push_back(columns[10] + " = " + std::to_string(e.npc_max_level));
v.push_back(columns[11] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[12] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[13] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -242,6 +266,10 @@ public:
v.push_back(std::to_string(e.multiplier));
v.push_back(std::to_string(e.npc_min_level));
v.push_back(std::to_string(e.npc_max_level));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -282,6 +310,10 @@ public:
v.push_back(std::to_string(e.multiplier));
v.push_back(std::to_string(e.npc_min_level));
v.push_back(std::to_string(e.npc_max_level));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -315,17 +347,21 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
LootdropEntries e{};
e.lootdrop_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.item_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.item_charges = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 1;
e.equip_item = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.chance = row[4] ? strtof(row[4], nullptr) : 1;
e.disabled_chance = row[5] ? strtof(row[5], nullptr) : 0;
e.trivial_min_level = row[6] ? static_cast<uint16_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trivial_max_level = row[7] ? static_cast<uint16_t>(strtoul(row[7], nullptr, 10)) : 0;
e.multiplier = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 1;
e.npc_min_level = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
e.npc_max_level = row[10] ? static_cast<uint16_t>(strtoul(row[10], nullptr, 10)) : 0;
e.lootdrop_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.item_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.item_charges = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 1;
e.equip_item = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.chance = row[4] ? strtof(row[4], nullptr) : 1;
e.disabled_chance = row[5] ? strtof(row[5], nullptr) : 0;
e.trivial_min_level = row[6] ? static_cast<uint16_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trivial_max_level = row[7] ? static_cast<uint16_t>(strtoul(row[7], nullptr, 10)) : 0;
e.multiplier = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 1;
e.npc_min_level = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
e.npc_max_level = row[10] ? static_cast<uint16_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
all_entries.push_back(e);
}
@@ -350,17 +386,21 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
LootdropEntries e{};
e.lootdrop_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.item_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.item_charges = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 1;
e.equip_item = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.chance = row[4] ? strtof(row[4], nullptr) : 1;
e.disabled_chance = row[5] ? strtof(row[5], nullptr) : 0;
e.trivial_min_level = row[6] ? static_cast<uint16_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trivial_max_level = row[7] ? static_cast<uint16_t>(strtoul(row[7], nullptr, 10)) : 0;
e.multiplier = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 1;
e.npc_min_level = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
e.npc_max_level = row[10] ? static_cast<uint16_t>(strtoul(row[10], nullptr, 10)) : 0;
e.lootdrop_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.item_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.item_charges = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 1;
e.equip_item = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.chance = row[4] ? strtof(row[4], nullptr) : 1;
e.disabled_chance = row[5] ? strtof(row[5], nullptr) : 0;
e.trivial_min_level = row[6] ? static_cast<uint16_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trivial_max_level = row[7] ? static_cast<uint16_t>(strtoul(row[7], nullptr, 10)) : 0;
e.multiplier = row[8] ? static_cast<uint8_t>(strtoul(row[8], nullptr, 10)) : 1;
e.npc_min_level = row[9] ? static_cast<uint16_t>(strtoul(row[9], nullptr, 10)) : 0;
e.npc_max_level = row[10] ? static_cast<uint16_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
all_entries.push_back(e);
}
@@ -446,6 +486,10 @@ public:
v.push_back(std::to_string(e.multiplier));
v.push_back(std::to_string(e.npc_min_level));
v.push_back(std::to_string(e.npc_max_level));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -479,6 +523,10 @@ public:
v.push_back(std::to_string(e.multiplier));
v.push_back(std::to_string(e.npc_min_level));
v.push_back(std::to_string(e.npc_max_level));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -19,18 +19,22 @@
class BaseNpcSpellsEntriesRepository {
public:
struct NpcSpellsEntries {
uint32_t id;
int32_t npc_spells_id;
uint16_t spellid;
uint32_t type;
uint8_t minlevel;
uint8_t maxlevel;
int16_t manacost;
int32_t recast_delay;
int16_t priority;
int32_t resist_adjust;
int16_t min_hp;
int16_t max_hp;
uint32_t id;
int32_t npc_spells_id;
uint16_t spellid;
uint32_t type;
uint8_t minlevel;
uint8_t maxlevel;
int16_t manacost;
int32_t recast_delay;
int16_t priority;
int32_t resist_adjust;
int16_t min_hp;
int16_t max_hp;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
std::string content_flags_disabled;
};
static std::string PrimaryKey()
@@ -53,6 +57,10 @@ public:
"resist_adjust",
"min_hp",
"max_hp",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
@@ -71,6 +79,10 @@ public:
"resist_adjust",
"min_hp",
"max_hp",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
@@ -111,18 +123,22 @@ public:
{
NpcSpellsEntries e{};
e.id = 0;
e.npc_spells_id = 0;
e.spellid = 0;
e.type = 0;
e.minlevel = 0;
e.maxlevel = 255;
e.manacost = -1;
e.recast_delay = -1;
e.priority = 0;
e.resist_adjust = 0;
e.min_hp = 0;
e.max_hp = 0;
e.id = 0;
e.npc_spells_id = 0;
e.spellid = 0;
e.type = 0;
e.minlevel = 0;
e.maxlevel = 255;
e.manacost = -1;
e.recast_delay = -1;
e.priority = 0;
e.resist_adjust = 0;
e.min_hp = 0;
e.max_hp = 0;
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
e.content_flags_disabled = "";
return e;
}
@@ -159,18 +175,22 @@ public:
if (results.RowCount() == 1) {
NpcSpellsEntries e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
e.min_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.max_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
return e;
}
@@ -215,6 +235,10 @@ public:
v.push_back(columns[9] + " = " + std::to_string(e.resist_adjust));
v.push_back(columns[10] + " = " + std::to_string(e.min_hp));
v.push_back(columns[11] + " = " + std::to_string(e.max_hp));
v.push_back(columns[12] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[13] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -248,6 +272,10 @@ public:
v.push_back(std::to_string(e.resist_adjust));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -289,6 +317,10 @@ public:
v.push_back(std::to_string(e.resist_adjust));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -322,18 +354,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
NpcSpellsEntries e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
e.min_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.max_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
all_entries.push_back(e);
}
@@ -358,18 +394,22 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
NpcSpellsEntries e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
e.min_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.max_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
all_entries.push_back(e);
}
@@ -456,6 +496,10 @@ public:
v.push_back(std::to_string(e.resist_adjust));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -490,6 +534,10 @@ public:
v.push_back(std::to_string(e.resist_adjust));
v.push_back(std::to_string(e.min_hp));
v.push_back(std::to_string(e.max_hp));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
File diff suppressed because it is too large Load Diff
@@ -116,7 +116,7 @@ public:
e.bagidx = 0;
e.itemid = 0;
e.charges = 0;
e.droptime = 0;
e.droptime = std::time(nullptr);
e.augslot1 = 0;
e.augslot2 = 0;
e.augslot3 = 0;
@@ -19,8 +19,9 @@
class BaseSkillCapsRepository {
public:
struct SkillCaps {
uint8_t skillID;
uint8_t class_;
uint32_t id;
uint8_t skill_id;
uint8_t class_id;
uint8_t level;
uint32_t cap;
uint8_t class_;
@@ -28,14 +29,15 @@ public:
static std::string PrimaryKey()
{
return std::string("skillID");
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"skillID",
"`class`",
"id",
"skill_id",
"class_id",
"level",
"cap",
"class_",
@@ -45,8 +47,9 @@ public:
static std::vector<std::string> SelectColumns()
{
return {
"skillID",
"`class`",
"id",
"skill_id",
"class_id",
"level",
"cap",
"class_",
@@ -90,11 +93,12 @@ public:
{
SkillCaps e{};
e.skillID = 0;
e.class_ = 0;
e.level = 0;
e.cap = 0;
e.class_ = 0;
e.id = 0;
e.skill_id = 0;
e.class_id = 0;
e.level = 0;
e.cap = 0;
e.class_ = 0;
return e;
}
@@ -105,7 +109,7 @@ public:
)
{
for (auto &skill_caps : skill_capss) {
if (skill_caps.skillID == skill_caps_id) {
if (skill_caps.id == skill_caps_id) {
return skill_caps;
}
}
@@ -131,11 +135,12 @@ public:
if (results.RowCount() == 1) {
SkillCaps e{};
e.skillID = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.level = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.cap = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.class_ = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.skill_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.class_id = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.level = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.cap = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.class_ = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
return e;
}
@@ -169,11 +174,11 @@ public:
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.skillID));
v.push_back(columns[1] + " = " + std::to_string(e.class_));
v.push_back(columns[2] + " = " + std::to_string(e.level));
v.push_back(columns[3] + " = " + std::to_string(e.cap));
v.push_back(columns[4] + " = " + std::to_string(e.class_));
v.push_back(columns[1] + " = " + std::to_string(e.skill_id));
v.push_back(columns[2] + " = " + std::to_string(e.class_id));
v.push_back(columns[3] + " = " + std::to_string(e.level));
v.push_back(columns[4] + " = " + std::to_string(e.cap));
v.push_back(columns[5] + " = " + std::to_string(e.class_));
auto results = db.QueryDatabase(
fmt::format(
@@ -181,7 +186,7 @@ public:
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.skillID
e.id
)
);
@@ -195,8 +200,9 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.skillID));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.skill_id));
v.push_back(std::to_string(e.class_id));
v.push_back(std::to_string(e.level));
v.push_back(std::to_string(e.cap));
v.push_back(std::to_string(e.class_));
@@ -210,7 +216,7 @@ public:
);
if (results.Success()) {
e.skillID = results.LastInsertedID();
e.id = results.LastInsertedID();
return e;
}
@@ -229,8 +235,9 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.skillID));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.skill_id));
v.push_back(std::to_string(e.class_id));
v.push_back(std::to_string(e.level));
v.push_back(std::to_string(e.cap));
v.push_back(std::to_string(e.class_));
@@ -267,11 +274,12 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
SkillCaps e{};
e.skillID = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.level = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.cap = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.class_ = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.skill_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.class_id = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.level = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.cap = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.class_ = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -296,11 +304,12 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
SkillCaps e{};
e.skillID = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.level = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.cap = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.class_ = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.skill_id = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.class_id = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 0;
e.level = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
e.cap = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.class_ = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -375,8 +384,9 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.skillID));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.skill_id));
v.push_back(std::to_string(e.class_id));
v.push_back(std::to_string(e.level));
v.push_back(std::to_string(e.cap));
v.push_back(std::to_string(e.class_));
@@ -402,8 +412,9 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.skillID));
v.push_back(std::to_string(e.class_));
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.skill_id));
v.push_back(std::to_string(e.class_id));
v.push_back(std::to_string(e.level));
v.push_back(std::to_string(e.cap));
v.push_back(std::to_string(e.class_));

Some files were not shown because too many files have changed in this diff Show More