Compare commits

..

89 Commits

Author SHA1 Message Date
JJ 871f320311 [Release] 22.35.0 (#3754)
### Bots

* Add BotHealOnLevel to fully heal/mana on level. ([#3745](https://github.com/EQEmu/Server/pull/3745)) @nytmyr 2023-12-08
* Fix bots learning spells on level ([#3744](https://github.com/EQEmu/Server/pull/3744)) @nytmyr 2023-12-08

### Bug

* Fix blocked spells regression from #3638 ([#3753](https://github.com/EQEmu/Server/pull/3753)) @joligario 2023-12-11
* PR 3638 Missed the blocked spells repository updates ([#3748](https://github.com/EQEmu/Server/pull/3748)) @fryguy503 2023-12-08

### CMake

* Update minimum version of CMake ([#3743](https://github.com/EQEmu/Server/pull/3743)) @joligario 2023-12-08

### Code

* Remove hard-coded Status Checks ([#3727](https://github.com/EQEmu/Server/pull/3727)) @Kinglykrab 2023-12-03

### Commands

* #guild set CharName 0 did not remove char from guild. ([#3717](https://github.com/EQEmu/Server/pull/3717)) @noudess 2023-11-25
* #petname changes PC to Nobody if selected. ([#3720](https://github.com/EQEmu/Server/pull/3720)) @noudess 2023-11-26
* Add #show aas Command ([#3710](https://github.com/EQEmu/Server/pull/3710)) @Kinglykrab 2023-11-26
* Add #task complete Command ([#3711](https://github.com/EQEmu/Server/pull/3711)) @Kinglykrab 2023-11-26
* Cleanup #acceptrules Command ([#3716](https://github.com/EQEmu/Server/pull/3716)) @Kinglykrab 2023-11-26
* Cleanup #disarmtrap Command ([#3713](https://github.com/EQEmu/Server/pull/3713)) @Kinglykrab 2023-11-26
* Cleanup #list Command ([#3714](https://github.com/EQEmu/Server/pull/3714)) @Kinglykrab 2023-11-26
* Cleanup #movement Command ([#3715](https://github.com/EQEmu/Server/pull/3715)) @Kinglykrab 2023-11-26
* Cleanup #object Command ([#3722](https://github.com/EQEmu/Server/pull/3722)) @Kinglykrab 2023-12-03
* Cleanup #zonebootup and #zoneshutdown Commands ([#3729](https://github.com/EQEmu/Server/pull/3729)) @Kinglykrab 2023-12-03
* Fix formatting of #wpinfo output. ([#3728](https://github.com/EQEmu/Server/pull/3728)) @noudess 2023-12-01

### Database

* Add primary key to keyring table ([#3746](https://github.com/EQEmu/Server/pull/3746)) @Kinglykrab 2023-12-08
* Consolidate Starting Items Table ([#3723](https://github.com/EQEmu/Server/pull/3723)) @Kinglykrab 2023-11-30
* Extra whitespace in #3723 ([#3730](https://github.com/EQEmu/Server/pull/3730)) @joligario 2023-12-02
* Minor adjustment to #3726 ([#3732](https://github.com/EQEmu/Server/pull/3732)) @joligario 2023-12-03
* Modify `updated` column in `items` table with proper default. ([#3726](https://github.com/EQEmu/Server/pull/3726)) @joligario 2023-12-02
* Pull Spell Group Cache from Content DB ([#3749](https://github.com/EQEmu/Server/pull/3749)) @fryguy503 2023-12-08

### Faction

* Alliance line is only allowed 1 faction change at a time. ([#3718](https://github.com/EQEmu/Server/pull/3718)) @noudess 2023-11-26

### Fixes

* Changing Group Leader Invalidated GetLeaderName() ([#3712](https://github.com/EQEmu/Server/pull/3712)) @Kinglykrab 2023-11-26
* Fix 9245 SQL ([#3740](https://github.com/EQEmu/Server/pull/3740)) @Kinglykrab 2023-12-05
* Fix Swarm Pets Requiring NPC Aggros Flag ([#3738](https://github.com/EQEmu/Server/pull/3738)) @Kinglykrab 2023-12-05
* Guild Message Limits ([#3724](https://github.com/EQEmu/Server/pull/3724)) @neckkola 2023-11-29

### Quest API

* Add EVENT_AA_GAIN to AddAAPoints() ([#3733](https://github.com/EQEmu/Server/pull/3733)) @Kinglykrab 2023-12-03
* Add GMMove Overloads to Perl/Lua ([#3719](https://github.com/EQEmu/Server/pull/3719)) @Kinglykrab 2023-11-25

### Scripts

* Import items into `items_new` table instead of writing directly to the existing `items` table. ([#3725](https://github.com/EQEmu/Server/pull/3725)) @joligario 2023-11-30
* Revert database engine change from #3702. ([#3736](https://github.com/EQEmu/Server/pull/3736)) @joligario 2023-12-03
* Update 13th Floor Import Tool ([#3702](https://github.com/EQEmu/Server/pull/3702)) @joligario 2023-11-26
2023-12-10 22:07:09 -05:00
JJ a222128599 [Bug] Fix blocked spells regression from #3638 (#3753)
Fixes #3747
2023-12-10 21:40:06 -05:00
JJ 45b249e33d [CMake] Update minimum version of CMake (#3743)
```
CMake Deprecation Warning at client_files/CMakeLists.txt:1 (CMAKE_MINIMUM_REQUIRED):
  Compatibility with CMake < 3.5 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.
```
2023-12-08 12:48:59 -08:00
Fryguy c24834de5d [Database] Pull Spell Group Cache from Content DB (#3749) 2023-12-08 15:41:09 -05:00
Fryguy 841d7f2700 [Bug] PR 3638 Missed the blocked spells repository updates (#3748)
Ran generator to update blocked_spells Repo
2023-12-08 15:19:54 -05:00
Alex King 56c29154f0 [Database] Add primary key to keyring table (#3746)
* [Database] Add primary key to keyring table

# Notes
- Adds a primary key of `id` to `keyring` table so we can use it with repositories.

* Update version.h

* Update client.cpp

* Update client.cpp
2023-12-07 23:12:01 -05:00
nytmyr 6466c2ff21 [Bots] Add BotHealOnLevel to fully heal/mana on level. (#3745)
Adds the rule ***Bots, BotHealOnLevel***, default false, to control whether or not bots will gain full health and mana when their owner levels.
2023-12-07 22:25:17 -05:00
nytmyr 16dc210cd8 [Bots] Fix bots learning spells on level (#3744)
Previously bots would need to be zoned or camped/spawned to begin using new spells for their level.
2023-12-07 21:19:21 -05:00
Alex King 77045f558e [Bug Fix] Fix 9245 SQL (#3740)
* [Bug Fix] Fix 9245 SQL

# Notes
- Should be a `;` not `,`.

* Update database_update_manifest.cpp
2023-12-04 22:21:31 -05:00
Alex King e1fa2d5bc5 [Bug Fix] Fix Swarm Pets Requiring NPC Aggros Flag (#3738)
# Notes
- https://github.com/EQEmu/Server/pull/3595 made swarm pets require the `npc_aggro` flag to be set to attack.
2023-12-04 19:05:16 -05:00
Alex King b03f52de18 [Commands] Cleanup #object Command (#3722)
* [Commands] Cleanup #object Command

# Notes
- Cleanup messages and logic.
- Introduce enum for object types.
- Set ground work for object manipulation similar to door manipulation.

* Update object_manipulation.cpp

* Final push

* Update client_packet.cpp

* Update object_manipulation.cpp

* Update object_manipulation.cpp

* Update object.h

* Update client_packet.cpp

* Update client_packet.cpp

* Push.

* Update version.h

* Update database_update_manifest.cpp

* Update zone.cpp
2023-12-03 17:42:27 -05:00
JJ 226cc3d6cb [Scripts] Revert database engine change from #3702. (#3736)
InnoDB doesn't like the lengths. Will need to address that in the future.
2023-12-03 14:17:58 -05:00
Alex King 7f54e26dec [Quest API] Add EVENT_AA_GAIN to AddAAPoints() (#3733)
# Notes
- Using this method did not call `EVENT_AA_GAIN`.
2023-12-03 12:41:06 -05:00
Alex King 11a81d8e8a [Commands] Cleanup #zonebootup and #zoneshutdown Commands (#3729)
# Notes
- Cleanup messages and logic.
2023-12-03 12:40:54 -05:00
Alex King e719aa43cf [Cleanup] Remove hard-coded Status Checks (#3727)
* [Cleanup] Remove hard-coded Status Checks

# Notes
- Removed the hard-coded GM status checks since if you have access to the command we can now limit access to subcommands if necessary.

* Update client_packet.cpp
2023-12-03 11:44:30 -05:00
JJ 22994e3264 [Database] Minor adjustment to #3726 (#3732) 2023-12-03 10:18:27 -05:00
JJ cfbdecad19 [Database] Extra whitespace in #3723 (#3730) 2023-12-01 21:13:08 -05:00
JJ 2427f7e034 [Database] Modify updated column in items table with proper default. (#3726)
* [Database] Modify `updated` column in `items` table with proper default.
From https://mariadb.com/kb/en/datetime/, `datetime` can be ZERO_DATE (`0000-00-00` with no time component) or between `1000-01-01 00:00:00.000000` and `9999-12-31 23:59:59.999999`. Currently, `updated` is the only datetime field that is `NOT NULL` and improperly defaulted to `0000-00-00 00:00:00`. This change matches existing structures of the other `datetime` columns.

* Update items_repository.h

* Update base_items_repository.h

* Revert "Update items_repository.h"

This reverts commit 3599f26818.
2023-12-01 21:10:52 -05:00
Paul Coene 9a6403b196 [Commands] Fix formatting of #wpinfo output. (#3728) 2023-12-01 15:28:24 -05:00
JJ d8953c5156 [Scripts] Import items into items_new table instead of writing directly to the existing items table. (#3725) 2023-11-30 17:21:00 -05:00
Alex King 33b40e83b7 [Database] Consolidate Starting Items Table (#3723)
* [Database] Consolidate Starting Items Table

# Notes
- Convert `class`, `deityId`, `race`, and `zoneid` columns to `|` separated columns.
- Consolidates up to 15 rows per item down to a singular row.
- Allows ease of use for operators.
- Entire process is automated and creates a backup of pre-existing table.

* Update shareddb.cpp

* Unnecessary.
2023-11-30 14:37:08 -05:00
Mitch Freeman e75c31d524 [Bug Fix] Guild Message Limits (#3724)
Mail to 'Guild' was failing after after 50ish members.
The buffer was set at 512, which cut truncated the message and caused the issue.
Refactored to adjust the size of the buffer based on the inbound message size.
2023-11-28 19:03:32 -05:00
Paul Coene cf1f8d5460 [Commands] #petname changes PC to Nobody if selected. (#3720) 2023-11-26 14:50:44 -05:00
Paul Coene 690cacdaab [Faction] Alliance line is only allowed 1 faction change at a time. (#3718) 2023-11-26 01:13:16 -05:00
Alex King f9f45eedcd [Commands] Cleanup #acceptrules Command (#3716)
# Note
- Cleanup messages and logic.
- Utilize repositories in database methods.
2023-11-26 01:13:08 -05:00
Alex King 93ddffa57f [Commands] Cleanup #movement Command (#3715)
# Notes
- Cleanup messages and logic.
2023-11-26 01:13:03 -05:00
Alex King c9993fb698 [Commands] Cleanup #list Command (#3714)
* [Commands] Cleanup #list Command

# Notes
- Cleanup messages and logic.
- Introduce a struct so we don't have to duplicate so much code.

* Update list.cpp
2023-11-26 01:12:58 -05:00
Alex King aa0fbb8b45 [Commands] Cleanup #disarmtrap Command (#3713)
# Notes
- Cleanup messages and logic.
2023-11-26 00:27:22 -05:00
Alex King 62532c6bdd [Bug Fix] Changing Group Leader Invalidated GetLeaderName() (#3712)
# Notes
- Utilizes fixes posted in https://github.com/EQEmu/Server/issues/3706 to resolve https://github.com/EQEmu/Server/issues/368.
- Changing group leader caused issues because we assumed `member[0]` was always leader.
2023-11-26 00:27:15 -05:00
Alex King f8c3c03185 [Commands] Add #task complete Command (#3711)
# Notes
- `#task complete [Task ID]` allows operators to complete an entire task without updating individual activities.
2023-11-26 00:27:08 -05:00
Alex King 692a90f3f0 [Commands] Add #show aas Command (#3710)
# Notes
- Allows operators to view AAs a player has purchased from ingame and their ranks.
2023-11-26 00:27:02 -05:00
JJ 3a49d851ca [Scripts] Update 13th Floor Import Tool (#3702) 2023-11-26 00:20:10 -05:00
Alex King fdc5c27061 [Quest API] Add GMMove Overloads to Perl/Lua (#3719)
# Perl
- Add `$mob->GMMove(x, y, z, heading, save_guard_spot)`.

# Lua
- Add `mob:GMMove(x, y, z, heading, save_guard_spot)`.

# Notes
- Operators weren't able to disable saving guard spots, so moving with `GMMove` meant NPCs stayed where they were moved.
2023-11-25 18:15:37 -05:00
Paul Coene 56be69ddb1 [Commands] #guild set CharName 0 did not remove char from guild. (#3717)
* [Commands] #guild set CharName 0 did not remove char from guild.

* Fix cut-n-paste error on this branch
2023-11-25 11:27:43 -05:00
Alex King 9477ff72ac [Release] 22.34.2 (#3709)
### Admin

* Update date in changelog ([#3698](https://github.com/EQEmu/Server/pull/3698)) @joligario 2023-11-19

### Code

* Fix typo in #giveitem ([#3704](https://github.com/EQEmu/Server/pull/3704)) @Kinglykrab 2023-11-22

### Fixes

* Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() ([#3705](https://github.com/EQEmu/Server/pull/3705)) @jcr4990 2023-11-23
* Fix bots/Mercenaries being removed from hatelist ([#3708](https://github.com/EQEmu/Server/pull/3708)) @Kinglykrab 2023-11-23
* Fix some spell types failing IsValidSpellRange check ([#3707](https://github.com/EQEmu/Server/pull/3707)) @nytmyr 2023-11-23

### Loginserver

* Update ticket login table structure ([#3703](https://github.com/EQEmu/Server/pull/3703)) @KimLS 2023-11-22
2023-11-24 13:23:10 -05:00
Alex King 6d8e80b1e5 [Bug Fix] Fix bots/Mercenaries being removed from hatelist (#3708)
# Notes
- https://github.com/EQEmu/Server/pull/3595 caused bots, bot pets, and mercenaries to be removed from hate list because we were only checking for `IsClient()` not `IsOfClientBotMerc()`.
- Resolves an issue mentioned [here](https://discord.com/channels/212663220849213441/1177288302383079534) where NPCs would run past bots/mercenaries to attack the owner.
2023-11-23 12:36:54 -05:00
Joel ebeaef598b [Bug Fix] Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() (#3705) 2023-11-22 22:45:53 -05:00
nytmyr 60b65da7f2 [Bug Fix] Fix some spell types failing IsValidSpellRange check (#3707)
Hate Reduction, Slow and DoT spells were failing IsValidSpellRange checks due to improper spell IDs being checked.

They were using the first spell in a bot's spell list by checking botSpell.id vs the proper spells in the loop.
2023-11-22 22:44:59 -05:00
Alex King 100e6698ea [Cleanup] Fix typo in #giveitem (#3704) 2023-11-22 08:26:54 -05:00
Alex 2bd94ab7a2 [Loginserver] Update ticket login table structure (#3703)
* Updates login table to support tickets in a way that makes more sense.

* Change to snake_case as requested by Akka

---------

Co-authored-by: KimLS <KimLS@peqtgc.com>
2023-11-22 02:56:47 -06:00
Akkadius 4c8d68c24b [Release] 22.34.1 2023-11-20 09:12:11 -06:00
Akkadius 1755678b1f [Release] 22.34.1 2023-11-20 09:10:22 -06:00
JJ 39e2763968 [Admin] Update date in changelog (#3698) 2023-11-19 13:22:56 -05:00
Fryguy f7780b0247 [Bug Fix] NPC Faction War prevention. (#3595)
* [Bug] NPC Faction War prevention.

This should assist with prevention of NPC Faction waring. I have been using this code on my server for over 5 years with no coredumps or any noted bugs. This was brought up as users have reported a few events where they can trigger NPC's to fight each other.

* Correct a few entries to line up with updated code.

* Re-add missing RestTimer functionality
2023-11-19 11:40:15 -05:00
JJ c0fe0f11f7 [Release] 22.34.0 (#3697)
* Update CHANGELOG.md

* Update package.json

* Update version.h

* Update CHANGELOG.md
2023-11-19 11:21:39 -05:00
nytmyr a1f1f11940 [Bots] Add ownerraid, byclass and byrace actionables and fix group-based arguments for raids. (#3680)
This adds raid support to actionables for bot commands.

This also addresses Issue #3567

If in a group, group based commands will function as normal, however if in a raid they will support raids and use the group of the bot that fits  the criteria.

This adds new actionables as well; namely, **ownerraid**, **byclass** and **byrace**.

**byclass** and **byrace** use the int of the chosen class/race. IE Shadowknight is 5, Barbarian is 2. **^create help** is an easy way for players to identify numbers associated with classes and races.

**targetgroup** will now select all bots that meet the criteria within a raid group in addition to the current functionality of groups.
**namesgroup** will now select all bots that meet the criteria within a raid group in addition to the current functionality of groups.
**ownerraid** will select all bots in the raid owned by the player.
**byclass** will selects all bots in the group or raid owned by the player that match the class.
**byrace** will selects all bots in the group or raid owned by the player that match the race

This adds actionables to **^casterrange** and **^camp** as well.
2023-11-18 23:24:49 -05:00
Alex King 4c5013e09e [Cleanup] Cleanup #giveitem and #summonitem (#3692)
# Notes
- Adds summoned messages for `#giveitem` and `#summonitem`.
- `#summonitem` did not stop you from summoning items beyond your status level.
2023-11-18 21:22:12 -05:00
Alex King 838ffbd8c7 [Commands] Add #show aa_points Command (#3695)
# Notes
- Adds a command to view a player's current, spent, and total AA Points.
2023-11-18 19:23:35 -05:00
JJ 42b41d973c [GM Commands] Remove duplicate comment (#3691) 2023-11-18 19:08:56 -05:00
JJ e7761133a9 [GM Commands] Add #takeplatinum (#3690)
* [GM Commands] Add `#takeplatinum`

* Revert database manifest change

* Revert database version change

* Remove duplicated messages

* Remove hint as to why `#takeplatinum` might fail.
2023-11-18 19:08:48 -05:00
Alex King 93f2bea96e [Cleanup] Cleanup #show currencies Command (#3693)
* [Cleanup] Cleanup #show currencies Command

# Notes
- Cleans up messages.
- Adds `AA Points` as a viewable currency.
- Adds an enum for `MoneyTypes` and `MoneySubtypes` so we're not using magic numbers for `GetMoney` anymore.
- Converts money amounts to `uint64`.

* Update currencies.cpp

* Update currencies.cpp
2023-11-18 19:05:04 -05:00
regneq ded82ac6d6 [Spawn] (imported from takp) Added min_time and max_time to spawnentry. This will prevent a NPC from… (#3685)
* Added mintime and maxtime to spawnentry. This will prevent a NPC from spawning outside of the times specified. NPCs spawned in this way will then behave like normal NPCs. They will not despawn on their own, unlike spawn_events/spawn_conditions. NPCs using this that are alone in their spawngroup will attempt to spawn after their respawn timer has expired if the time of day is outside their range. Otherwise, another NPC in the spawngroup will be chosen to spawn. The normal rules (chance, spawn_limit) still apply to these NPCs, this is just another rule added to the system.

mintime and maxtime both represent the in-game EQ Hour. Valid values are 1-24. If either or both of the values are 0, then the NPC will not have any time restriction.

Added a new rule World:BootHour. This allows server admins to specify the EQ hour the server will boot to. Valid options are 1-24. Setting this rule to 0 (default) disables it and world will use whatever time is specified in the DB.

* generated base_spawnentry_repository.h from script

* removed the rule insert from database_update_manifest.cpp.

* Add logging, initializers, minor cleanup

* Remove if/else branch

* Update eqtime.cpp

* Initializers, logging

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-11-18 14:23:04 -06:00
JJ 6ef182edfd [Database] Pull pet power from content database (#3689) 2023-11-18 14:19:33 -06:00
Paul Coene e466ca1c6d [Illusions] RandomizeFeastures erased texture. (#3686) 2023-11-12 16:02:54 -05:00
Akkadius fa5a3155fe [Release] 22.33.0 2023-11-11 21:09:06 -06:00
Chris Miles a20d333f9d [Spawn2] Fix edge case with instances not copying disabled spawn state (#3688)
* [Spawn2] Fix edge case with instances not copying disabled spawn state

* Update spawn2.cpp
2023-11-11 21:00:50 -06:00
Alex King 853739b538 [Feature] Add Comment to Item Data/Quest API (#3669)
* [Feature] Add Comment to Item Data/Quest API

# Perl
- Add `quest::getitemcomment(item_id)`.
- Add `quest::getitemlore(item_id)`.
- Add `$questitemdata->GetComment()`.

# Lua
- Add `eq.get_item_comment(item_id)`.
- Add `eq.get_item_lore(item_id)`.
- Add `item:Comment()`.
# Notes
- Added the ability for operators to pull these fields from item data without a database hit.
- Fixed a bug in `embparser_api.cpp` where `GetZoneGravity` was connected to the wrong methods.

* Update embparser_api.cpp
2023-11-07 18:12:39 -05:00
Alex King 6094ec9c7b [Bug Fix] Fix GetZoneGravity package.add (#3684)
# Notes
- This was incorrect and would cause `GetZoneGravity()` to function improperly in Perl.
2023-11-07 18:12:25 -05:00
Akkadius 9da1d6b397 [Release] 22.32.1 2023-11-06 18:38:21 -06:00
Chris Miles 8ea7299a57 [Release] 22.32.0 (#3683) 2023-11-06 17:56:51 -06:00
Chris Miles 0811a899d1 [Spawn] Split spawn2 enabled into its own state table (#3664)
* [Spawn] Split spawn2 enabled into its own state table

* Update spawn2.cpp

* Update repo

* Make spawn2 enabled/disabled instance aware

* Update questmgr.cpp

* Make sure packet stuff is aware of instance_id

* Update questmgr.cpp

* Update database_update_manifest.cpp

* Cleanup

* Revert "Cleanup"

This reverts commit 64b58bfc52.

* Update database_instances.cpp
2023-11-06 17:34:42 -06:00
hg fad9599642 [Quest API] Add details to Lua event dispatch errors (#3679) 2023-11-06 17:31:34 -06:00
Fryguy 62711b13d8 Revert "[Bug Fix] Fix Killed XYZH support in EVENT_DEATH in Perl. (#3591)" (#3682)
This reverts commit 9b992167f0.
2023-11-06 17:30:55 -06:00
nytmyr 2702485206 [Bots] Fix invalid races from being created (#3681)
Previously this check allowed bots of invalid races to be created. If a race was neither a valid combination or a valid player race, it would pass the check and allow bots of any race to be created.

**^create 1 123 0** could create a Male Innoruuk Warrior
2023-11-06 17:03:34 -05:00
Mitch Freeman 0aadb891a1 [CRASH] Fix crash on CentOS when forming a raid with PCs or BOTs (#3676)
* [CRASH] Fix crash on CentOS

Update raid crash in CentOS.  raid constructors and learnmembers used a memset that was overwriting std::string structure.
Added default initializers to RaidMember struct

* Update based on feedback
2023-11-06 13:36:59 -05:00
JJ d812310c5b [GCC] Compatibility fix for GCC 13 (#3677)
Fixes ` ‘uint64_t’ does not name a type ` error under GCC 13
2023-11-05 14:05:15 -05:00
regneq 1420983700 [Spells] Added IsNightTime() for Dance of the Fireflies (#3667)
* Added IsNightOnly for Dance of the Fireflies spell which should only be cast at night from 7pm to 4pm.

* Update to include IsDayTime and replace magic numbers.
2023-11-04 13:58:08 -04:00
Alex King d25cc35f1b [Bug Fix] Add IsTGBCompatibleSpell() to package.add (#3675)
# Notes
- `IsTGBCompatibleSpell` was not exported properly.
2023-11-04 13:55:47 -04:00
Alex King ed7f395612 [Parser] Cleanup Spire Parsing for crosszonemoveplayerbycharid (#3674)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 13:13:17 -04:00
Alex King 8dceb20dd8 [Parser] Cleanup Spire Parsing for crosszonemoveplayerbygroupid (#3673)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 12:59:25 -04:00
Alex King 6929d180ca [Parser] Cleanup Spire Parsing for crosszonemoveplayerbyguildid (#3672)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 12:45:21 -04:00
Alex King 011a66a75e [Parser] Cleanup Spire Parsing for crosszonemoveplayerbyexpeditionid (#3671)
# Notes
- This formatting was causing Spire not to pick up the parameters.
2023-11-04 12:31:47 -04:00
Alex King 07120563a2 [Bug Fix] Fix Perl__worldwideremovetask package (#3670)
# Notes
- Two lines were using the same parameters.
2023-11-04 12:18:25 -04:00
JJ cc985cbcd5 [Quest API] Add GetBaseRaceName() to Perl and Lua (#3668) 2023-10-31 21:43:04 -04:00
JJ 97caa79472 [Release] 22.31.3 (#3666)
* Update package.json

* Update version.h

* Update CHANGELOG.md
2023-10-31 20:26:30 -05:00
Alex King cfa575c756 [Logs] Convert Loot Messages to Error Logs (#3663)
* [Logs] Convert Loot Messages to Error Logs

# Notes
- These messages were sending to users and not being logged.
- `Message(Chat::Red, "Error: OP_EndLootRequest: Corpse not found (ent = 0)");` sends often when corpse expires right as you try to loot, so it makes the user think there's a true error.

* Update zoning.cpp
2023-10-31 18:58:06 -04:00
JJ 85063249b4 [Bug] Force raids off content database (#3665) 2023-10-31 18:46:03 -04:00
Akkadius 04d6f8feea [Release] 22.31.2 2023-10-31 09:47:18 -05:00
Akkadius dfc1bf0381 Revert "[Crash] Fix spell in AESpell related to beacons (#3659)"
This reverts commit 0b452f4ec1.
2023-10-31 09:46:08 -05:00
Akkadius 2237c3a056 [Release] 22.31.1 2023-10-31 08:08:29 -05:00
Akkadius 4af191c593 [Hotfix] Fix issue with blocked spells not loading properly 2023-10-31 08:06:51 -05:00
Chris Miles 0a3972deb9 [Release] 22.31.0 (#3662) 2023-10-29 18:50:46 -05:00
Chris Miles 9d2f258390 [Database] Add id to variables table (#3658) 2023-10-29 18:45:30 -05:00
Chris Miles 0b452f4ec1 [Crash] Fix spell in AESpell related to beacons (#3659) 2023-10-29 18:45:24 -05:00
Chris Miles fef629e1df [Crash] Fix crash when client pointer does not exist during #hotfix (#3661) 2023-10-29 18:45:18 -05:00
Chris Miles a5a51fbe44 [Linux] Add symbols to release builds (#3660)
* [Linux] Add symbols to release builds

* Update linux-build.sh
2023-10-29 18:45:11 -05:00
Paul Coene 47db92cdb6 [Trading] Fix part 3 of Issue 932. (#3654) 2023-10-29 09:50:04 -04:00
Akkadius 690301e80d [Release] 22.30.2 - Hotfix perl loading 2023-10-26 16:23:55 -05:00
Akkadius 1887e48b76 Revert "[Perl] Reload perl quests on zone bootup (#3648)"
This reverts commit 0bbfcf7adc.
2023-10-26 16:21:06 -05:00
122 changed files with 6140 additions and 3739 deletions
+239
View File
@@ -1,3 +1,242 @@
## [22.35.0] - 12/10/2023
### Bots
* Add BotHealOnLevel to fully heal/mana on level. ([#3745](https://github.com/EQEmu/Server/pull/3745)) @nytmyr 2023-12-08
* Fix bots learning spells on level ([#3744](https://github.com/EQEmu/Server/pull/3744)) @nytmyr 2023-12-08
### Bug
* Fix blocked spells regression from #3638 ([#3753](https://github.com/EQEmu/Server/pull/3753)) @joligario 2023-12-11
* PR 3638 Missed the blocked spells repository updates ([#3748](https://github.com/EQEmu/Server/pull/3748)) @fryguy503 2023-12-08
### CMake
* Update minimum version of CMake ([#3743](https://github.com/EQEmu/Server/pull/3743)) @joligario 2023-12-08
### Code
* Remove hard-coded Status Checks ([#3727](https://github.com/EQEmu/Server/pull/3727)) @Kinglykrab 2023-12-03
### Commands
* #guild set CharName 0 did not remove char from guild. ([#3717](https://github.com/EQEmu/Server/pull/3717)) @noudess 2023-11-25
* #petname changes PC to Nobody if selected. ([#3720](https://github.com/EQEmu/Server/pull/3720)) @noudess 2023-11-26
* Add #show aas Command ([#3710](https://github.com/EQEmu/Server/pull/3710)) @Kinglykrab 2023-11-26
* Add #task complete Command ([#3711](https://github.com/EQEmu/Server/pull/3711)) @Kinglykrab 2023-11-26
* Cleanup #acceptrules Command ([#3716](https://github.com/EQEmu/Server/pull/3716)) @Kinglykrab 2023-11-26
* Cleanup #disarmtrap Command ([#3713](https://github.com/EQEmu/Server/pull/3713)) @Kinglykrab 2023-11-26
* Cleanup #list Command ([#3714](https://github.com/EQEmu/Server/pull/3714)) @Kinglykrab 2023-11-26
* Cleanup #movement Command ([#3715](https://github.com/EQEmu/Server/pull/3715)) @Kinglykrab 2023-11-26
* Cleanup #object Command ([#3722](https://github.com/EQEmu/Server/pull/3722)) @Kinglykrab 2023-12-03
* Cleanup #zonebootup and #zoneshutdown Commands ([#3729](https://github.com/EQEmu/Server/pull/3729)) @Kinglykrab 2023-12-03
* Fix formatting of #wpinfo output. ([#3728](https://github.com/EQEmu/Server/pull/3728)) @noudess 2023-12-01
### Database
* Add primary key to keyring table ([#3746](https://github.com/EQEmu/Server/pull/3746)) @Kinglykrab 2023-12-08
* Consolidate Starting Items Table ([#3723](https://github.com/EQEmu/Server/pull/3723)) @Kinglykrab 2023-11-30
* Extra whitespace in #3723 ([#3730](https://github.com/EQEmu/Server/pull/3730)) @joligario 2023-12-02
* Minor adjustment to #3726 ([#3732](https://github.com/EQEmu/Server/pull/3732)) @joligario 2023-12-03
* Modify `updated` column in `items` table with proper default. ([#3726](https://github.com/EQEmu/Server/pull/3726)) @joligario 2023-12-02
* Pull Spell Group Cache from Content DB ([#3749](https://github.com/EQEmu/Server/pull/3749)) @fryguy503 2023-12-08
### Faction
* Alliance line is only allowed 1 faction change at a time. ([#3718](https://github.com/EQEmu/Server/pull/3718)) @noudess 2023-11-26
### Fixes
* Changing Group Leader Invalidated GetLeaderName() ([#3712](https://github.com/EQEmu/Server/pull/3712)) @Kinglykrab 2023-11-26
* Fix 9245 SQL ([#3740](https://github.com/EQEmu/Server/pull/3740)) @Kinglykrab 2023-12-05
* Fix Swarm Pets Requiring NPC Aggros Flag ([#3738](https://github.com/EQEmu/Server/pull/3738)) @Kinglykrab 2023-12-05
* Guild Message Limits ([#3724](https://github.com/EQEmu/Server/pull/3724)) @neckkola 2023-11-29
### Quest API
* Add EVENT_AA_GAIN to AddAAPoints() ([#3733](https://github.com/EQEmu/Server/pull/3733)) @Kinglykrab 2023-12-03
* Add GMMove Overloads to Perl/Lua ([#3719](https://github.com/EQEmu/Server/pull/3719)) @Kinglykrab 2023-11-25
### Scripts
* Import items into `items_new` table instead of writing directly to the existing `items` table. ([#3725](https://github.com/EQEmu/Server/pull/3725)) @joligario 2023-11-30
* Revert database engine change from #3702. ([#3736](https://github.com/EQEmu/Server/pull/3736)) @joligario 2023-12-03
* Update 13th Floor Import Tool ([#3702](https://github.com/EQEmu/Server/pull/3702)) @joligario 2023-11-26
## [22.34.2] - 11/23/2023
### Admin
* Update date in changelog ([#3698](https://github.com/EQEmu/Server/pull/3698)) @joligario 2023-11-19
### Code
* Fix typo in #giveitem ([#3704](https://github.com/EQEmu/Server/pull/3704)) @Kinglykrab 2023-11-22
### Fixes
* Add "IgnoreLevelBasedHasteCaps" rule to GetHaste() ([#3705](https://github.com/EQEmu/Server/pull/3705)) @jcr4990 2023-11-23
* Fix bots/Mercenaries being removed from hatelist ([#3708](https://github.com/EQEmu/Server/pull/3708)) @Kinglykrab 2023-11-23
* Fix some spell types failing IsValidSpellRange check ([#3707](https://github.com/EQEmu/Server/pull/3707)) @nytmyr 2023-11-23
### Loginserver
* Update ticket login table structure ([#3703](https://github.com/EQEmu/Server/pull/3703)) @KimLS 2023-11-22
## [22.34.1] - 11/20/2023
### EQTime
Hotfix for world not spamming save messages by setting to detail level logging @Akkadius 2023-11-20
## [22.34.0] - 11/19/2023
### Bots
* Add ownerraid, byclass and byrace actionables and fix group-based arguments for raids. ([#3680](https://github.com/EQEmu/Server/pull/3680)) @nytmyr 2023-11-19
### Code
* Cleanup #giveitem and #summonitem ([#3692](https://github.com/EQEmu/Server/pull/3692)) @Kinglykrab 2023-11-19
* Cleanup #show currencies Command ([#3693](https://github.com/EQEmu/Server/pull/3693)) @Kinglykrab 2023-11-19
### Commands
* Add #show aa_points Command ([#3695](https://github.com/EQEmu/Server/pull/3695)) @Kinglykrab 2023-11-19
### Database
* Pull pet power from content database ([#3689](https://github.com/EQEmu/Server/pull/3689)) @joligario 2023-11-18
### GM Commands
* Add `#takeplatinum` ([#3690](https://github.com/EQEmu/Server/pull/3690)) @joligario 2023-11-19
* Remove duplicate comment ([#3691](https://github.com/EQEmu/Server/pull/3691)) @joligario 2023-11-19
### Illusions
* RandomizeFeastures erased texture. ([#3686](https://github.com/EQEmu/Server/pull/3686)) @noudess 2023-11-12
### Spawn
* (imported from takp) Added min_time and max_time to spawnentry. This will prevent a NPC from… ([#3685](https://github.com/EQEmu/Server/pull/3685)) @regneq 2023-11-18
## [22.33.0] - 11/11/2023
### Feature
* Add Comment to Item Data/Quest API ([#3669](https://github.com/EQEmu/Server/pull/3669)) @Kinglykrab 2023-11-07
### Spawn2
* Fix edge case with instances not copying disabled spawn state ([#3688](https://github.com/EQEmu/Server/pull/3688)) @Akkadius 2023-11-12
## [22.32.1] - 11/6/2023
### Hotfix
* Adjust spawn2_disabled migration to copy data over
## [22.32.0] - 11/6/2023
### Bots
* Fix invalid races from being created ([#3681](https://github.com/EQEmu/Server/pull/3681)) @nytmyr 2023-11-06
### Crash
* Fix crash on CentOS when forming a raid with PCs or BOTs ([#3676](https://github.com/EQEmu/Server/pull/3676)) @neckkola 2023-11-06
### Fixes
* Add IsTGBCompatibleSpell() to package.add ([#3675](https://github.com/EQEmu/Server/pull/3675)) @Kinglykrab 2023-11-04
* Fix Perl__worldwideremovetask package ([#3670](https://github.com/EQEmu/Server/pull/3670)) @Kinglykrab 2023-11-04
* Revert " Fix Killed XYZH support in EVENT_DEATH in Perl. " (#3682) ([#3591](https://github.com/EQEmu/Server/pull/3591)) @fryguy503 2023-11-06
CRASH
### GCC
* Compatibility fix for GCC 13 ([#3677](https://github.com/EQEmu/Server/pull/3677)) @joligario 2023-11-05
### Parser
* Cleanup Spire Parsing for crosszonemoveplayerbycharid ([#3674](https://github.com/EQEmu/Server/pull/3674)) @Kinglykrab 2023-11-04
* Cleanup Spire Parsing for crosszonemoveplayerbyexpeditionid ([#3671](https://github.com/EQEmu/Server/pull/3671)) @Kinglykrab 2023-11-04
* Cleanup Spire Parsing for crosszonemoveplayerbygroupid ([#3673](https://github.com/EQEmu/Server/pull/3673)) @Kinglykrab 2023-11-04
* Cleanup Spire Parsing for crosszonemoveplayerbyguildid ([#3672](https://github.com/EQEmu/Server/pull/3672)) @Kinglykrab 2023-11-04
### Quest API
* Add GetBaseRaceName() to Perl and Lua ([#3668](https://github.com/EQEmu/Server/pull/3668)) @joligario 2023-11-01
* Add details to Lua event dispatch errors ([#3679](https://github.com/EQEmu/Server/pull/3679)) @hgtw 2023-11-06
### Spawn
* Split spawn2 enabled into its own state table ([#3664](https://github.com/EQEmu/Server/pull/3664)) @Akkadius 2023-11-06
### Spells
* Added IsNightTime() for Dance of the Fireflies ([#3667](https://github.com/EQEmu/Server/pull/3667)) @regneq 2023-11-04
## [22.31.3] - 10/31/2023
### Bug
* Force raids off content database ([#3665](https://github.com/EQEmu/Server/pull/3665)) @joligario 2023-10-31
### Crash
* Revert " Fix spell in AESpell related to beacons " ([#3659](https://github.com/EQEmu/Server/pull/3659)) @Akkadius 2023-10-31
### Fixes
* Fix issue with blocked spells not loading properly @Akkadius 2023-10-31
### Logs
* Convert Loot Messages to Error Logs ([#3663](https://github.com/EQEmu/Server/pull/3663)) @Kinglykrab 2023-10-31
## [22.31.2] - 10/31/2023
### Fixes
* Hotfix issue with beacon spells crashing @Akkadius 2023-10-31
## [22.31.1] - 10/31/2023
### Fixes
* Hotfix issue with blocked spells not loading properly @Akkadius 2023-10-31
## [22.31.0] - 10/29/2023
### Crash
* Fix crash when client pointer does not exist during #hotfix ([#3661](https://github.com/EQEmu/Server/pull/3661)) @Akkadius 2023-10-29
* Fix spell in AESpell related to beacons ([#3659](https://github.com/EQEmu/Server/pull/3659)) @Akkadius 2023-10-29
### Database
* Add id to variables table ([#3658](https://github.com/EQEmu/Server/pull/3658)) @Akkadius 2023-10-29
### Linux
* Add symbols to release builds ([#3660](https://github.com/EQEmu/Server/pull/3660)) @Akkadius 2023-10-29
### Perl
* Revert " Reload perl quests on zone bootup " ([#3648](https://github.com/EQEmu/Server/pull/3648)) @Akkadius 2023-10-26
### Trading
* Fix part 3 of Issue 932. ([#3654](https://github.com/EQEmu/Server/pull/3654)) @noudess 2023-10-29
## [22.30.2] - 10/26/2023
### Fixes
Revert Perl regression in #3648 causing scripts to not reliably initialize on zone bootup. @Akkadius 2023-10-26
## [22.30.1] - 10/24/2023 ## [22.30.1] - 10/24/2023
### Fixes ### Fixes
+1 -1
View File
@@ -1,4 +1,4 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.2) CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
add_subdirectory(import) add_subdirectory(import)
add_subdirectory(export) add_subdirectory(export)
+37 -32
View File
@@ -29,6 +29,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../common/repositories/account_repository.h"
// Disgrace: for windows compile // Disgrace: for windows compile
#ifdef _WINDOWS #ifdef _WINDOWS
#include <windows.h> #include <windows.h>
@@ -1643,25 +1645,20 @@ void Database::ClearGroupLeader(uint32 gid) {
std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl; std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl;
} }
uint8 Database::GetAgreementFlag(uint32 acctid) { uint8 Database::GetAgreementFlag(uint32 account_id)
{
std::string query = StringFormat("SELECT rulesflag FROM account WHERE id=%i",acctid); const auto& e = AccountRepository::FindOne(*this, account_id);
auto results = QueryDatabase(query); if (!e.id) {
if (!results.Success())
return 0; return 0;
if (results.RowCount() != 1)
return 0;
auto row = results.begin();
return Strings::ToUnsignedInt(row[0]);
} }
void Database::SetAgreementFlag(uint32 acctid) { return e.rulesflag;
std::string query = StringFormat("UPDATE account SET rulesflag=1 where id=%i", acctid); }
QueryDatabase(query);
void Database::SetAgreementFlag(uint32 account_id) {
auto e = AccountRepository::FindOne(*this, account_id);
e.rulesflag = 1;
AccountRepository::UpdateOne(*this, e);
} }
void Database::ClearRaid(uint32 rid) { void Database::ClearRaid(uint32 rid) {
@@ -2097,37 +2094,45 @@ void Database::ClearInvSnapshots(bool from_now) {
struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
{ {
TimeOfDay_Struct t{};
TimeOfDay_Struct eqTime;
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1"); std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0) { if (!results.Success() || results.RowCount() == 0) {
LogInfo("Loading EQ time of day failed. Using defaults"); LogInfo("Loading EQ time of day failed. Using defaults");
eqTime.minute = 0; t.minute = 0;
eqTime.hour = 9; t.hour = 9;
eqTime.day = 1; t.day = 1;
eqTime.month = 1; t.month = 1;
eqTime.year = 3100; t.year = 3100;
realtime = time(nullptr); realtime = time(nullptr);
return t;
} }
else{
auto row = results.begin(); auto row = results.begin();
eqTime.minute = Strings::ToUnsignedInt(row[0]); uint8 hour = Strings::ToUnsignedInt(row[1]);
eqTime.hour = Strings::ToUnsignedInt(row[1]); time_t realtime_ = Strings::ToBigInt(row[5]);
eqTime.day = Strings::ToUnsignedInt(row[2]); if (RuleI(World, BootHour) > 0 && RuleI(World, BootHour) <= 24) {
eqTime.month = Strings::ToUnsignedInt(row[3]); hour = RuleI(World, BootHour);
eqTime.year = Strings::ToUnsignedInt(row[4]); realtime_ = time(nullptr);
realtime = Strings::ToBigInt(row[5]);
} }
return eqTime; t.minute = Strings::ToUnsignedInt(row[0]);
t.hour = hour;
t.day = Strings::ToUnsignedInt(row[2]);
t.month = Strings::ToUnsignedInt(row[3]);
t.year = Strings::ToUnsignedInt(row[4]);
realtime = realtime_;
LogEqTime("Setting hour to [{}]", hour);
return t;
} }
bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year) bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year)
{ {
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0)); std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(nullptr));
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
return results.Success(); return results.Success();
+2 -2
View File
@@ -188,10 +188,10 @@ public:
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0); 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 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); 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 acctid); uint8 GetAgreementFlag(uint32 account_id);
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 acctid); void SetAgreementFlag(uint32 account_id);
int GetIPExemption(std::string account_ip); int GetIPExemption(std::string account_ip);
void SetIPExemption(std::string account_ip, int exemption_amount); void SetIPExemption(std::string account_ip, int exemption_amount);
@@ -4983,6 +4983,141 @@ ADD COLUMN `content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swed
ADD COLUMN `content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `content_flags`; ADD COLUMN `content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `content_flags`;
)" )"
}, },
ManifestEntry{
.version = 9240,
.description = "2023_10_29_variables_id.sql",
.check = "SHOW COLUMNS FROM `variables` LIKE 'id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `variables`
ADD COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`) USING BTREE,
ADD UNIQUE INDEX(`varname`);
)"
},
ManifestEntry{
.version = 9241,
.description = "2023_10_29_split_spawn2_enabled.sql",
.check = "SHOW TABLES LIKE 'spawn2_disabled'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `spawn2_backup_2023_10_29` LIKE `spawn2`;
INSERT INTO `spawn2_backup_2023_10_29` SELECT * FROM `spawn2`;
CREATE TABLE `spawn2_disabled` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`spawn2_id` int(11) DEFAULT NULL,
`instance_id` int(11) DEFAULT 0,
`disabled` smallint(11) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `spawn2_id` (`spawn2_id`,`instance_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE enabled = 0;
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
)"
},
ManifestEntry{
.version = 9242,
.description = "2023_11_7_mintime_maxtime_spawnentry.sql",
.check = "SHOW COLUMNS FROM `spawnentry` LIKE 'min_time'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `spawnentry`
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
)"
},
ManifestEntry{
.version = 9243,
.description = "2023_11_27_starting_items_revamp.sql",
.check = "SHOW COLUMNS FROM `starting_items` LIKE 'race_list'",
.condition = "empty",
.match = "",
.sql = R"(
CREATE TABLE `starting_items_backup_9243` LIKE `starting_items`;
INSERT INTO `starting_items_backup_9243` SELECT * FROM `starting_items`;
CREATE TABLE `starting_items_new` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`race_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`deity_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`zone_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`item_id` int(11) UNSIGNED NOT NULL DEFAULT 0,
`item_charges` tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
`gm` mediumint(3) UNSIGNED NOT NULL DEFAULT 0,
`slot` mediumint(9) NOT NULL DEFAULT -1,
`min_expansion` tinyint(4) NOT NULL DEFAULT -1,
`max_expansion` tinyint(4) NOT NULL DEFAULT -1,
`content_flags` varchar(100) NULL,
`content_flags_disabled` varchar(100) NULL,
PRIMARY KEY (`id`)
);
INSERT INTO
`starting_items_new`
(
SELECT
0 AS `id`,
GROUP_CONCAT(DISTINCT `class` ORDER BY class ASC SEPARATOR '|') AS `class_list`,
GROUP_CONCAT(DISTINCT `race` ORDER BY race ASC SEPARATOR '|') AS `race_list`,
GROUP_CONCAT(DISTINCT `deityid` ORDER BY deityid ASC SEPARATOR '|') AS `deity_list`,
GROUP_CONCAT(DISTINCT `zoneid` ORDER BY zoneid ASC SEPARATOR '|') AS `zone_list`,
`itemid`,
`item_charges`,
`gm`,
`slot`,
`min_expansion`,
`max_expansion`,
`content_flags`,
`content_flags_disabled`
FROM
`starting_items`
GROUP BY
`itemid`
);
DROP TABLE `starting_items`;
RENAME TABLE `starting_items_new` TO `starting_items`;
)"
},
ManifestEntry{
.version = 9244,
.description = "2023_11_30_items_table_schema.sql",
.check = "SHOW COLUMNS FROM `items` LIKE 'updated'",
.condition = "contains",
.match = "0000-00-00 00:00:00",
.sql = R"(
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
)"
},
ManifestEntry{
.version = 9245,
.description = "2023_12_03_object_incline.sql",
.check = "SHOW COLUMNS FROM `object` LIKE 'incline'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
)"
},
ManifestEntry{
.version = 9246,
.description = "2023_12_07_keyring_id.sql",
.check = "SHOW COLUMNS FROM `keyring` LIKE 'id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `keyring`
ADD COLUMN `id` int UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
)"
}
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
// ManifestEntry{ // ManifestEntry{
+3
View File
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/repositories/raid_members_repository.h" #include "../common/repositories/raid_members_repository.h"
#include "../common/repositories/respawn_times_repository.h" #include "../common/repositories/respawn_times_repository.h"
#include "../common/repositories/spawn_condition_values_repository.h" #include "../common/repositories/spawn_condition_values_repository.h"
#include "repositories/spawn2_disabled_repository.h"
#include "database.h" #include "database.h"
@@ -49,6 +50,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/time.h> #include <sys/time.h>
#endif #endif
bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id) bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id)
{ {
auto e = InstanceListPlayerRepository::NewEntity(); auto e = InstanceListPlayerRepository::NewEntity();
@@ -553,6 +555,7 @@ void Database::PurgeExpiredInstances()
CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids); CharacterCorpsesRepository::BuryInstances(*this, imploded_instance_ids);
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids); DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids)); DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
Spawn2DisabledRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
} }
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
+1
View File
@@ -345,6 +345,7 @@ namespace DatabaseSchema {
"respawn_times", "respawn_times",
"saylink", "saylink",
"server_scheduled_events", "server_scheduled_events",
"spawn2_disabled",
"player_event_log_settings", "player_event_log_settings",
"player_event_logs", "player_event_logs",
"shared_task_activity_state", "shared_task_activity_state",
+23
View File
@@ -1052,4 +1052,27 @@ enum ScribeSpellActions
Unmemorize Unmemorize
}; };
enum SpellTimeRestrictions
{
NoRestriction,
Day,
Night
};
enum MoneyTypes
{
Copper,
Silver,
Gold,
Platinum
};
enum MoneySubtypes
{
Personal,
Bank,
Cursor,
SharedBank // Platinum Only
};
#endif /*COMMON_EQ_CONSTANTS_H*/ #endif /*COMMON_EQ_CONSTANTS_H*/
+2 -2
View File
@@ -2594,11 +2594,11 @@ struct BookButton_Struct
struct Object_Struct { struct Object_Struct {
/*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list /*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list
/*08*/ float size; // /*08*/ float size; //
/*10*/ uint16 solidtype; // /*10*/ uint16 solid_type; //
/*12*/ uint32 drop_id; // Unique object id for zone /*12*/ uint32 drop_id; // Unique object id for zone
/*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in /*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in
/*18*/ uint16 zone_instance; // /*18*/ uint16 zone_instance; //
/*20*/ uint32 unknown020; // /*20*/ uint32 incline; //
/*24*/ uint32 unknown024; // /*24*/ uint32 unknown024; //
/*28*/ float tilt_x; /*28*/ float tilt_x;
/*32*/ float tilt_y; /*32*/ float tilt_y;
+2
View File
@@ -100,6 +100,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General); log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General); log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_gmsay = static_cast<uint8>(Logs::General);
/** /**
* RFC 5424 * RFC 5424
+2
View File
@@ -139,6 +139,7 @@ namespace Logs {
PlayerEvents, PlayerEvents,
DataBuckets, DataBuckets,
Zoning, Zoning,
EqTime,
MaxCategoryID /* Don't Remove this */ MaxCategoryID /* Don't Remove this */
}; };
@@ -237,6 +238,7 @@ namespace Logs {
"PlayerEvents", "PlayerEvents",
"DataBuckets", "DataBuckets",
"Zoning", "Zoning",
"EqTime",
}; };
} }
+10
View File
@@ -814,6 +814,16 @@
OutF(LogSys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ OutF(LogSys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0) } while (0)
#define LogEqTime(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::EqTime))\
OutF(LogSys, Logs::General, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogEqTimeDetail(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::EqTime))\
OutF(LogSys, Logs::Detail, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\ #define Log(debug_level, log_category, message, ...) do {\
if (LogSys.IsLogEnabled(debug_level, log_category))\ if (LogSys.IsLogEnabled(debug_level, log_category))\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
+51 -7
View File
@@ -46,16 +46,16 @@ EQTime::EQTime()
timezone = 0; timezone = 0;
memset(&eqTime, 0, sizeof(eqTime)); memset(&eqTime, 0, sizeof(eqTime));
//Defaults for time //Defaults for time
TimeOfDay_Struct start; TimeOfDay_Struct t{};
start.day = 1; t.day = 1;
start.hour = 9; t.hour = 9;
start.minute = 0; t.minute = 0;
start.month = 1; t.month = 1;
start.year = 3100; t.year = 3100;
//Set default time zone //Set default time zone
timezone = 0; timezone = 0;
//Start EQTimer //Start EQTimer
SetCurrentEQTimeOfDay(start, time(0)); SetCurrentEQTimeOfDay(t, time(nullptr));
} }
//getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay //getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay
@@ -200,3 +200,47 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) {
buf[127] = '\0'; buf[127] = '\0';
str = buf; str = buf;
} }
bool EQTime::IsDayTime() {
TimeOfDay_Struct tod{}; //Day time is 5am to 6:59pm (14 hours in-game)
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
if (tod.hour >= 5 || tod.hour < 19) {
return true;
}
return false;
}
bool EQTime::IsNightTime() {
TimeOfDay_Struct tod{}; //Night time is 7pm to 4:59am (10 hours in-game)
GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero?
if (tod.hour >= 19 || tod.hour < 5) {
return true;
}
return false;
}
bool EQTime::IsInbetweenTime(uint8 min_time, uint8 max_time) {
TimeOfDay_Struct tod{};
GetCurrentEQTimeOfDay(&tod);
if (min_time == 0 || max_time == 0 || min_time > 24 || max_time > 24) {
return true;
}
if (max_time < min_time) {
if ((tod.hour >= min_time && tod.hour > max_time) || (tod.hour < min_time && tod.hour <= max_time)) {
return true;
}
}
else {
if (tod.hour >= min_time && tod.hour <= max_time) {
return true;
}
}
return false;
}
+3
View File
@@ -28,6 +28,9 @@ public:
uint32 getEQTimeZone() { return timezone; } uint32 getEQTimeZone() { return timezone; }
uint32 getEQTimeZoneHr() { return timezone/60; } uint32 getEQTimeZoneHr() { return timezone/60; }
uint32 getEQTimeZoneMin() { return timezone%60; } uint32 getEQTimeZoneMin() { return timezone%60; }
bool IsDayTime();
bool IsNightTime();
bool IsInbetweenTime(uint8 min_time, uint8 max_time);
//Set functions //Set functions
int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real); int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real);
-19
View File
@@ -238,25 +238,6 @@ enum { //some random constants
// Timer to update aggrometer // Timer to update aggrometer
#define AGGRO_METER_UPDATE_MS 1000 #define AGGRO_METER_UPDATE_MS 1000
//Some hard coded statuses from commands and other places:
enum {
minStatusToBeGM = 40,
minStatusToUseGMCommands = 80,
minStatusToKick = 150,
minStatusToAvoidFalling = 100,
minStatusToIgnoreZoneFlags = 80,
minStatusToSeeOthersZoneFlags = 80,
minStatusToEditOtherGuilds = 80,
commandMovecharSelfOnly = 80, //below this == only self move allowed
commandMovecharToSpecials = 200, //ability to send people to cshom/load zones
commandCastSpecials = 100, //can cast special spells
commandDoAnimOthers = 100, //can #doanim on others
commandEditPlayerCorpses = 150, //can Edit Player Corpses
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump
commandInvSnapshot = 150 //ability to clear/restore snapshots
};
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars // This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
#define SAYLINK_ITEM_ID 0xFFFFF #define SAYLINK_ITEM_ID 0xFFFFF
+1
View File
@@ -356,6 +356,7 @@ namespace EQ
struct ItemData { struct ItemData {
// Non packet based fields // Non packet based fields
uint8 MinStatus {}; uint8 MinStatus {};
char Comment[255] {};
// Packet based fields // Packet based fields
uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book uint8 ItemClass {}; // Item Type: 0=common, 1=container, 2=book
@@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseBlockedSpellsRepository { class BaseBlockedSpellsRepository {
public: public:
struct BlockedSpells { struct BlockedSpells {
@@ -31,6 +32,10 @@ public:
float z_diff; float z_diff;
std::string message; std::string message;
std::string description; std::string description;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
std::string content_flags_disabled;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@@ -53,6 +58,10 @@ public:
"z_diff", "z_diff",
"message", "message",
"description", "description",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
}; };
} }
@@ -71,6 +80,10 @@ public:
"z_diff", "z_diff",
"message", "message",
"description", "description",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
}; };
} }
@@ -123,6 +136,10 @@ public:
e.z_diff = 0; e.z_diff = 0;
e.message = ""; e.message = "";
e.description = ""; e.description = "";
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
e.content_flags_disabled = "";
return e; return e;
} }
@@ -148,8 +165,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
blocked_spells_id blocked_spells_id
) )
); );
@@ -170,6 +188,10 @@ public:
e.z_diff = strtof(row[9], nullptr); e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : ""; e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : ""; e.description = row[11] ? row[11] : "";
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
return e; return e;
} }
@@ -214,6 +236,10 @@ public:
v.push_back(columns[9] + " = " + std::to_string(e.z_diff)); v.push_back(columns[9] + " = " + std::to_string(e.z_diff));
v.push_back(columns[10] + " = '" + Strings::Escape(e.message) + "'"); v.push_back(columns[10] + " = '" + Strings::Escape(e.message) + "'");
v.push_back(columns[11] + " = '" + Strings::Escape(e.description) + "'"); v.push_back(columns[11] + " = '" + Strings::Escape(e.description) + "'");
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( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -247,6 +273,10 @@ public:
v.push_back(std::to_string(e.z_diff)); v.push_back(std::to_string(e.z_diff));
v.push_back("'" + Strings::Escape(e.message) + "'"); v.push_back("'" + Strings::Escape(e.message) + "'");
v.push_back("'" + Strings::Escape(e.description) + "'"); v.push_back("'" + Strings::Escape(e.description) + "'");
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( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -288,6 +318,10 @@ public:
v.push_back(std::to_string(e.z_diff)); v.push_back(std::to_string(e.z_diff));
v.push_back("'" + Strings::Escape(e.message) + "'"); v.push_back("'" + Strings::Escape(e.message) + "'");
v.push_back("'" + Strings::Escape(e.description) + "'"); v.push_back("'" + Strings::Escape(e.description) + "'");
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) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@@ -333,6 +367,10 @@ public:
e.z_diff = strtof(row[9], nullptr); e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : ""; e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : ""; e.description = row[11] ? row[11] : "";
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -369,6 +407,10 @@ public:
e.z_diff = strtof(row[9], nullptr); e.z_diff = strtof(row[9], nullptr);
e.message = row[10] ? row[10] : ""; e.message = row[10] ? row[10] : "";
e.description = row[11] ? row[11] : ""; e.description = row[11] ? row[11] : "";
e.min_expansion = static_cast<int8_t>(atoi(row[12]));
e.max_expansion = static_cast<int8_t>(atoi(row[13]));
e.content_flags = row[14] ? row[14] : "";
e.content_flags_disabled = row[15] ? row[15] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -75,7 +75,7 @@ public:
int32_t damageshield; int32_t damageshield;
int32_t deity; int32_t deity;
int32_t delay; int32_t delay;
int32_t augdistiller; uint32_t augdistiller;
int32_t dotshielding; int32_t dotshielding;
int32_t dr; int32_t dr;
int32_t clicktype; int32_t clicktype;
@@ -227,7 +227,7 @@ public:
int32_t focusunk5; int32_t focusunk5;
std::string focusunk6; std::string focusunk6;
int32_t focusunk7; int32_t focusunk7;
int32_t scrollunk1; uint32_t scrollunk1;
int32_t scrollunk2; int32_t scrollunk2;
int32_t scrollunk3; int32_t scrollunk3;
int32_t scrollunk4; int32_t scrollunk4;
@@ -266,10 +266,10 @@ public:
std::string created; std::string created;
int16_t elitematerial; int16_t elitematerial;
int16_t ldonsellbackrate; int16_t ldonsellbackrate;
int16_t scriptfileid; int32_t scriptfileid;
int16_t expendablearrow; int16_t expendablearrow;
int16_t powersourcecapacity; int32_t powersourcecapacity;
int16_t bardeffect; int32_t bardeffect;
int16_t bardeffecttype; int16_t bardeffecttype;
int16_t bardlevel2; int16_t bardlevel2;
int16_t bardlevel; int16_t bardlevel;
@@ -1307,7 +1307,7 @@ public:
e.damageshield = static_cast<int32_t>(atoi(row[52])); e.damageshield = static_cast<int32_t>(atoi(row[52]));
e.deity = static_cast<int32_t>(atoi(row[53])); e.deity = static_cast<int32_t>(atoi(row[53]));
e.delay = static_cast<int32_t>(atoi(row[54])); e.delay = static_cast<int32_t>(atoi(row[54]));
e.augdistiller = static_cast<int32_t>(atoi(row[55])); e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.dotshielding = static_cast<int32_t>(atoi(row[56])); e.dotshielding = static_cast<int32_t>(atoi(row[56]));
e.dr = static_cast<int32_t>(atoi(row[57])); e.dr = static_cast<int32_t>(atoi(row[57]));
e.clicktype = static_cast<int32_t>(atoi(row[58])); e.clicktype = static_cast<int32_t>(atoi(row[58]));
@@ -1459,7 +1459,7 @@ public:
e.focusunk5 = static_cast<int32_t>(atoi(row[204])); e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
e.focusunk6 = row[205] ? row[205] : ""; e.focusunk6 = row[205] ? row[205] : "";
e.focusunk7 = static_cast<int32_t>(atoi(row[206])); e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
e.scrollunk1 = static_cast<int32_t>(atoi(row[207])); e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
e.scrollunk2 = static_cast<int32_t>(atoi(row[208])); e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
e.scrollunk3 = static_cast<int32_t>(atoi(row[209])); e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
e.scrollunk4 = static_cast<int32_t>(atoi(row[210])); e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
@@ -1498,10 +1498,10 @@ public:
e.created = row[243] ? row[243] : ""; e.created = row[243] ? row[243] : "";
e.elitematerial = static_cast<int16_t>(atoi(row[244])); e.elitematerial = static_cast<int16_t>(atoi(row[244]));
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245])); e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
e.scriptfileid = static_cast<int16_t>(atoi(row[246])); e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
e.expendablearrow = static_cast<int16_t>(atoi(row[247])); e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248])); e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
e.bardeffect = static_cast<int16_t>(atoi(row[249])); e.bardeffect = static_cast<int32_t>(atoi(row[249]));
e.bardeffecttype = static_cast<int16_t>(atoi(row[250])); e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
e.bardlevel2 = static_cast<int16_t>(atoi(row[251])); e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
e.bardlevel = static_cast<int16_t>(atoi(row[252])); e.bardlevel = static_cast<int16_t>(atoi(row[252]));
@@ -2563,7 +2563,7 @@ public:
e.damageshield = static_cast<int32_t>(atoi(row[52])); e.damageshield = static_cast<int32_t>(atoi(row[52]));
e.deity = static_cast<int32_t>(atoi(row[53])); e.deity = static_cast<int32_t>(atoi(row[53]));
e.delay = static_cast<int32_t>(atoi(row[54])); e.delay = static_cast<int32_t>(atoi(row[54]));
e.augdistiller = static_cast<int32_t>(atoi(row[55])); e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.dotshielding = static_cast<int32_t>(atoi(row[56])); e.dotshielding = static_cast<int32_t>(atoi(row[56]));
e.dr = static_cast<int32_t>(atoi(row[57])); e.dr = static_cast<int32_t>(atoi(row[57]));
e.clicktype = static_cast<int32_t>(atoi(row[58])); e.clicktype = static_cast<int32_t>(atoi(row[58]));
@@ -2715,7 +2715,7 @@ public:
e.focusunk5 = static_cast<int32_t>(atoi(row[204])); e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
e.focusunk6 = row[205] ? row[205] : ""; e.focusunk6 = row[205] ? row[205] : "";
e.focusunk7 = static_cast<int32_t>(atoi(row[206])); e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
e.scrollunk1 = static_cast<int32_t>(atoi(row[207])); e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
e.scrollunk2 = static_cast<int32_t>(atoi(row[208])); e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
e.scrollunk3 = static_cast<int32_t>(atoi(row[209])); e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
e.scrollunk4 = static_cast<int32_t>(atoi(row[210])); e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
@@ -2754,10 +2754,10 @@ public:
e.created = row[243] ? row[243] : ""; e.created = row[243] ? row[243] : "";
e.elitematerial = static_cast<int16_t>(atoi(row[244])); e.elitematerial = static_cast<int16_t>(atoi(row[244]));
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245])); e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
e.scriptfileid = static_cast<int16_t>(atoi(row[246])); e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
e.expendablearrow = static_cast<int16_t>(atoi(row[247])); e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248])); e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
e.bardeffect = static_cast<int16_t>(atoi(row[249])); e.bardeffect = static_cast<int32_t>(atoi(row[249]));
e.bardeffecttype = static_cast<int16_t>(atoi(row[250])); e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
e.bardlevel2 = static_cast<int16_t>(atoi(row[251])); e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
e.bardlevel = static_cast<int16_t>(atoi(row[252])); e.bardlevel = static_cast<int16_t>(atoi(row[252]));
@@ -2872,7 +2872,7 @@ public:
e.damageshield = static_cast<int32_t>(atoi(row[52])); e.damageshield = static_cast<int32_t>(atoi(row[52]));
e.deity = static_cast<int32_t>(atoi(row[53])); e.deity = static_cast<int32_t>(atoi(row[53]));
e.delay = static_cast<int32_t>(atoi(row[54])); e.delay = static_cast<int32_t>(atoi(row[54]));
e.augdistiller = static_cast<int32_t>(atoi(row[55])); e.augdistiller = static_cast<uint32_t>(strtoul(row[55], nullptr, 10));
e.dotshielding = static_cast<int32_t>(atoi(row[56])); e.dotshielding = static_cast<int32_t>(atoi(row[56]));
e.dr = static_cast<int32_t>(atoi(row[57])); e.dr = static_cast<int32_t>(atoi(row[57]));
e.clicktype = static_cast<int32_t>(atoi(row[58])); e.clicktype = static_cast<int32_t>(atoi(row[58]));
@@ -3024,7 +3024,7 @@ public:
e.focusunk5 = static_cast<int32_t>(atoi(row[204])); e.focusunk5 = static_cast<int32_t>(atoi(row[204]));
e.focusunk6 = row[205] ? row[205] : ""; e.focusunk6 = row[205] ? row[205] : "";
e.focusunk7 = static_cast<int32_t>(atoi(row[206])); e.focusunk7 = static_cast<int32_t>(atoi(row[206]));
e.scrollunk1 = static_cast<int32_t>(atoi(row[207])); e.scrollunk1 = static_cast<uint32_t>(strtoul(row[207], nullptr, 10));
e.scrollunk2 = static_cast<int32_t>(atoi(row[208])); e.scrollunk2 = static_cast<int32_t>(atoi(row[208]));
e.scrollunk3 = static_cast<int32_t>(atoi(row[209])); e.scrollunk3 = static_cast<int32_t>(atoi(row[209]));
e.scrollunk4 = static_cast<int32_t>(atoi(row[210])); e.scrollunk4 = static_cast<int32_t>(atoi(row[210]));
@@ -3063,10 +3063,10 @@ public:
e.created = row[243] ? row[243] : ""; e.created = row[243] ? row[243] : "";
e.elitematerial = static_cast<int16_t>(atoi(row[244])); e.elitematerial = static_cast<int16_t>(atoi(row[244]));
e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245])); e.ldonsellbackrate = static_cast<int16_t>(atoi(row[245]));
e.scriptfileid = static_cast<int16_t>(atoi(row[246])); e.scriptfileid = static_cast<int32_t>(atoi(row[246]));
e.expendablearrow = static_cast<int16_t>(atoi(row[247])); e.expendablearrow = static_cast<int16_t>(atoi(row[247]));
e.powersourcecapacity = static_cast<int16_t>(atoi(row[248])); e.powersourcecapacity = static_cast<int32_t>(atoi(row[248]));
e.bardeffect = static_cast<int16_t>(atoi(row[249])); e.bardeffect = static_cast<int32_t>(atoi(row[249]));
e.bardeffecttype = static_cast<int16_t>(atoi(row[250])); e.bardeffecttype = static_cast<int16_t>(atoi(row[250]));
e.bardlevel2 = static_cast<int16_t>(atoi(row[251])); e.bardlevel2 = static_cast<int16_t>(atoi(row[251]));
e.bardlevel = static_cast<int16_t>(atoi(row[252])); e.bardlevel = static_cast<int16_t>(atoi(row[252]));
@@ -0,0 +1,344 @@
/**
* 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://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_KEYRING_REPOSITORY_H
#define EQEMU_BASE_KEYRING_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseKeyringRepository {
public:
struct Keyring {
uint32_t id;
int32_t char_id;
int32_t item_id;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"char_id",
"item_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"char_id",
"item_id",
};
}
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("keyring");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static Keyring NewEntity()
{
Keyring e{};
e.id = 0;
e.char_id = 0;
e.item_id = 0;
return e;
}
static Keyring GetKeyring(
const std::vector<Keyring> &keyrings,
int keyring_id
)
{
for (auto &keyring : keyrings) {
if (keyring.id == keyring_id) {
return keyring;
}
}
return NewEntity();
}
static Keyring FindOne(
Database& db,
int keyring_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
keyring_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Keyring e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.char_id = static_cast<int32_t>(atoi(row[1]));
e.item_id = static_cast<int32_t>(atoi(row[2]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int keyring_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
keyring_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const Keyring &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));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Keyring InsertOne(
Database& db,
Keyring 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));
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<Keyring> &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));
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<Keyring> All(Database& db)
{
std::vector<Keyring> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Keyring e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.char_id = static_cast<int32_t>(atoi(row[1]));
e.item_id = static_cast<int32_t>(atoi(row[2]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<Keyring> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Keyring> 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) {
Keyring e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.char_id = static_cast<int32_t>(atoi(row[1]));
e.item_id = static_cast<int32_t>(atoi(row[2]));
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);
}
};
#endif //EQEMU_BASE_KEYRING_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseObjectRepository { class BaseObjectRepository {
public: public:
struct Object { struct Object {
@@ -31,9 +32,9 @@ public:
std::string objectname; std::string objectname;
int32_t type; int32_t type;
int32_t icon; int32_t icon;
int32_t unknown08; float size_percentage;
int32_t unknown10; int32_t solid_type;
int32_t unknown20; int32_t incline;
int32_t unknown24; int32_t unknown24;
int32_t unknown60; int32_t unknown60;
int32_t unknown64; int32_t unknown64;
@@ -71,9 +72,9 @@ public:
"objectname", "objectname",
"type", "type",
"icon", "icon",
"unknown08", "size_percentage",
"unknown10", "solid_type",
"unknown20", "incline",
"unknown24", "unknown24",
"unknown60", "unknown60",
"unknown64", "unknown64",
@@ -107,9 +108,9 @@ public:
"objectname", "objectname",
"type", "type",
"icon", "icon",
"unknown08", "size_percentage",
"unknown10", "solid_type",
"unknown20", "incline",
"unknown24", "unknown24",
"unknown60", "unknown60",
"unknown64", "unknown64",
@@ -177,9 +178,9 @@ public:
e.objectname = ""; e.objectname = "";
e.type = 0; e.type = 0;
e.icon = 0; e.icon = 0;
e.unknown08 = 0; e.size_percentage = 0;
e.unknown10 = 0; e.solid_type = 0;
e.unknown20 = 0; e.incline = 0;
e.unknown24 = 0; e.unknown24 = 0;
e.unknown60 = 0; e.unknown60 = 0;
e.unknown64 = 0; e.unknown64 = 0;
@@ -220,8 +221,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
object_id object_id
) )
); );
@@ -242,9 +244,9 @@ public:
e.objectname = row[9] ? row[9] : ""; e.objectname = row[9] ? row[9] : "";
e.type = static_cast<int32_t>(atoi(row[10])); e.type = static_cast<int32_t>(atoi(row[10]));
e.icon = static_cast<int32_t>(atoi(row[11])); e.icon = static_cast<int32_t>(atoi(row[11]));
e.unknown08 = static_cast<int32_t>(atoi(row[12])); e.size_percentage = strtof(row[12], nullptr);
e.unknown10 = static_cast<int32_t>(atoi(row[13])); e.solid_type = static_cast<int32_t>(atoi(row[13]));
e.unknown20 = static_cast<int32_t>(atoi(row[14])); e.incline = static_cast<int32_t>(atoi(row[14]));
e.unknown24 = static_cast<int32_t>(atoi(row[15])); e.unknown24 = static_cast<int32_t>(atoi(row[15]));
e.unknown60 = static_cast<int32_t>(atoi(row[16])); e.unknown60 = static_cast<int32_t>(atoi(row[16]));
e.unknown64 = static_cast<int32_t>(atoi(row[17])); e.unknown64 = static_cast<int32_t>(atoi(row[17]));
@@ -304,9 +306,9 @@ public:
v.push_back(columns[9] + " = '" + Strings::Escape(e.objectname) + "'"); v.push_back(columns[9] + " = '" + Strings::Escape(e.objectname) + "'");
v.push_back(columns[10] + " = " + std::to_string(e.type)); v.push_back(columns[10] + " = " + std::to_string(e.type));
v.push_back(columns[11] + " = " + std::to_string(e.icon)); v.push_back(columns[11] + " = " + std::to_string(e.icon));
v.push_back(columns[12] + " = " + std::to_string(e.unknown08)); v.push_back(columns[12] + " = " + std::to_string(e.size_percentage));
v.push_back(columns[13] + " = " + std::to_string(e.unknown10)); v.push_back(columns[13] + " = " + std::to_string(e.solid_type));
v.push_back(columns[14] + " = " + std::to_string(e.unknown20)); v.push_back(columns[14] + " = " + std::to_string(e.incline));
v.push_back(columns[15] + " = " + std::to_string(e.unknown24)); v.push_back(columns[15] + " = " + std::to_string(e.unknown24));
v.push_back(columns[16] + " = " + std::to_string(e.unknown60)); v.push_back(columns[16] + " = " + std::to_string(e.unknown60));
v.push_back(columns[17] + " = " + std::to_string(e.unknown64)); v.push_back(columns[17] + " = " + std::to_string(e.unknown64));
@@ -355,9 +357,9 @@ public:
v.push_back("'" + Strings::Escape(e.objectname) + "'"); v.push_back("'" + Strings::Escape(e.objectname) + "'");
v.push_back(std::to_string(e.type)); v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.icon)); v.push_back(std::to_string(e.icon));
v.push_back(std::to_string(e.unknown08)); v.push_back(std::to_string(e.size_percentage));
v.push_back(std::to_string(e.unknown10)); v.push_back(std::to_string(e.solid_type));
v.push_back(std::to_string(e.unknown20)); v.push_back(std::to_string(e.incline));
v.push_back(std::to_string(e.unknown24)); v.push_back(std::to_string(e.unknown24));
v.push_back(std::to_string(e.unknown60)); v.push_back(std::to_string(e.unknown60));
v.push_back(std::to_string(e.unknown64)); v.push_back(std::to_string(e.unknown64));
@@ -414,9 +416,9 @@ public:
v.push_back("'" + Strings::Escape(e.objectname) + "'"); v.push_back("'" + Strings::Escape(e.objectname) + "'");
v.push_back(std::to_string(e.type)); v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.icon)); v.push_back(std::to_string(e.icon));
v.push_back(std::to_string(e.unknown08)); v.push_back(std::to_string(e.size_percentage));
v.push_back(std::to_string(e.unknown10)); v.push_back(std::to_string(e.solid_type));
v.push_back(std::to_string(e.unknown20)); v.push_back(std::to_string(e.incline));
v.push_back(std::to_string(e.unknown24)); v.push_back(std::to_string(e.unknown24));
v.push_back(std::to_string(e.unknown60)); v.push_back(std::to_string(e.unknown60));
v.push_back(std::to_string(e.unknown64)); v.push_back(std::to_string(e.unknown64));
@@ -477,9 +479,9 @@ public:
e.objectname = row[9] ? row[9] : ""; e.objectname = row[9] ? row[9] : "";
e.type = static_cast<int32_t>(atoi(row[10])); e.type = static_cast<int32_t>(atoi(row[10]));
e.icon = static_cast<int32_t>(atoi(row[11])); e.icon = static_cast<int32_t>(atoi(row[11]));
e.unknown08 = static_cast<int32_t>(atoi(row[12])); e.size_percentage = strtof(row[12], nullptr);
e.unknown10 = static_cast<int32_t>(atoi(row[13])); e.solid_type = static_cast<int32_t>(atoi(row[13]));
e.unknown20 = static_cast<int32_t>(atoi(row[14])); e.incline = static_cast<int32_t>(atoi(row[14]));
e.unknown24 = static_cast<int32_t>(atoi(row[15])); e.unknown24 = static_cast<int32_t>(atoi(row[15]));
e.unknown60 = static_cast<int32_t>(atoi(row[16])); e.unknown60 = static_cast<int32_t>(atoi(row[16]));
e.unknown64 = static_cast<int32_t>(atoi(row[17])); e.unknown64 = static_cast<int32_t>(atoi(row[17]));
@@ -531,9 +533,9 @@ public:
e.objectname = row[9] ? row[9] : ""; e.objectname = row[9] ? row[9] : "";
e.type = static_cast<int32_t>(atoi(row[10])); e.type = static_cast<int32_t>(atoi(row[10]));
e.icon = static_cast<int32_t>(atoi(row[11])); e.icon = static_cast<int32_t>(atoi(row[11]));
e.unknown08 = static_cast<int32_t>(atoi(row[12])); e.size_percentage = strtof(row[12], nullptr);
e.unknown10 = static_cast<int32_t>(atoi(row[13])); e.solid_type = static_cast<int32_t>(atoi(row[13]));
e.unknown20 = static_cast<int32_t>(atoi(row[14])); e.incline = static_cast<int32_t>(atoi(row[14]));
e.unknown24 = static_cast<int32_t>(atoi(row[15])); e.unknown24 = static_cast<int32_t>(atoi(row[15]));
e.unknown60 = static_cast<int32_t>(atoi(row[16])); e.unknown60 = static_cast<int32_t>(atoi(row[16]));
e.unknown64 = static_cast<int32_t>(atoi(row[17])); e.unknown64 = static_cast<int32_t>(atoi(row[17]));
@@ -0,0 +1,354 @@
/**
* 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://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/
#ifndef EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H
#define EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseSpawn2DisabledRepository {
public:
struct Spawn2Disabled {
int64_t id;
int32_t spawn2_id;
int32_t instance_id;
int16_t disabled;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"spawn2_id",
"instance_id",
"disabled",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"spawn2_id",
"instance_id",
"disabled",
};
}
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("spawn2_disabled");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static Spawn2Disabled NewEntity()
{
Spawn2Disabled e{};
e.id = 0;
e.spawn2_id = 0;
e.instance_id = 0;
e.disabled = 0;
return e;
}
static Spawn2Disabled GetSpawn2Disabled(
const std::vector<Spawn2Disabled> &spawn2_disableds,
int spawn2_disabled_id
)
{
for (auto &spawn2_disabled : spawn2_disableds) {
if (spawn2_disabled.id == spawn2_disabled_id) {
return spawn2_disabled;
}
}
return NewEntity();
}
static Spawn2Disabled FindOne(
Database& db,
int spawn2_disabled_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
spawn2_disabled_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Spawn2Disabled e{};
e.id = strtoll(row[0], nullptr, 10);
e.spawn2_id = static_cast<int32_t>(atoi(row[1]));
e.instance_id = static_cast<int32_t>(atoi(row[2]));
e.disabled = static_cast<int16_t>(atoi(row[3]));
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int spawn2_disabled_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
spawn2_disabled_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const Spawn2Disabled &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.spawn2_id));
v.push_back(columns[2] + " = " + std::to_string(e.instance_id));
v.push_back(columns[3] + " = " + std::to_string(e.disabled));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Spawn2Disabled InsertOne(
Database& db,
Spawn2Disabled e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.spawn2_id));
v.push_back(std::to_string(e.instance_id));
v.push_back(std::to_string(e.disabled));
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<Spawn2Disabled> &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.spawn2_id));
v.push_back(std::to_string(e.instance_id));
v.push_back(std::to_string(e.disabled));
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<Spawn2Disabled> All(Database& db)
{
std::vector<Spawn2Disabled> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Spawn2Disabled e{};
e.id = strtoll(row[0], nullptr, 10);
e.spawn2_id = static_cast<int32_t>(atoi(row[1]));
e.instance_id = static_cast<int32_t>(atoi(row[2]));
e.disabled = static_cast<int16_t>(atoi(row[3]));
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<Spawn2Disabled> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Spawn2Disabled> 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) {
Spawn2Disabled e{};
e.id = strtoll(row[0], nullptr, 10);
e.spawn2_id = static_cast<int32_t>(atoi(row[1]));
e.instance_id = static_cast<int32_t>(atoi(row[2]));
e.disabled = static_cast<int16_t>(atoi(row[3]));
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);
}
};
#endif //EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseSpawn2Repository { class BaseSpawn2Repository {
public: public:
struct Spawn2 { struct Spawn2 {
@@ -33,7 +34,6 @@ public:
int8_t path_when_zone_idle; int8_t path_when_zone_idle;
uint32_t _condition; uint32_t _condition;
int32_t cond_value; int32_t cond_value;
uint8_t enabled;
uint8_t animation; uint8_t animation;
int8_t min_expansion; int8_t min_expansion;
int8_t max_expansion; int8_t max_expansion;
@@ -63,7 +63,6 @@ public:
"path_when_zone_idle", "path_when_zone_idle",
"_condition", "_condition",
"cond_value", "cond_value",
"enabled",
"animation", "animation",
"min_expansion", "min_expansion",
"max_expansion", "max_expansion",
@@ -89,7 +88,6 @@ public:
"path_when_zone_idle", "path_when_zone_idle",
"_condition", "_condition",
"cond_value", "cond_value",
"enabled",
"animation", "animation",
"min_expansion", "min_expansion",
"max_expansion", "max_expansion",
@@ -149,7 +147,6 @@ public:
e.path_when_zone_idle = 0; e.path_when_zone_idle = 0;
e._condition = 0; e._condition = 0;
e.cond_value = 1; e.cond_value = 1;
e.enabled = 1;
e.animation = 0; e.animation = 0;
e.min_expansion = -1; e.min_expansion = -1;
e.max_expansion = -1; e.max_expansion = -1;
@@ -180,8 +177,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
spawn2_id spawn2_id
) )
); );
@@ -204,12 +202,11 @@ public:
e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11])); e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11]));
e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10)); e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.cond_value = static_cast<int32_t>(atoi(row[13])); e.cond_value = static_cast<int32_t>(atoi(row[13]));
e.enabled = static_cast<uint8_t>(strtoul(row[14], nullptr, 10)); e.animation = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.animation = static_cast<uint8_t>(strtoul(row[15], nullptr, 10)); e.min_expansion = static_cast<int8_t>(atoi(row[15]));
e.min_expansion = static_cast<int8_t>(atoi(row[16])); e.max_expansion = static_cast<int8_t>(atoi(row[16]));
e.max_expansion = static_cast<int8_t>(atoi(row[17])); e.content_flags = row[17] ? row[17] : "";
e.content_flags = row[18] ? row[18] : ""; e.content_flags_disabled = row[18] ? row[18] : "";
e.content_flags_disabled = row[19] ? row[19] : "";
return e; return e;
} }
@@ -256,12 +253,11 @@ public:
v.push_back(columns[11] + " = " + std::to_string(e.path_when_zone_idle)); v.push_back(columns[11] + " = " + std::to_string(e.path_when_zone_idle));
v.push_back(columns[12] + " = " + std::to_string(e._condition)); v.push_back(columns[12] + " = " + std::to_string(e._condition));
v.push_back(columns[13] + " = " + std::to_string(e.cond_value)); v.push_back(columns[13] + " = " + std::to_string(e.cond_value));
v.push_back(columns[14] + " = " + std::to_string(e.enabled)); v.push_back(columns[14] + " = " + std::to_string(e.animation));
v.push_back(columns[15] + " = " + std::to_string(e.animation)); v.push_back(columns[15] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[16] + " = " + std::to_string(e.min_expansion)); v.push_back(columns[16] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[17] + " = " + std::to_string(e.max_expansion)); v.push_back(columns[17] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[18] + " = '" + Strings::Escape(e.content_flags) + "'"); v.push_back(columns[18] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[19] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -297,7 +293,6 @@ public:
v.push_back(std::to_string(e.path_when_zone_idle)); v.push_back(std::to_string(e.path_when_zone_idle));
v.push_back(std::to_string(e._condition)); v.push_back(std::to_string(e._condition));
v.push_back(std::to_string(e.cond_value)); v.push_back(std::to_string(e.cond_value));
v.push_back(std::to_string(e.enabled));
v.push_back(std::to_string(e.animation)); v.push_back(std::to_string(e.animation));
v.push_back(std::to_string(e.min_expansion)); v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion)); v.push_back(std::to_string(e.max_expansion));
@@ -346,7 +341,6 @@ public:
v.push_back(std::to_string(e.path_when_zone_idle)); v.push_back(std::to_string(e.path_when_zone_idle));
v.push_back(std::to_string(e._condition)); v.push_back(std::to_string(e._condition));
v.push_back(std::to_string(e.cond_value)); v.push_back(std::to_string(e.cond_value));
v.push_back(std::to_string(e.enabled));
v.push_back(std::to_string(e.animation)); v.push_back(std::to_string(e.animation));
v.push_back(std::to_string(e.min_expansion)); v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion)); v.push_back(std::to_string(e.max_expansion));
@@ -399,12 +393,11 @@ public:
e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11])); e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11]));
e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10)); e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.cond_value = static_cast<int32_t>(atoi(row[13])); e.cond_value = static_cast<int32_t>(atoi(row[13]));
e.enabled = static_cast<uint8_t>(strtoul(row[14], nullptr, 10)); e.animation = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.animation = static_cast<uint8_t>(strtoul(row[15], nullptr, 10)); e.min_expansion = static_cast<int8_t>(atoi(row[15]));
e.min_expansion = static_cast<int8_t>(atoi(row[16])); e.max_expansion = static_cast<int8_t>(atoi(row[16]));
e.max_expansion = static_cast<int8_t>(atoi(row[17])); e.content_flags = row[17] ? row[17] : "";
e.content_flags = row[18] ? row[18] : ""; e.content_flags_disabled = row[18] ? row[18] : "";
e.content_flags_disabled = row[19] ? row[19] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -443,12 +436,11 @@ public:
e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11])); e.path_when_zone_idle = static_cast<int8_t>(atoi(row[11]));
e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10)); e._condition = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.cond_value = static_cast<int32_t>(atoi(row[13])); e.cond_value = static_cast<int32_t>(atoi(row[13]));
e.enabled = static_cast<uint8_t>(strtoul(row[14], nullptr, 10)); e.animation = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
e.animation = static_cast<uint8_t>(strtoul(row[15], nullptr, 10)); e.min_expansion = static_cast<int8_t>(atoi(row[15]));
e.min_expansion = static_cast<int8_t>(atoi(row[16])); e.max_expansion = static_cast<int8_t>(atoi(row[16]));
e.max_expansion = static_cast<int8_t>(atoi(row[17])); e.content_flags = row[17] ? row[17] : "";
e.content_flags = row[18] ? row[18] : ""; e.content_flags_disabled = row[18] ? row[18] : "";
e.content_flags_disabled = row[19] ? row[19] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseSpawnentryRepository { class BaseSpawnentryRepository {
public: public:
struct Spawnentry { struct Spawnentry {
@@ -23,6 +24,8 @@ public:
int32_t npcID; int32_t npcID;
int16_t chance; int16_t chance;
int32_t condition_value_filter; int32_t condition_value_filter;
int16_t min_time;
int16_t max_time;
int8_t min_expansion; int8_t min_expansion;
int8_t max_expansion; int8_t max_expansion;
std::string content_flags; std::string content_flags;
@@ -41,6 +44,8 @@ public:
"npcID", "npcID",
"chance", "chance",
"condition_value_filter", "condition_value_filter",
"min_time",
"max_time",
"min_expansion", "min_expansion",
"max_expansion", "max_expansion",
"content_flags", "content_flags",
@@ -55,6 +60,8 @@ public:
"npcID", "npcID",
"chance", "chance",
"condition_value_filter", "condition_value_filter",
"min_time",
"max_time",
"min_expansion", "min_expansion",
"max_expansion", "max_expansion",
"content_flags", "content_flags",
@@ -103,6 +110,8 @@ public:
e.npcID = 0; e.npcID = 0;
e.chance = 0; e.chance = 0;
e.condition_value_filter = 1; e.condition_value_filter = 1;
e.min_time = 0;
e.max_time = 0;
e.min_expansion = -1; e.min_expansion = -1;
e.max_expansion = -1; e.max_expansion = -1;
e.content_flags = ""; e.content_flags = "";
@@ -132,8 +141,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
spawnentry_id spawnentry_id
) )
); );
@@ -146,10 +156,12 @@ public:
e.npcID = static_cast<int32_t>(atoi(row[1])); e.npcID = static_cast<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2])); e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3])); e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4])); e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5])); e.max_time = static_cast<int16_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : ""; e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.content_flags_disabled = row[7] ? row[7] : ""; e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
return e; return e;
} }
@@ -187,10 +199,12 @@ public:
v.push_back(columns[1] + " = " + std::to_string(e.npcID)); v.push_back(columns[1] + " = " + std::to_string(e.npcID));
v.push_back(columns[2] + " = " + std::to_string(e.chance)); v.push_back(columns[2] + " = " + std::to_string(e.chance));
v.push_back(columns[3] + " = " + std::to_string(e.condition_value_filter)); v.push_back(columns[3] + " = " + std::to_string(e.condition_value_filter));
v.push_back(columns[4] + " = " + std::to_string(e.min_expansion)); v.push_back(columns[4] + " = " + std::to_string(e.min_time));
v.push_back(columns[5] + " = " + std::to_string(e.max_expansion)); v.push_back(columns[5] + " = " + std::to_string(e.max_time));
v.push_back(columns[6] + " = '" + Strings::Escape(e.content_flags) + "'"); v.push_back(columns[6] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[7] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); v.push_back(columns[7] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -216,6 +230,8 @@ public:
v.push_back(std::to_string(e.npcID)); v.push_back(std::to_string(e.npcID));
v.push_back(std::to_string(e.chance)); v.push_back(std::to_string(e.chance));
v.push_back(std::to_string(e.condition_value_filter)); v.push_back(std::to_string(e.condition_value_filter));
v.push_back(std::to_string(e.min_time));
v.push_back(std::to_string(e.max_time));
v.push_back(std::to_string(e.min_expansion)); v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_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) + "'");
@@ -253,6 +269,8 @@ public:
v.push_back(std::to_string(e.npcID)); v.push_back(std::to_string(e.npcID));
v.push_back(std::to_string(e.chance)); v.push_back(std::to_string(e.chance));
v.push_back(std::to_string(e.condition_value_filter)); v.push_back(std::to_string(e.condition_value_filter));
v.push_back(std::to_string(e.min_time));
v.push_back(std::to_string(e.max_time));
v.push_back(std::to_string(e.min_expansion)); v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_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) + "'");
@@ -294,10 +312,12 @@ public:
e.npcID = static_cast<int32_t>(atoi(row[1])); e.npcID = static_cast<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2])); e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3])); e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4])); e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5])); e.max_time = static_cast<int16_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : ""; e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.content_flags_disabled = row[7] ? row[7] : ""; e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -326,10 +346,12 @@ public:
e.npcID = static_cast<int32_t>(atoi(row[1])); e.npcID = static_cast<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2])); e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3])); e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4])); e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5])); e.max_time = static_cast<int16_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : ""; e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.content_flags_disabled = row[7] ? row[7] : ""; e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -16,17 +16,18 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseStartingItemsRepository { class BaseStartingItemsRepository {
public: public:
struct StartingItems { struct StartingItems {
uint32_t id; uint32_t id;
int32_t race; std::string race_list;
int32_t class_; std::string class_list;
int32_t deityid; std::string deity_list;
int32_t zoneid; std::string zone_id_list;
int32_t itemid; uint32_t item_id;
uint8_t item_charges; uint8_t item_charges;
int8_t gm; uint8_t gm;
int32_t slot; int32_t slot;
int8_t min_expansion; int8_t min_expansion;
int8_t max_expansion; int8_t max_expansion;
@@ -43,11 +44,11 @@ public:
{ {
return { return {
"id", "id",
"race", "race_list",
"`class`", "class_list",
"deityid", "deity_list",
"zoneid", "zone_id_list",
"itemid", "item_id",
"item_charges", "item_charges",
"gm", "gm",
"slot", "slot",
@@ -62,11 +63,11 @@ public:
{ {
return { return {
"id", "id",
"race", "race_list",
"`class`", "class_list",
"deityid", "deity_list",
"zoneid", "zone_id_list",
"itemid", "item_id",
"item_charges", "item_charges",
"gm", "gm",
"slot", "slot",
@@ -115,11 +116,11 @@ public:
StartingItems e{}; StartingItems e{};
e.id = 0; e.id = 0;
e.race = 0; e.race_list = "";
e.class_ = 0; e.class_list = "";
e.deityid = 0; e.deity_list = "";
e.zoneid = 0; e.zone_id_list = "";
e.itemid = 0; e.item_id = 0;
e.item_charges = 1; e.item_charges = 1;
e.gm = 0; e.gm = 0;
e.slot = -1; e.slot = -1;
@@ -152,8 +153,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
starting_items_id starting_items_id
) )
); );
@@ -163,13 +165,13 @@ public:
StartingItems e{}; StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10)); e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race = static_cast<int32_t>(atoi(row[1])); e.race_list = row[1] ? row[1] : "";
e.class_ = static_cast<int32_t>(atoi(row[2])); e.class_list = row[2] ? row[2] : "";
e.deityid = static_cast<int32_t>(atoi(row[3])); e.deity_list = row[3] ? row[3] : "";
e.zoneid = static_cast<int32_t>(atoi(row[4])); e.zone_id_list = row[4] ? row[4] : "";
e.itemid = static_cast<int32_t>(atoi(row[5])); e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10)); e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.gm = static_cast<int8_t>(atoi(row[7])); e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.slot = static_cast<int32_t>(atoi(row[8])); e.slot = static_cast<int32_t>(atoi(row[8]));
e.min_expansion = static_cast<int8_t>(atoi(row[9])); e.min_expansion = static_cast<int8_t>(atoi(row[9]));
e.max_expansion = static_cast<int8_t>(atoi(row[10])); e.max_expansion = static_cast<int8_t>(atoi(row[10]));
@@ -208,11 +210,11 @@ public:
auto columns = Columns(); auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.race)); v.push_back(columns[1] + " = '" + Strings::Escape(e.race_list) + "'");
v.push_back(columns[2] + " = " + std::to_string(e.class_)); v.push_back(columns[2] + " = '" + Strings::Escape(e.class_list) + "'");
v.push_back(columns[3] + " = " + std::to_string(e.deityid)); v.push_back(columns[3] + " = '" + Strings::Escape(e.deity_list) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.zoneid)); v.push_back(columns[4] + " = '" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(columns[5] + " = " + std::to_string(e.itemid)); v.push_back(columns[5] + " = " + std::to_string(e.item_id));
v.push_back(columns[6] + " = " + std::to_string(e.item_charges)); v.push_back(columns[6] + " = " + std::to_string(e.item_charges));
v.push_back(columns[7] + " = " + std::to_string(e.gm)); v.push_back(columns[7] + " = " + std::to_string(e.gm));
v.push_back(columns[8] + " = " + std::to_string(e.slot)); v.push_back(columns[8] + " = " + std::to_string(e.slot));
@@ -242,11 +244,11 @@ public:
std::vector<std::string> v; std::vector<std::string> v;
v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.race)); v.push_back("'" + Strings::Escape(e.race_list) + "'");
v.push_back(std::to_string(e.class_)); v.push_back("'" + Strings::Escape(e.class_list) + "'");
v.push_back(std::to_string(e.deityid)); v.push_back("'" + Strings::Escape(e.deity_list) + "'");
v.push_back(std::to_string(e.zoneid)); v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.itemid)); 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.item_charges));
v.push_back(std::to_string(e.gm)); v.push_back(std::to_string(e.gm));
v.push_back(std::to_string(e.slot)); v.push_back(std::to_string(e.slot));
@@ -284,11 +286,11 @@ public:
std::vector<std::string> v; std::vector<std::string> v;
v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.race)); v.push_back("'" + Strings::Escape(e.race_list) + "'");
v.push_back(std::to_string(e.class_)); v.push_back("'" + Strings::Escape(e.class_list) + "'");
v.push_back(std::to_string(e.deityid)); v.push_back("'" + Strings::Escape(e.deity_list) + "'");
v.push_back(std::to_string(e.zoneid)); v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.itemid)); 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.item_charges));
v.push_back(std::to_string(e.gm)); v.push_back(std::to_string(e.gm));
v.push_back(std::to_string(e.slot)); v.push_back(std::to_string(e.slot));
@@ -330,13 +332,13 @@ public:
StartingItems e{}; StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10)); e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race = static_cast<int32_t>(atoi(row[1])); e.race_list = row[1] ? row[1] : "";
e.class_ = static_cast<int32_t>(atoi(row[2])); e.class_list = row[2] ? row[2] : "";
e.deityid = static_cast<int32_t>(atoi(row[3])); e.deity_list = row[3] ? row[3] : "";
e.zoneid = static_cast<int32_t>(atoi(row[4])); e.zone_id_list = row[4] ? row[4] : "";
e.itemid = static_cast<int32_t>(atoi(row[5])); e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10)); e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.gm = static_cast<int8_t>(atoi(row[7])); e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.slot = static_cast<int32_t>(atoi(row[8])); e.slot = static_cast<int32_t>(atoi(row[8]));
e.min_expansion = static_cast<int8_t>(atoi(row[9])); e.min_expansion = static_cast<int8_t>(atoi(row[9]));
e.max_expansion = static_cast<int8_t>(atoi(row[10])); e.max_expansion = static_cast<int8_t>(atoi(row[10]));
@@ -367,13 +369,13 @@ public:
StartingItems e{}; StartingItems e{};
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10)); e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.race = static_cast<int32_t>(atoi(row[1])); e.race_list = row[1] ? row[1] : "";
e.class_ = static_cast<int32_t>(atoi(row[2])); e.class_list = row[2] ? row[2] : "";
e.deityid = static_cast<int32_t>(atoi(row[3])); e.deity_list = row[3] ? row[3] : "";
e.zoneid = static_cast<int32_t>(atoi(row[4])); e.zone_id_list = row[4] ? row[4] : "";
e.itemid = static_cast<int32_t>(atoi(row[5])); e.item_id = static_cast<uint32_t>(strtoul(row[5], nullptr, 10));
e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10)); e.item_charges = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.gm = static_cast<int8_t>(atoi(row[7])); e.gm = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.slot = static_cast<int32_t>(atoi(row[8])); e.slot = static_cast<int32_t>(atoi(row[8]));
e.min_expansion = static_cast<int8_t>(atoi(row[9])); e.min_expansion = static_cast<int8_t>(atoi(row[9]));
e.max_expansion = static_cast<int8_t>(atoi(row[10])); e.max_expansion = static_cast<int8_t>(atoi(row[10]));
@@ -120,6 +120,8 @@ public:
{.parent_command = "set", .sub_command = "title_suffix", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "titlesuffix"}, {.parent_command = "set", .sub_command = "title_suffix", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "titlesuffix"},
{.parent_command = "set", .sub_command = "weather", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "weather"}, {.parent_command = "set", .sub_command = "weather", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "weather"},
{.parent_command = "set", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zclip|zcolor|zheader|zonelock|zsafecoords|zsky|zunderworld"}, {.parent_command = "set", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zclip|zcolor|zheader|zonelock|zsafecoords|zsky|zunderworld"},
{.parent_command = "show", .sub_command = "aas", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaas"},
{.parent_command = "show", .sub_command = "aa_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaapoints|showaapts"},
{.parent_command = "show", .sub_command = "aggro", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "aggro"}, {.parent_command = "show", .sub_command = "aggro", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "aggro"},
{.parent_command = "show", .sub_command = "buffs", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showbuffs"}, {.parent_command = "show", .sub_command = "buffs", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showbuffs"},
{.parent_command = "show", .sub_command = "buried_corpse_count", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getplayerburiedcorpsecount"}, {.parent_command = "show", .sub_command = "buried_corpse_count", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getplayerburiedcorpsecount"},
+50
View File
@@ -0,0 +1,50 @@
#ifndef EQEMU_KEYRING_REPOSITORY_H
#define EQEMU_KEYRING_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_keyring_repository.h"
class KeyringRepository: public BaseKeyringRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* KeyringRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* KeyringRepository::GetWhereNeverExpires()
* KeyringRepository::GetWhereXAndY()
* KeyringRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_KEYRING_REPOSITORY_H
@@ -0,0 +1,50 @@
#ifndef EQEMU_SPAWN2_DISABLED_REPOSITORY_H
#define EQEMU_SPAWN2_DISABLED_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_spawn2_disabled_repository.h"
class Spawn2DisabledRepository: public BaseSpawn2DisabledRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* Spawn2DisabledRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* Spawn2DisabledRepository::GetWhereNeverExpires()
* Spawn2DisabledRepository::GetWhereXAndY()
* Spawn2DisabledRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_SPAWN2_DISABLED_REPOSITORY_H
+3
View File
@@ -303,6 +303,8 @@ RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for cha
RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)") RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt") RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30") RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30")
RULE_INT(World, BootHour, 0, "Sets the in-game hour world will set when it first boots. 0-24 are valid options, where 0 disables this rule")
RULE_BOOL(World, UseItemLinksForKeyRing, false, "Uses item links for Key Ring Listing instead of item name")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Zone) RULE_CATEGORY(Zone)
@@ -648,6 +650,7 @@ RULE_BOOL(Bots, ResurrectionSickness, true, "Use Resurrection Sickness based on
RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell") RULE_INT(Bots, OldResurrectionSicknessSpell, 757, "757 is Default Old Resurrection Sickness Spell")
RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell") RULE_INT(Bots, ResurrectionSicknessSpell, 756, "756 is Default Resurrection Sickness Spell")
RULE_BOOL(Bots, AllowPickpocketCommand, true, "Allows the use of the bot command 'pickpocket'") RULE_BOOL(Bots, AllowPickpocketCommand, true, "Allows the use of the bot command 'pickpocket'")
RULE_BOOL(Bots, BotHealOnLevel, false, "Setting whether a bot should heal completely when leveling. Default FALSE.")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Chat) RULE_CATEGORY(Chat)
+1
View File
@@ -19,6 +19,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdint.h>
typedef struct eq_cpu_info_s { typedef struct eq_cpu_info_s {
std::string model; std::string model;
+8 -8
View File
@@ -461,12 +461,12 @@ struct SPackSendQueue {
uchar buffer[0]; uchar buffer[0];
}; };
struct ServerZoneStateChange_struct { struct ServerZoneStateChange_Struct {
uint32 ZoneServerID; uint32 zone_server_id;
char adminname[64]; uint32 zone_id;
uint32 zoneid; uint16 instance_id;
uint16 instanceid; bool is_static;
bool makestatic; char admin_name[64];
}; };
struct ServerZoneIncomingClient_Struct { struct ServerZoneIncomingClient_Struct {
@@ -1142,10 +1142,10 @@ struct ServerInstanceUpdateTime_Struct
uint32 new_duration; uint32 new_duration;
}; };
struct ServerSpawnStatusChange_Struct struct ServerSpawnStatusChange_Struct {
{
uint32 id; uint32 id;
bool new_status; bool new_status;
uint32 instance_id;
}; };
struct ServerQGlobalUpdate_Struct struct ServerQGlobalUpdate_Struct
+74 -31
View File
@@ -41,6 +41,7 @@
#include "repositories/criteria/content_filter_criteria.h" #include "repositories/criteria/content_filter_criteria.h"
#include "repositories/account_repository.h" #include "repositories/account_repository.h"
#include "repositories/faction_association_repository.h" #include "repositories/faction_association_repository.h"
#include "repositories/starting_items_repository.h"
#include "path_manager.h" #include "path_manager.h"
#include "repositories/loottable_repository.h" #include "repositories/loottable_repository.h"
@@ -51,7 +52,9 @@ namespace ItemField
#define F(x) x, #define F(x) x,
#include "item_fieldlist.h" #include "item_fieldlist.h"
#undef F #undef F
updated updated,
minstatus,
comment,
}; };
} }
@@ -444,45 +447,81 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
return true; return true;
} }
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQ::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { bool SharedDatabase::SetStartingItems(
PlayerProfile_Struct *pp,
EQ::InventoryProfile *inv,
uint32 si_race,
uint32 si_class,
uint32 si_deity,
uint32 si_current_zone,
char *si_name,
int admin_level
)
{
const EQ::ItemData *item_data;
const EQ::ItemData *myitem; const auto &l = StartingItemsRepository::All(*this);
const std::string query = StringFormat( if (l.empty()) {
"SELECT itemid, item_charges, slot FROM starting_items "
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
"(deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND "
"gm <= %i %s ORDER BY id",
si_race,
si_class,
si_deity,
si_current_zone,
admin_level,
ContentFilterCriteria::apply().c_str()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false; return false;
} }
std::vector<StartingItemsRepository::StartingItems> v;
for (auto& row = results.begin(); row != results.end(); ++row) { for (const auto &e : l) {
const int32 itemid = Strings::ToInt(row[0]); const auto &classes = Strings::Split(e.class_list, "|");
const int32 charges = Strings::ToInt(row[1]); const auto &deities = Strings::Split(e.deity_list, "|");
int32 slot = Strings::ToInt(row[2]); const auto &races = Strings::Split(e.race_list, "|");
myitem = GetItem(itemid); const auto &zones = Strings::Split(e.zone_id_list, "|");
if(!myitem) const std::string &all = std::to_string(0);
if (classes[0] != all) {
if (!Strings::Contains(classes, std::to_string(si_class))) {
continue; continue;
}
}
const EQ::ItemInstance* myinst = CreateBaseItem(myitem, charges); if (deities[0] != all) {
if (!Strings::Contains(deities, std::to_string(si_deity))) {
continue;
}
}
if(slot < 0) if (races[0] != all) {
slot = inv->FindFreeSlot(0, 0); if (!Strings::Contains(races, std::to_string(si_race))) {
continue;
}
}
inv->PutItem(slot, *myinst); if (zones[0] != all) {
safe_delete(myinst); if (!Strings::Contains(zones, std::to_string(si_current_zone))) {
continue;
}
}
v.emplace_back(e);
}
for (const auto &e : v) {
const uint32 item_id = e.item_id;
const uint8 item_charges = e.item_charges;
int32 slot = e.slot;
item_data = GetItem(item_id);
if (!item_data) {
continue;
}
const auto *inst = CreateBaseItem(item_data, item_charges);
if (slot < EQ::invslot::slotCharm) {
slot = inv->FindFreeSlot(false, false);
}
inv->PutItem(slot, *inst);
safe_delete(inst);
} }
return true; return true;
@@ -965,7 +1004,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
#define F(x) "`"#x"`," #define F(x) "`"#x"`,"
#include "item_fieldlist.h" #include "item_fieldlist.h"
#undef F #undef F
"updated FROM items ORDER BY id"; "updated, minstatus, comment FROM items ORDER BY id";
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return; return;
@@ -977,9 +1016,13 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
// Unique Identifier // Unique Identifier
item.ID = Strings::ToUnsignedInt(row[ItemField::id]); item.ID = Strings::ToUnsignedInt(row[ItemField::id]);
// Name and Lore // Minimum Status
item.MinStatus = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::minstatus]));
// Name, Lore, and Comment
strn0cpy(item.Name, row[ItemField::name], sizeof(item.Name)); strn0cpy(item.Name, row[ItemField::name], sizeof(item.Name));
strn0cpy(item.Lore, row[ItemField::lore], sizeof(item.Lore)); strn0cpy(item.Lore, row[ItemField::lore], sizeof(item.Lore));
strn0cpy(item.Comment, row[ItemField::comment], sizeof(item.Comment));
// Flags // Flags
item.ArtifactFlag = Strings::ToBool(row[ItemField::artifactflag]); item.ArtifactFlag = Strings::ToBool(row[ItemField::artifactflag]);
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables // Build variables
// these get injected during the build pipeline // these get injected during the build pipeline
#define CURRENT_VERSION "22.30.1-dev" // always append -dev to the current version for custom-builds #define CURRENT_VERSION "22.35.0-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0" #define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__ #define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__ #define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9239 #define CURRENT_BINARY_DATABASE_VERSION 9246
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040
+9 -27
View File
@@ -121,43 +121,25 @@ bool Database::GetLoginTokenDataFromToken(
std::string &user std::string &user
) )
{ {
auto query = fmt::format( auto query = fmt::format("SELECT login_server, username, account_id FROM login_tickets WHERE expires > NOW()"
"SELECT tbllogintokens.Id, tbllogintokens.IpAddress, tbllogintokenclaims.Name, tbllogintokenclaims.Value FROM tbllogintokens " " AND id='{0}' AND ip_address='{1}' LIMIT 1",
"JOIN tbllogintokenclaims ON tbllogintokens.Id = tbllogintokenclaims.TokenId WHERE tbllogintokens.Expires > NOW() "
"AND tbllogintokens.Id='{0}' AND tbllogintokens.IpAddress='{1}'",
Strings::Escape(token), Strings::Escape(token),
Strings::Escape(ip) Strings::Escape(ip));
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (results.RowCount() == 0 || !results.Success()) { if (results.RowCount() == 0 || !results.Success()) {
return false; return false;
} }
bool found_username = false;
bool found_login_id = false;
bool found_login_server_name = false;
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
if (strcmp(row[2], "username") == 0) { db_loginserver = row[0];
user = row[3]; user = row[1];
found_username = true; db_account_id = Strings::ToUnsignedInt(row[2]);
continue;
return true;
} }
if (strcmp(row[2], "login_server_id") == 0) { return false;
db_account_id = Strings::ToUnsignedInt(row[3]);
found_login_id = true;
continue;
}
if (strcmp(row[2], "login_server_name") == 0) {
db_loginserver = row[3];
found_login_server_name = true;
continue;
}
}
return found_username && found_login_id && found_login_server_name;
} }
/** /**
+11
View File
@@ -0,0 +1,11 @@
DROP TABLE IF EXISTS `login_tickets`;
CREATE TABLE `login_tickets` (
`id` VARCHAR(128) NOT NULL,
`login_server` TEXT NOT NULL,
`username` TEXT NOT NULL,
`account_id` INT(10) UNSIGNED NOT NULL,
`ip_address` VARCHAR(45) NOT NULL,
`expires` DATETIME NOT NULL,
PRIMARY KEY (`id`) USING BTREE
)
ENGINE=InnoDB;
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "eqemu-server", "name": "eqemu-server",
"version": "22.30.1", "version": "22.35.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/EQEmu/Server.git" "url": "https://github.com/EQEmu/Server.git"
+11 -1
View File
@@ -9,7 +9,17 @@ git submodule init && git submodule update
perl utils/scripts/build/tag-version.pl perl utils/scripts/build/tag-version.pl
mkdir -p build && cd build && cmake -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_STATIC=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DEQEMU_BUILD_PERL=ON -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-Os" -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -G 'Unix Makefiles' .. && make -j$((`nproc`-4)) mkdir -p build && cd build && \
cmake -DEQEMU_BUILD_TESTS=ON \
-DEQEMU_BUILD_STATIC=ON \
-DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_LUA=ON \
-DEQEMU_BUILD_PERL=ON \
-DCMAKE_CXX_FLAGS:STRING="-O1 -g" \
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O1 -g" \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-G 'Unix Makefiles' \
.. && make -j$((`nproc`-4))
curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json curl https://raw.githubusercontent.com/Akkadius/eqemu-install-v2/master/eqemu_config.json --output eqemu_config.json
./bin/tests ./bin/tests
+28 -11
View File
@@ -2,8 +2,13 @@
######################################################################## ########################################################################
#::: 13th floor import script #::: 13th floor import script
#::: Current Source: http://items.sodeq.org/download.php #::: Items Source: http://items.sodeq.org/download.php
#::: Authors: (Natedog, Akkadius) #::: How To:
#::: 1. Place this script with your server eqemu_config.json
#::: 2. Download the items.txt file and place with this script
#::: 3. Run this script with Perl
#::: 4. Review new and updated items in the items_new table
#::: 5. Make any desired changes and replace the items table contents
######################################################################## ########################################################################
use DBI; use DBI;
@@ -16,6 +21,7 @@ my $db_user = "";
my $db_pass = ""; my $db_pass = "";
my $total_items = 0; my $total_items = 0;
my $read_items_file = "items.txt"; #default my $read_items_file = "items.txt"; #default
my $keep_temp_items_table = 0; #keeps the imported items table
read_eqemu_config_json(); read_eqemu_config_json();
@@ -24,7 +30,7 @@ my $dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;port=$db_port"
read_items_file_from_13th_floor_text(); read_items_file_from_13th_floor_text();
update_items_table(); update_items_table();
print "\n\nImport complete!\n\n"; print "\n\nImport complete! Review items_new table before replacing into items table.\n\n";
sub read_eqemu_config_json { sub read_eqemu_config_json {
use JSON; use JSON;
@@ -139,7 +145,12 @@ sub read_items_file_from_13th_floor_text {
sub update_items_table { sub update_items_table {
print "Updating items table...\n"; #::: Establish items_new table
print "Setting up new items table...\n";
$dbh->do("DROP TABLE IF EXISTS items_new");
$dbh->do("CREATE TABLE items_new AS SELECT * FROM items");
print "Updating new items table...\n";
my @matching_table; my @matching_table;
my @missing_items_table; my @missing_items_table;
@@ -147,7 +158,7 @@ sub update_items_table {
print "Comparing table structure...\n"; print "Comparing table structure...\n";
#::: Get columns from `items` #::: Get columns from `items`
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items`;"); my $sth = $dbh->prepare("SHOW COLUMNS FROM `items_new`;");
$sth->execute(); $sth->execute();
my @items_table; my @items_table;
while (my @row = $sth->fetchrow_array()) { while (my @row = $sth->fetchrow_array()) {
@@ -230,7 +241,7 @@ sub update_items_table {
} }
my $update_query = " my $update_query = "
INSERT INTO items (" . $items_field_list . ") INSERT INTO items_new (" . $items_field_list . ")
SELECT " . $items_floor_field_list . " SELECT " . $items_floor_field_list . "
FROM items_floor fi FROM items_floor fi
ON DUPLICATE KEY UPDATE " . $update_fields; ON DUPLICATE KEY UPDATE " . $update_fields;
@@ -257,14 +268,20 @@ sub update_items_table {
#::: Update stackables #::: Update stackables
print "Updating stackable field...\n"; print "Updating stackable field...\n";
$dbh->do("UPDATE items i SET i.stackable = 1 WHERE i.stacksize > 1"); $dbh->do("UPDATE items_new i SET i.stackable = 1 WHERE i.stacksize > 1");
#::: Update legacy research tome bagtypes #::: Update legacy research tome bagtypes
print "Updating legacy research tomes...\n"; print "Updating legacy research tomes...\n";
$dbh->do("UPDATE items i SET i.bagtype = 24 WHERE i.id IN (17655, 17903)"); #RESEARCHWIZ $dbh->do("UPDATE items_new i SET i.bagtype = 24 WHERE i.id IN (17655, 17903)"); #RESEARCHWIZ
$dbh->do("UPDATE items i SET i.bagtype = 25 WHERE i.id IN (17502, 17653)"); #RESEARCHMAG $dbh->do("UPDATE items_new i SET i.bagtype = 25 WHERE i.id IN (17502, 17653)"); #RESEARCHMAG
$dbh->do("UPDATE items i SET i.bagtype = 26 WHERE i.id IN (17501, 17654)"); #RESEARCHNEC $dbh->do("UPDATE items_new i SET i.bagtype = 26 WHERE i.id IN (17501, 17654)"); #RESEARCHNEC
$dbh->do("UPDATE items i SET i.bagtype = 27 WHERE i.id IN (17500, 17652)"); #RESEARCHENC $dbh->do("UPDATE items_new i SET i.bagtype = 27 WHERE i.id IN (17500, 17652)"); #RESEARCHENC
#::: Remove temp table
if (!$keep_temp_items_table) {
print "Cleaning up temp items table...\n";
$dbh->do("DROP TABLE items_floor");
}
} }
sub trim($) { sub trim($) {
+10 -10
View File
@@ -578,25 +578,25 @@ void ConsoleZoneShutdown(
strcpy(&tmpname[1], connection->UserName().c_str()); strcpy(&tmpname[1], connection->UserName().c_str());
auto pack = new ServerPacket; auto pack = new ServerPacket;
pack->size = sizeof(ServerZoneStateChange_struct); pack->size = sizeof(ServerZoneStateChange_Struct);
pack->pBuffer = new uchar[pack->size]; pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct)); memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_Struct));
ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer; auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
pack->opcode = ServerOP_ZoneShutdown; pack->opcode = ServerOP_ZoneShutdown;
strcpy(s->adminname, tmpname); strcpy(s->admin_name, tmpname);
if (Strings::IsNumber(args[0])) { if (Strings::IsNumber(args[0])) {
s->ZoneServerID = Strings::ToInt(args[0]); s->zone_server_id = Strings::ToInt(args[0]);
} }
else { else {
s->zoneid = ZoneID(args[0].c_str()); s->zone_id = ZoneID(args[0].c_str());
} }
ZoneServer *zs = 0; ZoneServer *zs = 0;
if (s->ZoneServerID != 0) { if (s->zone_server_id != 0) {
zs = zoneserver_list.FindByID(s->ZoneServerID); zs = zoneserver_list.FindByID(s->zone_server_id);
} }
else if (s->zoneid != 0) { else if (s->zone_id != 0) {
zs = zoneserver_list.FindByName(ZoneName(s->zoneid)); zs = zoneserver_list.FindByName(ZoneName(s->zone_id));
} }
else { else {
connection->SendLine("Error: ZoneShutdown: neither ID nor name specified"); connection->SendLine("Error: ZoneShutdown: neither ID nor name specified");
+14 -6
View File
@@ -424,12 +424,20 @@ int main(int argc, char **argv)
} }
if (EQTimeTimer.Check()) { if (EQTimeTimer.Check()) {
TimeOfDay_Struct tod; TimeOfDay_Struct tod{};
zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(0), &tod); zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(nullptr), &tod);
if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year)) if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year)) {
LogError("Failed to save eqtime"); LogEqTime("Failed to save eqtime");
else }
LogDebug("EQTime successfully saved"); else {
LogEqTimeDetail("EQTime successfully saved - time is now year [{}] month [{}] day [{}] hour [{}] minute [{}]",
tod.year,
tod.month,
tod.day,
tod.hour,
tod.minute
);
}
} }
zoneserver_list.Process(); zoneserver_list.Process();
+19 -16
View File
@@ -720,15 +720,15 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
break; break;
} }
case ServerOP_ZoneShutdown: { case ServerOP_ZoneShutdown: {
auto s = (ServerZoneStateChange_struct*) pack->pBuffer; auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
ZoneServer* zs = 0; ZoneServer* zs = 0;
if (s->ZoneServerID) { if (s->zone_server_id) {
zs = zoneserver_list.FindByID(s->ZoneServerID); zs = zoneserver_list.FindByID(s->zone_server_id);
} else if (s->zoneid) { } else if (s->zone_id) {
zs = zoneserver_list.FindByName(ZoneName(s->zoneid)); zs = zoneserver_list.FindByName(ZoneName(s->zone_id));
} else { } else {
zoneserver_list.SendEmoteMessage( zoneserver_list.SendEmoteMessage(
s->adminname, s->admin_name,
0, 0,
AccountStatus::Player, AccountStatus::Player,
Chat::White, Chat::White,
@@ -738,7 +738,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
if (!zs) { if (!zs) {
zoneserver_list.SendEmoteMessage( zoneserver_list.SendEmoteMessage(
s->adminname, s->admin_name,
0, 0,
AccountStatus::Player, AccountStatus::Player,
Chat::White, Chat::White,
@@ -751,8 +751,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
break; break;
} }
case ServerOP_ZoneBootup: { case ServerOP_ZoneBootup: {
auto s = (ServerZoneStateChange_struct*) pack->pBuffer; auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
zoneserver_list.SOPZoneBootup(s->adminname, s->ZoneServerID, ZoneName(s->zoneid), s->makestatic); zoneserver_list.SOPZoneBootup(s->admin_name, s->zone_server_id, ZoneName(s->zone_id), s->is_static);
break; break;
} }
case ServerOP_ZoneStatus: { case ServerOP_ZoneStatus: {
@@ -1610,16 +1610,19 @@ void ZoneServer::TriggerBootup(uint32 in_zone_id, uint32 in_instance_id, const c
zone_server_zone_id = in_zone_id; zone_server_zone_id = in_zone_id;
instance_id = in_instance_id; instance_id = in_instance_id;
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct)); auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_Struct));
auto s = (ServerZoneStateChange_struct*) pack->pBuffer; auto *s = (ServerZoneStateChange_Struct*) pack->pBuffer;
s->ZoneServerID = zone_server_id;
s->zone_server_id = zone_server_id;
s->zone_id = in_zone_id ? in_zone_id : GetZoneID();
s->instance_id = in_instance_id;
s->is_static = is_static_zone;
if (admin_name) { if (admin_name) {
strn0cpy(s->adminname, admin_name, sizeof(s->adminname)); strn0cpy(s->admin_name, admin_name, sizeof(s->admin_name));
} }
s->zoneid = in_zone_id ? in_zone_id : GetZoneID();
s->instanceid = in_instance_id;
s->makestatic = is_static_zone;
SendPacket(pack); SendPacket(pack);
delete pack; delete pack;
LSBootUpdate(in_zone_id, in_instance_id); LSBootUpdate(in_zone_id, in_instance_id);
+94
View File
@@ -2207,3 +2207,97 @@ bool Client::HasAlreadyPurchasedRank(AA::Rank* rank) {
return false; return false;
} }
void Client::ListPurchasedAAs(Client *to, std::string search_criteria)
{
if (!to) {
return;
}
std::map<std::string, uint8> client_aa_ranks;
for (auto &aa : zone->aa_abilities) {
AA::Ability *ability = aa.second.get();
AA::Rank *rank = ability->first;
while (rank) {
if (!CanUseAlternateAdvancementRank(rank)) {
break;
}
if (HasAlreadyPurchasedRank(rank)) {
const std::string aa_name = zone->GetAAName(rank->id);
if (
search_criteria.empty() ||
Strings::Contains(
Strings::ToLower(aa_name),
Strings::ToLower(search_criteria)
)
) {
if (client_aa_ranks.find(aa_name) == client_aa_ranks.end()) {
client_aa_ranks[aa_name] = 1;
} else {
client_aa_ranks[aa_name]++;
}
}
}
rank = rank->next;
}
}
if (client_aa_ranks.empty()) {
to->Message(
Chat::White,
fmt::format(
"{} {} no purchased AAs{}.",
to->GetTargetDescription(this, TargetDescriptionType::UCYou),
this == to ? "have" : "has",
(
!search_criteria.empty() ?
fmt::format(
" matching '{}'",
search_criteria
) :
""
)
).c_str()
);
return;
}
int aa_number = 1;
for (const auto &aa : client_aa_ranks) {
to->Message(
Chat::White,
fmt::format(
"{}. {} (Rank {})",
aa_number,
aa.first,
aa.second
).c_str()
);
aa_number++;
}
to->Message(
Chat::White,
fmt::format(
"{} {} {} purchased AA{}{}.",
to->GetTargetDescription(this, TargetDescriptionType::UCYou),
this == to ? "have" : "has",
client_aa_ranks.size(),
client_aa_ranks.size() > 1 ? "s" : "",
(
!search_criteria.empty() ?
fmt::format(
" matching '{}'",
search_criteria
) :
""
)
).c_str()
);
}
+3 -7
View File
@@ -1741,8 +1741,7 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill
static_cast<int>(attack_skill) static_cast<int>(attack_skill)
); );
std::vector<std::any> args = { CastToMob() }; if (parse->EventPlayer(EVENT_DEATH, this, export_string, 0) != 0) {
if (parse->EventPlayer(EVENT_DEATH, this, export_string, 0, &args) != 0) {
if (GetHP() < 0) { if (GetHP() < 0) {
SetHP(0); SetHP(0);
} }
@@ -2389,8 +2388,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
static_cast<int>(attack_skill) static_cast<int>(attack_skill)
); );
std::vector<std::any> args = { CastToMob() }; if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) {
if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0, &args) != 0) {
if (GetHP() < 0) { if (GetHP() < 0) {
SetHP(0); SetHP(0);
} }
@@ -2407,9 +2405,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
spell, spell,
static_cast<int>(attack_skill) static_cast<int>(attack_skill)
); );
if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0) != 0) {
std::vector<std::any> args = { CastToMob() };
if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0, &args) != 0) {
if (GetHP() < 0) { if (GetHP() < 0) {
SetHP(0); SetHP(0);
} }
+17 -1
View File
@@ -3634,13 +3634,29 @@ void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) {
for (auto biter = blist.begin(); biter != blist.end(); ++biter) { for (auto biter = blist.begin(); biter != blist.end(); ++biter) {
Bot* bot = *biter; Bot* bot = *biter;
if (bot && (bot->GetLevel() != client->GetLevel())) { if (bot && (bot->GetLevel() != client->GetLevel())) {
bot->SetPetChooser(false); // not sure what this does, but was in bot 'update' code bot->SetPetChooser(false); // not sure what this does, but was in bot 'update' code
bot->CalcBotStats(client->GetBotOption(Client::booStatsUpdate)); bot->CalcBotStats(client->GetBotOption(Client::booStatsUpdate));
if (sendlvlapp)
if (sendlvlapp) {
bot->SendLevelAppearance(); bot->SendLevelAppearance();
}
// modified from Client::SetLevel() // modified from Client::SetLevel()
if (!RuleB(Bots, BotHealOnLevel)) {
int mhp = bot->CalcMaxHP();
if (bot->GetHP() > mhp) {
bot->SetHP(mhp);
}
}
else {
bot->SetHP(bot->CalcMaxHP());
bot->SetMana(bot->CalcMaxMana());
}
bot->SendHPUpdate();
bot->SendAppearancePacket(AT_WhoLevel, level, true, true); // who level change bot->SendAppearancePacket(AT_WhoLevel, level, true, true); // who level change
bot->AI_AddBotSpells(bot->GetBotSpellID());
} }
} }
+595 -157
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -183,7 +183,7 @@ bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpel
if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0)
continue; continue;
if (IsValidSpellRange(botSpell.SpellId, tar)) { if (IsValidSpellRange(iter.SpellId, tar)) {
casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost);
} }
if (casted_spell) { if (casted_spell) {
@@ -328,7 +328,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
continue; continue;
} }
if (IsValidSpellRange(botSpell.SpellId, tar)) { if (IsValidSpellRange(iter.SpellId, tar)) {
casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); casted_spell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost);
} }
@@ -447,7 +447,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); uint32 TempDontDotMeBefore = tar->DontDotMeBefore();
if (IsValidSpellRange(botSpell.SpellId, tar)) { if (IsValidSpellRange(s.SpellId, tar)) {
casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontDotMeBefore); casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontDotMeBefore);
} }
+97 -52
View File
@@ -65,6 +65,7 @@ extern volatile bool RunLoops;
#include "../common/repositories/character_disciplines_repository.h" #include "../common/repositories/character_disciplines_repository.h"
#include "../common/repositories/character_data_repository.h" #include "../common/repositories/character_data_repository.h"
#include "../common/repositories/discovered_items_repository.h" #include "../common/repositories/discovered_items_repository.h"
#include "../common/repositories/keyring_repository.h"
#include "../common/events/player_events.h" #include "../common/events/player_events.h"
#include "../common/events/player_event_logs.h" #include "../common/events/player_event_logs.h"
#include "dialogue_window.h" #include "dialogue_window.h"
@@ -2262,10 +2263,10 @@ void Client::QuestReadBook(const char* text, uint8 type) {
uint32 Client::GetCarriedPlatinum() { uint32 Client::GetCarriedPlatinum() {
return ( return (
GetMoney(3, 0) + GetMoney(MoneyTypes::Platinum, MoneySubtypes::Personal) +
(GetMoney(2, 0) / 10) + (GetMoney(MoneyTypes::Gold, MoneySubtypes::Personal) / 10) +
(GetMoney(1, 0) / 100) + (GetMoney(MoneyTypes::Silver, MoneySubtypes::Personal) / 100) +
(GetMoney(0, 0) / 1000) (GetMoney(MoneyTypes::Copper, MoneySubtypes::Personal) / 1000)
); );
} }
@@ -4087,54 +4088,87 @@ void Client::SendWindow(
void Client::KeyRingLoad() void Client::KeyRingLoad()
{ {
std::string query = StringFormat("SELECT item_id FROM keyring " const auto &l = KeyringRepository::GetWhere(
"WHERE char_id = '%i' ORDER BY item_id", character_id); database,
auto results = database.QueryDatabase(query); fmt::format(
if (!results.Success()) { "`char_id` = {} ORDER BY `item_id`",
character_id
)
);
if (l.empty()) {
return; return;
} }
for (auto row = results.begin(); row != results.end(); ++row)
keyring.push_back(Strings::ToInt(row[0]));
for (const auto &e : l) {
keyring.emplace_back(e.item_id);
}
} }
void Client::KeyRingAdd(uint32 item_id) void Client::KeyRingAdd(uint32 item_id)
{ {
if(0==item_id) if (!item_id) {
return;
bool found = KeyRingCheck(item_id);
if (found)
return;
std::string query = StringFormat("INSERT INTO keyring(char_id, item_id) VALUES(%i, %i)", character_id, item_id);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return; return;
} }
Message(Chat::LightBlue,"Added to keyring."); const bool found = KeyRingCheck(item_id);
if (found) {
return;
}
keyring.push_back(item_id); auto e = KeyringRepository::NewEntity();
e.char_id = CharacterID();
e.item_id = item_id;
e = KeyringRepository::InsertOne(database, e);
if (!e.id) {
return;
}
keyring.emplace_back(item_id);
if (!RuleB(World, UseItemLinksForKeyRing)) {
Message(Chat::LightBlue, "Added to keyring.");
return;
}
const std::string &item_link = database.CreateItemLink(item_id);
Message(
Chat::LightBlue,
fmt::format(
"Added {} to keyring.",
item_link
).c_str()
);
} }
bool Client::KeyRingCheck(uint32 item_id) bool Client::KeyRingCheck(uint32 item_id)
{ {
for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) { for (const auto &e : keyring) {
if(*iter == item_id) if (e == item_id) {
return true; return true;
} }
}
return false; return false;
} }
void Client::KeyRingList() void Client::KeyRingList()
{ {
Message(Chat::LightBlue, "Keys on Keyring:"); Message(Chat::LightBlue, "Keys on Keyring:");
const EQ::ItemData *item = nullptr; const EQ::ItemData *item = nullptr;
for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) {
if ((item = database.GetItem(*iter))!=nullptr) { for (const auto &e : keyring) {
Message(Chat::LightBlue,item->Name); item = database.GetItem(e);
if (item) {
const std::string &item_string = RuleB(World, UseItemLinksForKeyRing) ? database.CreateItemLink(e) : item->Name;
Message(Chat::LightBlue, item_string.c_str());
} }
} }
} }
@@ -8119,16 +8153,17 @@ void Client::SendHPUpdateMarquee(){
uint32 Client::GetMoney(uint8 type, uint8 subtype) { uint32 Client::GetMoney(uint8 type, uint8 subtype) {
uint32 value = 0; uint32 value = 0;
switch (type) { switch (type) {
case 0: { case MoneyTypes::Copper: {
switch (subtype) { switch (subtype) {
case 0: case MoneySubtypes::Personal:
value = static_cast<uint32>(m_pp.copper); value = static_cast<uint32>(m_pp.copper);
break; break;
case 1: case MoneySubtypes::Bank:
value = static_cast<uint32>(m_pp.copper_bank); value = static_cast<uint32>(m_pp.copper_bank);
break; break;
case 2: case MoneySubtypes::Cursor:
value = static_cast<uint32>(m_pp.copper_cursor); value = static_cast<uint32>(m_pp.copper_cursor);
break; break;
default: default:
@@ -8136,15 +8171,15 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
} }
break; break;
} }
case 1: { case MoneyTypes::Silver: {
switch (subtype) { switch (subtype) {
case 0: case MoneySubtypes::Personal:
value = static_cast<uint32>(m_pp.silver); value = static_cast<uint32>(m_pp.silver);
break; break;
case 1: case MoneySubtypes::Bank:
value = static_cast<uint32>(m_pp.silver_bank); value = static_cast<uint32>(m_pp.silver_bank);
break; break;
case 2: case MoneySubtypes::Cursor:
value = static_cast<uint32>(m_pp.silver_cursor); value = static_cast<uint32>(m_pp.silver_cursor);
break; break;
default: default:
@@ -8152,15 +8187,15 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
} }
break; break;
} }
case 2: { case MoneyTypes::Gold: {
switch (subtype) { switch (subtype) {
case 0: case MoneySubtypes::Personal:
value = static_cast<uint32>(m_pp.gold); value = static_cast<uint32>(m_pp.gold);
break; break;
case 1: case MoneySubtypes::Bank:
value = static_cast<uint32>(m_pp.gold_bank); value = static_cast<uint32>(m_pp.gold_bank);
break; break;
case 2: case MoneySubtypes::Cursor:
value = static_cast<uint32>(m_pp.gold_cursor); value = static_cast<uint32>(m_pp.gold_cursor);
break; break;
default: default:
@@ -8168,18 +8203,18 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
} }
break; break;
} }
case 3: { case MoneyTypes::Platinum: {
switch (subtype) { switch (subtype) {
case 0: case MoneySubtypes::Personal:
value = static_cast<uint32>(m_pp.platinum); value = static_cast<uint32>(m_pp.platinum);
break; break;
case 1: case MoneySubtypes::Bank:
value = static_cast<uint32>(m_pp.platinum_bank); value = static_cast<uint32>(m_pp.platinum_bank);
break; break;
case 2: case MoneySubtypes::Cursor:
value = static_cast<uint32>(m_pp.platinum_cursor); value = static_cast<uint32>(m_pp.platinum_cursor);
break; break;
case 3: case MoneySubtypes::SharedBank:
value = static_cast<uint32>(m_pp.platinum_shared); value = static_cast<uint32>(m_pp.platinum_shared);
break; break;
default: default:
@@ -8190,6 +8225,7 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
default: default:
break; break;
} }
return value; return value;
} }
@@ -10353,6 +10389,16 @@ void Client::SetDoorToolEntityId(uint16 door_tool_entity_id)
Client::m_door_tool_entity_id = door_tool_entity_id; Client::m_door_tool_entity_id = door_tool_entity_id;
} }
uint16 Client::GetObjectToolEntityId() const
{
return m_object_tool_entity_id;
}
void Client::SetObjectToolEntityId(uint16 object_tool_entity_id)
{
Client::m_object_tool_entity_id = object_tool_entity_id;
}
int Client::GetIPExemption() int Client::GetIPExemption()
{ {
return database.GetIPExemption(GetIPString()); return database.GetIPExemption(GetIPString());
@@ -11125,16 +11171,15 @@ void Client::AddAAPoints(uint32 points)
{ {
m_pp.aapoints += points; m_pp.aapoints += points;
if (points == 1 && m_pp.aapoints == 1) if (parse->PlayerHasQuestSub(EVENT_AA_GAIN)) {
{ parse->EventPlayer(EVENT_AA_GAIN, this, std::to_string(points), 0);
}
if (points == 1 && m_pp.aapoints == 1) {
MessageString(Chat::Yellow, GAIN_SINGLE_AA_SINGLE_AA, fmt::format_int(m_pp.aapoints).c_str()); MessageString(Chat::Yellow, GAIN_SINGLE_AA_SINGLE_AA, fmt::format_int(m_pp.aapoints).c_str());
} } else if (points == 1 && m_pp.aapoints > 1) {
else if (points == 1 && m_pp.aapoints > 1)
{
MessageString(Chat::Yellow, GAIN_SINGLE_AA_MULTI_AA, fmt::format_int(m_pp.aapoints).c_str()); MessageString(Chat::Yellow, GAIN_SINGLE_AA_MULTI_AA, fmt::format_int(m_pp.aapoints).c_str());
} } else {
else
{
MessageString(Chat::Yellow, GAIN_MULTI_AA_MULTI_AA, fmt::format_int(points).c_str(), fmt::format_int(m_pp.aapoints).c_str()); MessageString(Chat::Yellow, GAIN_MULTI_AA_MULTI_AA, fmt::format_int(points).c_str(), fmt::format_int(m_pp.aapoints).c_str());
} }
+8
View File
@@ -908,6 +908,7 @@ public:
void AutoGrantAAPoints(); void AutoGrantAAPoints();
void GrantAllAAPoints(uint8 unlock_level = 0); void GrantAllAAPoints(uint8 unlock_level = 0);
bool HasAlreadyPurchasedRank(AA::Rank* rank); bool HasAlreadyPurchasedRank(AA::Rank* rank);
void ListPurchasedAAs(Client *to, std::string search_criteria = std::string());
bool SendGMCommand(std::string message, bool ignore_status = false); bool SendGMCommand(std::string message, bool ignore_status = false);
@@ -1274,6 +1275,10 @@ public:
} }
else { return 0; } else { return 0; }
} }
inline bool CompleteTask(uint32 task_id)
{
return task_state ? task_state->CompleteTask(this, task_id) : false;
}
inline void FailTask(int task_id) { if (task_state) { task_state->FailTask(this, task_id); }} inline void FailTask(int task_id) { if (task_state) { task_state->FailTask(this, task_id); }}
inline int TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); } inline int TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); }
inline int EnabledTaskCount(int task_set_id) inline int EnabledTaskCount(int task_set_id)
@@ -1809,9 +1814,12 @@ private:
bool dev_tools_enabled; bool dev_tools_enabled;
uint16 m_door_tool_entity_id; uint16 m_door_tool_entity_id;
uint16 m_object_tool_entity_id;
public: public:
uint16 GetDoorToolEntityId() const; uint16 GetDoorToolEntityId() const;
void SetDoorToolEntityId(uint16 door_tool_entity_id); void SetDoorToolEntityId(uint16 door_tool_entity_id);
uint16 GetObjectToolEntityId() const;
void SetObjectToolEntityId(uint16 object_tool_entity_id);
private: private:
int32 max_end; int32 max_end;
+201 -173
View File
@@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/criteria/content_filter_criteria.h"
#include "../common/shared_tasks.h" #include "../common/shared_tasks.h"
#include "gm_commands/door_manipulation.h" #include "gm_commands/door_manipulation.h"
#include "gm_commands/object_manipulation.h"
#include "client.h" #include "client.h"
#include "../common/repositories/account_repository.h" #include "../common/repositories/account_repository.h"
@@ -1385,10 +1386,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
InitInnates(); InitInnates();
/* If GM not set in DB, and does not meet min status to be GM, reset */
if (m_pp.gm && admin < minStatusToBeGM)
m_pp.gm = 0;
/* Load Guild */ /* Load Guild */
if (!IsInAGuild()) { if (!IsInAGuild()) {
m_pp.guild_id = GUILD_NONE; m_pp.guild_id = GUILD_NONE;
@@ -1702,8 +1699,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
this is not quite where live sends inventory, they do it after tribute this is not quite where live sends inventory, they do it after tribute
*/ */
if (loaditems) { /* Don't load if a length error occurs */ if (loaditems) { /* Don't load if a length error occurs */
if (admin >= minStatusToBeGM) if (m_pp.gm) {
m_inv.SetGMInventory(true); // set to true to allow expansion-restricted packets through m_inv.SetGMInventory(true); // set to true to allow expansion-restricted packets through
}
BulkSendInventoryItems(); BulkSendInventoryItems();
/* Send stuff on the cursor which isn't sent in bulk */ /* Send stuff on the cursor which isn't sent in bulk */
@@ -4653,6 +4651,20 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app)
std::vector<std::any> args = { object }; std::vector<std::any> args = { object };
parse->EventPlayer(EVENT_CLICK_OBJECT, this, std::to_string(click_object->drop_id), GetID(), &args); parse->EventPlayer(EVENT_CLICK_OBJECT, this, std::to_string(click_object->drop_id), GetID(), &args);
} }
if (IsDevToolsEnabled()) {
SetObjectToolEntityId(entity->GetID());
ObjectManipulation::CommandHeader(this);
Message(
Chat::White,
fmt::format(
"Object ({}) [{}] [{}]",
entity->CastToObject()->GetDBID(),
Saylink::Silent("#object edit", "Edit"),
Saylink::Silent("#object delete", "Delete")
).c_str()
);
}
} }
// Observed in RoF after OP_ClickObjectAction: // Observed in RoF after OP_ClickObjectAction:
@@ -6238,7 +6250,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
damage = 31337; damage = 31337;
} }
if (admin >= minStatusToAvoidFalling && GetGM()) { if (GetGM()) {
Message( Message(
Chat::Red, Chat::Red,
fmt::format( fmt::format(
@@ -6446,86 +6458,92 @@ void Client::Handle_OP_GetGuildsList(const EQApplicationPacket *app)
void Client::Handle_OP_GMBecomeNPC(const EQApplicationPacket *app) void Client::Handle_OP_GMBecomeNPC(const EQApplicationPacket *app)
{ {
if (Admin() < minStatusToUseGMCommands) { if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /becomenpc when they shouldn't be able to"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /becomenpc when they shouldn't be able to"});
return; return;
} }
if (app->size != sizeof(BecomeNPC_Struct)) { if (app->size != sizeof(BecomeNPC_Struct)) {
LogError("Wrong size: OP_GMBecomeNPC, size=[{}], expected [{}]", app->size, sizeof(BecomeNPC_Struct)); LogError("Wrong size: OP_GMBecomeNPC, size=[{}], expected [{}]", app->size, sizeof(BecomeNPC_Struct));
return; return;
} }
//entity_list.QueueClients(this, app, false);
BecomeNPC_Struct* bnpc = (BecomeNPC_Struct*)app->pBuffer;
Mob* cli = (Mob*)entity_list.GetMob(bnpc->id); auto *b = (BecomeNPC_Struct *) app->pBuffer;
if (cli == nullptr) {
Mob *m = entity_list.GetMob(b->id);
if (!m) {
return; return;
} }
if (cli->IsClient()) { if (m->IsClient()) {
Client* target = cli->CastToClient(); Client *t = m->CastToClient();
target->QueuePacket(app); t->QueuePacket(app);
if(target->GetGM()) { if (t->GetGM()) {
target->SetInvul(false); t->SetInvul(false);
target->SetHideMe(false); t->SetHideMe(false);
target->SetGM(false); t->SetGM(false);
} }
cli->SendAppearancePacket(AT_NPCName, 1, true); m->SendAppearancePacket(AT_NPCName, 1, true);
target->SetBecomeNPC(true); t->SetBecomeNPC(true);
target->SetBecomeNPCLevel(bnpc->maxlevel); t->SetBecomeNPCLevel(b->maxlevel);
cli->MessageString(Chat::White, TOGGLE_OFF); m->MessageString(Chat::White, TOGGLE_OFF);
target->tellsoff = true; t->tellsoff = true;
target->UpdateWho(); t->UpdateWho();
} }
return;
} }
void Client::Handle_OP_GMDelCorpse(const EQApplicationPacket *app) void Client::Handle_OP_GMDelCorpse(const EQApplicationPacket *app)
{ {
if (app->size != sizeof(GMDelCorpse_Struct)) if (app->size != sizeof(GMDelCorpse_Struct)) {
return; return;
if (Admin() < commandEditPlayerCorpses) { }
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /delcorpse"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /delcorpse"});
return; return;
} }
GMDelCorpse_Struct* dc = (GMDelCorpse_Struct *)app->pBuffer;
Mob* corpse = entity_list.GetMob(dc->corpsename); auto *c = (GMDelCorpse_Struct *) app->pBuffer;
if (corpse == 0) { Mob *corpse = entity_list.GetMob(c->corpsename);
if (!c) {
return; return;
} }
if (corpse->IsCorpse() != true) {
if (!corpse->IsCorpse()) {
return; return;
} }
corpse->CastToCorpse()->Delete(); corpse->CastToCorpse()->Delete();
std::cout << name << " deleted corpse " << dc->corpsename << std::endl; Message(Chat::Red, fmt::format("Corpse {} deleted.", c->corpsename).c_str());
Message(Chat::Red, "Corpse %s deleted.", dc->corpsename);
return;
} }
void Client::Handle_OP_GMEmoteZone(const EQApplicationPacket *app) void Client::Handle_OP_GMEmoteZone(const EQApplicationPacket *app)
{ {
if (Admin() < minStatusToUseGMCommands) {
Message(Chat::Red, "Your account has been reported for hacking.");
return;
}
if (app->size != sizeof(GMEmoteZone_Struct)) { if (app->size != sizeof(GMEmoteZone_Struct)) {
LogError("Wrong size: OP_GMEmoteZone, size=[{}], expected [{}]", app->size, sizeof(GMEmoteZone_Struct)); LogError("Wrong size: OP_GMEmoteZone, size=[{}], expected [{}]", app->size, sizeof(GMEmoteZone_Struct));
return; return;
} }
GMEmoteZone_Struct* gmez = (GMEmoteZone_Struct*)app->pBuffer;
char* newmessage = nullptr; if (!GetGM()) {
if (strstr(gmez->text, "^") == 0) Message(Chat::Red, "Your account has been reported for hacking.");
entity_list.Message(Chat::White, 15, gmez->text); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /emote"});
else {
for (newmessage = strtok((char*)gmez->text, "^"); newmessage != nullptr; newmessage = strtok(nullptr, "^"))
entity_list.Message(Chat::White, 15, newmessage);
}
return; return;
} }
auto *gmez = (GMEmoteZone_Struct*)app->pBuffer;
char *newmessage = nullptr;
if (strstr(gmez->text, "^") == 0) {
entity_list.Message(0, Chat::White, gmez->text);
} else {
for (newmessage = strtok((char *) gmez->text, "^"); newmessage != nullptr; newmessage = strtok(nullptr, "^")) {
entity_list.Message(0, Chat::White, newmessage);
}
}
}
void Client::Handle_OP_GMEndTraining(const EQApplicationPacket *app) void Client::Handle_OP_GMEndTraining(const EQApplicationPacket *app)
{ {
if (app->size != sizeof(GMTrainEnd_Struct)) { if (app->size != sizeof(GMTrainEnd_Struct)) {
@@ -6533,64 +6551,62 @@ void Client::Handle_OP_GMEndTraining(const EQApplicationPacket *app)
DumpPacket(app); DumpPacket(app);
return; return;
} }
OPGMEndTraining(app); OPGMEndTraining(app);
return;
} }
void Client::Handle_OP_GMFind(const EQApplicationPacket *app) void Client::Handle_OP_GMFind(const EQApplicationPacket *app)
{ {
if (Admin() < minStatusToUseGMCommands) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"});
return;
}
if (app->size != sizeof(GMFind_Struct)) { if (app->size != sizeof(GMFind_Struct)) {
LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMFind_Struct)); LogError("Wrong size: OP_GMFind, size=[{}], expected [{}]", app->size, sizeof(GMFind_Struct));
return; return;
} }
//Break down incoming if (!GetGM()) {
auto* request = (GMFind_Struct*) app->pBuffer; Message(Chat::Red, "Your account has been reported for hacking.");
//Create a new outgoing RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /find"});
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMFind_Struct));
auto* foundplayer = (GMFind_Struct*) outapp->pBuffer;
//Copy the constants
strcpy(foundplayer->charname, request->charname);
strcpy(foundplayer->gmname, request->gmname);
//Check if the NPC exits intrazone...
auto* gt = entity_list.GetMob(request->charname);
if (gt) {
foundplayer->success = 1;
foundplayer->x = gt->GetX();
foundplayer->y = gt->GetY();
foundplayer->z = gt->GetZ();
foundplayer->zoneID = zone->GetZoneID();
}
//Send the packet...
FastQueuePacket(&outapp);
return; return;
} }
auto *r = (GMFind_Struct *) app->pBuffer;
auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMFind_Struct));
auto *f = (GMFind_Struct *) outapp->pBuffer;
strcpy(f->charname, r->charname);
strcpy(f->gmname, r->gmname);
auto* gt = entity_list.GetMob(r->charname);
if (gt) {
f->success = 1;
f->x = gt->GetX();
f->y = gt->GetY();
f->z = gt->GetZ();
f->zoneID = zone->GetZoneID();
}
FastQueuePacket(&outapp);
}
void Client::Handle_OP_GMGoto(const EQApplicationPacket *app) void Client::Handle_OP_GMGoto(const EQApplicationPacket *app)
{ {
if (app->size != sizeof(GMSummon_Struct)) { if (app->size != sizeof(GMSummon_Struct)) {
std::cout << "Wrong size on OP_GMGoto. Got: " << app->size << ", Expected: " << sizeof(GMSummon_Struct) << std::endl; LogError("Wrong size: OP_GMGoto, size=[{}], expected [{}]", app->size, sizeof(GMSummon_Struct));
return; return;
} }
if (Admin() < minStatusToUseGMCommands) {
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /goto"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /goto"});
return; return;
} }
GMSummon_Struct* gmg = (GMSummon_Struct*)app->pBuffer;
auto *gmg = (GMSummon_Struct *) app->pBuffer;
Mob *gt = entity_list.GetMob(gmg->charname); Mob *gt = entity_list.GetMob(gmg->charname);
if (gt != nullptr) { if (!gt) {
MovePC(zone->GetZoneID(), zone->GetInstanceID(), gt->GetX(), gt->GetY(), gt->GetZ(), gt->GetHeading()); MovePC(zone->GetZoneID(), zone->GetInstanceID(), gt->GetX(), gt->GetY(), gt->GetZ(), gt->GetHeading());
} } else if (!worldserver.Connected()) {
else if (!worldserver.Connected())
Message(Chat::Red, "Error: World server disconnected."); Message(Chat::Red, "Error: World server disconnected.");
else { } else {
auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct)); auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct));
memset(pack->pBuffer, 0, pack->size); memset(pack->pBuffer, 0, pack->size);
ServerGMGoto_Struct *wsgmg = (ServerGMGoto_Struct *) pack->pBuffer; ServerGMGoto_Struct *wsgmg = (ServerGMGoto_Struct *) pack->pBuffer;
@@ -6600,87 +6616,84 @@ void Client::Handle_OP_GMGoto(const EQApplicationPacket *app)
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
return;
} }
void Client::Handle_OP_GMHideMe(const EQApplicationPacket *app) void Client::Handle_OP_GMHideMe(const EQApplicationPacket *app)
{ {
if (Admin() < minStatusToUseGMCommands) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /hideme"});
return;
}
if (app->size != sizeof(SpawnAppearance_Struct)) { if (app->size != sizeof(SpawnAppearance_Struct)) {
LogError("Wrong size: OP_GMHideMe, size=[{}], expected [{}]", app->size, sizeof(SpawnAppearance_Struct)); LogError("Wrong size: OP_GMHideMe, size=[{}], expected [{}]", app->size, sizeof(SpawnAppearance_Struct));
return; return;
} }
SpawnAppearance_Struct* sa = (SpawnAppearance_Struct*)app->pBuffer;
Message(Chat::Red, "#: %i, %i", sa->type, sa->parameter);
SetHideMe(!sa->parameter);
return;
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /hideme"});
return;
}
auto *sa = (SpawnAppearance_Struct *) app->pBuffer;
SetHideMe(!sa->parameter);
} }
void Client::Handle_OP_GMKick(const EQApplicationPacket *app) void Client::Handle_OP_GMKick(const EQApplicationPacket *app)
{ {
if (app->size != sizeof(GMKick_Struct)) if (app->size != sizeof(GMKick_Struct)) {
return; return;
if (Admin() < minStatusToKick) { }
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kick"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kick"});
return; return;
} }
GMKick_Struct* gmk = (GMKick_Struct *)app->pBuffer;
Client* client = entity_list.GetClientByName(gmk->name); auto *gmk = (GMKick_Struct *)app->pBuffer;
if (client == 0) { Client *c = entity_list.GetClientByName(gmk->name);
if (!worldserver.Connected()) if (!c) {
if (!worldserver.Connected()) {
Message(Chat::Red, "Error: World server disconnected"); Message(Chat::Red, "Error: World server disconnected");
else { } else {
auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack->pBuffer; auto *skp = (ServerKickPlayer_Struct *) pack->pBuffer;
strcpy(skp->adminname, gmk->gmname); strcpy(skp->adminname, gmk->gmname);
strcpy(skp->name, gmk->name); strcpy(skp->name, gmk->name);
skp->adminrank = Admin(); skp->adminrank = Admin();
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
} } else {
else {
entity_list.QueueClients(this, app); entity_list.QueueClients(this, app);
//client->Kick();
} }
return;
} }
void Client::Handle_OP_GMKill(const EQApplicationPacket *app) void Client::Handle_OP_GMKill(const EQApplicationPacket *app)
{ {
if (Admin() < minStatusToUseGMCommands) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kill"});
return;
}
if (app->size != sizeof(GMKill_Struct)) { if (app->size != sizeof(GMKill_Struct)) {
LogError("Wrong size: OP_GMKill, size=[{}], expected [{}]", app->size, sizeof(GMKill_Struct)); LogError("Wrong size: OP_GMKill, size=[{}], expected [{}]", app->size, sizeof(GMKill_Struct));
return; return;
} }
GMKill_Struct* gmk = (GMKill_Struct *)app->pBuffer;
Mob* obj = entity_list.GetMob(gmk->name); if (!GetGM()) {
Client* client = entity_list.GetClientByName(gmk->name); Message(Chat::Red, "Your account has been reported for hacking.");
if (obj != 0) { RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /kill"});
if (client != 0) { return;
entity_list.QueueClients(this, app);
} }
else {
auto *gmk = (GMKill_Struct *) app->pBuffer;
Mob *obj = entity_list.GetMob(gmk->name);
Client *c = entity_list.GetClientByName(gmk->name);
if (obj) {
if (c) {
entity_list.QueueClients(this, app);
} else {
obj->Kill(); obj->Kill();
} }
} } else {
else { if (!worldserver.Connected()) {
if (!worldserver.Connected())
Message(Chat::Red, "Error: World server disconnected"); Message(Chat::Red, "Error: World server disconnected");
else { } else {
auto pack = new ServerPacket(ServerOP_KillPlayer, sizeof(ServerKillPlayer_Struct)); auto pack = new ServerPacket(ServerOP_KillPlayer, sizeof(ServerKillPlayer_Struct));
ServerKillPlayer_Struct* skp = (ServerKillPlayer_Struct*)pack->pBuffer; auto *skp = (ServerKillPlayer_Struct *) pack->pBuffer;
strcpy(skp->gmname, gmk->gmname); strcpy(skp->gmname, gmk->gmname);
strcpy(skp->target, gmk->name); strcpy(skp->target, gmk->name);
skp->admin = Admin(); skp->admin = Admin();
@@ -6688,7 +6701,6 @@ void Client::Handle_OP_GMKill(const EQApplicationPacket *app)
safe_delete(pack); safe_delete(pack);
} }
} }
return;
} }
void Client::Handle_OP_GMLastName(const EQApplicationPacket *app) void Client::Handle_OP_GMLastName(const EQApplicationPacket *app)
@@ -6697,32 +6709,30 @@ void Client::Handle_OP_GMLastName(const EQApplicationPacket *app)
std::cout << "Wrong size on OP_GMLastName. Got: " << app->size << ", Expected: " << sizeof(GMLastName_Struct) << std::endl; std::cout << "Wrong size on OP_GMLastName. Got: " << app->size << ", Expected: " << sizeof(GMLastName_Struct) << std::endl;
return; return;
} }
GMLastName_Struct* gmln = (GMLastName_Struct*)app->pBuffer;
if (strlen(gmln->lastname) >= 64) { if (!GetGM()) {
Message(Chat::Red, "/LastName: New last name too long. (max=63)");
}
else {
Client* client = entity_list.GetClientByName(gmln->name);
if (client == 0) {
Message(Chat::Red, "/LastName: %s not found", gmln->name);
}
else {
if (Admin() < minStatusToUseGMCommands) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /lastname"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /lastname"});
return; return;
} }
else
client->ChangeLastName(gmln->lastname); auto *gmln = (GMLastName_Struct *) app->pBuffer;
if (strlen(gmln->lastname) >= 64) {
Message(Chat::Red, "/LastName: New last name too long. Max length is 63.");
} else {
Client *c = entity_list.GetClientByName(gmln->name);
if (!c) {
Message(Chat::Red, fmt::format("/LastName: {} not found", gmln->name).c_str());
} else {
c->ChangeLastName(gmln->lastname);
} }
gmln->unknown[0] = 1; gmln->unknown[0] = 1;
gmln->unknown[1] = 1; gmln->unknown[1] = 1;
gmln->unknown[2] = 1; gmln->unknown[2] = 1;
gmln->unknown[3] = 1; gmln->unknown[3] = 1;
entity_list.QueueClients(this, app, false); entity_list.QueueClients(this, app, false);
} }
return;
} }
void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app) void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app)
@@ -6731,44 +6741,49 @@ void Client::Handle_OP_GMNameChange(const EQApplicationPacket *app)
LogError("Wrong size: OP_GMNameChange, size=[{}], expected [{}]", app->size, sizeof(GMName_Struct)); LogError("Wrong size: OP_GMNameChange, size=[{}], expected [{}]", app->size, sizeof(GMName_Struct));
return; return;
} }
const GMName_Struct* gmn = (const GMName_Struct *)app->pBuffer;
if (Admin() < minStatusToUseGMCommands) { auto *gmn = (GMName_Struct *) app->pBuffer;
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /name"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /name"});
return; return;
} }
Client* client = entity_list.GetClientByName(gmn->oldname);
LogInfo("GM([{}]) changeing players name. Old:[{}] New:[{}]", GetName(), gmn->oldname, gmn->newname);
bool usedname = database.CheckUsedName(gmn->newname);
if (client == 0) {
Message(Chat::Red, "%s not found for name change. Operation failed!", gmn->oldname);
return;
}
if ((strlen(gmn->newname) > 63) || (strlen(gmn->newname) == 0)) {
Message(Chat::Red, "Invalid number of characters in new name (%s).", gmn->newname);
return;
}
if (!usedname) {
Message(Chat::Red, "%s is already in use. Operation failed!", gmn->newname);
return;
Client *c = entity_list.GetClientByName(gmn->oldname);
LogInfo("GM([{}]) changeing players name. Old:[{}] New:[{}]", GetName(), gmn->oldname, gmn->newname);
const bool used_name = database.CheckUsedName(gmn->newname);
if (!c) {
Message(Chat::Red, fmt::format("{} not found for name change. Operation failed!", gmn->oldname).c_str());
return;
} }
if (strlen(gmn->newname) > 63 || strlen(gmn->newname) == 0) {
Message(Chat::Red, fmt::format("Invalid number of characters in new name '{}'.", gmn->newname).c_str());
return;
}
if (!used_name) {
Message(Chat::Red, fmt::format("{} is already in use. Operation failed!", gmn->newname).c_str());
return;
}
database.UpdateName(gmn->oldname, gmn->newname); database.UpdateName(gmn->oldname, gmn->newname);
strcpy(client->name, gmn->newname); strcpy(c->name, gmn->newname);
client->Save(); c->Save();
if (gmn->badname == 1) { if (gmn->badname == 1) {
database.AddToNameFilter(gmn->oldname); database.AddToNameFilter(gmn->oldname);
} }
EQApplicationPacket* outapp = app->Copy();
GMName_Struct* gmn2 = (GMName_Struct*)outapp->pBuffer; auto *outapp = app->Copy();
auto *gmn2 = (GMName_Struct *) outapp->pBuffer;
gmn2->unknown[0] = 1; gmn2->unknown[0] = 1;
gmn2->unknown[1] = 1; gmn2->unknown[1] = 1;
gmn2->unknown[2] = 1; gmn2->unknown[2] = 1;
entity_list.QueueClients(this, outapp, false); entity_list.QueueClients(this, outapp, false);
safe_delete(outapp); safe_delete(outapp);
UpdateWho(); UpdateWho();
return;
} }
void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app) void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app)
@@ -6863,6 +6878,13 @@ void Client::Handle_OP_GMSummon(const EQApplicationPacket *app)
std::cout << "Wrong size on OP_GMSummon. Got: " << app->size << ", Expected: " << sizeof(GMSummon_Struct) << std::endl; std::cout << "Wrong size on OP_GMSummon. Got: " << app->size << ", Expected: " << sizeof(GMSummon_Struct) << std::endl;
return; return;
} }
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /summon"});
return;
}
OPGMSummon(app); OPGMSummon(app);
return; return;
} }
@@ -6873,12 +6895,14 @@ void Client::Handle_OP_GMToggle(const EQApplicationPacket *app)
std::cout << "Wrong size on OP_GMToggle. Got: " << app->size << ", Expected: " << sizeof(GMToggle_Struct) << std::endl; std::cout << "Wrong size on OP_GMToggle. Got: " << app->size << ", Expected: " << sizeof(GMToggle_Struct) << std::endl;
return; return;
} }
if (Admin() < minStatusToUseGMCommands) {
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /toggle"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /toggle"});
return; return;
} }
GMToggle_Struct *ts = (GMToggle_Struct *)app->pBuffer;
auto *ts = (GMToggle_Struct *)app->pBuffer;
if (ts->toggle == 0) { if (ts->toggle == 0) {
MessageString(Chat::White, TOGGLE_OFF); MessageString(Chat::White, TOGGLE_OFF);
tellsoff = true; tellsoff = true;
@@ -6886,10 +6910,10 @@ void Client::Handle_OP_GMToggle(const EQApplicationPacket *app)
MessageString(Chat::White, TOGGLE_ON); MessageString(Chat::White, TOGGLE_ON);
tellsoff = false; tellsoff = false;
} else { } else {
Message(Chat::White, "Unkown value in /toggle packet"); Message(Chat::White, "Unknown value in /toggle packet.");
} }
UpdateWho(); UpdateWho();
return;
} }
void Client::Handle_OP_GMTraining(const EQApplicationPacket *app) void Client::Handle_OP_GMTraining(const EQApplicationPacket *app)
@@ -6899,6 +6923,7 @@ void Client::Handle_OP_GMTraining(const EQApplicationPacket *app)
DumpPacket(app); DumpPacket(app);
return; return;
} }
OPGMTraining(app); OPGMTraining(app);
return; return;
} }
@@ -6910,6 +6935,7 @@ void Client::Handle_OP_GMTrainSkill(const EQApplicationPacket *app)
DumpPacket(app); DumpPacket(app);
return; return;
} }
OPGMTrainSkill(app); OPGMTrainSkill(app);
return; return;
} }
@@ -6920,7 +6946,8 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
std::cout << "Wrong size on OP_GMZoneRequest. Got: " << app->size << ", Expected: " << sizeof(GMZoneRequest_Struct) << std::endl; std::cout << "Wrong size on OP_GMZoneRequest. Got: " << app->size << ", Expected: " << sizeof(GMZoneRequest_Struct) << std::endl;
return; return;
} }
if (Admin() < minStatusToBeGM) {
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking."); Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"}); RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"});
return; return;
@@ -6933,14 +6960,16 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
uint8 min_level = 0; uint8 min_level = 0;
char target_zone[32]; char target_zone[32];
uint16 zone_id = gmzr->zone_id; uint16 zone_id = gmzr->zone_id;
if (gmzr->zone_id == 0) if (gmzr->zone_id == 0) {
zone_id = zonesummon_id; zone_id = zonesummon_id;
}
const char *zone_short_name = ZoneName(zone_id); const char *zone_short_name = ZoneName(zone_id);
if (zone_short_name == nullptr) if (zone_short_name == nullptr) {
target_zone[0] = 0; target_zone[0] = 0;
else } else {
strcpy(target_zone, zone_short_name); strcpy(target_zone, zone_short_name);
}
// this both loads the safe points and does a sanity check on zone name // this both loads the safe points and does a sanity check on zone name
auto z = GetZone(target_zone, 0); auto z = GetZone(target_zone, 0);
@@ -6961,34 +6990,33 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app)
gmzr2->y = target_y; gmzr2->y = target_y;
gmzr2->z = target_z; gmzr2->z = target_z;
gmzr2->heading = target_heading; gmzr2->heading = target_heading;
// Next line stolen from ZoneChange as well... - This gives us a nicer message than the normal "zone is down" message...
if (target_zone[0] != 0 && admin >= min_status && GetLevel() >= min_level) if (target_zone[0] != 0 && admin >= min_status && GetLevel() >= min_level) {
gmzr2->success = 1; gmzr2->success = 1;
else { } else {
std::cout << "GetZoneSafeCoords failed. zoneid = " << gmzr->zone_id << "; czone = " << zone->GetZoneID() << std::endl; LogError("GetZoneSafeCoords failed. Zone ID [{}] Current Zone [{}]", gmzr->zone_id, zone->GetZoneID());
gmzr2->success = 0; gmzr2->success = 0;
} }
QueuePacket(outapp); QueuePacket(outapp);
safe_delete(outapp); safe_delete(outapp);
return;
} }
void Client::Handle_OP_GMZoneRequest2(const EQApplicationPacket *app) void Client::Handle_OP_GMZoneRequest2(const EQApplicationPacket *app)
{ {
if (Admin() < minStatusToBeGM) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"});
return;
}
if (app->size < sizeof(uint32)) { if (app->size < sizeof(uint32)) {
LogError("OP size error: OP_GMZoneRequest2 expected:[{}] got:[{}]", sizeof(uint32), app->size); LogError("OP size error: OP_GMZoneRequest2 expected:[{}] got:[{}]", sizeof(uint32), app->size);
return; return;
} }
if (!GetGM()) {
Message(Chat::Red, "Your account has been reported for hacking.");
RecordPlayerEventLog(PlayerEvent::POSSIBLE_HACK, PlayerEvent::PossibleHackEvent{.message = "Used /zone"});
return;
}
uint32 zonereq = *((uint32 *)app->pBuffer); uint32 zonereq = *((uint32 *)app->pBuffer);
GoToSafeCoords(zonereq, 0); GoToSafeCoords(zonereq, 0);
return;
} }
void Client::Handle_OP_GroupAcknowledge(const EQApplicationPacket *app) void Client::Handle_OP_GroupAcknowledge(const EQApplicationPacket *app)
+4 -1
View File
@@ -217,6 +217,7 @@ int command_init(void)
command_add("summonitem", "[itemid] [charges] - Summon an item onto your cursor. Charges are optional.", AccountStatus::GMMgmt, command_summonitem) || command_add("summonitem", "[itemid] [charges] - Summon an item onto your cursor. Charges are optional.", AccountStatus::GMMgmt, command_summonitem) ||
command_add("suspend", "[name] [days] [reason] - Suspend by character name and for specificed number of days", AccountStatus::GMLeadAdmin, command_suspend) || command_add("suspend", "[name] [days] [reason] - Suspend by character name and for specificed number of days", AccountStatus::GMLeadAdmin, command_suspend) ||
command_add("suspendmulti", "[Character Name One|Character Name Two|etc] [Days] [Reason] - Suspend multiple characters by name for specified number of days", AccountStatus::GMLeadAdmin, command_suspendmulti) || command_add("suspendmulti", "[Character Name One|Character Name Two|etc] [Days] [Reason] - Suspend multiple characters by name for specified number of days", AccountStatus::GMLeadAdmin, command_suspendmulti) ||
command_add("takeplatinum", "[Platinum] - Takes specified amount of platinum from you or your player target", AccountStatus::GMMgmt, command_takeplatinum) ||
command_add("task", "(subcommand) - Task system commands", AccountStatus::GMLeadAdmin, command_task) || command_add("task", "(subcommand) - Task system commands", AccountStatus::GMLeadAdmin, command_task) ||
command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_petname) || command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", AccountStatus::GMAdmin, command_petname) ||
command_add("traindisc", "[level] - Trains all the disciplines usable by the target, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_traindisc) || command_add("traindisc", "[level] - Trains all the disciplines usable by the target, up to level specified. (may freeze client for a few seconds)", AccountStatus::GMLeadAdmin, command_traindisc) ||
@@ -691,7 +692,7 @@ void command_hotfix(Client *c, const Seperator *sep)
} }
worldserver.SendPacket(&pack); worldserver.SendPacket(&pack);
if (c) { c->Message(Chat::White, "Hotfix applied"); } worldserver.SendEmoteMessage(0, 0, AccountStatus::ApprenticeGuide, Chat::Yellow, "Hotfix applied");
} }
); );
@@ -865,6 +866,7 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/nukebuffs.cpp" #include "gm_commands/nukebuffs.cpp"
#include "gm_commands/nukeitem.cpp" #include "gm_commands/nukeitem.cpp"
#include "gm_commands/object.cpp" #include "gm_commands/object.cpp"
#include "gm_commands/object_manipulation.cpp"
#include "gm_commands/path.cpp" #include "gm_commands/path.cpp"
#include "gm_commands/peqzone.cpp" #include "gm_commands/peqzone.cpp"
#include "gm_commands/petitems.cpp" #include "gm_commands/petitems.cpp"
@@ -903,6 +905,7 @@ void command_bot(Client *c, const Seperator *sep)
#include "gm_commands/summonitem.cpp" #include "gm_commands/summonitem.cpp"
#include "gm_commands/suspend.cpp" #include "gm_commands/suspend.cpp"
#include "gm_commands/suspendmulti.cpp" #include "gm_commands/suspendmulti.cpp"
#include "gm_commands/takeplatinum.cpp"
#include "gm_commands/task.cpp" #include "gm_commands/task.cpp"
#include "gm_commands/traindisc.cpp" #include "gm_commands/traindisc.cpp"
#include "gm_commands/tune.cpp" #include "gm_commands/tune.cpp"
+1
View File
@@ -168,6 +168,7 @@ void command_summonburiedplayercorpse(Client *c, const Seperator *sep);
void command_summonitem(Client *c, const Seperator *sep); void command_summonitem(Client *c, const Seperator *sep);
void command_suspend(Client *c, const Seperator *sep); void command_suspend(Client *c, const Seperator *sep);
void command_suspendmulti(Client *c, const Seperator *sep); void command_suspendmulti(Client *c, const Seperator *sep);
void command_takeplatinum(Client* c, const Seperator* sep);
void command_task(Client *c, const Seperator *sep); void command_task(Client *c, const Seperator *sep);
void command_petname(Client *c, const Seperator *sep); void command_petname(Client *c, const Seperator *sep);
void command_traindisc(Client *c, const Seperator *sep); void command_traindisc(Client *c, const Seperator *sep);
+1 -1
View File
@@ -277,7 +277,7 @@ void Doors::HandleClick(Client *sender, uint8 trigger)
// enforce flags before they hit zoning process // enforce flags before they hit zoning process
auto z = GetZone(m_destination_zone_name, 0); auto z = GetZone(m_destination_zone_name, 0);
if (z && !z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && Strings::ToInt(z->flag_needed) == 1) { if (z && !z->flag_needed.empty() && Strings::IsNumber(z->flag_needed) && Strings::ToInt(z->flag_needed) == 1) {
if (sender->Admin() < minStatusToIgnoreZoneFlags && !sender->HasZoneFlag(z->zoneidnumber)) { if (!sender->GetGM() && !sender->HasZoneFlag(z->zoneidnumber)) {
LogInfo( LogInfo(
"Character [{}] does not have the flag to be in this zone [{}]!", "Character [{}] does not have the flag to be in this zone [{}]!",
sender->GetCleanName(), sender->GetCleanName(),
+10 -44
View File
@@ -205,11 +205,6 @@ PerlembParser::~PerlembParser()
safe_delete(perl); safe_delete(perl);
} }
void PerlembParser::Init()
{
ReloadQuests();
}
void PerlembParser::ReloadQuests() void PerlembParser::ReloadQuests()
{ {
try { try {
@@ -1445,7 +1440,7 @@ void PerlembParser::ExportZoneVariables(std::string &package_name)
ExportVar(package_name.c_str(), "zonesn", zone->GetShortName()); ExportVar(package_name.c_str(), "zonesn", zone->GetShortName());
ExportVar(package_name.c_str(), "instanceid", zone->GetInstanceID()); ExportVar(package_name.c_str(), "instanceid", zone->GetInstanceID());
ExportVar(package_name.c_str(), "instanceversion", zone->GetInstanceVersion()); ExportVar(package_name.c_str(), "instanceversion", zone->GetInstanceVersion());
TimeOfDay_Struct eqTime; TimeOfDay_Struct eqTime{};
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime); zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime);
ExportVar(package_name.c_str(), "zonehour", eqTime.hour - 1); ExportVar(package_name.c_str(), "zonehour", eqTime.hour - 1);
ExportVar(package_name.c_str(), "zonemin", eqTime.minute); ExportVar(package_name.c_str(), "zonemin", eqTime.minute);
@@ -1880,55 +1875,27 @@ void PerlembParser::ExportEventVariables(
break; break;
} }
case EVENT_DEATH: {
Seperator sep(data);
ExportVar(package_name.c_str(), "killer_id", sep.arg[0]);
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[2]))) {
ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[2])]);
}
if (extra_pointers && extra_pointers->size() == 1) {
Mob* killed = std::any_cast<Mob*>(extra_pointers->at(0));
if (killed) {
ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID());
ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
ExportVar(package_name.c_str(), "killed_x", killed->GetX());
ExportVar(package_name.c_str(), "killed_y", killed->GetY());
ExportVar(package_name.c_str(), "killed_z", killed->GetZ());
ExportVar(package_name.c_str(), "killed_h", killed->GetHeading());
}
}
break;
}
case EVENT_DEATH_ZONE: case EVENT_DEATH_ZONE:
case EVENT_DEATH:
case EVENT_DEATH_COMPLETE: { case EVENT_DEATH_COMPLETE: {
Seperator sep(data); Seperator sep(data);
ExportVar(package_name.c_str(), "killer_id", sep.arg[0]); ExportVar(package_name.c_str(), "killer_id", sep.arg[0]);
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]); ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]); ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
if (extra_pointers && extra_pointers->size() >= 1)
if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[2]))) { {
ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[2])]);
}
if (extra_pointers && extra_pointers->size() >= 1) {
Corpse* corpse = std::any_cast<Corpse*>(extra_pointers->at(0)); Corpse* corpse = std::any_cast<Corpse*>(extra_pointers->at(0));
if (corpse) { if (corpse)
{
ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID()); ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID());
} }
} }
if (extra_pointers && extra_pointers->size() >= 2)
if (extra_pointers && extra_pointers->size() >= 2) { {
NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1)); NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1));
if (killed) { if (killed)
{
ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID()); ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID());
ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0); ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0); ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
@@ -1938,7 +1905,6 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "killed_h", killed->GetHeading()); ExportVar(package_name.c_str(), "killed_h", killed->GetHeading());
} }
} }
break; break;
} }
-1
View File
@@ -133,7 +133,6 @@ public:
virtual void AddVar(std::string name, std::string val); virtual void AddVar(std::string name, std::string val);
virtual std::string GetVar(std::string name); virtual std::string GetVar(std::string name);
virtual void Init() override;
virtual void ReloadQuests(); virtual void ReloadQuests();
virtual uint32 GetIdentifier() { return 0xf8b05c11; } virtual uint32 GetIdentifier() { return 0xf8b05c11; }
+20 -35
View File
@@ -1433,6 +1433,16 @@ void Perl__removeitem(uint32_t item_id, int quantity)
quest_manager.removeitem(item_id, quantity); quest_manager.removeitem(item_id, quantity);
} }
std::string Perl__getitemcomment(uint32 item_id)
{
return quest_manager.getitemcomment(item_id);
}
std::string Perl__getitemlore(uint32 item_id)
{
return quest_manager.getitemlore(item_id);
}
std::string Perl__getitemname(uint32 item_id) std::string Perl__getitemname(uint32 item_id)
{ {
return quest_manager.getitemname(item_id); return quest_manager.getitemname(item_id);
@@ -3506,14 +3516,7 @@ void Perl__crosszonemoveplayerbycharid(uint32 character_id, std::string zone_sho
); );
} }
void Perl__crosszonemoveplayerbycharid( void Perl__crosszonemoveplayerbycharid(uint32 character_id, std::string zone_short_name, float x, float y, float z, float heading)
uint32 character_id,
std::string zone_short_name,
float x,
float y,
float z,
float heading
)
{ {
quest_manager.CrossZoneMove( quest_manager.CrossZoneMove(
CZMove_Struct{ CZMove_Struct{
@@ -3551,14 +3554,7 @@ void Perl__crosszonemoveplayerbygroupid(uint32 group_id, std::string zone_short_
); );
} }
void Perl__crosszonemoveplayerbygroupid( void Perl__crosszonemoveplayerbygroupid(uint32 group_id, std::string zone_short_name, float x, float y, float z, float heading)
uint32 group_id,
std::string zone_short_name,
float x,
float y,
float z,
float heading
)
{ {
quest_manager.CrossZoneMove( quest_manager.CrossZoneMove(
CZMove_Struct{ CZMove_Struct{
@@ -3634,14 +3630,7 @@ void Perl__crosszonemoveplayerbyguildid(uint32 guild_id, std::string zone_short_
); );
} }
void Perl__crosszonemoveplayerbyguildid( void Perl__crosszonemoveplayerbyguildid(uint32 guild_id, std::string zone_short_name, float x, float y, float z, float heading)
uint32 guild_id,
std::string zone_short_name,
float x,
float y,
float z,
float heading
)
{ {
quest_manager.CrossZoneMove( quest_manager.CrossZoneMove(
CZMove_Struct{ CZMove_Struct{
@@ -3679,14 +3668,7 @@ void Perl__crosszonemoveplayerbyexpeditionid(uint32 expedition_id, std::string z
); );
} }
void Perl__crosszonemoveplayerbyexpeditionid( void Perl__crosszonemoveplayerbyexpeditionid(uint32 expedition_id, std::string zone_short_name, float x, float y, float z, float heading)
uint32 expedition_id,
std::string zone_short_name,
float x,
float y,
float z,
float heading
)
{ {
quest_manager.CrossZoneMove( quest_manager.CrossZoneMove(
CZMove_Struct{ CZMove_Struct{
@@ -5860,8 +5842,8 @@ void perl_register_quest()
package.add("GetZoneFogRed", (uint8(*)(uint32))&Perl__GetZoneFogRed); package.add("GetZoneFogRed", (uint8(*)(uint32))&Perl__GetZoneFogRed);
package.add("GetZoneFogRed", (uint8(*)(uint32, uint8))&Perl__GetZoneFogRed); package.add("GetZoneFogRed", (uint8(*)(uint32, uint8))&Perl__GetZoneFogRed);
package.add("GetZoneFogRed", (uint8(*)(uint32, uint8, int))&Perl__GetZoneFogRed); package.add("GetZoneFogRed", (uint8(*)(uint32, uint8, int))&Perl__GetZoneFogRed);
package.add("GetZoneGravity", (float(*)(uint32))&Perl__GetZoneMaximumClip); package.add("GetZoneGravity", (float(*)(uint32))&Perl__GetZoneGravity);
package.add("GetZoneGravity", (float(*)(uint32, int))&Perl__GetZoneMaximumClip); package.add("GetZoneGravity", (float(*)(uint32, int))&Perl__GetZoneGravity);
package.add("GetZoneMaximumClip", (float(*)(uint32))&Perl__GetZoneMaximumClip); package.add("GetZoneMaximumClip", (float(*)(uint32))&Perl__GetZoneMaximumClip);
package.add("GetZoneMaximumClip", (float(*)(uint32, int))&Perl__GetZoneMaximumClip); package.add("GetZoneMaximumClip", (float(*)(uint32, int))&Perl__GetZoneMaximumClip);
package.add("GetZoneMaximumExpansion", (int8(*)(uint32))&Perl__GetZoneMaximumExpansion); package.add("GetZoneMaximumExpansion", (int8(*)(uint32))&Perl__GetZoneMaximumExpansion);
@@ -6033,6 +6015,7 @@ void perl_register_quest()
package.add("IsTargetRequiredForSpell", &Perl__IsTargetRequiredForSpell); package.add("IsTargetRequiredForSpell", &Perl__IsTargetRequiredForSpell);
package.add("IsTeleportSpell", &Perl__IsTeleportSpell); package.add("IsTeleportSpell", &Perl__IsTeleportSpell);
package.add("IsTranslocateSpell", &Perl__IsTranslocateSpell); package.add("IsTranslocateSpell", &Perl__IsTranslocateSpell);
package.add("IsTGBCompatibleSpell", &Perl__IsTGBCompatibleSpell);
package.add("IsVeryFastHealSpell", &Perl__IsVeryFastHealSpell); package.add("IsVeryFastHealSpell", &Perl__IsVeryFastHealSpell);
package.add("IsVirusSpell", &Perl__IsVirusSpell); package.add("IsVirusSpell", &Perl__IsVirusSpell);
package.add("IsValidSpell", &Perl__IsValidSpell); package.add("IsValidSpell", &Perl__IsValidSpell);
@@ -6315,7 +6298,7 @@ void perl_register_quest()
package.add("worldwideremovespell", (void(*)(uint32, uint8))&Perl__worldwideremovespell); package.add("worldwideremovespell", (void(*)(uint32, uint8))&Perl__worldwideremovespell);
package.add("worldwideremovespell", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovespell); package.add("worldwideremovespell", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovespell);
package.add("worldwideremovetask", (void(*)(uint32))&Perl__worldwideremovetask); package.add("worldwideremovetask", (void(*)(uint32))&Perl__worldwideremovetask);
package.add("worldwideremovetask", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovetask); package.add("worldwideremovetask", (void(*)(uint32, uint8))&Perl__worldwideremovetask);
package.add("worldwideremovetask", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovetask); package.add("worldwideremovetask", (void(*)(uint32, uint8, uint8))&Perl__worldwideremovetask);
package.add("worldwideresetactivity", (void(*)(uint32, int))&Perl__worldwideresetactivity); package.add("worldwideresetactivity", (void(*)(uint32, int))&Perl__worldwideresetactivity);
package.add("worldwideresetactivity", (void(*)(uint32, int, uint8))&Perl__worldwideresetactivity); package.add("worldwideresetactivity", (void(*)(uint32, int, uint8))&Perl__worldwideresetactivity);
@@ -6404,6 +6387,8 @@ void perl_register_quest()
package.add("get_expedition_lockouts_by_char_id", (perl::reference(*)(uint32, std::string))&Perl__get_expedition_lockouts_by_char_id); package.add("get_expedition_lockouts_by_char_id", (perl::reference(*)(uint32, std::string))&Perl__get_expedition_lockouts_by_char_id);
package.add("getfactionname", &Perl__getfactionname); package.add("getfactionname", &Perl__getfactionname);
package.add("getinventoryslotid", &Perl__getinventoryslotid); package.add("getinventoryslotid", &Perl__getinventoryslotid);
package.add("getitemcomment", &Perl__getitemcomment);
package.add("getitemlore", &Perl__getitemlore);
package.add("getitemname", &Perl__getitemname); package.add("getitemname", &Perl__getitemname);
package.add("getitemstat", &Perl__getitemstat); package.add("getitemstat", &Perl__getitemstat);
package.add("getlanguagename", &Perl__getlanguagename); package.add("getlanguagename", &Perl__getlanguagename);
+5 -3
View File
@@ -2,10 +2,12 @@
void command_acceptrules(Client *c, const Seperator *sep) void command_acceptrules(Client *c, const Seperator *sep)
{ {
if (!database.GetAgreementFlag(c->AccountID())) { if (database.GetAgreementFlag(c->AccountID())) {
c->Message(Chat::White, "You have already agreed to the rules.");
return;
}
database.SetAgreementFlag(c->AccountID()); database.SetAgreementFlag(c->AccountID());
c->SendAppearancePacket(AT_Anim, ANIM_STAND); c->SendAppearancePacket(AT_Anim, ANIM_STAND);
c->Message(Chat::White, "It is recorded you have agreed to the rules."); c->Message(Chat::White, "It is recorded you have agreed to the rules.");
} }
}
+1 -4
View File
@@ -23,10 +23,7 @@ void command_castspell(Client *c, const Seperator *sep)
const uint16 spell_id = Strings::ToUnsignedInt(sep->arg[1]); const uint16 spell_id = Strings::ToUnsignedInt(sep->arg[1]);
if (IsCastRestrictedSpell(spell_id) && c->Admin() < commandCastSpecials) { if (spell_id >= SPDAT_RECORDS) {
c->Message(Chat::White, "Unable to cast spell.");
return;
} else if (spell_id >= SPDAT_RECORDS) {
c->Message(Chat::White, "Invalid Spell ID."); c->Message(Chat::White, "Invalid Spell ID.");
return; return;
} }
+28 -97
View File
@@ -9,18 +9,22 @@ void command_corpse(Client *c, const Seperator *sep)
c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses"); c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses");
c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse"); c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse");
c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses"); c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses");
c->Message(Chat::White, "Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"); c->Message(
Chat::White,
"Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"
);
c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse"); c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse");
c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse"); c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse");
if (c->Admin() >= commandEditPlayerCorpses) {
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner"); c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses"); c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse."); c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses."); c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses"); c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
c->Message(Chat::White, "Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"); c->Message(
Chat::White,
"Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"
);
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses."); c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
}
return; return;
} }
@@ -59,24 +63,27 @@ void command_corpse(Client *c, const Seperator *sep)
c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses"); c->Message(Chat::White, "Usage: #corpse deletenpccorpses - Deletes all NPC corpses");
c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse"); c->Message(Chat::White, "Usage: #corpse inspectloot - Inspects the loot on a corpse");
c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses"); c->Message(Chat::White, "Usage: #corpse listnpc - Lists all NPC corpses");
c->Message(Chat::White, "Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"); c->Message(
Chat::White,
"Usage: #corpse lock - Locks the corpse, only GMs can loot the corpse when it is locked"
);
c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse"); c->Message(Chat::White, "Usage: #corpse removecash - Removes the cash from a corpse");
c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse"); c->Message(Chat::White, "Usage: #corpse unlock - Unlocks the corpses, allowing non-GMs to loot the corpse");
if (c->Admin() >= commandEditPlayerCorpses) {
c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner"); c->Message(Chat::White, "Usage: #corpse charid [Character ID] - Change player corpse's owner");
c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses"); c->Message(Chat::White, "Usage: #corpse deleteplayercorpses - Deletes all player corpses");
c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse."); c->Message(Chat::White, "Usage: #corpse depop [Bury] - Depops single target corpse.");
c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses."); c->Message(Chat::White, "Usage: #corpse depopall [Bury] - Depops all target player's corpses.");
c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses"); c->Message(Chat::White, "Usage: #corpse listplayer - Lists all player corpses");
c->Message(Chat::White, "Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"); c->Message(
Chat::White,
"Usage: #corpse moveallgraveyard - Moves all player corpses to the current zone's graveyard or non-instance"
);
c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses."); c->Message(Chat::White, "Note: Set bury to 0 to skip burying the corpses.");
}
return; return;
} }
if (is_delete_player_corpses) { if (is_delete_player_corpses) {
if (c->Admin() >= commandEditPlayerCorpses) {
auto corpses_deleted = entity_list.DeletePlayerCorpses(); auto corpses_deleted = entity_list.DeletePlayerCorpses();
auto deleted_string = ( auto deleted_string = (
corpses_deleted ? corpses_deleted ?
@@ -88,25 +95,12 @@ void command_corpse(Client *c, const Seperator *sep)
"There are no player corpses to delete." "There are no player corpses to delete."
); );
c->Message(Chat::White, deleted_string.c_str()); c->Message(Chat::White, deleted_string.c_str());
} else {
c->Message(Chat::White, "Your status is not high enough to delete player corpses.");
return;
}
} else if (is_delete) { } else if (is_delete) {
if (!target || !target->IsCorpse()) { if (!target || !target->IsCorpse()) {
c->Message(Chat::White, "You must target a corpse to use this command."); c->Message(Chat::White, "You must target a corpse to use this command.");
return; return;
} }
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
c->Message(Chat::White, "Your status is not high enough to delete a player corpse.");
return;
}
if (
target->IsNPCCorpse() ||
c->Admin() >= commandEditPlayerCorpses
) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -115,16 +109,11 @@ void command_corpse(Client *c, const Seperator *sep)
c->GetTargetDescription(target) c->GetTargetDescription(target)
).c_str() ).c_str()
); );
target->CastToCorpse()->Delete(); target->CastToCorpse()->Delete();
}
} else if (is_list_npc) { } else if (is_list_npc) {
entity_list.ListNPCCorpses(c); entity_list.ListNPCCorpses(c);
} else if (is_list_player) { } else if (is_list_player) {
if (c->Admin() < commandEditPlayerCorpses) {
c->Message(Chat::White, "Your status is not high enough to list player corpses.");
return;
}
entity_list.ListPlayerCorpses(c); entity_list.ListPlayerCorpses(c);
} else if (is_delete_npc_corpses) { } else if (is_delete_npc_corpses) {
auto corpses_deleted = entity_list.DeleteNPCCorpses(); auto corpses_deleted = entity_list.DeleteNPCCorpses();
@@ -139,7 +128,6 @@ void command_corpse(Client *c, const Seperator *sep)
); );
c->Message(Chat::White, deleted_string.c_str()); c->Message(Chat::White, deleted_string.c_str());
} else if (is_character_id) { } else if (is_character_id) {
if (c->Admin() >= commandEditPlayerCorpses) {
if (!target || !target->IsPlayerCorpse()) { if (!target || !target->IsPlayerCorpse()) {
c->Message(Chat::White, "You must target a player corpse to use this command."); c->Message(Chat::White, "You must target a player corpse to use this command.");
return; return;
@@ -150,7 +138,7 @@ void command_corpse(Client *c, const Seperator *sep)
return; return;
} }
auto character_id = Strings::ToInt(sep->arg[2]); const uint32 character_id = Strings::ToUnsignedInt(sep->arg[2]);
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -160,21 +148,12 @@ void command_corpse(Client *c, const Seperator *sep)
c->GetTargetDescription(target) c->GetTargetDescription(target)
).c_str() ).c_str()
); );
} else {
c->Message(Chat::White, "Your status is not high enough to modify a player corpse's owner.");
return;
}
} else if (is_reset_looter) { } else if (is_reset_looter) {
if (!target || !target->IsCorpse()) { if (!target || !target->IsCorpse()) {
c->Message(Chat::White, "You must target a corpse to use this command."); c->Message(Chat::White, "You must target a corpse to use this command.");
return; return;
} }
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
c->Message(Chat::White, "Your status is not high enough to reset looter on a player corpse.");
return;
}
target->CastToCorpse()->ResetLooter(); target->CastToCorpse()->ResetLooter();
c->Message( c->Message(
Chat::White, Chat::White,
@@ -190,16 +169,8 @@ void command_corpse(Client *c, const Seperator *sep)
return; return;
} }
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
c->Message(Chat::White, "Your status is not high enough to remove cash from a player corpse.");
return;
}
if (
target->IsNPCCorpse() ||
c->Admin() >= commandEditPlayerCorpses
) {
target->CastToCorpse()->RemoveCash(); target->CastToCorpse()->RemoveCash();
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -208,18 +179,12 @@ void command_corpse(Client *c, const Seperator *sep)
c->GetTargetDescription(target) c->GetTargetDescription(target)
).c_str() ).c_str()
); );
}
} else if (is_inspect_loot) { } else if (is_inspect_loot) {
if (!target || !target->IsCorpse()) { if (!target || !target->IsCorpse()) {
c->Message(Chat::White, "You must target a corpse to use this command."); c->Message(Chat::White, "You must target a corpse to use this command.");
return; return;
} }
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
c->Message(Chat::White, "Your status is not high enough to inspect the loot of a player corpse.");
return;
}
target->CastToCorpse()->QueryLoot(c); target->CastToCorpse()->QueryLoot(c);
} else if (is_lock) { } else if (is_lock) {
if (!target || !target->IsCorpse()) { if (!target || !target->IsCorpse()) {
@@ -227,11 +192,6 @@ void command_corpse(Client *c, const Seperator *sep)
return; return;
} }
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
c->Message(Chat::White, "Your status is not high enough to lock player corpses.");
return;
}
target->CastToCorpse()->Lock(); target->CastToCorpse()->Lock();
c->Message( c->Message(
Chat::White, Chat::White,
@@ -247,11 +207,6 @@ void command_corpse(Client *c, const Seperator *sep)
return; return;
} }
if (target->IsPlayerCorpse() && c->Admin() < commandEditPlayerCorpses) {
c->Message(Chat::White, "Your status is not high enough to unlock player corpses.");
return;
}
target->CastToCorpse()->UnLock(); target->CastToCorpse()->UnLock();
c->Message( c->Message(
Chat::White, Chat::White,
@@ -267,16 +222,8 @@ void command_corpse(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() >= commandEditPlayerCorpses) { const bool bury_corpse = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
bool bury_corpse = (
sep->IsNumber(2) ?
(
Strings::ToInt(sep->arg[2]) != 0 ?
true :
false
) :
false
);
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -284,30 +231,20 @@ void command_corpse(Client *c, const Seperator *sep)
c->GetTargetDescription(target) c->GetTargetDescription(target)
).c_str() ).c_str()
); );
target->CastToCorpse()->DepopPlayerCorpse(); target->CastToCorpse()->DepopPlayerCorpse();
if (bury_corpse) { if (bury_corpse) {
target->CastToCorpse()->Bury(); target->CastToCorpse()->Bury();
} }
} else {
c->Message(Chat::White, "Your status is not high enough to depop a player corpse.");
return;
}
} else if (is_depop_all) { } else if (is_depop_all) {
if (!target || !target->IsClient()) { if (!target || !target->IsClient()) {
c->Message(Chat::White, "You must target a player to use this command."); c->Message(Chat::White, "You must target a player to use this command.");
return; return;
} }
if (c->Admin() >= commandEditPlayerCorpses) { const bool bury_corpse = sep->IsNumber(2) ? Strings::ToBool(sep->arg[2]) : false;
bool bury_corpse = (
sep->IsNumber(2) ?
(
Strings::ToInt(sep->arg[2]) != 0 ?
true :
false
) :
false
);
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -315,17 +252,14 @@ void command_corpse(Client *c, const Seperator *sep)
c->GetTargetDescription(target) c->GetTargetDescription(target)
).c_str() ).c_str()
); );
target->CastToClient()->DepopAllCorpses(); target->CastToClient()->DepopAllCorpses();
if (bury_corpse) { if (bury_corpse) {
target->CastToClient()->BuryPlayerCorpses(); target->CastToClient()->BuryPlayerCorpses();
} }
} else {
c->Message(Chat::White, "Your status is not high enough to depop all of a player's corpses.");
return;
}
} else if (is_move_all_to_graveyard) { } else if (is_move_all_to_graveyard) {
int moved_count = entity_list.MovePlayerCorpsesToGraveyard(true); const int moved_count = entity_list.MovePlayerCorpsesToGraveyard(true);
if (c->Admin() >= commandEditPlayerCorpses) {
if (moved_count) { if (moved_count) {
c->Message( c->Message(
Chat::White, Chat::White,
@@ -340,9 +274,6 @@ void command_corpse(Client *c, const Seperator *sep)
} else { } else {
c->Message(Chat::White, "There are no player corpses to move to the graveyard."); c->Message(Chat::White, "There are no player corpses to move to the graveyard.");
} }
} else {
c->Message(Chat::White, "Your status is not high enough to move all player corpses to the graveyard.");
}
} }
} }
+17 -14
View File
@@ -2,24 +2,27 @@
void command_disarmtrap(Client *c, const Seperator *sep) void command_disarmtrap(Client *c, const Seperator *sep)
{ {
Mob *target = c->GetTarget(); Mob *t = c->GetTarget();
if (!t || !t->IsNPC()) {
if (!target) { c->Message(Chat::White, "You must target an NPC to use this command.");
c->Message(Chat::Red, "You must have a target.");
return; return;
} }
if (target->IsNPC()) { if (!c->HasSkill(EQ::skills::SkillDisarmTraps)) {
if (c->HasSkill(EQ::skills::SkillDisarmTraps)) { c->Message(Chat::White, "You do not have the Disarm Trap skill.");
if (DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) {
c->Message(Chat::Red, "%s is too far away.", target->GetCleanName());
return; return;
} }
c->HandleLDoNDisarm(target->CastToNPC(), c->GetSkill(EQ::skills::SkillDisarmTraps), LDoNTypeMechanical);
} if (DistanceSquaredNoZ(c->GetPosition(), t->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) {
else { c->Message(
c->Message(Chat::Red, "You do not have the disarm trap skill."); Chat::White,
} fmt::format(
} "{} is too far away.",
t->GetCleanName()
).c_str()
);
return;
} }
c->HandleLDoNDisarm(t->CastToNPC(), c->GetSkill(EQ::skills::SkillDisarmTraps), LDoNTypeMechanical);
}
+1 -1
View File
@@ -10,7 +10,7 @@ void command_doanim(Client *c, const Seperator *sep)
} }
Mob* t = c; Mob* t = c;
if (c->GetTarget() && c->Admin() >= commandDoAnimOthers) { if (c->GetTarget()) {
t = c->GetTarget(); t = c->GetTarget();
} }
-1
View File
@@ -1,6 +1,5 @@
#include "../client.h" #include "../client.h"
#include "door_manipulation.h" #include "door_manipulation.h"
#include "../doors.h"
void command_door(Client *c, const Seperator *sep) void command_door(Client *c, const Seperator *sep)
{ {
+62 -32
View File
@@ -2,6 +2,11 @@
void command_giveitem(Client *c, const Seperator *sep) void command_giveitem(Client *c, const Seperator *sep)
{ {
if (!c->GetTarget() || !c->GetTarget()->IsClient()) {
c->Message(Chat::White, "You must target a player to use this command.");
return;
}
uint32 item_id = 0; uint32 item_id = 0;
int16 charges = -1; int16 charges = -1;
uint32 augment_one = 0; uint32 augment_one = 0;
@@ -10,21 +15,17 @@ void command_giveitem(Client *c, const Seperator *sep)
uint32 augment_four = 0; uint32 augment_four = 0;
uint32 augment_five = 0; uint32 augment_five = 0;
uint32 augment_six = 0; uint32 augment_six = 0;
int arguments = sep->argnum; const uint16 arguments = sep->argnum;
std::string cmd_msg = sep->msg; std::string cmd_msg = sep->msg;
size_t link_open = cmd_msg.find('\x12'); size_t link_open = cmd_msg.find('\x12');
size_t link_close = cmd_msg.find_last_of('\x12'); size_t link_close = cmd_msg.find_last_of('\x12');
if (c->GetTarget()) {
if (!c->GetTarget()->IsClient()) {
c->Message(Chat::Red, "You can only give items to players with this command.");
return;
}
if (link_open != link_close && (cmd_msg.length() - link_open) > EQ::constants::SAY_LINK_BODY_SIZE) { if (link_open != link_close && (cmd_msg.length() - link_open) > EQ::constants::SAY_LINK_BODY_SIZE) {
EQ::SayLinkBody_Struct link_body; EQ::SayLinkBody_Struct link_body;
EQ::saylink::DegenerateLinkBody( EQ::saylink::DegenerateLinkBody(
link_body, link_body,
cmd_msg.substr(link_open + 1, EQ::constants::SAY_LINK_BODY_SIZE)); cmd_msg.substr(link_open + 1, EQ::constants::SAY_LINK_BODY_SIZE)
);
item_id = link_body.item_id; item_id = link_body.item_id;
augment_one = link_body.augment_1; augment_one = link_body.augment_1;
augment_two = link_body.augment_2; augment_two = link_body.augment_2;
@@ -32,26 +33,35 @@ void command_giveitem(Client *c, const Seperator *sep)
augment_four = link_body.augment_4; augment_four = link_body.augment_4;
augment_five = link_body.augment_5; augment_five = link_body.augment_5;
augment_six = link_body.augment_6; augment_six = link_body.augment_6;
} } else if (sep->IsNumber(1)) {
else if (sep->IsNumber(1)) { item_id = Strings::ToUnsignedInt(sep->arg[1]);
item_id = Strings::ToInt(sep->arg[1]); } else if (!sep->IsNumber(1)) {
}
else if (!sep->IsNumber(1)) {
c->Message( c->Message(
Chat::Red, Chat::Red,
"Usage: #giveitem [item id | link] [charges] [augment_one_id] [augment_two_id] [augment_three_id] [augment_four_id] [augment_five_id] [augment_six_id] (Charges are optional.)" "Usage: #giveitem [item id | link] [charges] [augment_one_id] [augment_two_id] [augment_three_id] [augment_four_id] [augment_five_id] [augment_six_id] (Charges and augments are optional.)"
); );
return; return;
} }
Client *client_target = c->GetTarget()->CastToClient(); Client* t = c->GetTarget()->CastToClient();
uint8 item_status = 0; uint8 item_status = 0;
uint8 current_status = c->Admin(); const uint8 current_status = c->Admin();
const EQ::ItemData *item = database.GetItem(item_id);
if (item) { const auto *item = database.GetItem(item_id);
item_status = item->MinStatus; if (!item) {
c->Message(
Chat::White,
fmt::format(
"Item ID {} does not exist.",
item_id
).c_str()
);
return;
} }
item_status = item->MinStatus;
if (item_status > current_status) { if (item_status > current_status) {
c->Message( c->Message(
Chat::White, Chat::White,
@@ -65,34 +75,34 @@ void command_giveitem(Client *c, const Seperator *sep)
} }
if (arguments >= 2 && sep->IsNumber(2)) { if (arguments >= 2 && sep->IsNumber(2)) {
charges = Strings::ToInt(sep->arg[2]); charges = static_cast<int16>(Strings::ToInt(sep->arg[2]));
} }
if (arguments >= 3 && sep->IsNumber(3)) { if (arguments >= 3 && sep->IsNumber(3)) {
augment_one = Strings::ToInt(sep->arg[3]); augment_one = Strings::ToUnsignedInt(sep->arg[3]);
} }
if (arguments >= 4 && sep->IsNumber(4)) { if (arguments >= 4 && sep->IsNumber(4)) {
augment_two = Strings::ToInt(sep->arg[4]); augment_two = Strings::ToUnsignedInt(sep->arg[4]);
} }
if (arguments >= 5 && sep->IsNumber(5)) { if (arguments >= 5 && sep->IsNumber(5)) {
augment_three = Strings::ToInt(sep->arg[5]); augment_three = Strings::ToUnsignedInt(sep->arg[5]);
} }
if (arguments >= 6 && sep->IsNumber(6)) { if (arguments >= 6 && sep->IsNumber(6)) {
augment_four = Strings::ToInt(sep->arg[6]); augment_four = Strings::ToUnsignedInt(sep->arg[6]);
} }
if (arguments >= 7 && sep->IsNumber(7)) { if (arguments >= 7 && sep->IsNumber(7)) {
augment_five = Strings::ToInt(sep->arg[7]); augment_five = Strings::ToUnsignedInt(sep->arg[7]);
} }
if (arguments == 8 && sep->IsNumber(8)) { if (arguments == 8 && sep->IsNumber(8)) {
augment_six = Strings::ToInt(sep->arg[8]); augment_six = Strings::ToUnsignedInt(sep->arg[8]);
} }
client_target->SummonItem( t->SummonItem(
item_id, item_id,
charges, charges,
augment_one, augment_one,
@@ -102,10 +112,30 @@ void command_giveitem(Client *c, const Seperator *sep)
augment_five, augment_five,
augment_six augment_six
); );
}
else {
c->Message(Chat::Red, "You must target a client to give the item to.");
return;
}
}
const auto *new_item = database.CreateItem(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
EQ::SayLinkEngine linker;
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
linker.SetItemInst(new_item);
const std::string &item_link = linker.GenerateLink();
c->Message(
Chat::White,
fmt::format(
"You have given {} to {}.",
item_link,
c->GetTargetDescription(t)
).c_str()
);
}
+2 -2
View File
@@ -4,7 +4,7 @@ void command_givemoney(Client *c, const Seperator *sep)
{ {
int arguments = sep->argnum; int arguments = sep->argnum;
if (!arguments || !sep->IsNumber(1)) { //as long as the first one is a number, we'll just let atoi convert the rest to 0 or a number if (!arguments || !sep->IsNumber(1)) { //as long as the first one is a number, we'll just let atoi convert the rest to 0 or a number
c->Message(Chat::Red, "Usage: #Usage: #givemoney [Platinum] [Gold] [Silver] [Copper]"); c->Message(Chat::Red, "Usage: #givemoney [Platinum] [Gold] [Silver] [Copper]");
return; return;
} }
@@ -19,7 +19,7 @@ void command_givemoney(Client *c, const Seperator *sep)
uint32 silver = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0; uint32 silver = sep->IsNumber(3) ? Strings::ToUnsignedInt(sep->arg[3]) : 0;
uint32 copper = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0; uint32 copper = sep->IsNumber(4) ? Strings::ToUnsignedInt(sep->arg[4]) : 0;
if (!platinum && !gold && !silver && !copper) { if (!platinum && !gold && !silver && !copper) {
c->Message(Chat::Red, "Usage: #Usage: #givemoney [Platinum] [Gold] [Silver] [Copper]"); c->Message(Chat::Red, "Usage: #givemoney [Platinum] [Gold] [Silver] [Copper]");
return; return;
} }
+2 -59
View File
@@ -81,11 +81,6 @@ void command_guild(Client *c, const Seperator *sep)
).c_str() ).c_str()
); );
} else { } else {
if (c->Admin() < minStatusToEditOtherGuilds) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
return;
}
auto guild_name = sep->argplus[3]; auto guild_name = sep->argplus[3];
auto guild_id = guild_mgr.CreateGuild(sep->argplus[3], leader_id); auto guild_id = guild_mgr.CreateGuild(sep->argplus[3], leader_id);
@@ -144,16 +139,6 @@ void command_guild(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() < minStatusToEditOtherGuilds) {
if (c->GuildID() != guild_id) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
return;
} else if (!guild_mgr.CheckGMStatus(guild_id, c->Admin())) {
c->Message(Chat::White, "You cannot edit your current guild, your status is not high enough.");
return;
}
}
LogGuilds( LogGuilds(
"[{}]: Deleting guild [{}] ([{}]) with GM command", "[{}]: Deleting guild [{}] ([{}]) with GM command",
c->GetName(), c->GetName(),
@@ -175,16 +160,10 @@ void command_guild(Client *c, const Seperator *sep)
SendGuildSubCommands(c); SendGuildSubCommands(c);
} else if (is_info) { } else if (is_info) {
if (arguments != 2 && c->IsInAGuild()) { if (arguments != 2 && c->IsInAGuild()) {
if (c->Admin() >= minStatusToEditOtherGuilds) {
c->Message(Chat::White, "#guild info [Guild ID]"); c->Message(Chat::White, "#guild info [Guild ID]");
} else {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
}
} else { } else {
auto guild_id = GUILD_NONE; auto guild_id = GUILD_NONE;
if (arguments != 2 || !sep->IsNumber(2)) { if (sep->IsNumber(2)) {
guild_id = c->GuildID();
} else if (c->Admin() >= minStatusToEditOtherGuilds) {
guild_id = Strings::ToUnsignedInt(sep->arg[2]); guild_id = Strings::ToUnsignedInt(sep->arg[2]);
} }
@@ -193,11 +172,6 @@ void command_guild(Client *c, const Seperator *sep)
} }
} }
} else if (is_list) { } else if (is_list) {
if (c->Admin() < minStatusToEditOtherGuilds) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
return;
}
guild_mgr.ListGuilds(c, std::string()); guild_mgr.ListGuilds(c, std::string());
} else if (is_rename) { } else if (is_rename) {
if (!sep->IsNumber(2)) { if (!sep->IsNumber(2)) {
@@ -215,16 +189,6 @@ void command_guild(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() < minStatusToEditOtherGuilds) {
if (c->GuildID() != guild_id) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
return;
} else if (!guild_mgr.CheckGMStatus(guild_id, c->Admin())) {
c->Message(Chat::White, "You cannot edit your current guild, your status is not high enough.");
return;
}
}
auto new_guild_name = sep->argplus[3]; auto new_guild_name = sep->argplus[3];
LogGuilds( LogGuilds(
"[{}]: Renaming guild [{}] ([{}]) to [{}] with GM command", "[{}]: Renaming guild [{}] ([{}]) to [{}] with GM command",
@@ -293,11 +257,6 @@ void command_guild(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() < minStatusToEditOtherGuilds && guild_id != c->GuildID()) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
return;
}
if (!guild_id || guild_id == GUILD_NONE) { if (!guild_id || guild_id == GUILD_NONE) {
LogGuilds( LogGuilds(
"[{}]: Removing [{}] ([{}]) from guild with GM command", "[{}]: Removing [{}] ([{}]) from guild with GM command",
@@ -329,6 +288,7 @@ void command_guild(Client *c, const Seperator *sep)
).c_str() ).c_str()
); );
} else { } else {
guild_mgr.SetGuild(character_id, GUILD_NONE, 0);
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -389,16 +349,6 @@ void command_guild(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() < minStatusToEditOtherGuilds) {
if (c->GuildID() != guild_id) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
return;
} else if (!guild_mgr.CheckGMStatus(guild_id, c->Admin())) {
c->Message(Chat::White, "You cannot edit your current guild, your status is not high enough.");
return;
}
}
LogGuilds( LogGuilds(
"[{}]: Setting leader of guild [{}] ([{}]) to [{}] with GM command", "[{}]: Setting leader of guild [{}] ([{}]) to [{}] with GM command",
c->GetName(), c->GetName(),
@@ -460,11 +410,6 @@ void command_guild(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() < minStatusToEditOtherGuilds && character_id != c->CharacterID()) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
return;
}
LogGuilds( LogGuilds(
"[{}]: Setting [{}] ([{}])'s guild rank to [{}] with GM command", "[{}]: Setting [{}] ([{}])'s guild rank to [{}] with GM command",
c->GetName(), c->GetName(),
@@ -497,8 +442,6 @@ void command_guild(Client *c, const Seperator *sep)
); );
if (!client) { if (!client) {
c->Message(Chat::White, "You must target someone or specify a character name."); c->Message(Chat::White, "You must target someone or specify a character name.");
} else if (c->Admin() < minStatusToEditOtherGuilds && client->GuildID() != c->GuildID()) {
c->Message(Chat::White, "You cannot edit other peoples' guilds.");
} else { } else {
if (!client->IsInAGuild()) { if (!client->IsInAGuild()) {
c->Message( c->Message(
+2 -22
View File
@@ -15,11 +15,6 @@ void command_interrogateinv(Client *c, const Seperator *sep)
// same or not. // same or not.
if (strcasecmp(sep->arg[1], "help") == 0) { if (strcasecmp(sep->arg[1], "help") == 0) {
if (c->Admin() < commandInterrogateInv) {
c->Message(Chat::White, "Usage: #interrogateinv");
c->Message(Chat::White, " Displays your inventory's current in-memory nested storage references");
}
else {
c->Message(Chat::White, "Usage: #interrogateinv [log] [silent]"); c->Message(Chat::White, "Usage: #interrogateinv [log] [silent]");
c->Message( c->Message(
Chat::White, Chat::White,
@@ -28,8 +23,6 @@ void command_interrogateinv(Client *c, const Seperator *sep)
c->Message(Chat::White, " [log] - Logs interrogation to file"); c->Message(Chat::White, " [log] - Logs interrogation to file");
c->Message(Chat::White, " [silent] - Omits the in-game message portion of the interrogation"); c->Message(Chat::White, " [silent] - Omits the in-game message portion of the interrogation");
} }
return;
}
Client *target = nullptr; Client *target = nullptr;
std::map<int16, const EQ::ItemInstance *> instmap; std::map<int16, const EQ::ItemInstance *> instmap;
@@ -38,23 +31,11 @@ void command_interrogateinv(Client *c, const Seperator *sep)
bool error = false; bool error = false;
bool allowtrip = false; bool allowtrip = false;
if (c->Admin() < commandInterrogateInv) {
if (c->GetInterrogateInvState()) {
c->Message(Chat::Red, "The last use of #interrogateinv on this inventory instance discovered an error...");
c->Message(Chat::Red, "Logging out, zoning or re-arranging items at this point will result in item loss!");
return;
}
target = c;
allowtrip = true;
}
else {
if (c->GetTarget() == nullptr) { if (c->GetTarget() == nullptr) {
target = c; target = c;
} } else if (c->GetTarget()->IsClient()) {
else if (c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient(); target = c->GetTarget()->CastToClient();
} } else {
else {
c->Message(Chat::Default, "Use of this command is limited to Client entities"); c->Message(Chat::Default, "Use of this command is limited to Client entities");
return; return;
} }
@@ -65,7 +46,6 @@ void command_interrogateinv(Client *c, const Seperator *sep)
if (strcasecmp(sep->arg[2], "silent") == 0) { if (strcasecmp(sep->arg[2], "silent") == 0) {
silent = true; silent = true;
} }
}
bool success = target->InterrogateInventory(c, log, silent, allowtrip, error); bool success = target->InterrogateInventory(c, log, silent, allowtrip, error);
+12 -31
View File
@@ -27,7 +27,6 @@ void command_invsnapshot(Client *c, const Seperator *sep)
"<td><c \"#AAAAAA\">takes snapshot of character inventory</td>" "<td><c \"#AAAAAA\">takes snapshot of character inventory</td>"
"</tr>"; "</tr>";
if (c->Admin() >= commandInvSnapshot) {
window_text.append( window_text.append(
"<tr>" "<tr>"
"<td><c \"#00FF00\">gcount</td>" "<td><c \"#00FF00\">gcount</td>"
@@ -70,7 +69,6 @@ void command_invsnapshot(Client *c, const Seperator *sep)
"<td><c \"#AAAAAA\">restores slots and items in snapshot</td>" "<td><c \"#AAAAAA\">restores slots and items in snapshot</td>"
"</tr>" "</tr>"
); );
}
window_text.append( window_text.append(
"</table>" "</table>"
@@ -81,8 +79,6 @@ void command_invsnapshot(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() >= commandInvSnapshot) { // global arguments
if (strcmp(sep->arg[1], "gcount") == 0) { if (strcmp(sep->arg[1], "gcount") == 0) {
auto is_count = database.CountInvSnapshots(); auto is_count = database.CountInvSnapshots();
c->Message( c->Message(
@@ -99,8 +95,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
if (strcmp(sep->arg[2], "now") == 0) { if (strcmp(sep->arg[2], "now") == 0) {
database.ClearInvSnapshots(true); database.ClearInvSnapshots(true);
c->Message(Chat::White, "Inventory snapshots cleared using current time."); c->Message(Chat::White, "Inventory snapshots cleared using current time.");
} } else {
else {
database.ClearInvSnapshots(); database.ClearInvSnapshots();
c->Message( c->Message(
Chat::White, "Inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).", Chat::White, "Inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).",
@@ -109,7 +104,6 @@ void command_invsnapshot(Client *c, const Seperator *sep)
return; return;
} }
}
if (!c->GetTarget() || !c->GetTarget()->IsClient()) { if (!c->GetTarget() || !c->GetTarget()->IsClient()) {
c->Message(Chat::White, "Target must be a client."); c->Message(Chat::White, "Target must be a client.");
@@ -127,8 +121,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
tc->GetName(), tc->GetName(),
RuleI(Character, InvSnapshotMinIntervalM), RuleI(Character, InvSnapshotMinIntervalM),
(RuleI(Character, InvSnapshotMinIntervalM) == 1 ? "" : "s")); (RuleI(Character, InvSnapshotMinIntervalM) == 1 ? "" : "s"));
} } else {
else {
tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinRetryM)); tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinRetryM));
c->Message( c->Message(
Chat::White, Chat::White,
@@ -141,7 +134,6 @@ void command_invsnapshot(Client *c, const Seperator *sep)
return; return;
} }
if (c->Admin() >= commandInvSnapshot) {
if (strcmp(sep->arg[1], "count") == 0) { if (strcmp(sep->arg[1], "count") == 0) {
auto is_count = database.CountCharacterInvSnapshots(tc->CharacterID()); auto is_count = database.CountCharacterInvSnapshots(tc->CharacterID());
c->Message( c->Message(
@@ -163,8 +155,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
"%s\'s (id: %u) inventory snapshots cleared using current time.", "%s\'s (id: %u) inventory snapshots cleared using current time.",
tc->GetName(), tc->GetName(),
tc->CharacterID()); tc->CharacterID());
} } else {
else {
database.ClearCharacterInvSnapshots(tc->CharacterID()); database.ClearCharacterInvSnapshots(tc->CharacterID());
c->Message( c->Message(
Chat::White, Chat::White,
@@ -267,8 +258,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
if (window_text.length() + window_line.length() < 4095) { if (window_text.length() + window_line.length() < 4095) {
window_text.append(window_line); window_text.append(window_line);
} } else {
else {
c->Message(Chat::White, "Too many snapshot entries to list..."); c->Message(Chat::White, "Too many snapshot entries to list...");
break; break;
} }
@@ -316,16 +306,13 @@ void command_invsnapshot(Client *c, const Seperator *sep)
if (inv_iter == inv_compare_list.end() && iss_iter == iss_compare_list.end()) { if (inv_iter == inv_compare_list.end() && iss_iter == iss_compare_list.end()) {
break; break;
} } else if (inv_iter != inv_compare_list.end() && iss_iter == iss_compare_list.end()) {
else if (inv_iter != inv_compare_list.end() && iss_iter == iss_compare_list.end()) {
window_line = StringFormat("%i: (delete) [empty] -&gt; %u<br>", inv_iter->first, inv_iter->second); window_line = StringFormat("%i: (delete) [empty] -&gt; %u<br>", inv_iter->first, inv_iter->second);
++inv_iter; ++inv_iter;
} } else if (inv_iter == inv_compare_list.end() && iss_iter != iss_compare_list.end()) {
else if (inv_iter == inv_compare_list.end() && iss_iter != iss_compare_list.end()) {
window_line = StringFormat("%i: (insert) %u -&gt; [empty]<br>", iss_iter->first, iss_iter->second); window_line = StringFormat("%i: (insert) %u -&gt; [empty]<br>", iss_iter->first, iss_iter->second);
++iss_iter; ++iss_iter;
} } else {
else {
if (inv_iter->first < iss_iter->first) { if (inv_iter->first < iss_iter->first) {
window_line = StringFormat( window_line = StringFormat(
"%i: (delete) [empty] -&gt; %u<br>", "%i: (delete) [empty] -&gt; %u<br>",
@@ -333,16 +320,14 @@ void command_invsnapshot(Client *c, const Seperator *sep)
inv_iter->second inv_iter->second
); );
++inv_iter; ++inv_iter;
} } else if (inv_iter->first > iss_iter->first) {
else if (inv_iter->first > iss_iter->first) {
window_line = StringFormat( window_line = StringFormat(
"%i: (insert) %u -&gt; [empty]<br>", "%i: (insert) %u -&gt; [empty]<br>",
iss_iter->first, iss_iter->first,
iss_iter->second iss_iter->second
); );
++iss_iter; ++iss_iter;
} } else {
else {
window_line = StringFormat( window_line = StringFormat(
"%i: (replace) %u -&gt; %u<br>", "%i: (replace) %u -&gt; %u<br>",
iss_iter->first, iss_iter->first,
@@ -356,8 +341,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
if (window_text.length() + window_line.length() < 4095) { if (window_text.length() + window_line.length() < 4095) {
window_text.append(window_line); window_text.append(window_line);
} } else {
else {
c->Message(Chat::White, "Too many comparison entries to list..."); c->Message(Chat::White, "Too many comparison entries to list...");
break; break;
} }
@@ -389,8 +373,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
if (database.SaveCharacterInvSnapshot(tc->CharacterID())) { if (database.SaveCharacterInvSnapshot(tc->CharacterID())) {
tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM)); tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM));
} } else {
else {
c->Message( c->Message(
Chat::Red, "Failed to take pre-restore inventory snapshot of %s (id: %u).", Chat::Red, "Failed to take pre-restore inventory snapshot of %s (id: %u).",
tc->GetName(), tc->CharacterID()); tc->GetName(), tc->CharacterID());
@@ -404,8 +387,7 @@ void command_invsnapshot(Client *c, const Seperator *sep)
c->Message( c->Message(
Chat::White, "Successfully applied snapshot %u to %s's (id: %u) inventory.", Chat::White, "Successfully applied snapshot %u to %s's (id: %u) inventory.",
timestamp, tc->GetName(), tc->CharacterID()); timestamp, tc->GetName(), tc->CharacterID());
} } else {
else {
c->Message( c->Message(
Chat::Red, "Failed to apply snapshot %u to %s's (id: %u) inventory.", Chat::Red, "Failed to apply snapshot %u to %s's (id: %u) inventory.",
timestamp, tc->GetName(), tc->CharacterID()); timestamp, tc->GetName(), tc->CharacterID());
@@ -414,5 +396,4 @@ void command_invsnapshot(Client *c, const Seperator *sep)
return; return;
} }
} }
}
+206 -170
View File
@@ -3,237 +3,273 @@
#include "../object.h" #include "../object.h"
#include "../doors.h" #include "../doors.h"
struct UniqueEntity {
uint16 entity_id;
std::string entity_name;
uint32 unique_id;
glm::vec4 position;
};
void command_list(Client *c, const Seperator *sep) void command_list(Client *c, const Seperator *sep)
{ {
const int arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #list [corpses|doors|npcs|objects|players] [search]");
c->Message(Chat::White, "Example: #list npcs (Blank for all)");
return;
}
const bool is_corpses = !strcasecmp(sep->arg[1], "corpses");
const bool is_doors = !strcasecmp(sep->arg[1], "doors");
const bool is_npcs = !strcasecmp(sep->arg[1], "npcs");
const bool is_objects = !strcasecmp(sep->arg[1], "objects");
const bool is_players = !strcasecmp(sep->arg[1], "players");
if (
!is_corpses &&
!is_doors &&
!is_npcs &&
!is_objects &&
!is_players
) {
c->Message(Chat::White, "Usage: #list [npcs|players|corpses|doors|objects] [search]");
c->Message(Chat::White, "Example: #list npcs (Blank for all)");
return;
}
std::string search_type; std::string search_type;
if (strcasecmp(sep->arg[1], "npcs") == 0) { std::string unique_type;
search_type = "npcs";
if (is_corpses) {
search_type = "corpse";
unique_type = "Corpse ID";
} else if (is_doors) {
search_type = "door";
unique_type = "Door ID";
} else if (is_npcs) {
search_type = "NPC";
unique_type = "NPC ID";
} else if (is_objects) {
search_type = "object";
unique_type = "Object ID";
} else if (is_players) {
search_type = "player";
unique_type = "Character ID";
} }
if (strcasecmp(sep->arg[1], "players") == 0) { uint32 entity_count = 0;
search_type = "players"; uint32 found_count = 0;
const std::string &search_string = sep->arg[2] ? Strings::ToLower(sep->arg[2]) : std::string();
std::vector<UniqueEntity> unique_entities;
if (is_corpses) {
const auto &l = entity_list.GetCorpseList();
for (const auto &e : l) {
Corpse *entity = e.second;
entity_count++;
const std::string &entity_name = Strings::ToLower(entity->GetName());
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
continue;
} }
if (strcasecmp(sep->arg[1], "corpses") == 0) { unique_entities.emplace_back(
search_type = "corpses"; UniqueEntity{
.entity_id = entity->GetID(),
.entity_name = entity->GetName(),
.unique_id = entity->GetCorpseDBID(),
.position = entity->GetPosition()
}
);
found_count++;
}
} else if (is_doors) {
const auto &l = entity_list.GetDoorsList();
for (const auto &e : l) {
Doors *entity = e.second;
entity_count++;
const std::string &entity_name = Strings::ToLower(entity->GetDoorName());
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
continue;
} }
if (strcasecmp(sep->arg[1], "doors") == 0) { unique_entities.emplace_back(
search_type = "doors"; UniqueEntity{
.entity_id = entity->GetID(),
.entity_name = entity->GetDoorName(),
.unique_id = entity->GetDoorID(),
.position = entity->GetPosition()
} }
);
if (strcasecmp(sep->arg[1], "objects") == 0) { found_count++;
search_type = "objects";
} }
} else if (is_npcs) {
const auto &l = entity_list.GetMobList();
if (search_type.length() > 0) { for (const auto &e : l) {
Mob *entity = e.second;
int entity_count = 0;
int found_count = 0;
std::string search_string;
if (sep->arg[2]) {
search_string = Strings::ToLower(sep->arg[2]);
}
// NPC
if (search_type.find("npcs") != std::string::npos) {
auto &entity_list_search = entity_list.GetMobList();
for (auto &itr : entity_list_search) {
Mob *entity = itr.second;
if (!entity->IsNPC()) { if (!entity->IsNPC()) {
continue; continue;
} }
entity_count++; entity_count++;
std::string entity_name = Strings::ToLower(entity->GetName()); const std::string &entity_name = Strings::ToLower(entity->GetName());
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) { if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
continue; continue;
} }
std::string saylink = StringFormat( unique_entities.emplace_back(
"#goto %.0f %0.f %.0f", UniqueEntity{
entity->GetX(), .entity_id = entity->GetID(),
entity->GetY(), .entity_name = entity->GetName(),
entity->GetZ() + (entity->IsBoat() ? 50 : 0)); .unique_id = entity->GetNPCTypeID(),
.position = entity->GetPosition()
c->Message( }
0,
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
Saylink::Silent(saylink, "Goto").c_str(),
entity->GetID(),
entity->GetName(),
entity->GetX(),
entity->GetY(),
entity->GetZ()
); );
found_count++; found_count++;
} }
} } else if (is_objects) {
const auto &l = entity_list.GetObjectList();
// Client for (const auto &e : l) {
if (search_type.find("players") != std::string::npos) { Object *entity = e.second;
auto &entity_list_search = entity_list.GetClientList();
for (auto &itr : entity_list_search) {
Client *entity = itr.second;
entity_count++; entity_count++;
std::string entity_name = Strings::ToLower(entity->GetName()); const std::string &entity_name = Strings::ToLower(entity->GetModelName());
if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
/**
* Filter by name
*/
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
continue; continue;
} }
std::string saylink = StringFormat( unique_entities.emplace_back(
"#goto %.0f %0.f %.0f", UniqueEntity{
entity->GetX(), .entity_id = entity->GetID(),
entity->GetY(), .entity_name = entity->GetModelName(),
entity->GetZ()); .unique_id = entity->GetDBID(),
.position = glm::vec4(entity->GetX(), entity->GetY(), entity->GetZ(), 0.0f)
c->Message( }
0,
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
Saylink::Silent(saylink, "Goto").c_str(),
entity->GetID(),
entity->GetName(),
entity->GetX(),
entity->GetY(),
entity->GetZ()
); );
found_count++; found_count++;
} }
} } else if (is_players) {
const auto &l = entity_list.GetClientList();
// Corpse for (const auto &e : l) {
if (search_type.find("corpses") != std::string::npos) { Client *entity = e.second;
auto &entity_list_search = entity_list.GetCorpseList();
for (auto &itr : entity_list_search) {
Corpse *entity = itr.second;
entity_count++; entity_count++;
std::string entity_name = Strings::ToLower(entity->GetName()); const std::string &entity_name = Strings::ToLower(entity->GetName());
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) { if (!search_string.empty() && entity_name.find(search_string) == std::string::npos) {
continue; continue;
} }
std::string saylink = StringFormat( unique_entities.emplace_back(
"#goto %.0f %0.f %.0f", UniqueEntity{
entity->GetX(), .entity_id = entity->GetID(),
entity->GetY(), .entity_name = entity->GetName(),
entity->GetZ()); .unique_id = entity->CharacterID(),
.position = entity->GetPosition()
c->Message( }
0,
"| %s | ID %5d | %s | x %.0f | y %0.f | z %.0f",
Saylink::Silent(saylink, "Goto").c_str(),
entity->GetID(),
entity->GetName(),
entity->GetX(),
entity->GetY(),
entity->GetZ()
); );
found_count++; found_count++;
} }
} }
// Doors if (!found_count) {
if (search_type.find("doors") != std::string::npos) { c->Message(
auto &entity_list_search = entity_list.GetDoorsList(); Chat::White,
fmt::format(
for (auto &itr : entity_list_search) { "Could not find any {}{}.",
Doors *entity = itr.second; search_type,
(
entity_count++; !search_string.empty() ?
fmt::format(
std::string entity_name = Strings::ToLower(entity->GetDoorName()); " matching '{}'",
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) { search_string
continue; ) :
""
)
).c_str()
);
return;
} }
std::string saylink = StringFormat( std::sort(unique_entities.begin(), unique_entities.end(), [](UniqueEntity a, UniqueEntity b) {
"#goto %.0f %0.f %.0f", if (a.entity_id && b.entity_id) {
entity->GetX(), return a.entity_id < b.entity_id;
entity->GetY(), } else {
entity->GetZ()); return a.unique_id < b.unique_id;
}
});
c->Message( for (const auto& e : unique_entities) {
0, const std::string &saylink = Saylink::Silent(
"| %s | Entity ID %5d | Door ID %i | %s | x %.0f | y %0.f | z %.0f", fmt::format(
Saylink::Silent(saylink, "Goto").c_str(), "#goto {:.2f} {:.2f} {:.2f}",
entity->GetID(), e.position.x,
entity->GetDoorID(), e.position.y,
entity->GetDoorName(), e.position.z
entity->GetX(), ),
entity->GetY(), "Goto"
entity->GetZ()
); );
found_count++;
}
}
// Objects
if (search_type.find("objects") != std::string::npos) {
auto &entity_list_search = entity_list.GetObjectList();
for (auto &itr : entity_list_search) {
Object *entity = itr.second;
entity_count++;
std::string entity_name = Strings::ToLower(entity->GetModelName());
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
continue;
}
std::string saylink = StringFormat(
"#goto %.0f %0.f %.0f",
entity->GetX(),
entity->GetY(),
entity->GetZ());
c->Message( c->Message(
0, Chat::White,
"| %s | Entity ID %5d | Object DBID %i | %s | x %.0f | y %0.f | z %.0f", fmt::format(
Saylink::Silent(saylink, "Goto").c_str(), "| {}{}{} | {} |",
entity->GetID(), saylink,
entity->GetDBID(), (
entity->GetModelName(), e.entity_id ?
entity->GetX(), fmt::format(
entity->GetY(), " | ID {}",
entity->GetZ() e.entity_id
) :
""
),
(
e.unique_id ?
fmt::format(
" | {} {}",
unique_type,
e.unique_id
) :
""
),
e.entity_name
).c_str()
); );
found_count++;
}
} }
if (found_count) {
c->Message( c->Message(
0, "Found (%i) of type (%s) in zone (%i) total", Chat::White,
fmt::format(
"Found {} {}{}{}, {} total.",
found_count, found_count,
search_type.c_str(), search_type,
found_count != 1 ? "s" : "",
(
!search_string.empty() ?
fmt::format(
" matching '{}'",
search_string
) :
""
),
entity_count entity_count
).c_str()
); );
} }
}
else {
c->Message(Chat::White, "Usage of #list");
c->Message(Chat::White, "- #list [npcs|players|corpses|doors|objects] [search]");
c->Message(Chat::White, "- Example: #list npcs (Blank for all)");
}
}
+9 -38
View File
@@ -2,18 +2,18 @@
void command_movechar(Client *c, const Seperator *sep) void command_movechar(Client *c, const Seperator *sep)
{ {
int arguments = sep->argnum; const int arguments = sep->argnum;
if (arguments < 2) { if (arguments < 2) {
c->Message(Chat::White, "Usage: #movechar [Character ID|Character Name] [Zone ID|Zone Short Name]"); c->Message(Chat::White, "Usage: #movechar [Character ID|Character Name] [Zone ID|Zone Short Name]");
return; return;
} }
std::string character_name = ( const std::string &character_name = (
sep->IsNumber(1) ? sep->IsNumber(1) ?
database.GetCharNameByID(Strings::ToUnsignedInt(sep->arg[1])) : database.GetCharNameByID(Strings::ToUnsignedInt(sep->arg[1])) :
sep->arg[1] sep->arg[1]
); );
auto character_id = database.GetCharacterID(character_name.c_str()); const uint32 character_id = database.GetCharacterID(character_name.c_str());
if (!character_id) { if (!character_id) {
c->Message( c->Message(
Chat::White, Chat::White,
@@ -25,15 +25,15 @@ void command_movechar(Client *c, const Seperator *sep)
return; return;
} }
auto account_id = database.GetAccountIDByChar(character_name.c_str()); const uint32 account_id = database.GetAccountIDByChar(character_name.c_str());
std::string zone_short_name = Strings::ToLower( const std::string &zone_short_name = Strings::ToLower(
sep->IsNumber(2) ? sep->IsNumber(2) ?
ZoneName(Strings::ToUnsignedInt(sep->arg[2]), true) : ZoneName(Strings::ToUnsignedInt(sep->arg[2]), true) :
sep->arg[2] sep->arg[2]
); );
bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos; const bool is_unknown_zone = zone_short_name.find("unknown") != std::string::npos;
if (is_unknown_zone) { if (is_unknown_zone) {
c->Message( c->Message(
Chat::White, Chat::White,
@@ -45,7 +45,7 @@ void command_movechar(Client *c, const Seperator *sep)
return; return;
} }
auto zone_id = ZoneID(zone_short_name); const uint32 zone_id = ZoneID(zone_short_name);
auto z = GetZone(zone_id); auto z = GetZone(zone_id);
if (!z) { if (!z) {
@@ -53,34 +53,8 @@ void command_movechar(Client *c, const Seperator *sep)
return; return;
} }
bool is_special_zone = ( const bool moved = database.MoveCharacterToZone(character_name.c_str(), zone_id);
zone_short_name.find("cshome") != std::string::npos || std::string moved_string = moved ? "Succeeded" : "Failed";
zone_short_name.find("load") != std::string::npos ||
zone_short_name.find("load2") != std::string::npos
);
if (c->Admin() < commandMovecharToSpecials && is_special_zone) {
c->Message(
Chat::White,
fmt::format(
"{} ({}) is a special zone and you cannot move someone there.",
z->long_name,
zone_short_name
).c_str()
);
return;
}
if (
c->Admin() >= commandMovecharSelfOnly ||
account_id == c->AccountID()
) {
bool moved = database.MoveCharacterToZone(character_name.c_str(), zone_id);
std::string moved_string = (
moved ?
"Succeeded" :
"Failed"
);
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -101,7 +75,4 @@ void command_movechar(Client *c, const Seperator *sep)
zone_id zone_id
).c_str() ).c_str()
); );
} else {
c->Message(Chat::White, "You cannot move characters that are not on your account.");
}
} }
+61 -51
View File
@@ -3,74 +3,84 @@
void command_movement(Client *c, const Seperator *sep) void command_movement(Client *c, const Seperator *sep)
{ {
auto &mgr = MobMovementManager::Get(); const int arguments = sep->argnum;
if (!arguments) {
if (sep->arg[1][0] == 0) { c->Message(Chat::White, "Usage: #movement [clear|packet|rotate|run|stats|stop|walk]");
c->Message(Chat::White, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop/packet");
return; return;
} }
if (strcasecmp(sep->arg[1], "stats") == 0) { const bool is_clear = !strcasecmp(sep->arg[1], "clear");
mgr.DumpStats(c); const bool is_packet = !strcasecmp(sep->arg[1], "packet");
} const bool is_rotate = !strcasecmp(sep->arg[1], "rotate");
else if (strcasecmp(sep->arg[1], "clearstats") == 0) { const bool is_run = !strcasecmp(sep->arg[1], "run");
mgr.ClearStats(); const bool is_stats = !strcasecmp(sep->arg[1], "stats");
} const bool is_stop = !strcasecmp(sep->arg[1], "stop");
else if (strcasecmp(sep->arg[1], "walkto") == 0) { const bool is_walk = !strcasecmp(sep->arg[1], "walk");
auto target = c->GetTarget();
if (target == nullptr) { if (
c->Message(Chat::White, "No target found."); !is_clear &&
!is_packet &&
!is_rotate &&
!is_run &&
!is_stats &&
!is_stop &&
!is_walk
) {
c->Message(Chat::White, "Usage: #movement [clear|packet|rotate|run|stats|stop|walk]");
return; return;
} }
target->WalkTo(c->GetX(), c->GetY(), c->GetZ()); auto &m = MobMovementManager::Get();
}
else if (strcasecmp(sep->arg[1], "runto") == 0) { if (is_clear) {
auto target = c->GetTarget(); m.ClearStats();
if (target == nullptr) { } else if (is_packet) {
c->Message(Chat::White, "No target found."); Mob *t = c->GetTarget();
if (!t) {
c->Message(Chat::White, "You must have a target to use this command.");
return; return;
} }
target->RunTo(c->GetX(), c->GetY(), c->GetZ()); const float x = sep->IsNumber(2) ? Strings::ToFloat(sep->arg[2]) : 0.0f;
} const float y = sep->IsNumber(3) ? Strings::ToFloat(sep->arg[3]) : 0.0f;
else if (strcasecmp(sep->arg[1], "rotateto") == 0) { const float z = sep->IsNumber(4) ? Strings::ToFloat(sep->arg[4]) : 0.0f;
auto target = c->GetTarget(); const float heading = sep->IsNumber(5) ? Strings::ToFloat(sep->arg[5]) : 0.0f;
if (target == nullptr) { const int animation = sep->IsNumber(6) ? Strings::ToInt(sep->arg[6]) : 0.0f;
c->Message(Chat::White, "No target found.");
m.SendCommandToClients(t, x, y, z, heading, animation, ClientRangeAny);
} else if (is_rotate) {
Mob *t = c->GetTarget();
if (!t) {
c->Message(Chat::White, "You must have a target to use this command.");
return; return;
} }
target->RotateToWalking(target->CalculateHeadingToTarget(c->GetX(), c->GetY())); t->RotateToWalking(t->CalculateHeadingToTarget(c->GetX(), c->GetY()));
} } else if (is_run) {
else if (strcasecmp(sep->arg[1], "stop") == 0) { Mob *t = c->GetTarget();
auto target = c->GetTarget(); if (!t) {
if (target == nullptr) { c->Message(Chat::White, "You must have a target to use this command.");
c->Message(Chat::White, "No target found.");
return; return;
} }
target->StopNavigation(); t->RunTo(c->GetX(), c->GetY(), c->GetZ());
} } else if (is_stats) {
else if (strcasecmp(sep->arg[1], "packet") == 0) { m.DumpStats(c);
auto target = c->GetTarget(); } else if (is_stop) {
if (target == nullptr) { Mob *t = c->GetTarget();
c->Message(Chat::White, "No target found."); if (!t) {
c->Message(Chat::White, "You must have a target to use this command.");
return; return;
} }
mgr.SendCommandToClients( t->StopNavigation();
target, } else if (is_walk) {
Strings::ToFloat(sep->arg[2]), Mob *t = c->GetTarget();
Strings::ToFloat(sep->arg[3]), if (!t) {
Strings::ToFloat(sep->arg[4]), c->Message(Chat::White, "You must have a target to use this command.");
Strings::ToFloat(sep->arg[5]), return;
Strings::ToInt(sep->arg[6]),
ClientRangeAny
);
}
else {
c->Message(Chat::White, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop/packet");
}
} }
t->WalkTo(c->GetX(), c->GetY(), c->GetZ());
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
#ifndef EQEMU_OBJECT_MANIPULATION_H
#define EQEMU_OBJECT_MANIPULATION_H
#include "../client.h"
class ObjectManipulation {
public:
static void CommandHandler(Client *c, const Seperator *sep);
static void CommandHeader(Client *c);
static void SendSubcommands(Client *c);
};
#endif //EQEMU_OBJECT_MANIPULATION_H
+3 -3
View File
@@ -5,10 +5,10 @@ void command_petname(Client *c, const Seperator *sep)
Mob *target; Mob *target;
target = c->GetTarget(); target = c->GetTarget();
if (!target) { if (!target || !target->IsPet()) {
c->Message(Chat::White, "Usage: #petname newname (requires a target)"); c->Message(Chat::White, "Usage: #petname newname (requires a pet target)");
} }
else if (target->IsPet() && (target->GetOwnerID() == c->GetID()) && strlen(sep->arg[1]) > 0) { else if (target->GetOwnerID() == c->GetID() && strlen(sep->arg[1]) > 0) {
char *oldname = strdup(target->GetName()); char *oldname = strdup(target->GetName());
target->TempName(sep->arg[1]); target->TempName(sep->arg[1]);
c->Message(Chat::White, "Renamed %s to %s", oldname, sep->arg[1]); c->Message(Chat::White, "Renamed %s to %s", oldname, sep->arg[1]);
+4 -4
View File
@@ -14,14 +14,14 @@ void SetDate(Client *c, const Seperator *sep)
return; return;
} }
TimeOfDay_Struct eq_time; TimeOfDay_Struct t{};
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time); zone->zone_time.GetCurrentEQTimeOfDay(time(0), &t);
const uint16 year = Strings::ToUnsignedInt(sep->arg[2]); const uint16 year = Strings::ToUnsignedInt(sep->arg[2]);
const uint8 month = Strings::ToUnsignedInt(sep->arg[3]); const uint8 month = Strings::ToUnsignedInt(sep->arg[3]);
const uint8 day = Strings::ToUnsignedInt(sep->arg[4]); const uint8 day = Strings::ToUnsignedInt(sep->arg[4]);
const uint8 hour = !sep->IsNumber(5) ? eq_time.hour : Strings::ToUnsignedInt(sep->arg[5]) + 1; const uint8 hour = !sep->IsNumber(5) ? t.hour : Strings::ToUnsignedInt(sep->arg[5]) + 1;
const uint8 minute = !sep->IsNumber(6) ? eq_time.minute : Strings::ToUnsignedInt(sep->arg[6]); const uint8 minute = !sep->IsNumber(6) ? t.minute : Strings::ToUnsignedInt(sep->arg[6]);
c->Message( c->Message(
Chat::White, Chat::White,
+1 -1
View File
@@ -6,7 +6,7 @@ void SetTime(Client *c, const Seperator *sep)
if (arguments < 2 || !sep->IsNumber(2)) { if (arguments < 2 || !sep->IsNumber(2)) {
c->Message(Chat::White, "Usage: #set time [Hour] [Minute]"); c->Message(Chat::White, "Usage: #set time [Hour] [Minute]");
TimeOfDay_Struct world_time; TimeOfDay_Struct world_time{};
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time); zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time);
auto time_string = fmt::format( auto time_string = fmt::format(
+4
View File
@@ -1,4 +1,6 @@
#include "../client.h" #include "../client.h"
#include "show/aas.cpp"
#include "show/aa_points.cpp"
#include "show/aggro.cpp" #include "show/aggro.cpp"
#include "show/buffs.cpp" #include "show/buffs.cpp"
#include "show/buried_corpse_count.cpp" #include "show/buried_corpse_count.cpp"
@@ -55,6 +57,8 @@ void command_show(Client *c, const Seperator *sep)
}; };
std::vector<Cmd> commands = { std::vector<Cmd> commands = {
Cmd{.cmd = "aas", .u = "aas", .fn = ShowAAs, .a = {"#showaas"}},
Cmd{.cmd = "aa_points", .u = "aa_points", .fn = ShowAAPoints, .a = {"#showaapoints", "#showaapts"}},
Cmd{.cmd = "aggro", .u = "aggro [Distance] [-v] (-v is verbose Faction Information)", .fn = ShowAggro, .a = {"#aggro"}}, Cmd{.cmd = "aggro", .u = "aggro [Distance] [-v] (-v is verbose Faction Information)", .fn = ShowAggro, .a = {"#aggro"}},
Cmd{.cmd = "buffs", .u = "buffs", .fn = ShowBuffs, .a = {"#showbuffs"}}, Cmd{.cmd = "buffs", .u = "buffs", .fn = ShowBuffs, .a = {"#showbuffs"}},
Cmd{.cmd = "buried_corpse_count", .u = "buried_corpse_count", .fn = ShowBuriedCorpseCount, .a = {"#getplayerburiedcorpsecount"}}, Cmd{.cmd = "buried_corpse_count", .u = "buried_corpse_count", .fn = ShowBuriedCorpseCount, .a = {"#getplayerburiedcorpsecount"}},
+37
View File
@@ -0,0 +1,37 @@
#include "../../client.h"
#include "../../dialogue_window.h"
void ShowAAPoints(Client *c, const Seperator *sep)
{
Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const int aa_points = t->GetAAPoints();
const int spent_aa_points = t->GetSpentAA();
const int total_aa_points = (aa_points + spent_aa_points);
if (!total_aa_points) {
c->Message(
Chat::White,
fmt::format(
"{} {} no AA Points.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has"
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"AA Points for {} | Current: {} Spent: {} Total: {}",
c->GetTargetDescription(t, TargetDescriptionType::UCSelf),
Strings::Commify(aa_points),
Strings::Commify(spent_aa_points),
Strings::Commify(total_aa_points)
).c_str()
);
}
+13
View File
@@ -0,0 +1,13 @@
#include "../../client.h"
void ShowAAs(Client *c, const Seperator *sep)
{
Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
const std::string& search_criteria = sep->argnum >= 2 ? sep->argplus[2] : std::string();
t->ListPurchasedAAs(c, search_criteria);
}
+20 -20
View File
@@ -3,34 +3,34 @@
void ShowCurrencies(Client *c, const Seperator *sep) void ShowCurrencies(Client *c, const Seperator *sep)
{ {
auto t = c; Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) { if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
const uint32 platinum = ( const uint64 platinum = (
t->GetMoney(3, 0) + t->GetMoney(MoneyTypes::Platinum, MoneySubtypes::Personal) +
t->GetMoney(3, 1) + t->GetMoney(MoneyTypes::Platinum, MoneySubtypes::Bank) +
t->GetMoney(3, 2) + t->GetMoney(MoneyTypes::Platinum, MoneySubtypes::Cursor) +
t->GetMoney(3, 3) t->GetMoney(MoneyTypes::Platinum, MoneySubtypes::SharedBank)
); );
const uint32 gold = ( const uint64 gold = (
t->GetMoney(2, 0) + t->GetMoney(MoneyTypes::Gold, MoneySubtypes::Personal) +
t->GetMoney(2, 1) + t->GetMoney(MoneyTypes::Gold, MoneySubtypes::Bank) +
t->GetMoney(2, 2) t->GetMoney(MoneyTypes::Gold, MoneySubtypes::Cursor)
); );
const uint32 silver = ( const uint64 silver = (
t->GetMoney(1, 0) + t->GetMoney(MoneyTypes::Silver, MoneySubtypes::Personal) +
t->GetMoney(1, 1) + t->GetMoney(MoneyTypes::Silver, MoneySubtypes::Bank) +
t->GetMoney(1, 2) t->GetMoney(MoneyTypes::Silver, MoneySubtypes::Cursor)
); );
const uint32 copper = ( const uint64 copper = (
t->GetMoney(0, 0) + t->GetMoney(MoneyTypes::Copper, MoneySubtypes::Personal) +
t->GetMoney(0, 1) + t->GetMoney(MoneyTypes::Copper, MoneySubtypes::Bank) +
t->GetMoney(0, 2) t->GetMoney(MoneyTypes::Copper, MoneySubtypes::Cursor)
); );
std::string currency_table; std::string currency_table;
@@ -79,9 +79,9 @@ void ShowCurrencies(Client *c, const Seperator *sep)
for (const auto& a : zone->AlternateCurrencies) { for (const auto& a : zone->AlternateCurrencies) {
const uint32 currency_value = t->GetAlternateCurrencyValue(a.id); const uint32 currency_value = t->GetAlternateCurrencyValue(a.id);
if (currency_value) { if (currency_value) {
const auto* d = database.GetItem(a.item_id); const auto *item = database.GetItem(a.item_id);
currency_table += DialogueWindow::TableRow( currency_table += DialogueWindow::TableRow(
DialogueWindow::TableCell(d->Name) + DialogueWindow::TableCell(item->Name) +
DialogueWindow::TableCell(Strings::Commify(currency_value)) DialogueWindow::TableCell(Strings::Commify(currency_value))
); );
+2 -7
View File
@@ -2,13 +2,8 @@
void ShowFlags(Client *c, const Seperator *sep) void ShowFlags(Client *c, const Seperator *sep)
{ {
auto t = c; Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
if (
c->GetTarget() &&
c->GetTarget()->IsClient() &&
c->Admin() >= minStatusToSeeOthersZoneFlags
) {
t = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
+2 -6
View File
@@ -2,12 +2,8 @@
void ShowPEQZoneFlags(Client *c, const Seperator *sep) void ShowPEQZoneFlags(Client *c, const Seperator *sep)
{ {
auto t = c; Client *t = c;
if ( if (c->GetTarget() && c->GetTarget()->IsClient()) {
c->GetTarget() &&
c->GetTarget()->IsClient() &&
c->Admin() >= minStatusToSeeOthersZoneFlags
) {
t = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
+63 -20
View File
@@ -10,10 +10,11 @@ void command_summonitem(Client *c, const Seperator *sep)
uint32 augment_four = 0; uint32 augment_four = 0;
uint32 augment_five = 0; uint32 augment_five = 0;
uint32 augment_six = 0; uint32 augment_six = 0;
int arguments = sep->argnum; const uint16 arguments = sep->argnum;
std::string cmd_msg = sep->msg; std::string cmd_msg = sep->msg;
size_t link_open = cmd_msg.find('\x12'); size_t link_open = cmd_msg.find('\x12');
size_t link_close = cmd_msg.find_last_of('\x12'); size_t link_close = cmd_msg.find_last_of('\x12');
if (link_open != link_close && (cmd_msg.length() - link_open) > EQ::constants::SAY_LINK_BODY_SIZE) { if (link_open != link_close && (cmd_msg.length() - link_open) > EQ::constants::SAY_LINK_BODY_SIZE) {
EQ::SayLinkBody_Struct link_body; EQ::SayLinkBody_Struct link_body;
EQ::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQ::constants::SAY_LINK_BODY_SIZE)); EQ::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQ::constants::SAY_LINK_BODY_SIZE));
@@ -24,16 +25,14 @@ void command_summonitem(Client *c, const Seperator *sep)
augment_four = link_body.augment_4; augment_four = link_body.augment_4;
augment_five = link_body.augment_5; augment_five = link_body.augment_5;
augment_six = link_body.augment_6; augment_six = link_body.augment_6;
} } else if (!sep->IsNumber(1)) {
else if (!sep->IsNumber(1)) {
c->Message( c->Message(
Chat::White, Chat::White,
"Usage: #summonitem [item id | link] [charges] [augment_one_id] [augment_two_id] [augment_three_id] [augment_four_id] [augment_five_id] [augment_six_id] (Charges are optional.)" "Usage: #summonitem [item id | link] [charges] [augment_one_id] [augment_two_id] [augment_three_id] [augment_four_id] [augment_five_id] [augment_six_id] (Charges and augments are optional.)"
); );
return; return;
} } else {
else { item_id = Strings::ToUnsignedInt(sep->arg[1]);
item_id = Strings::ToInt(sep->arg[1]);
} }
if (!item_id) { if (!item_id) {
@@ -42,12 +41,22 @@ void command_summonitem(Client *c, const Seperator *sep)
} }
uint8 item_status = 0; uint8 item_status = 0;
uint8 current_status = c->Admin(); const uint8 current_status = c->Admin();
const EQ::ItemData *item = database.GetItem(item_id);
if (item) { const auto *item = database.GetItem(item_id);
item_status = item->MinStatus; if (!item) {
c->Message(
Chat::White,
fmt::format(
"Item ID {} does not exist.",
item_id
).c_str()
);
return;
} }
item_status = item->MinStatus;
if (item_status > current_status) { if (item_status > current_status) {
c->Message( c->Message(
Chat::White, Chat::White,
@@ -57,36 +66,70 @@ void command_summonitem(Client *c, const Seperator *sep)
item_status item_status
).c_str() ).c_str()
); );
return;
} }
if (arguments >= 2 && sep->IsNumber(2)) { if (arguments >= 2 && sep->IsNumber(2)) {
charges = Strings::ToInt(sep->arg[2]); charges = static_cast<int16>(Strings::ToInt(sep->arg[2]));
} }
if (arguments >= 3 && sep->IsNumber(3)) { if (arguments >= 3 && sep->IsNumber(3)) {
augment_one = Strings::ToInt(sep->arg[3]); augment_one = Strings::ToUnsignedInt(sep->arg[3]);
} }
if (arguments >= 4 && sep->IsNumber(4)) { if (arguments >= 4 && sep->IsNumber(4)) {
augment_two = Strings::ToInt(sep->arg[4]); augment_two = Strings::ToUnsignedInt(sep->arg[4]);
} }
if (arguments >= 5 && sep->IsNumber(5)) { if (arguments >= 5 && sep->IsNumber(5)) {
augment_three = Strings::ToInt(sep->arg[5]); augment_three = Strings::ToUnsignedInt(sep->arg[5]);
} }
if (arguments >= 6 && sep->IsNumber(6)) { if (arguments >= 6 && sep->IsNumber(6)) {
augment_four = Strings::ToInt(sep->arg[6]); augment_four = Strings::ToUnsignedInt(sep->arg[6]);
} }
if (arguments >= 7 && sep->IsNumber(7)) { if (arguments >= 7 && sep->IsNumber(7)) {
augment_five = Strings::ToInt(sep->arg[7]); augment_five = Strings::ToUnsignedInt(sep->arg[7]);
} }
if (arguments == 8 && sep->IsNumber(8)) { if (arguments == 8 && sep->IsNumber(8)) {
augment_six = Strings::ToInt(sep->arg[8]); augment_six = Strings::ToUnsignedInt(sep->arg[8]);
} }
c->SummonItem(item_id, charges, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six); c->SummonItem(
} item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
const auto *new_item = database.CreateItem(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
EQ::SayLinkEngine linker;
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
linker.SetItemInst(new_item);
const std::string &item_link = linker.GenerateLink();
c->Message(
Chat::White,
fmt::format(
"You have summoned {}.",
item_link
).c_str()
);
}
+57
View File
@@ -0,0 +1,57 @@
#include "../client.h"
void command_takeplatinum(Client *c, const Seperator *sep)
{
int arguments = sep->argnum;
if (!arguments || !sep->IsNumber(1)) { //must be a number
c->Message(Chat::Red, "Usage: #takeplatinum [Platinum]");
return;
}
Client *target = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient();
}
uint32 platinum = Strings::ToUnsignedInt(sep->arg[1]);
if (!platinum) {
c->Message(Chat::Red, "Usage: #takeplatinum [Platinum]");
return;
}
bool success = target->TakePlatinum(
platinum,
true
);
if (success) {
c->Message(
Chat::White,
fmt::format(
"Subtracted {} from {}.",
Strings::Money(
platinum,
0,
0,
0
),
c->GetTargetDescription(target)
).c_str()
);
}
else {
c->Message(
Chat::Red,
fmt::format(
"Unable to subtract {} from {}.",
Strings::Money(
platinum,
0,
0,
0
),
c->GetTargetDescription(target)
).c_str()
);
}
}
+110 -60
View File
@@ -8,7 +8,7 @@ extern WorldServer worldserver;
void command_task(Client *c, const Seperator *sep) void command_task(Client *c, const Seperator *sep)
{ {
int arguments = sep->argnum; const int arguments = sep->argnum;
if (!arguments) { if (!arguments) {
c->Message(Chat::White, "Syntax: #task [subcommand]"); c->Message(Chat::White, "Syntax: #task [subcommand]");
c->Message(Chat::White, "------------------------------------------------"); c->Message(Chat::White, "------------------------------------------------");
@@ -23,6 +23,7 @@ void command_task(Client *c, const Seperator *sep)
); );
c->Message(Chat::White, "--- update <task_id> <activity_id> [count] | Updates task"); c->Message(Chat::White, "--- update <task_id> <activity_id> [count] | Updates task");
c->Message(Chat::White, "--- assign <task_id> | Assigns task to client"); c->Message(Chat::White, "--- assign <task_id> | Assigns task to client");
c->Message(Chat::White, "--- complete <task_id> | Completes a task if a client has it assigned to them");
c->Message(Chat::White, "--- uncomplete <task_id> | Uncompletes a task if a client has completed it"); c->Message(Chat::White, "--- uncomplete <task_id> | Uncompletes a task if a client has completed it");
c->Message( c->Message(
Chat::White, Chat::White,
@@ -73,22 +74,24 @@ void command_task(Client *c, const Seperator *sep)
return; return;
} }
Client *target = c; Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) { if (c->GetTarget() && c->GetTarget()->IsClient()) {
target = c->GetTarget()->CastToClient(); t = c->GetTarget()->CastToClient();
} }
bool is_assign = !strcasecmp(sep->arg[1], "assign"); const bool is_assign = !strcasecmp(sep->arg[1], "assign");
bool is_purgetimers = !strcasecmp(sep->arg[1], "purgetimers"); const bool is_complete = !strcasecmp(sep->arg[1], "complete");
bool is_reload = !strcasecmp(sep->arg[1], "reload"); const bool is_purgetimers = !strcasecmp(sep->arg[1], "purgetimers");
bool is_reloadall = !strcasecmp(sep->arg[1], "reloadall"); const bool is_reload = !strcasecmp(sep->arg[1], "reload");
bool is_sharedpurge = !strcasecmp(sep->arg[1], "sharedpurge"); const bool is_reloadall = !strcasecmp(sep->arg[1], "reloadall");
bool is_show = !strcasecmp(sep->arg[1], "show"); const bool is_sharedpurge = !strcasecmp(sep->arg[1], "sharedpurge");
bool is_uncomplete = !strcasecmp(sep->arg[1], "uncomplete"); const bool is_show = !strcasecmp(sep->arg[1], "show");
bool is_update = !strcasecmp(sep->arg[1], "update"); const bool is_uncomplete = !strcasecmp(sep->arg[1], "uncomplete");
const bool is_update = !strcasecmp(sep->arg[1], "update");
if ( if (
!is_assign && !is_assign &&
!is_complete &&
!is_purgetimers && !is_purgetimers &&
!is_reload && !is_reload &&
!is_reloadall && !is_reloadall &&
@@ -161,70 +164,117 @@ void command_task(Client *c, const Seperator *sep)
} }
if (is_assign) { if (is_assign) {
auto task_id = std::strtoul(sep->arg[2], nullptr, 10); const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
if (task_id) { if (task_id) {
target->AssignTask(task_id, 0, false); t->AssignTask(task_id, 0, false);
c->Message( c->Message(
Chat::Yellow, Chat::White,
fmt::format( fmt::format(
"Assigned task ID {} to {}.", "Assigned {} (ID {}) to {}.",
task_manager->GetTaskName(task_id),
task_id, task_id,
c->GetTargetDescription(target) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
} }
} else if (is_complete) {
if (sep->IsNumber(2)) {
const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
if (!task_id) {
c->Message(Chat::White, "Invalid task ID specified.");
return; return;
}
if (t->IsTaskActive(task_id)) {
const bool did_complete = t->CompleteTask(task_id);
if (did_complete) {
c->Message(
Chat::White,
fmt::format(
"Successfully completed {} (ID {}) for {}.",
task_manager->GetTaskName(task_id),
task_id,
c->GetTargetDescription(t)
).c_str()
);
} else {
c->Message(
Chat::White,
fmt::format(
"Failed to complete {} (ID {}) for {}.",
task_manager->GetTaskName(task_id),
task_id,
c->GetTargetDescription(t)
).c_str()
);
}
} else {
c->Message(
Chat::White,
fmt::format(
"{} {} not have not {} (ID {}) assigned to them.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "do" : "does",
task_manager->GetTaskName(task_id),
task_id
).c_str()
);
}
}
} else if (is_purgetimers) { } else if (is_purgetimers) {
c->Message( c->Message(
Chat::Yellow, Chat::White,
fmt::format( fmt::format(
"Task timers have been purged for {}.", "Task timers have been purged for {}.",
c->GetTargetDescription(target) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
if (c != target) { if (c != t) {
target->Message(Chat::Yellow, "Your task timers have been purged by a GM."); t->Message(Chat::White, "Your task timers have been purged by a GM.");
} }
target->PurgeTaskTimers(); t->PurgeTaskTimers();
return;
} else if (is_reload) { } else if (is_reload) {
if (arguments >= 2) { if (arguments >= 2) {
if (!strcasecmp(sep->arg[2], "sets")) { const bool is_sets = !strcasecmp(sep->arg[2], "sets");
c->Message(Chat::Yellow, "Attempting to reload task sets."); const bool is_task = !strcasecmp(sep->arg[2], "task");
if (is_sets) {
c->Message(Chat::White, "Attempting to reload task sets.");
worldserver.SendReloadTasks(RELOADTASKSETS); worldserver.SendReloadTasks(RELOADTASKSETS);
c->Message(Chat::Yellow, "Successfully reloaded task sets."); c->Message(Chat::White, "Successfully reloaded task sets.");
return; } else if (is_task && arguments == 3 && sep->IsNumber(3)) {
} else if (!strcasecmp(sep->arg[2], "task") && arguments == 3) { const uint32 task_id = Strings::ToUnsignedInt(sep->arg[3]);
int task_id = std::strtoul(sep->arg[3], nullptr, 10);
if (task_id) { if (task_id) {
c->Message( c->Message(
Chat::Yellow, Chat::White,
fmt::format( fmt::format(
"Attempted to reload task ID {}.", "Attempting to reload {} (ID {}).",
task_manager->GetTaskName(task_id),
task_id task_id
).c_str() ).c_str()
); );
worldserver.SendReloadTasks(RELOADTASKS, task_id); worldserver.SendReloadTasks(RELOADTASKS, task_id);
c->Message( c->Message(
Chat::Yellow, Chat::White,
fmt::format( fmt::format(
"Successfully reloaded task ID {}.", "Successfully reloaded {} (ID {}).",
task_manager->GetTaskName(task_id),
task_id task_id
).c_str() ).c_str()
); );
return;
} }
} }
} }
} else if (is_reloadall) { } else if (is_reloadall) {
c->Message(Chat::Yellow, "Attempting to reload tasks."); c->Message(Chat::White, "Attempting to reload tasks.");
worldserver.SendReloadTasks(RELOADTASKS); worldserver.SendReloadTasks(RELOADTASKS);
c->Message(Chat::Yellow, "Successfully reloaded tasks."); c->Message(Chat::White, "Successfully reloaded tasks.");
return;
} else if (is_sharedpurge) { } else if (is_sharedpurge) {
if (!strcasecmp(sep->arg[2], "confirm")) { const bool is_confirm = !strcasecmp(sep->arg[2], "confirm");
if (is_confirm) {
LogTasksDetail("Sending purge request"); LogTasksDetail("Sending purge request");
auto pack = new ServerPacket(ServerOP_SharedTaskPurgeAllCommand, 0); auto pack = new ServerPacket(ServerOP_SharedTaskPurgeAllCommand, 0);
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
@@ -239,14 +289,11 @@ void command_task(Client *c, const Seperator *sep)
Saylink::Silent("#task sharedpurge confirm", "confirm") Saylink::Silent("#task sharedpurge confirm", "confirm")
).c_str() ).c_str()
); );
return;
} else if (is_show) { } else if (is_show) {
target->ShowClientTasks(c); t->ShowClientTasks(c);
return;
} else if (is_uncomplete) { } else if (is_uncomplete) {
if (sep->IsNumber(2)) { if (sep->IsNumber(2)) {
auto task_id = Strings::ToUnsignedInt(sep->arg[2]); const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
if (!task_id) { if (!task_id) {
c->Message(Chat::White, "Invalid task ID specified."); c->Message(Chat::White, "Invalid task ID specified.");
return; return;
@@ -257,57 +304,60 @@ void command_task(Client *c, const Seperator *sep)
database, database,
fmt::format( fmt::format(
"charid = {} AND taskid = {}", "charid = {} AND taskid = {}",
target->CharacterID(), t->CharacterID(),
task_id task_id
) )
) )
) { ) {
c->Message( c->Message(
Chat::Yellow, Chat::White,
fmt::format( fmt::format(
"Successfully uncompleted task ID {} for {}.", "Successfully uncompleted {} (ID {}) for {}.",
task_manager->GetTaskName(task_id),
task_id, task_id,
c->GetTargetDescription(target) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
} else { } else {
c->Message( c->Message(
Chat::Yellow, Chat::White,
fmt::format( fmt::format(
"{} {} not completed task ID {}.", "{} {} not completed {} (ID {}).",
c->GetTargetDescription(target, TargetDescriptionType::UCYou), c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == target ? "have" : "has", c == t ? "have" : "has",
task_manager->GetTaskName(task_id),
task_id task_id
).c_str() ).c_str()
); );
} }
} }
} else if (is_update) { } else if (is_update) {
if (arguments >= 3) { if (arguments >= 3 && sep->IsNumber(2) && sep->IsNumber(3)) {
auto task_id = std::strtoul(sep->arg[2], nullptr, 10); const uint32 task_id = Strings::ToUnsignedInt(sep->arg[2]);
auto activity_id = std::strtoul(sep->arg[3], nullptr, 10); const uint32 activity_id = Strings::ToUnsignedInt(sep->arg[3]);
int count = 1; int count = 1;
if (arguments >= 4) { if (arguments == 4 && sep->IsNumber(4)) {
count = std::strtol(sep->arg[4], nullptr, 10); count = Strings::ToInt(sep->arg[4]);
if (count <= 0) { if (count <= 0) {
count = 1; count = 1;
} }
} }
c->Message( c->Message(
Chat::Yellow, Chat::White,
fmt::format( fmt::format(
"Updating task ID {}, activity {} with a count of {} for {}.", "Updating {} (ID {}), activity {} with a count of {} for {}.",
task_manager->GetTaskName(task_id),
task_id, task_id,
activity_id, activity_id,
count, count,
c->GetTargetDescription(target) c->GetTargetDescription(t)
).c_str() ).c_str()
); );
target->UpdateTaskActivity(task_id, activity_id, count); t->UpdateTaskActivity(task_id, activity_id, count);
target->ShowClientTasks(c); t->ShowClientTasks(c);
} }
} }
} }
+34 -12
View File
@@ -5,21 +5,43 @@ extern WorldServer worldserver;
void command_zonebootup(Client *c, const Seperator *sep) void command_zonebootup(Client *c, const Seperator *sep)
{ {
const int arguments = sep->argnum;
if (arguments < 2 || !sep->IsNumber(1)) {
c->Message(Chat::White, "Usage: #zonebootup [Zone Server ID] [Zone ID|Zone Short Name] [Instance ID]");
return;
}
if (!worldserver.Connected()) { if (!worldserver.Connected()) {
c->Message(Chat::White, "Error: World server disconnected"); c->Message(Chat::White, "World server disconnected.");
return;
} }
else if (sep->arg[2][0] == 0) {
c->Message(Chat::White, "Usage: #zonebootup ZoneServerID# zoneshortname"); const uint32 zone_server_id = Strings::ToUnsignedInt(sep->arg[1]);
const uint32 zone_id = Strings::IsNumber(sep->arg[2]) ? Strings::ToUnsignedInt(sep->arg[2]) : ZoneID(sep->arg[2]);
const bool is_static = arguments > 2 ? !strcasecmp(sep->arg[3], "static") : false;
const uint16 instance_id = arguments > 3 ? static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[4])) : 0;
if (!zone_id) {
c->Message(
Chat::White,
fmt::format(
"Zone '{}' does not exist.",
sep->arg[1]
).c_str()
);
return;
} }
else {
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct)); auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_Struct));
ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer; auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
s->ZoneServerID = Strings::ToInt(sep->arg[1]);
strcpy(s->adminname, c->GetName()); s->zone_server_id = zone_server_id;
s->zoneid = ZoneID(sep->arg[2]); s->zone_id = zone_id;
s->makestatic = (bool) (strcasecmp(sep->arg[3], "static") == 0); s->instance_id = instance_id;
s->is_static = is_static;
strn0cpy(s->admin_name, c->GetName(), sizeof(s->admin_name));
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
}
+28 -17
View File
@@ -5,26 +5,37 @@ extern WorldServer worldserver;
void command_zoneshutdown(Client *c, const Seperator *sep) void command_zoneshutdown(Client *c, const Seperator *sep)
{ {
const int arguments = sep->argnum;
if (!arguments) {
c->Message(Chat::White, "Usage: #zoneshutdown [Zone ID|Zone Short Name]");
return;
}
if (!worldserver.Connected()) { if (!worldserver.Connected()) {
c->Message(Chat::White, "Error: World server disconnected"); c->Message(Chat::White, "World server disconnected.");
return;
} }
else if (sep->arg[1][0] == 0) {
c->Message(Chat::White, "Usage: #zoneshutdown zoneshortname"); const uint32 zone_id = sep->IsNumber(1) ? Strings::ToUnsignedInt(sep->arg[1]) : ZoneID(sep->arg[1]);
}
else { if (!zone_id) {
auto pack = new ServerPacket( c->Message(
ServerOP_ZoneShutdown, Chat::White,
sizeof(ServerZoneStateChange_struct)); fmt::format(
ServerZoneStateChange_struct *s = (ServerZoneStateChange_struct *) pack->pBuffer; "Zone '{}' does not exist.",
strcpy(s->adminname, c->GetName()); sep->arg[1]
if (sep->arg[1][0] >= '0' && sep->arg[1][0] <= '9') { ).c_str()
s->ZoneServerID = Strings::ToInt(sep->arg[1]); );
} return;
else {
s->zoneid = ZoneID(sep->arg[1]);
} }
auto pack = new ServerPacket(ServerOP_ZoneShutdown, sizeof(ServerZoneStateChange_Struct));
auto *s = (ServerZoneStateChange_Struct *) pack->pBuffer;
s->zone_id = zone_id;
strn0cpy(s->admin_name, c->GetName(), sizeof(s->admin_name));
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
}
+6
View File
@@ -2510,3 +2510,9 @@ bool Group::IsLeader(const char* name) {
return false; return false;
} }
std::string Group::GetGroupLeaderName(uint32 group_id) {
char leader_name_buffer[64] = { 0 };
database.GetGroupLeadershipInfo(group_id, leader_name_buffer);
return std::string(leader_name_buffer);
}
+3 -1
View File
@@ -76,7 +76,7 @@ public:
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr); void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
inline void SetLeader(Mob* c){ leader = c; }; inline void SetLeader(Mob* c){ leader = c; };
inline Mob* GetLeader() { return leader; }; inline Mob* GetLeader() { return leader; };
const char* GetLeaderName() { return membername[0]; }; const char* GetLeaderName() { return GetGroupLeaderName(GetID()).c_str(); };
void SendHPManaEndPacketsTo(Mob* newmember); void SendHPManaEndPacketsTo(Mob* newmember);
void SendHPPacketsFrom(Mob* member); void SendHPPacketsFrom(Mob* member);
void SendManaPacketFrom(Mob* member); void SendManaPacketFrom(Mob* member);
@@ -177,6 +177,8 @@ private:
int mentor_percent; int mentor_percent;
XTargetAutoHaters m_autohatermgr; XTargetAutoHaters m_autohatermgr;
std::string GetGroupLeaderName(uint32 group_id);
}; };
#endif #endif
+16 -9
View File
@@ -42,15 +42,21 @@ HateList::~HateList()
{ {
} }
void HateList::WipeHateList() void HateList::WipeHateList(bool npc_only) {
{
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) {
while (iterator != list.end())
{
Mob *m = (*iterator)->entity_on_hatelist; Mob *m = (*iterator)->entity_on_hatelist;
if (m) if (
{ m &&
(
m->IsOfClientBotMerc() ||
(m->IsPet() && m->GetOwner() && m->GetOwner()->IsOfClientBotMerc())
) &&
npc_only
) {
iterator++;
} else {
if (m) {
if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) { if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) {
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0); parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0);
} }
@@ -59,10 +65,11 @@ void HateList::WipeHateList()
m->CastToClient()->DecrementAggroCount(); m->CastToClient()->DecrementAggroCount();
m->CastToClient()->RemoveXTarget(hate_owner, true); m->CastToClient()->RemoveXTarget(hate_owner, true);
} }
}
delete (*iterator); delete (*iterator);
iterator = list.erase(iterator); iterator = list.erase(iterator);
}
}
} }
} }
+1 -1
View File
@@ -88,7 +88,7 @@ public:
void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage); void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage);
void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; } void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; }
void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr); void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr);
void WipeHateList(); void WipeHateList(bool npc_only = false);
void RemoveStaleEntries(int time_ms, float dist); void RemoveStaleEntries(int time_ms, float dist);
+11 -2
View File
@@ -349,7 +349,6 @@ void lua_stop_all_timers(Lua_Encounter enc) {
void lua_pause_timer(const char *timer) { void lua_pause_timer(const char *timer) {
quest_manager.pausetimer(timer); quest_manager.pausetimer(timer);
} }
void lua_resume_timer(const char *timer) { void lua_resume_timer(const char *timer) {
@@ -879,6 +878,14 @@ int lua_merchant_count_item(uint32 npc_id, uint32 item_id) {
return quest_manager.MerchantCountItem(npc_id, item_id); return quest_manager.MerchantCountItem(npc_id, item_id);
} }
std::string lua_get_item_comment(uint32 item_id) {
return quest_manager.getitemcomment(item_id);
}
std::string lua_get_item_lore(uint32 item_id) {
return quest_manager.getitemlore(item_id);
}
std::string lua_get_item_name(uint32 item_id) { std::string lua_get_item_name(uint32 item_id) {
return quest_manager.getitemname(item_id); return quest_manager.getitemname(item_id);
} }
@@ -1266,7 +1273,7 @@ int lua_get_zone_weather() {
} }
luabind::adl::object lua_get_zone_time(lua_State *L) { luabind::adl::object lua_get_zone_time(lua_State *L) {
TimeOfDay_Struct eqTime; TimeOfDay_Struct eqTime{};
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime); zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime);
luabind::adl::object ret = luabind::newtable(L); luabind::adl::object ret = luabind::newtable(L);
@@ -5720,6 +5727,8 @@ luabind::scope lua_register_general() {
luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32))&lua_item_link), luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32))&lua_item_link),
luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32,uint32))&lua_item_link), luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32,uint32))&lua_item_link),
luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32,uint32,bool))&lua_item_link), luabind::def("item_link", (std::string(*)(uint32,int16,uint32,uint32,uint32,uint32,uint32,uint32,bool))&lua_item_link),
luabind::def("get_item_comment", (std::string(*)(uint32))&lua_get_item_comment),
luabind::def("get_item_lore", (std::string(*)(uint32))&lua_get_item_lore),
luabind::def("get_item_name", (std::string(*)(uint32))&lua_get_item_name), luabind::def("get_item_name", (std::string(*)(uint32))&lua_get_item_name),
luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link), luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link),
luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link), luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link),
+6
View File
@@ -30,6 +30,11 @@ const char *Lua_Item::GetLore() {
return self->Lore; return self->Lore;
} }
const char *Lua_Item::GetComment() {
Lua_Safe_Call_String();
return self->Comment;
}
const char *Lua_Item::GetIDFile() { const char *Lua_Item::GetIDFile() {
Lua_Safe_Call_String(); Lua_Safe_Call_String();
return self->IDFile; return self->IDFile;
@@ -957,6 +962,7 @@ luabind::scope lua_register_item() {
.def("Click_Type", &Lua_Item::GetClick_Type) .def("Click_Type", &Lua_Item::GetClick_Type)
.def("Color", &Lua_Item::GetColor) .def("Color", &Lua_Item::GetColor)
.def("CombatEffects", &Lua_Item::GetCombatEffects) .def("CombatEffects", &Lua_Item::GetCombatEffects)
.def("Comment", &Lua_Item::GetComment)
.def("DR", &Lua_Item::GetDR) .def("DR", &Lua_Item::GetDR)
.def("DSMitigation", &Lua_Item::GetDSMitigation) .def("DSMitigation", &Lua_Item::GetDSMitigation)
.def("Damage", &Lua_Item::GetDamage) .def("Damage", &Lua_Item::GetDamage)
+1
View File
@@ -32,6 +32,7 @@ public:
int GetItemClass(); int GetItemClass();
const char *GetName(); const char *GetName();
const char *GetLore(); const char *GetLore();
const char *GetComment();
const char *GetIDFile(); const char *GetIDFile();
uint32 GetID(); uint32 GetID();
int GetWeight(); int GetWeight();
+12
View File
@@ -285,6 +285,11 @@ void Lua_Mob::GMMove(double x, double y, double z, double heading) {
self->GMMove(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading)); self->GMMove(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading));
} }
void Lua_Mob::GMMove(double x, double y, double z, double heading, bool save_guard_spot) {
Lua_Safe_Call_Void();
self->GMMove(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading), save_guard_spot);
}
void Lua_Mob::TryMoveAlong(float distance, float angle) { void Lua_Mob::TryMoveAlong(float distance, float angle) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->TryMoveAlong(distance, angle); self->TryMoveAlong(distance, angle);
@@ -375,6 +380,11 @@ const char *Lua_Mob::GetRaceName() {
return GetRaceIDName(self->GetRace()); return GetRaceIDName(self->GetRace());
} }
const char* Lua_Mob::GetBaseRaceName() {
Lua_Safe_Call_String();
return GetRaceIDName(self->GetBaseRace());
}
int Lua_Mob::GetGender() { int Lua_Mob::GetGender() {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->GetGender(); return self->GetGender();
@@ -3345,6 +3355,7 @@ luabind::scope lua_register_mob() {
.def("FindType", (bool(Lua_Mob::*)(int,bool,int))&Lua_Mob::FindType) .def("FindType", (bool(Lua_Mob::*)(int,bool,int))&Lua_Mob::FindType)
.def("GMMove", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::GMMove) .def("GMMove", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::GMMove)
.def("GMMove", (void(Lua_Mob::*)(double,double,double,double))&Lua_Mob::GMMove) .def("GMMove", (void(Lua_Mob::*)(double,double,double,double))&Lua_Mob::GMMove)
.def("GMMove", (void(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::GMMove)
.def("GetAA", (int(Lua_Mob::*)(int))&Lua_Mob::GetAA) .def("GetAA", (int(Lua_Mob::*)(int))&Lua_Mob::GetAA)
.def("GetAABonuses", &Lua_Mob::GetAABonuses) .def("GetAABonuses", &Lua_Mob::GetAABonuses)
.def("GetAAByAAID", (int(Lua_Mob::*)(int))&Lua_Mob::GetAAByAAID) .def("GetAAByAAID", (int(Lua_Mob::*)(int))&Lua_Mob::GetAAByAAID)
@@ -3386,6 +3397,7 @@ luabind::scope lua_register_mob() {
.def("GetCasterLevel", &Lua_Mob::GetCasterLevel) .def("GetCasterLevel", &Lua_Mob::GetCasterLevel)
.def("GetClass", &Lua_Mob::GetClass) .def("GetClass", &Lua_Mob::GetClass)
.def("GetClassName", &Lua_Mob::GetClassName) .def("GetClassName", &Lua_Mob::GetClassName)
.def("GetBaseRaceName", &Lua_Mob::GetBaseRaceName)
.def("GetClassPlural", &Lua_Mob::GetClassPlural) .def("GetClassPlural", &Lua_Mob::GetClassPlural)
.def("GetCleanName", &Lua_Mob::GetCleanName) .def("GetCleanName", &Lua_Mob::GetCleanName)
.def("GetCloseMobList", (Lua_Mob_List(Lua_Mob::*)(void))&Lua_Mob::GetCloseMobList) .def("GetCloseMobList", (Lua_Mob_List(Lua_Mob::*)(void))&Lua_Mob::GetCloseMobList)
+2
View File
@@ -80,6 +80,7 @@ public:
bool RandomizeFeatures(bool send_illusion, bool save_variables); bool RandomizeFeatures(bool send_illusion, bool save_variables);
void GMMove(double x, double y, double z); void GMMove(double x, double y, double z);
void GMMove(double x, double y, double z, double heading); void GMMove(double x, double y, double z, double heading);
void GMMove(double x, double y, double z, double heading, bool save_guard_spot);
void TryMoveAlong(float distance, float heading); void TryMoveAlong(float distance, float heading);
void TryMoveAlong(float distance, float heading, bool send); void TryMoveAlong(float distance, float heading, bool send);
bool HasProcs(); bool HasProcs();
@@ -106,6 +107,7 @@ public:
int GetRace(); int GetRace();
const char *GetClassName(); const char *GetClassName();
const char *GetRaceName(); const char *GetRaceName();
const char* GetBaseRaceName();
int GetGender(); int GetGender();
int GetTexture(); int GetTexture();
int GetHelmTexture(); int GetHelmTexture();
+7 -18
View File
@@ -438,9 +438,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M
lua_pop(L, npop); lua_pop(L, npop);
} catch(std::exception &ex) { } catch(std::exception &ex) {
std::string error = "Lua Exception: "; AddError(fmt::format("Lua Exception | [{}] for NPC [{}] in [{}]: {}", sub_name, npc->GetNPCTypeID(), package_name, ex.what()));
error += std::string(ex.what());
AddError(error);
//Restore our stack to the best of our ability //Restore our stack to the best of our ability
int end = lua_gettop(L); int end = lua_gettop(L);
@@ -532,9 +530,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *
lua_pop(L, npop); lua_pop(L, npop);
} catch(std::exception &ex) { } catch(std::exception &ex) {
std::string error = "Lua Exception: "; AddError(fmt::format("Lua Exception | [{}] for Player in [{}]: {}", sub_name, package_name, ex.what()));
error += std::string(ex.what());
AddError(error);
//Restore our stack to the best of our ability //Restore our stack to the best of our ability
int end = lua_gettop(L); int end = lua_gettop(L);
@@ -617,9 +613,8 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
lua_pop(L, npop); lua_pop(L, npop);
} catch(std::exception &ex) { } catch(std::exception &ex) {
std::string error = "Lua Exception: "; uint32_t item_id = item->GetItem() ? item->GetItem()->ID : 0;
error += std::string(ex.what()); AddError(fmt::format("Lua Exception | [{}] for Item [{}] in [{}]: {}", sub_name, item_id, package_name, ex.what()));
AddError(error);
//Restore our stack to the best of our ability //Restore our stack to the best of our ability
int end = lua_gettop(L); int end = lua_gettop(L);
@@ -699,9 +694,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, Mob* mob,
lua_pop(L, npop); lua_pop(L, npop);
} catch(std::exception &ex) { } catch(std::exception &ex) {
std::string error = "Lua Exception: "; AddError(fmt::format("Lua Exception | [{}] for Spell [{}] in [{}]: {}", sub_name, spell_id, package_name, ex.what()));
error += std::string(ex.what());
AddError(error);
//Restore our stack to the best of our ability //Restore our stack to the best of our ability
int end = lua_gettop(L); int end = lua_gettop(L);
@@ -766,9 +759,7 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::
lua_pop(L, 2); lua_pop(L, 2);
} catch(std::exception &ex) { } catch(std::exception &ex) {
std::string error = "Lua Exception: "; AddError(fmt::format("Lua Exception | [{}] for Encounter [{}]: {}", sub_name, encounter_name, ex.what()));
error += std::string(ex.what());
AddError(error);
//Restore our stack to the best of our ability //Restore our stack to the best of our ability
int end = lua_gettop(L); int end = lua_gettop(L);
@@ -1630,9 +1621,7 @@ int LuaParser::_EventBot(
lua_pop(L, npop); lua_pop(L, npop);
} catch(std::exception &ex) { } catch(std::exception &ex) {
std::string error = "Lua Exception: "; AddError(fmt::format("Lua Exception | [{}] for Bot [{}] in [{}]: {}", sub_name, bot->GetBotID(), package_name, ex.what()));
error += std::string(ex.what());
AddError(error);
//Restore our stack to the best of our ability //Restore our stack to the best of our ability
int end = lua_gettop(L); int end = lua_gettop(L);
+22 -32
View File
@@ -515,6 +515,7 @@ Mob::Mob(
is_boat = IsBoat(); is_boat = IsBoat();
current_alliance_faction = -1;
} }
Mob::~Mob() Mob::~Mob()
@@ -3586,10 +3587,17 @@ void Mob::SendIllusionPacket(const AppearanceStruct& a)
gender = new_gender; gender = new_gender;
hairstyle = new_hair; hairstyle = new_hair;
haircolor = new_hair_color; haircolor = new_hair_color;
helmtexture = new_helmet_texture;
race = new_race; race = new_race;
size = new_size; size = new_size;
// These two should not be modified in base data - it kills db texture
// when illusion is only for RandomizeFeatures...
if (new_helmet_texture != UINT8_MAX) {
helmtexture = new_helmet_texture;
}
if (new_texture != UINT8_MAX) {
texture = new_texture; texture = new_texture;
}
auto outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct)); auto outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct));
auto is = (Illusion_Struct *) outapp->pBuffer; auto is = (Illusion_Struct *) outapp->pBuffer;
@@ -4881,16 +4889,14 @@ bool Mob::RemoveFromHateList(Mob* mob)
return bFound; return bFound;
} }
void Mob::WipeHateList() void Mob::WipeHateList(bool npc_only) {
{ if (IsEngaged()) {
if(IsEngaged()) hate_list.WipeHateList(npc_only);
{ if (hate_list.IsHateListEmpty()) {
hate_list.WipeHateList();
AI_Event_NoLongerEngaged(); AI_Event_NoLongerEngaged();
} }
else } else {
{ hate_list.WipeHateList(npc_only);
hate_list.WipeHateList();
} }
} }
@@ -5310,7 +5316,7 @@ int Mob::GetHaste()
h += spellbonuses.hastetype2 > 10 ? 10 : spellbonuses.hastetype2; h += spellbonuses.hastetype2 > 10 ? 10 : spellbonuses.hastetype2;
// 26+ no cap, 1-25 10 // 26+ no cap, 1-25 10
if (level > 25) // 26+ if (level > 25 || (IsClient() && RuleB(Character, IgnoreLevelBasedHasteCaps))) // 26+
h += itembonuses.haste; h += itembonuses.haste;
else // 1-25 else // 1-25
h += itembonuses.haste > 10 ? 10 : itembonuses.haste; h += itembonuses.haste > 10 ? 10 : itembonuses.haste;
@@ -5332,7 +5338,7 @@ int Mob::GetHaste()
h = cap; h = cap;
// 51+ 25 (despite there being higher spells...), 1-50 10 // 51+ 25 (despite there being higher spells...), 1-50 10
if (level > 50) { // 51+ if (level > 50 || (IsClient() && RuleB(Character, IgnoreLevelBasedHasteCaps))) { // 51+
cap = RuleI(Character, Hastev3Cap); cap = RuleI(Character, Hastev3Cap);
if (spellbonuses.hastetype3 > cap) { if (spellbonuses.hastetype3 > cap) {
h += cap; h += cap;
@@ -7121,24 +7127,10 @@ int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) {
return effect_value; return effect_value;
} }
// Faction Mods for Alliance type spells // Faction Mods for Alliance type spells (only 1 ever active)
void Mob::AddFactionBonus(uint32 pFactionID,int32 bonus) { void Mob::AddFactionBonus(uint32 pFactionID,int32 bonus) {
std::map <uint32, int32> :: const_iterator faction_bonus; current_alliance_faction = pFactionID;
typedef std::pair <uint32, int32> NewFactionBonus; current_alliance_mod = bonus;
faction_bonus = faction_bonuses.find(pFactionID);
if(faction_bonus == faction_bonuses.end())
{
faction_bonuses.emplace(NewFactionBonus(pFactionID,bonus));
}
else
{
if(faction_bonus->second<bonus)
{
faction_bonuses.erase(pFactionID);
faction_bonuses.emplace(NewFactionBonus(pFactionID,bonus));
}
}
} }
// Faction Mods from items // Faction Mods from items
@@ -7162,11 +7154,9 @@ void Mob::AddItemFactionBonus(uint32 pFactionID,int32 bonus) {
} }
int32 Mob::GetFactionBonus(uint32 pFactionID) { int32 Mob::GetFactionBonus(uint32 pFactionID) {
std::map <uint32, int32> :: const_iterator faction_bonus; if(current_alliance_faction == pFactionID)
faction_bonus = faction_bonuses.find(pFactionID);
if(faction_bonus != faction_bonuses.end())
{ {
return (*faction_bonus).second; return current_alliance_mod;
} }
return 0; return 0;
} }
+4 -3
View File
@@ -767,7 +767,7 @@ public:
void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; } void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; }
bool HateSummon(); bool HateSummon();
void FaceTarget(Mob* mob_to_face = 0); void FaceTarget(Mob* mob_to_face = 0);
void WipeHateList(); void WipeHateList(bool npc_only = false);
void AddFeignMemory(Mob* attacker); void AddFeignMemory(Mob* attacker);
void RemoveFromFeignMemory(Mob* attacker); void RemoveFromFeignMemory(Mob* attacker);
void ClearFeignMemory(); void ClearFeignMemory();
@@ -1774,8 +1774,9 @@ protected:
uint32 time_until_can_move; uint32 time_until_can_move;
HateList hate_list; HateList hate_list;
std::set<uint32> feign_memory_list; std::set<uint32> feign_memory_list;
// This is to keep track of mobs we cast faction mod spells on // This is to keep track of the current (one only) faction mod (alliance)
std::map<uint32,int32> faction_bonuses; // Primary FactionID, Bonus uint32 current_alliance_faction;
int32 current_alliance_mod;
void AddFactionBonus(uint32 pFactionID,int32 bonus); void AddFactionBonus(uint32 pFactionID,int32 bonus);
int32 GetFactionBonus(uint32 pFactionID); int32 GetFactionBonus(uint32 pFactionID);
// This is to keep track of item faction modifiers // This is to keep track of item faction modifiers
+9
View File
@@ -1062,6 +1062,15 @@ void Mob::AI_Process() {
SetTarget(hate_list.GetClosestEntOnHateList(this)); SetTarget(hate_list.GetClosestEntOnHateList(this));
else { else {
if (AI_target_check_timer->Check()) { if (AI_target_check_timer->Check()) {
if (
IsNPC() &&
!CastToNPC()->GetSwarmInfo() &&
(!IsPet() || (HasOwner() && GetOwner()->IsNPC())) &&
!CastToNPC()->WillAggroNPCs()
) {
WipeHateList(true); // wipe NPCs from hate list to prevent faction war
}
if (IsFocused()) { if (IsFocused()) {
if (!target) { if (!target) {
SetTarget(hate_list.GetEntWithMostHateOnList(this)); SetTarget(hate_list.GetEntWithMostHateOnList(this));
+16 -10
View File
@@ -40,10 +40,14 @@ extern EntityList entity_list;
extern WorldServer worldserver; extern WorldServer worldserver;
// Loading object from database // Loading object from database
Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const EQ::ItemInstance* inst) Object::Object(
: respawn_timer(0), decay_timer(300000) uint32 id,
uint32 type,
uint32 icon,
const Object_Struct &object,
const EQ::ItemInstance *inst
) : respawn_timer(0), decay_timer(300000)
{ {
user = nullptr; user = nullptr;
last_user = nullptr; last_user = nullptr;
@@ -53,6 +57,7 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object,
m_icon = icon; m_icon = icon;
m_inst = nullptr; m_inst = nullptr;
m_ground_spawn = false; m_ground_spawn = false;
// Copy object data // Copy object data
memcpy(&m_data, &object, sizeof(Object_Struct)); memcpy(&m_data, &object, sizeof(Object_Struct));
if (inst) { if (inst) {
@@ -61,6 +66,7 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object,
} else { } else {
decay_timer.Disable(); decay_timer.Disable();
} }
respawn_timer.Disable(); respawn_timer.Disable();
// Set drop_id to zero - it will be set when added to zone with SetID() // Set drop_id to zero - it will be set when added to zone with SetID()
@@ -85,7 +91,7 @@ Object::Object(const EQ::ItemInstance* inst, char* name,float max_x,float min_x,
m_min_y=min_y; m_min_y=min_y;
m_id = 0; m_id = 0;
m_inst = (inst) ? inst->Clone() : nullptr; m_inst = (inst) ? inst->Clone() : nullptr;
m_type = OT_DROPPEDITEM; m_type = ObjectTypes::Temporary;
m_icon = 0; m_icon = 0;
m_ground_spawn = true; m_ground_spawn = true;
decay_timer.Disable(); decay_timer.Disable();
@@ -116,7 +122,7 @@ Object::Object(Client* client, const EQ::ItemInstance* inst)
// Initialize members // Initialize members
m_id = 0; m_id = 0;
m_inst = (inst) ? inst->Clone() : nullptr; m_inst = (inst) ? inst->Clone() : nullptr;
m_type = OT_DROPPEDITEM; m_type = ObjectTypes::Temporary;
m_icon = 0; m_icon = 0;
m_ground_spawn = false; m_ground_spawn = false;
// Set as much struct data as we can // Set as much struct data as we can
@@ -179,7 +185,7 @@ Object::Object(const EQ::ItemInstance *inst, float x, float y, float z, float he
// Initialize members // Initialize members
m_id = 0; m_id = 0;
m_inst = (inst) ? inst->Clone() : nullptr; m_inst = (inst) ? inst->Clone() : nullptr;
m_type = OT_DROPPEDITEM; m_type = ObjectTypes::Temporary;
m_icon = 0; m_icon = 0;
m_ground_spawn = false; m_ground_spawn = false;
// Set as much struct data as we can // Set as much struct data as we can
@@ -436,7 +442,7 @@ void Object::CreateDeSpawnPacket(EQApplicationPacket* app)
} }
bool Object::Process(){ bool Object::Process(){
if(m_type == OT_DROPPEDITEM && decay_timer.Enabled() && decay_timer.Check()) { if(m_type == ObjectTypes::Temporary && decay_timer.Enabled() && decay_timer.Check()) {
// Send click to all clients (removes entity on client) // Send click to all clients (removes entity on client)
auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct));
ClickObject_Struct* click_object = (ClickObject_Struct*)outapp->pBuffer; ClickObject_Struct* click_object = (ClickObject_Struct*)outapp->pBuffer;
@@ -497,7 +503,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
if(m_ground_spawn) {//This is a Cool Groundspawn if(m_ground_spawn) {//This is a Cool Groundspawn
respawn_timer.Start(); respawn_timer.Start();
} }
if (m_type == OT_DROPPEDITEM) { if (m_type == ObjectTypes::Temporary) {
bool cursordelete = false; bool cursordelete = false;
bool duplicate_lore = false; bool duplicate_lore = false;
if (m_inst && sender) { if (m_inst && sender) {
@@ -969,7 +975,7 @@ void Object::SetSize(float size)
void Object::SetSolidType(uint16 solidtype) void Object::SetSolidType(uint16 solidtype)
{ {
m_data.solidtype = solidtype; m_data.solid_type = solidtype;
auto app = new EQApplicationPacket(); auto app = new EQApplicationPacket();
auto app2 = new EQApplicationPacket(); auto app2 = new EQApplicationPacket();
CreateDeSpawnPacket(app); CreateDeSpawnPacket(app);
@@ -987,7 +993,7 @@ float Object::GetSize()
uint16 Object::GetSolidType() uint16 Object::GetSolidType()
{ {
return m_data.solidtype; return m_data.solid_type;
} }
const char* Object::GetModelName() const char* Object::GetModelName()
+45 -2
View File
@@ -73,8 +73,6 @@ IT10714_ACTORDEF=Augmentation Sealer
IT10725_ACTORDEF=Shuriken IT10725_ACTORDEF=Shuriken
*/ */
#define OT_DROPPEDITEM EQ::item::BagTypeLargeBag
// Icon values: // Icon values:
//0x0453 a pie //0x0453 a pie
//0x0454 cookies? //0x0454 cookies?
@@ -89,6 +87,51 @@ IT10725_ACTORDEF=Shuriken
//0x045D is a hammer //0x045D is a hammer
//0x045E is a wierd rope shape //0x045E is a wierd rope shape
enum ObjectTypes {
StaticLocked = 0,
Temporary = 1,
ToolBox = 10,
Research = 11,
Mortar = 12,
SelfDusting = 13,
Baking1 = 14,
Baking2 = 15,
Tailoring = 16,
Forge = 17,
Fletching = 18,
BrewBarrel = 19,
Jewelcrafting = 20,
PotteryWheel = 21,
PotteryKiln = 22,
WizardResearch = 24,
MagicianResearch = 25,
NecromancerResearch = 26,
EnchanterResearch = 27,
Invalid1 = 28,
Invalid2 = 29,
Experimental = 30,
HighElfForge = 31,
DarkElfForge = 32,
OgreForge = 33,
DwarfForge = 34,
GnomeForge = 35,
BarbarianForge = 36,
IksarForge = 38,
HumanForge = 39,
HumanForge2 = 40,
HalflingTailoring = 41,
EruditeTailoring = 42,
WoodElfTailoring = 43,
WoodElfFletching = 44,
IksarPotteryWheel = 45,
TrollForge = 47,
WoodElfForge = 48,
HalflingForge = 49,
EruditeForge = 50,
AugmentationPool = 53,
StaticUnlocked = 255
};
class Object: public Entity class Object: public Entity
{ {
public: public:

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