Compare commits

...

42 Commits

Author SHA1 Message Date
dependabot[bot]
9b3f9f356d
Bump golang.org/x/crypto in /utils/scripts/build/should-release (#5032)
Some checks failed
Build / Linux (push) Has been cancelled
Build / Windows (push) Has been cancelled
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.36.0 to 0.45.0.
- [Commits](https://github.com/golang/crypto/compare/v0.36.0...v0.45.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.45.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-20 19:44:17 +01:00
brainiac
e42dc2e1d2
Add Github Actions support (#5031)
Some checks failed
Build / Linux (push) Has been cancelled
Build / Windows (push) Has been cancelled
Basic support for building linux and windows in pull requests and also
the master branch.

Removes search for local perl on windows. Just always use the packaged
perl until we can switch to a package manager.

Removes drone config file, since that isn't doing anything useful anymore.
2025-11-17 10:21:05 -08:00
m0th
c611a25385
Dev Container Overhaul (#5023)
* Cleanup & Reorganize Makefile for Dev Containers

* Fix Makefile & misc fixes

---------

Co-authored-by: m0th <43860202+m0th@users.noreply.github.com>
2025-10-29 22:22:23 -07:00
Vayle
f74efcaa5f
[Bug Fix] Enhance SummonItemIntoInventory() to support stacking of items (#5022)
* Initial plan

* Initial plan

* Enhance SummonItemIntoInventory to support stacking

Co-authored-by: Valorith <76063792+Valorith@users.noreply.github.com>

* Update .gitignore

* Revert "Update .gitignore"

This reverts commit 16159398d8a69c53a719a1d54d068bbe0fa5284c.

* Disable PCH for patch sources compiled with -O0

Disables precompiled headers for specific patch source files that are compiled with -O0 on UNIX. This avoids Clang errors caused by __OPTIMIZE__ macro state mismatches between the PCH and translation units.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2025-10-22 22:50:00 -07:00
Jordan Conner
eb4e7d694c
Update client.cpp HandleEnterWorldPacket for UCS Local Address (#5020)
world/client.cpp's EnterWorld will correctly serve a LAN client the eqemu_config.json.world.localaddress based off IsLocalClient. It will then serve a non-LAN client the world.address value. This concept needs to be applied to UCS as that system also receives direct client connections. Inside world/client.cpp HandleEnterWorldPacket is where world sends the client info about UCS connection. This fix specifically handles the issue when you have a server on LAN and want to connect to it via another LAN computer + you have external clients.
2025-10-22 22:37:37 -07:00
Exonintrendo
ecc0d4b5c0
updated crash report url to new hosted spire location (#5024) 2025-10-16 10:22:49 -07:00
Chris Miles
8175ae6187 [Release] 23.10.3 2025-09-17 01:31:48 -05:00
Chris Miles
e8f4ffd628 [Release] 23.10.2 2025-09-17 00:52:31 -05:00
Chris Miles
0447618f7e hotfix: merge fix 2025-09-17 00:50:03 -05:00
Chris Miles
e71ce001ff Hotfix: revert #4996 2025-09-17 00:47:42 -05:00
Alex King
1575a2af40
[Hotfix] Fixed Mail Key Bug (#5015)
* [Hotfix] Fixed Mail Key Bug

* Release
2025-09-16 22:52:57 -04:00
JJ
4b69df646c
[Release] 23.10.0 (#5014)
* Update CHANGELOG.md

* Update version.h

* Update package.json
2025-09-16 11:35:03 -04:00
Alex King
044b9c1420
[Repositories] Convert Mail Key to Repositories (#5007)
* [Repositories] Convert Mail Key to Repositories

* Update shareddb.cpp

---------

Co-authored-by: JJ <3617814+joligario@users.noreply.github.com>
2025-09-15 14:23:48 -04:00
Alex King
0bbb5b90e7
[Repositories] Convert Total Time Played to Repositories (#5008) 2025-09-15 09:14:59 -04:00
Alex King
6506ad5b51
[Quest API] Add EVENT_CHARM_START and EVENT_CHARM_END (#5013) 2025-09-15 09:14:46 -04:00
Alex King
dcaa0ecdaa
[Quest API] Add Identifiers to Get/Modify NPC Stat Methods (#5012) 2025-09-15 09:14:29 -04:00
Mitch Freeman
9b143132be
[Bug Fix] Fix Several Evolving Item Bugs (#4992)
* Add sending evolving items via parcels
Send, retrieve and inspect tested ok

* Sell evolving items to a merchant and purchase tested ok.

* Fix a problem with potions and quantity
2025-09-07 22:51:39 -04:00
Mitch Freeman
231bf8b4ec
Update database_update_manifest.cpp (#5011) 2025-09-07 19:13:00 -04:00
Alex King
dee58f9a91
[Repositories] Convert Shared Bank Platinum to Repositories (#5006) 2025-09-01 21:39:24 -04:00
Alex King
1eb89edbbd
[Repositories] Convert Item Loading to Repositories (#4998) 2025-08-30 16:39:23 -04:00
Alex King
e015d0d67e
[Repositories] Convert Damage Shield Types to Repositories (#4995)
* [Repositories] Convert Damage Shield Types to Repositories

* Remove max spell ID
2025-08-30 16:23:33 -04:00
Alex King
ba78394ce9
[Repositories] Convert Spell Loading to Repositories (#4996) 2025-08-30 15:42:04 -04:00
Alex King
060f6e377d
[Constants] Convert SE Defines to SpellEffect Namespace (#4999) 2025-08-30 15:33:19 -04:00
Alex King
92c8b0e585
[Constants] Change Race Changes to Race Namespace (#5000) 2025-08-30 15:33:11 -04:00
Alex King
33df8ea665
[Repositories] Convert Character Inspect Messages to Repositories (#4997) 2025-08-30 14:42:40 -04:00
Alex King
9668074d94
[Bug Fix] Fix Recipe Inspect Bug (#4994) 2025-08-30 13:56:14 -04:00
Alex King
822a5dcac4
[Cleanup] Cleanup #show ip_lookup Message (#5005)
* [Cleanup] Cleanup #show ip_lookup Message

* Test

* Update clientlist.cpp
2025-08-30 13:05:18 -04:00
Alex King
0c65a4febe
[Cleanup] Fix #set race 0 Message (#5004) 2025-08-29 20:08:03 -04:00
Alex King
02f66de679
[Cleanup] Remove Unused errorname Variable (#5001) 2025-08-29 12:02:11 -04:00
Alex King
145111f11e
[Bug Fix] Fix Task Reloading (#5002) 2025-08-29 06:52:51 -04:00
Alex King
a4e47d9180
[Pets] Add Pet Constants and Methods (#4987)
* [Pets] Add Pet Constants and Methods

* Remove GetID

* GetPetTypeName()

* Cleanup
2025-08-17 01:00:31 -04:00
Alex King
207ee2daa0
[Database] Add heal_amount to character_stats_record (#4986)
* [Database] Add heal_amount to character_stats_record

* Update version.h
2025-08-16 21:35:55 -04:00
Alex King
1fe5d9fa4f
[Commands] Add #task complete Saylink to #task show (#4985) 2025-08-16 21:35:38 -04:00
Alex King
ed3f6c2a40
[Cleanup] Fix Issues with Strings::Commify and Mob::SendStatsWindow (#4984) 2025-08-16 21:35:13 -04:00
Alex King
adb3196ca5
[Cleanup] Add #npcedit npc_tint_id Help Message (#4982)
* [Cleanup] Add #npcedit npc_tint_id Help Message

* Update npcedit.cpp

* Update npcedit.cpp
2025-08-16 21:34:55 -04:00
Alex King
e13b133ac8
[Quest API] Add GetNPCTintIndex() to Perl/Lua (#4983) 2025-08-16 21:34:39 -04:00
Alex King
d475428157
[Quest API] Add GetKeyRing() to Perl/Lua (#4980) 2025-08-16 21:34:28 -04:00
Alex King
00b66ce432
[Commands] Add #find account Subcommand (#4981)
Credit goes to https://github.com/The-Heroes-Journey-EQEMU/Server/pull/281
2025-08-16 21:34:16 -04:00
Alex
4d12dd5c43
[Code] Remove Attributions (#4988) 2025-08-15 23:36:35 -05:00
regneq
c4f408bffc
[Bug Fix] Fix Race 474 for Titanium (#4979) 2025-08-11 16:49:59 -04:00
Alex King
d876c6df2a
[Bug Fix] Fix #show recipe uint16 Cap (#4978) 2025-08-11 14:06:13 -04:00
Alex King
d142e1ca81
[Hotfix] Fix Quest Ownership Edge Case (#4977)
* [Hotfix] Fix Quest Ownership Edge Case

* Push
2025-08-02 22:09:30 -05:00
125 changed files with 7242 additions and 7248 deletions

View File

@ -1,6 +1,5 @@
!Makefile
base/*.sql
base/*.zip
base/db/
base/maps/
!base/expansion/Makefile
base/
!base/*.json
override/
repo/
cache/

View File

@ -1,196 +1,127 @@
# Build binaries: make cmake, make build
# One time initial setup (or to reset db): make prep, make inject-mariadb, make maps
# Update custom db edits: make inject-custom
# Start up server: make shared, make login, make world, make zone
# in game, stop combat spam #logs set gmsay 79 0
# in game, stop loot spam #logs set gmsay 69 0
NAME := eqemu-server
.ONESHELL:
DOCKER_ARGS := --rm --name ${NAME} -v $$PWD:/src -w /src ${NAME}
DOCKER_ARM64_ARGS := --rm --platform linux/arm64 --name ${NAME}-arm64 -v $$PWD:/src -w /src ${NAME}-arm64
.PHONY: build
build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile build --no-print-directory
exit
endif
cd build$$BUILD_SUFFIX && cmake --build . --config Release --target all --
.PHONY: cmake
cmake:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile cmake --no-print-directory
exit
endif
@echo "working directory: $$PWD"
mkdir -p build$$BUILD_SUFFIX
@cd build$$BUILD_SUFFIX && cmake -DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_TESTS=ON \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja ..
clean:
ifneq (,$(findstring .devcontainer,$$PWD))
@make -C ../ -f .devcontainer/Makefile clean --no-print-directory
endif
rm -rf build
docker-cmake:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-cmake --no-print-directory
exit
endif
@echo "working directory: $$PWD"
git submodule update --init --recursive
docker run ${DOCKER_ARGS} make cmake
docker-build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-build --no-print-directory
exit
endif
docker run ${DOCKER_ARGS} make build
# Build image if it doesn't exist
docker-image-build:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-image-build --no-print-directory
exit
endif
ifeq ($(shell docker images -q ${NAME} 2> /dev/null),)
@echo "Docker image not found. Building..."
docker build -f Dockerfile.debian.dev -t ${NAME} .
endif
docker-arm-cmake: docker-arm-image-build
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-arm-cmake --no-print-directory
exit
endif
git submodule update --init --recursive
docker run ${DOCKER_ARM64_ARGS} make cmake BUILD_SUFFIX=arm64
docker-arm-build: docker-arm-image-build
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile docker-arm-build --no-print-directory
exit
endif
docker run ${DOCKER_ARM64_ARGS} make build BUILD_SUFFIX=arm64
docker-arm-image-build:
ifeq ($(shell docker images -q ${NAME}-arm64 2> /dev/null),)
@echo "Docker image not found. Building..."
docker build -f Dockerfile.debian.arm.dev -t ${NAME}-arm64 .
endif
docker-clean: clean
.PHONY: prep
prep:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile prep --no-print-directory
exit
endif
prep: is-vscode
@echo "Preparing build/bin for usage..."
mkdir -p build/bin/assets/patches
cp -R -u -p .devcontainer/base/eqemu_config.json build/bin/eqemu_config.json
cp -R -u -p .devcontainer/base/login.json build/bin/login.json
cp -R -u -p loginserver/login_util/* build/bin/assets/patches/
mkdir -p build/bin/assets
cp -R -u -p utils/patches build/bin/assets/
-unlink build/bin/lua_modules
cd build/bin && ln -s quests/lua_modules lua_modules
-unlink build/bin/mods
cd build/bin && ln -s quests/mods mods
-unlink build/bin/maps
cd build/bin && ln -s ../../base/maps maps
mkdir -p build/bin/logs
mkdir -p build/bin/shared
@echo "Prepping folders..."
@mkdir -p .devcontainer/override
@mkdir -p .devcontainer/repo
@mkdir -p .devcontainer/cache
@mkdir -p build/bin/logs
@mkdir -p build/bin/shared
@mkdir -p build/bin/assets
@echo "Applying overrides..."
@if [ ! -f .devcontainer/override/eqemu_config.json ]; then cp .devcontainer/base/eqemu_config.json .devcontainer/override/eqemu_config.json; fi
@if [ -f build/bin/eqemu_config.json ]; then unlink build/bin/eqemu_config.json; fi
cd build/bin && ln -s ../../.devcontainer/override/eqemu_config.json eqemu_config.json
@if [ ! -f .devcontainer/override/login.json ]; then cp .devcontainer/base/login.json .devcontainer/override/login.json; fi
@if [ -f build/bin/login.json ]; then unlink build/bin/login.json; fi
cd build/bin && ln -s ../../.devcontainer/override/login.json login.json
@echo "Cloning repositories..."
cd .devcontainer/repo && if [ ! -d "quests" ]; then cd ../../.devcontainer/repo/ && git clone https://github.com/ProjectEQ/projecteqquests.git quests; fi
cd .devcontainer/repo && if [ ! -d "eqemu-definitions" ]; then cd ../../.devcontainer/repo/ && git clone https://github.com/xackery/eqemu-definitions.git eqemu-definitions; fi
cd .devcontainer/repo && if [ ! -d "maps" ]; then cd ../../ && make maps; fi
@if [ -d build/bin/quests ]; then unlink build/bin/quests; fi
cd build/bin && ln -s ../../.devcontainer/repo/quests quests
@if [ -d build/bin/maps ]; then unlink build/bin/maps; fi
cd build/bin && ln -s ../../.devcontainer/repo/maps maps
@if [ -d build/bin/eqemu-definitions ]; then unlink build/bin/eqemu-definitions; fi
cd build/bin && ln -s ../../.devcontainer/repo/eqemu-definitions eqemu-definitions
@mkdir -p build/bin/quests/mods
@echo "Applying base links..."
cp -R -u -p utils/patches .devcontainer/base/
@if [ -d build/bin/assets/patches ]; then unlink build/bin/assets/patches; fi
cd build/bin/assets && ln -s ../../../.devcontainer/base/patches patches
@if [ -d build/bin/lua_modules ]; then unlink build/bin/lua_modules; fi
cd build/bin && ln -s ../../.devcontainer/repo/quests/lua_modules lua_modules
@if [ -d build/bin/mods ]; then unlink build/bin/mods; fi
cd build/bin && ln -s ../../.devcontainer/repo/quests/mods mods
@if [ -d build/bin/plugins ]; then unlink build/bin/plugins; fi
cd build/bin && ln -s ../../.devcontainer/repo/quests/plugins plugins
@echo "Eqemu is prepared. Edit build/bin/eqemu_config.json to configure."
maps:
@echo "Downloading maps..."
@mkdir -p base/maps
@cd base/maps && wget -nc https://github.com/Akkadius/eqemu-maps/archive/refs/heads/master.zip
@cd base/maps && unzip -o master.zip
@cd base/maps && mv eqemu-maps-master/* .
@cd base/maps && rm -rf eqemu-maps-master
@echo "Maps downloaded."
is-vscode:
@if [ -z "$$REMOTE_CONTAINERS" ]; then \
echo "Not running in VS Code devcontainer"; \
exit 1; \
fi
quests:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile quests --no-print-directory
exit
endif
@cd build/bin && git clone https://github.com/ProjectEQ/projecteqquests.git quests
clean: is-vscode
rm -rf build
.PHONY: maps
maps: is-vscode
@echo "Downloading maps..."
@mkdir -p .devcontainer/repo/maps
@cd .devcontainer/repo/maps && wget -nc https://github.com/EQEmu/maps/archive/refs/heads/master.zip
@cd .devcontainer/repo/maps && unzip -o master.zip
@cd .devcontainer/repo/maps && mv maps-master/* .
@cd .devcontainer/repo/maps && rm -rf maps-master
@echo "Maps downloaded."
# Runs tests
.PHONY: test
test:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile test --no-print-directory
exit
endif
test: is-vscode
cd build/bin && ./tests
# Runs login binary
.PHONY: login
login:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile login --no-print-directory
exit
endif
login: is-vscode check-mariadb
cd build/bin && ./loginserver
.PHONY: hotfix
hotfix: shared
# Runs shared_memory binary
.PHONY: shared
shared:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile shared --no-print-directory
exit
endif
shared: is-vscode check-mariadb
cd build/bin && ./shared_memory
# Runs zone binary
.PHONY: zone
zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile zone --no-print-directory
exit
endif
@-rm build/bin/logs/zone/zone*.log
zone: is-vscode check-mariadb
@find build/bin/logs/zone/ -type f -name 'zone*.log' -exec rm -f {} +
cd build/bin && ./zone
check-mariadb: is-vscode
@if ! sudo service mariadb status | grep -q 'active (running)'; then \
sudo service mariadb start; \
fi
# Runs world binary
.PHONY: world
world:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile world --no-print-directory
exit
endif
@-rm build/bin/logs/world*.log
world: is-vscode check-mariadb
@find build/bin/logs/ -type f -name 'world*.log' -exec rm -f {} +
cd build/bin && ./world
# Runs ucs binary
.PHONY: ucs
ucs:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile ucs --no-print-directory
exit
endif
@-rm build/bin/logs/ucs*.log
ucs: is-vscode check-mariadb
@find build/bin/logs/ -type f -name 'ucs*.log' -exec rm -f {} +
cd build/bin && ./ucs
# Runs queryserv binary
.PHONY: queryserv
queryserv:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile queryserv --no-print-directory
exit
endif
@-rm build/bin/logs/query_server*.log
queryserv: is-vscode check-mariadb
@find build/bin/logs/ -type f -name 'query_server*.log' -exec rm -f {} +
cd build/bin && ./queryserv
valgrind-%:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile valgrind --no-print-directory
exit
endif
reset-content:
@echo "Resetting content tables in database peq..."
cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_content.sql"
valgrind-%: is-vscode
cd build/bin && valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=logs/$*.valgrind.log ./$*
# Start mariaDB standalone
@ -201,30 +132,33 @@ mariadb:
.PHONY: inject-mariadb
inject-mariadb:
-sudo service mariadb start
-mkdir -p base/db/
-mkdir -p .devcontainer/cache/db/
-sudo mariadb -e 'DROP DATABASE IF EXISTS peq;'
-sudo mariadb -e 'CREATE DATABASE peq;'
-sudo mariadb -e "CREATE USER 'peq'@'127.0.0.1' IDENTIFIED BY 'peqpass';"
-sudo mariadb -e "CREATE USER IF NOT EXISTS 'peq'@'127.0.0.1' IDENTIFIED BY 'peqpass';"
-sudo mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'peq'@'127.0.0.1';"
ifeq (,$(wildcard base/db/db.sql.zip))
@echo "base/db.sql.zip not found. Downloading latest from https://db.projecteq.net/"
wget -nc https://db.projecteq.net/latest -O base/db/db.sql.zip
-cd base/db && unzip db.sql.zip
ifeq (,$(wildcard .devcontainer/cache/db/db.sql.zip))
@echo ".devcontainer/cache/db.sql.zip not found. Downloading database from https://db.eqemu.dev/latest"
wget -nc https://db.eqemu.dev/latest -O .devcontainer/cache/db/db.sql.zip
-cd .devcontainer/cache/db && unzip db.sql.zip
endif
@echo "Sourcing db may take a while, please wait..."
@cd base/db/peq-dump && sudo mariadb --database peq -e "source create_all_tables.sql"
@cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_content.sql"
@cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_login.sql"
@cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_player.sql"
@# deprecated cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_queryserv.sql"
@cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_state.sql"
@cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_system.sql"
@echo "MariaDB is now injected."
.PHONY: gm-%
gm-%:
gm-%: is-vscode
sudo mariadb --database peq -e "UPDATE account SET status=255 WHERE name = '$*';"
@echo "Account $* is now a GM. /camp to have it go into effect."
depends:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile depends --no-print-directory
exit
endif
depends: is-vscode
sudo apt install graphviz pip time
pip3 install graphviz
mkdir -p build/depends
@ -241,44 +175,54 @@ endif
@echo "Common..."
time python3 build/depends/dependency_graph.py -f png common build/depends/common.dot
backup:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile backup --no-print-directory
exit
endif
backup: is-vscode
@mkdir -p build/bin/backup
cd build/bin && ./world database:dump --compress --player-tables --state-tables --system-tables --query-serv-tables
cpu-zone:
restore-%: is-vscode
@if [ -z "$*" ]; then \
echo "Please provide a backup file to restore from. Example: make restore-backup.sql"; \
exit 1; \
fi
@echo "Restoring from backup $*"
@sudo mariadb --database peq -e "$*"
cpu-zone: is-vscode
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile cpu-zone --no-print-directory
@echo "This makefile is not intended to be run from the .devcontainer directory."
exit
endif
@cd build/bin && mkdir -p tmp
cd build/bin && CPUPROFILE=prof.out ./zone
pprof-zone:
pprof-zone: is-vscode
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-zone --no-print-directory
@echo "This makefile is not intended to be run from the .devcontainer directory."
exit
endif
cd build/bin && google-pprof --pdf zone prof.out > prof.pdf
pprof-web-zone:
pprof-gv-zone: is-vscode
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-web-zone --no-print-directory
exit
endif
cd build/bin && google-pprof --web zone prof.out
pprof-gv-zone:
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile pprof-gv-zone --no-print-directory
@echo "This makefile is not intended to be run from the .devcontainer directory."
exit
endif
cd build/bin && google-pprof --gv zone prof.out > prof.gv
heap-zone:
heap-zone: is-vscode
ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer)
@make -C ../ -f .devcontainer/Makefile heap-zone --no-print-directory
@echo "This makefile is not intended to be run from the .devcontainer directory."
exit
endif
@cd build/bin && mkdir -p tmp
cd build/bin && HEAPPROFILE=prof.out ./zone
.PHONY: pull
pull:
git pull
@if [ ! -d "quests" ]; then git clone https://github.com/rebuildeq/quests.git quests; fi
cd quests && git pull
@if [ ! -d "eqemu-definitions" ]; then git clone https://github.com/xackery/eqemu-definitions.git eqemu-definitions; fi
cd eqemu-definitions && git pull

View File

@ -40,10 +40,41 @@
"GitHub.copilot",
"xackery.make-magic",
"Gruntfuggly.todo-tree",
"ms-vscode.cmake-tools"
]
"ms-vscode.cmake-tools",
"sumneko.lua"
],
"settings": {
"Lua.runtime.version": "Lua 5.1",
"Lua.workspace.library": [
"/src/repo/eqemu-definitions"
],
"Lua.diagnostics.disable": [
"lowercase-global"
],
"cmake.statusbar.advanced": {
"kit": {
"visibility": "hidden"
},
"debug": {
"visibility": "hidden"
},
"buildTarget": {
"visibility": "compact"
},
"launch": {
"visibility": "hidden"
},
"ctest": {
"visibility": "icon"
}
}
}
}
},
"mounts": [
"source=${localWorkspaceFolder}/.devcontainer/Makefile,target=/src/Makefile,type=bind,consistency=cached"
],
"workspaceFolder": "/src",
"workspaceMount": "source=${localWorkspaceFolder},target=/src,type=bind,consistency=cached"
}

View File

@ -1,98 +0,0 @@
---
kind: pipeline
type: docker
name: Build Linux
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency:
limit: 1
volumes:
- name: cache
host:
path: /var/lib/cache-release
steps:
- name: Build Linux X64
image: akkadius/eqemu-server:v14
environment:
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
commands:
- ./utils/scripts/build/linux-build.sh
volumes:
- name: cache
path: /home/eqemu/.ccache/
---
kind: pipeline
type: exec
name: Build Windows
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
concurrency:
limit: 1
platform:
os: windows
arch: amd64
steps:
- name: Build Windows X64
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- .\utils\scripts\build\windows-build.ps1
---
kind: pipeline
type: docker
name: Publish Artifacts to Github
steps:
- name: Upload Artifacts
image: akkadius/eqemu-build-releaser:v3
environment:
RCLONE_CONFIG_REMOTE_TYPE: ftp
RCLONE_FTP_HOST: drone.akkadius.com
RCLONE_FTP_USER: artifacts
RCLONE_FTP_PASS:
from_secret: RCLONE_FTP_PASS
GH_RELEASE_GITHUB_API_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN
commands:
- ./utils/scripts/build/should-release/should-release
- rclone config create remote ftp env_auth true > /dev/null
- |
rclone copy remote: --include "eqemu-server*.zip" .
- gh-release --assets=eqemu-server-linux-x64.zip,eqemu-server-windows-x64.zip -y
- |
rclone delete remote: --include "eqemu-server*.zip"
trigger:
branch:
- master
event:
- push
depends_on:
- Build Windows
- Build Linux

81
.github/workflows/build.yaml vendored Normal file
View File

@ -0,0 +1,81 @@
name: Build
on:
push:
branches:
- master
pull_request:
jobs:
linux:
name: Linux
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v5
with:
submodules: recursive
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-ccache
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential ninja-build ccache libmariadb-dev libmariadb-dev-compat libboost-all-dev libperl-dev liblua5.1-0-dev libluajit-5.1-dev zlib1g-dev uuid-dev libssl-dev libsodium-dev libmbedtls-dev
- name: Configure
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DEQEMU_BUILD_TESTS=ON \
-DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_LUA=ON \
-DEQEMU_BUILD_PERL=ON \
-DEQEMU_BUILD_CLIENT_FILES=ON
- name: Build
run: cmake --build build --parallel
- name: Test
working-directory: build
run: ./bin/tests
windows:
name: Windows
runs-on: windows-latest
steps:
- name: Checkout source
uses: actions/checkout@v5
with:
submodules: recursive
- name: Enable long paths
run: git config --global core.longpaths true
- name: Setup MSVC environment
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Configure
shell: pwsh
run: |
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 `
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
-DEQEMU_BUILD_TESTS=ON `
-DEQEMU_BUILD_LOGIN=ON `
-DEQEMU_BUILD_LUA=ON `
-DEQEMU_BUILD_ZLIB=ON `
-DEQEMU_BUILD_CLIENT_FILES=ON
- name: Build
shell: pwsh
run: cmake --build build --config RelWithDebInfo --target ALL_BUILD -- /m
- name: Test
working-directory: build
run: ./bin/RelWithDebInfo/tests.exe

25
.vscode/settings.json vendored
View File

@ -21,14 +21,6 @@
"${workspaceFolder}/dependencies/zlibng"
],
"telemetry.enableTelemetry": false,
"cmake.buildDirectory": "${workspaceFolder}/build",
"cmake.configureArgs": [
"-DEQEMU_BUILD_LOGIN=ON",
"-DEQEMU_BUILD_TESTS=ON",
"-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",
"-DEQEMU_ADD_PROFILER=ON",
"Ninja"
],
"cmake.skipConfigureIfCachePresent": true,
"cmake.configureOnOpen": false,
"files.associations": {
@ -115,22 +107,5 @@
"format": "cpp",
"ranges": "cpp",
"span": "cpp"
},
"cmake.statusbar.advanced": {
"kit": {
"visibility": "hidden",
},
"debug": {
"visibility": "hidden",
},
"buildTarget": {
"visibility": "hidden",
},
"launch": {
"visibility": "hidden",
},
"ctest": {
"visibility": "icon",
}
}
}

View File

@ -1,3 +1,90 @@
## [23.10.3] 9/16/2025
### Hotfix
* Hotfix crashes occurring in #4987. @Akkadius 2025-09-17
## [23.10.2] 9/16/2025
### Hotfix
* Revert #4996 as it was causing critical issues with spells that needs to be further investigated. @Akkadius 2025-09-17
## [23.10.1] 9/16/2025
### Hotfix
* Fixed Mail Key Bug ([#5015](https://github.com/EQEmu/Server/pull/5015)) @Kinglykrab 2025-09-16
## [23.10.0] 9/15/2025
### Build
* Fix Linking with GCC ([#4969](https://github.com/EQEmu/Server/pull/4969)) @solar984 2025-08-03
### Code
* Add #npcedit npc_tint_id Help Message ([#4982](https://github.com/EQEmu/Server/pull/4982)) @Kinglykrab 2025-08-17
* Cleanup #show ip_lookup Message ([#5005](https://github.com/EQEmu/Server/pull/5005)) @Kinglykrab 2025-08-30
* Fix #set race 0 Message ([#5004](https://github.com/EQEmu/Server/pull/5004)) @Kinglykrab 2025-08-30
* Fix Issues with Strings::Commify and Mob::SendStatsWindow ([#4984](https://github.com/EQEmu/Server/pull/4984)) @Kinglykrab 2025-08-17
* Remove Attributions ([#4988](https://github.com/EQEmu/Server/pull/4988)) @KimLS 2025-08-16
* Remove Unused errorname Variable ([#5001](https://github.com/EQEmu/Server/pull/5001)) @Kinglykrab 2025-08-29
### Commands
* Add #find account Subcommand ([#4981](https://github.com/EQEmu/Server/pull/4981)) @Kinglykrab 2025-08-17
* Add #show keyring Subcommand ([#4973](https://github.com/EQEmu/Server/pull/4973)) @Kinglykrab 2025-08-03
* Add #task complete Saylink to #task show ([#4985](https://github.com/EQEmu/Server/pull/4985)) @Kinglykrab 2025-08-17
### Constants
* Change Race Changes to Race Namespace ([#5000](https://github.com/EQEmu/Server/pull/5000)) @Kinglykrab 2025-08-30
* Convert SE Defines to SpellEffect Namespace ([#4999](https://github.com/EQEmu/Server/pull/4999)) @Kinglykrab 2025-08-30
### Database
* Add `heal_amount` to `character_stats_record` ([#4986](https://github.com/EQEmu/Server/pull/4986)) @Kinglykrab 2025-08-17
### Fixes
* Fix #show recipe uint16 Cap ([#4978](https://github.com/EQEmu/Server/pull/4978)) @Kinglykrab 2025-08-11
* Fix Race 474 for Titanium ([#4979](https://github.com/EQEmu/Server/pull/4979)) @regneq 2025-08-11
* Fix Recipe Inspect Bug ([#4994](https://github.com/EQEmu/Server/pull/4994)) @Kinglykrab 2025-08-30
* Fix Several Evolving Item Bugs ([#4992](https://github.com/EQEmu/Server/pull/4992)) @neckkola 2025-09-08
* Fix Task Reloading ([#5002](https://github.com/EQEmu/Server/pull/5002)) @Kinglykrab 2025-08-29
### Loginserver
* Fix Legacy World When Using Local DB ([#4970](https://github.com/EQEmu/Server/pull/4970)) @solar984 2025-08-03
### Pets
* Add Pet Constants and Methods ([#4987](https://github.com/EQEmu/Server/pull/4987)) @Kinglykrab 2025-08-17
### Quest API
* Add EVENT_CHARM_START and EVENT_CHARM_END ([#5013](https://github.com/EQEmu/Server/pull/5013)) @Kinglykrab 2025-09-15
* Add GetKeyRing() to Perl/Lua ([#4980](https://github.com/EQEmu/Server/pull/4980)) @Kinglykrab 2025-08-17
* Add GetNPCTintIndex() to Perl/Lua ([#4983](https://github.com/EQEmu/Server/pull/4983)) @Kinglykrab 2025-08-17
* Add GetTimers() and GetPausedTimers() to Perl/Lua ([#4965](https://github.com/EQEmu/Server/pull/4965)) @Kinglykrab 2025-08-03
* Add Identifiers to Get/Modify NPC Stat Methods ([#5012](https://github.com/EQEmu/Server/pull/5012)) @Kinglykrab 2025-09-15
### Repositories
* Convert Character Inspect Messages to Repositories ([#4997](https://github.com/EQEmu/Server/pull/4997)) @Kinglykrab 2025-08-30
* Convert Damage Shield Types to Repositories ([#4995](https://github.com/EQEmu/Server/pull/4995)) @Kinglykrab 2025-08-30
* Convert Item Loading to Repositories ([#4998](https://github.com/EQEmu/Server/pull/4998)) @Kinglykrab 2025-08-30
* Convert Mail Key to Repositories ([#5007](https://github.com/EQEmu/Server/pull/5007)) @Kinglykrab 2025-09-15
* Convert Shared Bank Platinum to Repositories ([#5006](https://github.com/EQEmu/Server/pull/5006)) @Kinglykrab 2025-09-02
* Convert Spell Loading to Repositories ([#4996](https://github.com/EQEmu/Server/pull/4996)) @Kinglykrab 2025-08-30
* Convert Total Time Played to Repositories ([#5008](https://github.com/EQEmu/Server/pull/5008)) @Kinglykrab 2025-09-15
## [23.9.1] 8/2/2025
### Hotfix
* Fix Quest Ownership Edge Case ([#4977](https://github.com/EQEmu/Server/pull/4977)) @Kinglykrab 2025-08-02
## [23.9.0] 8/2/2025
### Bots

49
CMakePresets.json Normal file
View File

@ -0,0 +1,49 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 19,
"patch": 0
},
"configurePresets": [
{
"name": "linux-debug",
"displayName": "Linux Debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_C_COMPILER_LAUNCHER": "ccache",
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
"EQEMU_BUILD_LOGIN": "ON",
"EQEMU_BUILD_TESTS": "ON",
"EQEMU_ADD_PROFILER": "ON"
}
},
{
"name": "linux-release",
"displayName": "Linux Release",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_C_COMPILER_LAUNCHER": "ccache",
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
"EQEMU_BUILD_LOGIN": "ON"
}
},
{
"name": "win-msvc",
"displayName": "Windows MSVC (VS 2022)",
"generator": "Visual Studio 17 2022",
"binaryDir": "${sourceDir}/build/{presetName}",
"architecture": { "value": "x64" },
"cacheVariables": {
"CMAKE_CONFIGURATION_TYPES": "Debug;Release",
"EQEMU_BUILD_LOGIN": "ON",
"EQEMU_BUILD_TESTS": "ON"
}
}
]
}

View File

@ -35,60 +35,55 @@ ENDIF()
IF(EQEMU_FETCH_MSVC_DEPENDENCIES_VCPKG)
MESSAGE(STATUS "Resolving vcpkg dependencies...")
IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP})
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/vcpkg)
MESSAGE(STATUS "Downloading existing vcpkg dependencies from releases...")
FILE(DOWNLOAD ${EQEMU_VCPKG_URL} ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP}
FILE(DOWNLOAD ${EQEMU_VCPKG_URL} ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP}
SHOW_PROGRESS
STATUS DOWNLOAD_STATUS)
LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE)
IF(NOT STATUS_CODE EQUAL 0)
MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_VCPKG_URL}")
ENDIF()
MESSAGE(STATUS "Extracting files...")
EXECUTE_PROCESS(
COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/vcpkg
)
ENDIF()
INCLUDE(${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake)
ENDIF()
IF(EQEMU_FETCH_MSVC_DEPENDENCIES_PERL)
#Try to find perl first, (so you can use your active install first)
FIND_PACKAGE(PerlLibs)
IF(NOT PerlLibs_FOUND)
MESSAGE(STATUS "Resolving perl dependencies...")
IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP})
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR})
MESSAGE(STATUS "Downloading portable perl...")
FILE(DOWNLOAD ${EQEMU_PERL_URL} ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP}
SHOW_PROGRESS
STATUS DOWNLOAD_STATUS)
LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE)
IF(NOT STATUS_CODE EQUAL 0)
MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_PERL_URL}")
ENDIF()
MESSAGE(STATUS "Extracting files...")
EXECUTE_PROCESS(
COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}
)
MESSAGE(STATUS "Resolving perl dependencies...")
IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP})
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR})
MESSAGE(STATUS "Downloading portable perl...")
FILE(DOWNLOAD ${EQEMU_PERL_URL} ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP}
SHOW_PROGRESS
STATUS DOWNLOAD_STATUS)
LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE)
IF(NOT STATUS_CODE EQUAL 0)
MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_PERL_URL}")
ENDIF()
SET(PERL_EXECUTABLE ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/bin/perl.exe CACHE FILEPATH "Path to perl program" FORCE)
SET(PERL_INCLUDE_PATH ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE CACHE PATH "Path to perl include files" FORCE)
SET(PERL_LIBRARY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE/libperl524.a CACHE FILEPATH "Path to perl library" FORCE)
MESSAGE(STATUS "Extracting files...")
EXECUTE_PROCESS(
COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}
)
ENDIF()
ENDIF()
SET(PERL_EXECUTABLE ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/bin/perl.exe CACHE FILEPATH "Path to perl program" FORCE)
SET(PERL_INCLUDE_PATH ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE CACHE PATH "Path to perl include files" FORCE)
SET(PERL_LIBRARY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE/libperl524.a CACHE FILEPATH "Path to perl library" FORCE)
ENDIF()

View File

@ -104,9 +104,9 @@ SET(common_sources
net/console_server.cpp
net/console_server_connection.cpp
net/crc32.cpp
net/daybreak_connection.cpp
net/eqstream.cpp
net/packet.cpp
net/reliable_stream_connection.cpp
net/servertalk_client_connection.cpp
net/servertalk_legacy_client_connection.cpp
net/servertalk_server.cpp
@ -603,7 +603,6 @@ SET(common_headers
ipc_mutex.h
ip_util.h
item_data.h
item_fieldlist.h
item_instance.h
json_config.h
light_source.h
@ -671,13 +670,13 @@ SET(common_headers
net/console_server.h
net/console_server_connection.h
net/crc32.h
net/daybreak_connection.h
net/daybreak_pooling.h
net/daybreak_structs.h
net/dns.h
net/endian.h
net/eqstream.h
net/packet.h
net/reliable_stream_connection.h
net/reliable_stream_pooling.h
net/reliable_stream_structs.h
net/servertalk_client_connection.h
net/servertalk_legacy_client_connection.h
net/servertalk_common.h
@ -743,10 +742,6 @@ SOURCE_GROUP(Net FILES
net/console_server_connection.h
net/crc32.cpp
net/crc32.h
net/daybreak_connection.cpp
net/daybreak_connection.h
net/daybreak_pooling.h
net/daybreak_structs.h
net/dns.h
net/endian.h
net/eqmq.cpp
@ -755,6 +750,10 @@ SOURCE_GROUP(Net FILES
net/eqstream.h
net/packet.cpp
net/packet.h
net/reliable_stream_connection.cpp
net/reliable_stream_connection.h
net/reliable_stream_pooling.h
net/reliable_stream_structs.h
net/servertalk_client_connection.cpp
net/servertalk_client_connection.h
net/servertalk_legacy_client_connection.cpp
@ -843,6 +842,11 @@ ENDIF (UNIX)
IF (EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/std-pch.h)
# Avoid PCH/__OPTIMIZE__ mismatch when compiling certain patch sources with -O0
# These files are compiled with -O0 on UNIX (see COMPILE_FLAGS above), which
# disables the __OPTIMIZE__ predefined macro. Disabling PCH for them prevents
# Clang from erroring due to macro state differences between the PCH and TU.
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
ENDIF ()
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

View File

@ -23,7 +23,7 @@ void SendCrashReport(const std::string &crash_report)
{
// can configure multiple endpoints if need be
std::vector<std::string> endpoints = {
"https://spire.akkadius.com/api/v1/analytics/server-crash-report",
"https://spire.eqemu.dev/api/v1/analytics/server-crash-report",
// "http://localhost:3010/api/v1/analytics/server-crash-report", // development
};

View File

@ -7160,7 +7160,32 @@ ALTER TABLE loottable_entries
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9327,
.description = "2025_08_13_character_stats_record_heal_amount.sql",
.check = "SHOW COLUMNS FROM `character_stats_record` LIKE 'heal_amount'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `character_stats_record`
ADD COLUMN `heal_amount` int(11) NULL DEFAULT 0 AFTER `spell_damage`;
)"
},
ManifestEntry{
.version = 9328,
.description = "2025_08_22_character_parcel_updates.sql",
.check = "SHOW COLUMNS FROM `character_parcels` LIKE 'evolve_amount'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `character_parcels`
ADD COLUMN `evolve_amount` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `quantity`;
ALTER TABLE `character_parcels_containers`
ADD COLUMN `evolve_amount` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `quantity`;
)",
.content_schema_update = false
},
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
// .version = 9228,

View File

@ -451,3 +451,23 @@ bool LDoNTheme::IsValid(uint32 theme_id)
{
return ldon_theme_names.find(theme_id) != ldon_theme_names.end();
}
std::string PetCommand::GetName(uint8 pet_command)
{
return IsValid(pet_command) ? pet_commands[pet_command] : "UNKNOWN PET COMMAND";
}
bool PetCommand::IsValid(uint8 pet_command)
{
return pet_commands.find(pet_command) != pet_commands.end();
}
std::string PetType::GetName(uint8 pet_type)
{
return IsValid(pet_type) ? pet_types[pet_type] : "UNKNOWN PET TYPE";
}
bool PetType::IsValid(uint8 pet_type)
{
return pet_types.find(pet_type) != pet_types.end();
}

View File

@ -792,4 +792,131 @@ namespace BookType {
constexpr uint8 ItemInfo = 2;
}
namespace PetButton {
constexpr uint8 Sit = 0;
constexpr uint8 Stop = 1;
constexpr uint8 Regroup = 2;
constexpr uint8 Follow = 3;
constexpr uint8 Guard = 4;
constexpr uint8 Taunt = 5;
constexpr uint8 Hold = 6;
constexpr uint8 GreaterHold = 7;
constexpr uint8 Focus = 8;
constexpr uint8 SpellHold = 9;
}
namespace PetButtonState {
constexpr uint8 Off = 0;
constexpr uint8 On = 1;
}
namespace PetCommand {
constexpr uint8 HealthReport = 0; // /pet health or Pet Window
constexpr uint8 Leader = 1; // /pet leader or Pet Window
constexpr uint8 Attack = 2; // /pet attack or Pet Window
constexpr uint8 QAttack = 3; // /pet qattack or Pet Window
constexpr uint8 FollowMe = 4; // /pet follow or Pet Window
constexpr uint8 GuardHere = 5; // /pet guard or Pet Window
constexpr uint8 Sit = 6; // /pet sit or Pet Window
constexpr uint8 SitDown = 7; // /pet sit on
constexpr uint8 StandUp = 8; // /pet sit off
constexpr uint8 Stop = 9; // /pet stop or Pet Window - Not implemented
constexpr uint8 StopOn = 10; // /pet stop on - Not implemented
constexpr uint8 StopOff = 11; // /pet stop off - Not implemented
constexpr uint8 Taunt = 12; // /pet taunt or Pet Window
constexpr uint8 TauntOn = 13; // /pet taunt on
constexpr uint8 TauntOff = 14; // /pet taunt off
constexpr uint8 Hold = 15; // /pet hold or Pet Window, won't add to hate list unless attacking
constexpr uint8 HoldOn = 16; // /pet hold on
constexpr uint8 HoldOff = 17; // /pet hold off
constexpr uint8 GreaterHold = 18; // /pet ghold, will never add to hate list unless told to
constexpr uint8 GreaterHoldOn = 19; // /pet ghold on
constexpr uint8 GreaterHoldOff = 20; // /pet ghold off
constexpr uint8 SpellHold = 21; // /pet no cast or /pet spellhold or Pet Window
constexpr uint8 SpellHoldOn = 22; // /pet spellhold on
constexpr uint8 SpellHoldOff = 23; // /pet spellhold off
constexpr uint8 Focus = 24; // /pet focus or Pet Window
constexpr uint8 FocusOn = 25; // /pet focus on
constexpr uint8 FocusOff = 26; // /pet focus off
constexpr uint8 Feign = 27; // /pet feign
constexpr uint8 BackOff = 28; // /pet back off
constexpr uint8 GetLost = 29; // /pet get lost
constexpr uint8 GuardMe = 30; // Same as /pet follow, but different message in older clients
constexpr uint8 Regroup = 31; // /pet regroup, acts like classic hold
constexpr uint8 RegroupOn = 32; // /pet regroup on
constexpr uint8 RegroupOff = 33; // /pet regroup off
constexpr uint8 Max = 34;
static std::map<uint8, std::string> pet_commands = {
{ PetCommand::HealthReport, "Health Report" },
{ PetCommand::Leader, "Leader" },
{ PetCommand::Attack, "Attack" },
{ PetCommand::QAttack, "QAttack" },
{ PetCommand::FollowMe, "Follow Me" },
{ PetCommand::GuardHere, "Guard Here" },
{ PetCommand::Sit, "Sit" },
{ PetCommand::SitDown, "Sit Down" },
{ PetCommand::StandUp, "Stand Up" },
{ PetCommand::Stop, "Stop" },
{ PetCommand::StopOn, "Stop On" },
{ PetCommand::StopOff, "Stop Off" },
{ PetCommand::Taunt, "Taunt" },
{ PetCommand::TauntOn, "Taunt On" },
{ PetCommand::TauntOff, "Taunt Off" },
{ PetCommand::Hold, "Hold" },
{ PetCommand::HoldOn, "Hold On" },
{ PetCommand::HoldOff, "Hold Off" },
{ PetCommand::GreaterHold, "Greater Hold" },
{ PetCommand::GreaterHoldOn, "Greater Hold On" },
{ PetCommand::GreaterHoldOff, "Greater Hold Off" },
{ PetCommand::SpellHold, "Spell Hold" },
{ PetCommand::SpellHoldOn, "Spell Hold On" },
{ PetCommand::SpellHoldOff, "Spell Hold Off" },
{ PetCommand::Focus, "Focus" },
{ PetCommand::FocusOn, "Focus On" },
{ PetCommand::FocusOff, "Focus Off" },
{ PetCommand::Feign, "Feign" },
{ PetCommand::BackOff, "Back Off" },
{ PetCommand::GetLost, "Get Lost" },
{ PetCommand::GuardMe, "Guard Me" },
{ PetCommand::Regroup, "Regroup" },
{ PetCommand::RegroupOn, "Regroup On" },
{ PetCommand::RegroupOff, "Regroup Off" },
{ PetCommand::Max, "Max" }
};
std::string GetName(uint8 pet_command);
bool IsValid(uint8 pet_command);
}
namespace PetOrder {
constexpr uint8 Follow = 0;
constexpr uint8 Sit = 1;
constexpr uint8 Guard = 2;
constexpr uint8 Feign = 3;
}
namespace PetType {
constexpr uint8 Familiar = 0;
constexpr uint8 Animation = 1;
constexpr uint8 Normal = 2;
constexpr uint8 Charmed = 3;
constexpr uint8 Follow = 4;
constexpr uint8 TargetLock = 5;
constexpr uint8 None = 255;
static std::map<uint8, std::string> pet_types = {
{ PetType::Familiar, "Familiar" },
{ PetType::Animation, "Animation" },
{ PetType::Normal, "Normal" },
{ PetType::Charmed, "Charmed" },
{ PetType::Follow, "Follow" },
{ PetType::TargetLock, "Target Lock" },
{ PetType::None, "None" }
};
std::string GetName(uint8 pet_type);
bool IsValid(uint8 pet_type);
}
#endif /*COMMON_EMU_CONSTANTS_H*/

View File

@ -6,7 +6,7 @@
#include <string>
#include "emu_versions.h"
#include "eq_packet.h"
#include "net/daybreak_connection.h"
#include "net/reliable_stream_connection.h"
typedef enum {
ESTABLISHED,
@ -33,18 +33,18 @@ struct EQStreamManagerInterfaceOptions
//Login I had trouble getting to recognize compression at all
//but that might be because it was still a bit buggy when i was testing that.
if (compressed) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression;
reliable_stream_options.encode_passes[0] = EQ::Net::EncodeCompression;
}
else if (encoded) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeXOR;
reliable_stream_options.encode_passes[0] = EQ::Net::EncodeXOR;
}
daybreak_options.port = port;
reliable_stream_options.port = port;
}
int opcode_size;
bool track_opcode_stats;
EQ::Net::DaybreakConnectionManagerOptions daybreak_options;
EQ::Net::ReliableStreamConnectionManagerOptions reliable_stream_options;
};
class EQStreamManagerInterface
@ -80,7 +80,7 @@ public:
struct Stats
{
EQ::Net::DaybreakConnectionStats DaybreakStats;
EQ::Net::ReliableStreamConnectionStats ReliableStreamStats;
int RecvCount[_maxEmuOpcode];
int SentCount[_maxEmuOpcode];
};

View File

@ -74,6 +74,10 @@ void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_
e.item_id = inst.GetID();
e.equipped = inst.GetEvolveEquipped();
e.final_item_id = EvolvingItemsManager::Instance()->GetFinalItemID(inst);
if (inst.GetEvolveCurrentAmount() > 0) {
e.current_amount = inst.GetEvolveCurrentAmount();
inst.CalculateEvolveProgression();
}
auto r = CharacterEvolvingItemsRepository::InsertOne(*m_db, e);
e.id = r.id;

View File

@ -95,12 +95,12 @@ bool IsOfEqualRace(int r1, int r2)
}
// TODO: add more values
switch (r1) {
case DARK_ELF:
case Race::DarkElf:
if (r2 == Race::NeriakCitizen) {
return true;
}
break;
case BARBARIAN:
case Race::Barbarian:
if (r2 == Race::HalasCitizen) {
return true;
}
@ -116,49 +116,49 @@ bool IsOfIndiffRace(int r1, int r2)
}
// TODO: add more values
switch (r1) {
case DARK_ELF:
case OGRE:
case TROLL:
if (r2 == OGRE || r2 == TROLL || r2 == DARK_ELF) {
case Race::DarkElf:
case Race::Ogre:
case Race::Troll:
if (r2 == Race::Ogre || r2 == Race::Troll || r2 == Race::DarkElf) {
return true;
}
break;
case HUMAN:
case BARBARIAN:
case HALF_ELF:
case GNOME:
case HALFLING:
case WOOD_ELF:
if (r2 == HUMAN ||
r2 == BARBARIAN ||
r2 == ERUDITE ||
r2 == HALF_ELF ||
r2 == GNOME ||
r2 == HALFLING ||
r2 == DWARF ||
r2 == HIGH_ELF ||
r2 == WOOD_ELF) {
case Race::Human:
case Race::Barbarian:
case Race::HalfElf:
case Race::Gnome:
case Race::Halfling:
case Race::WoodElf:
if (r2 == Race::Human ||
r2 == Race::Barbarian ||
r2 == Race::Erudite ||
r2 == Race::HalfElf ||
r2 == Race::Gnome ||
r2 == Race::Halfling ||
r2 == Race::Dwarf ||
r2 == Race::HighElf ||
r2 == Race::WoodElf) {
return true;
}
break;
case ERUDITE:
if (r2 == HUMAN || r2 == HALF_ELF) {
case Race::Erudite:
if (r2 == Race::Human || r2 == Race::HalfElf) {
return true;
}
break;
case DWARF:
if (r2 == HALFLING || r2 == GNOME) {
case Race::Dwarf:
if (r2 == Race::Halfling || r2 == Race::Gnome) {
return true;
}
break;
case HIGH_ELF:
if (r2 == WOOD_ELF) {
case Race::HighElf:
if (r2 == Race::WoodElf) {
return true;
}
break;
case VAHSHIR:
case Race::VahShir:
return true;
case IKSAR:
case Race::Iksar:
return false;
}
return false;

View File

@ -438,7 +438,7 @@ namespace EQ
//uint32 Unk054 {};
int16 MaxCharges {}; // Maximum charges items can hold: -1 if not a chargeable item
uint8 ItemType {}; // Item Type/Skill (itemClass* from above)
int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass)
int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SpellEffect::FFItemClass)
uint8 Material {}; // Item material type
uint32 HerosForgeModel {};// Hero's Forge Armor Model Type (2-13?)
float SellRate {}; // Sell rate

View File

@ -1,206 +0,0 @@
/*
These fields must be in the order of how they are serialized!
*/
F(itemclass)
F(name)
F(lore)
F(idfile)
F(id)
F(weight)
F(norent)
F(nodrop)
F(size)
F(slots)
F(price)
F(icon)
F(UNK012)
F(UNK013)
F(benefitflag)
F(tradeskills)
F(cr)
F(dr)
F(pr)
F(mr)
F(fr)
F(astr)
F(asta)
F(aagi)
F(adex)
F(acha)
F(aint)
F(awis)
F(hp)
F(mana)
F(ac)
F(deity)
F(skillmodvalue)
F(UNK033)
F(skillmodmax)
F(skillmodtype)
F(banedmgrace)
F(banedmgamt)
F(banedmgbody)
F(magic)
F(casttime_)
F(reqlevel)
F(bardtype)
F(bardvalue)
F(light)
F(delay)
F(reclevel)
F(recskill)
F(elemdmgtype)
F(elemdmgamt)
F(range)
F(damage)
F(color)
F(classes)
F(races)
F(UNK054)
F(maxcharges)
F(itemtype)
F(material)
F(herosforgemodel)
F(sellrate)
F(UNK059)
F(casttime)
F(elitematerial)
F(procrate)
F(combateffects)
F(shielding)
F(stunresist)
F(strikethrough)
F(extradmgskill)
F(extradmgamt)
F(spellshield)
F(avoidance)
F(accuracy)
F(charmfileid)
F(factionmod1)
F(factionmod2)
F(factionmod3)
F(factionmod4)
F(factionamt1)
F(factionamt2)
F(factionamt3)
F(factionamt4)
F(charmfile)
F(augtype)
F(augslot1type)
F(augslot1visible)
F(augslot2type)
F(augslot2visible)
F(augslot3type)
F(augslot3visible)
F(augslot4type)
F(augslot4visible)
F(augslot5type)
F(augslot5visible)
F(augslot6type)
F(augslot6visible)
F(ldontheme)
F(ldonprice)
F(ldonsold)
F(bagtype)
F(bagslots)
F(bagsize)
F(bagwr)
F(book)
F(booktype)
F(filename)
F(banedmgraceamt)
F(augrestrict)
F(loregroup)
F(pendingloreflag)
F(artifactflag)
F(summonedflag)
F(favor)
F(fvnodrop)
F(endur)
F(dotshielding)
F(attack)
F(regen)
F(manaregen)
F(enduranceregen)
F(haste)
F(damageshield)
F(recastdelay)
F(recasttype)
F(guildfavor)
F(augdistiller)
F(UNK123)
F(UNK124)
F(attuneable)
F(nopet)
F(UNK127)
F(pointtype)
F(potionbelt)
F(potionbeltslots)
F(stacksize)
F(notransfer)
F(stackable)
F(UNK134)
F(clickeffect)
F(clicktype)
F(clicklevel)
F(clicklevel2)
F(proceffect)
F(proctype)
F(proclevel)
F(proclevel2)
F(worneffect)
F(worntype)
F(wornlevel)
F(wornlevel2)
F(focuseffect)
F(focustype)
F(focuslevel)
F(focuslevel2)
F(scrolleffect)
F(scrolltype)
F(scrolllevel)
F(scrolllevel2)
F(bardeffect)
F(bardeffecttype)
F(bardlevel2)
F(bardlevel)
F(questitemflag)
F(svcorruption)
F(purity)
F(evoitem)
F(evoid)
F(evolvinglevel)
F(evomax)
F(backstabdmg)
F(dsmitigation)
F(heroic_str)
F(heroic_int)
F(heroic_wis)
F(heroic_agi)
F(heroic_dex)
F(heroic_sta)
F(heroic_cha)
F(heroic_mr)
F(heroic_fr)
F(heroic_cr)
F(heroic_dr)
F(heroic_pr)
F(heroic_svcorrup)
F(healamt)
F(spelldmg)
F(ldonsellbackrate)
F(scriptfileid)
F(expendablearrow)
F(clairvoyance)
F(clickname)
F(procname)
F(wornname)
F(focusname)
F(scrollname)
F(subtype)

View File

@ -1,11 +1,11 @@
#include "eqstream.h"
#include "../eqemu_logsys.h"
EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_daybreak(options.daybreak_options)
EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_reliable_stream(options.reliable_stream_options)
{
m_daybreak.OnNewConnection(std::bind(&EQStreamManager::DaybreakNewConnection, this, std::placeholders::_1));
m_daybreak.OnConnectionStateChange(std::bind(&EQStreamManager::DaybreakConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_daybreak.OnPacketRecv(std::bind(&EQStreamManager::DaybreakPacketRecv, this, std::placeholders::_1, std::placeholders::_2));
m_reliable_stream.OnNewConnection(std::bind(&EQStreamManager::ReliableStreamNewConnection, this, std::placeholders::_1));
m_reliable_stream.OnConnectionStateChange(std::bind(&EQStreamManager::ReliableStreamConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_reliable_stream.OnPacketRecv(std::bind(&EQStreamManager::ReliableStreamPacketRecv, this, std::placeholders::_1, std::placeholders::_2));
}
EQ::Net::EQStreamManager::~EQStreamManager()
@ -15,11 +15,11 @@ EQ::Net::EQStreamManager::~EQStreamManager()
void EQ::Net::EQStreamManager::SetOptions(const EQStreamManagerInterfaceOptions &options)
{
m_options = options;
auto &opts = m_daybreak.GetOptions();
opts = options.daybreak_options;
auto &opts = m_reliable_stream.GetOptions();
opts = options.reliable_stream_options;
}
void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection)
void EQ::Net::EQStreamManager::ReliableStreamNewConnection(std::shared_ptr<ReliableStreamConnection> connection)
{
std::shared_ptr<EQStream> stream(new EQStream(this, connection));
m_streams.emplace(std::make_pair(connection, stream));
@ -28,7 +28,7 @@ void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakCon
}
}
void EQ::Net::EQStreamManager::DaybreakConnectionStateChange(std::shared_ptr<DaybreakConnection> connection, DbProtocolStatus from, DbProtocolStatus to)
void EQ::Net::EQStreamManager::ReliableStreamConnectionStateChange(std::shared_ptr<ReliableStreamConnection> connection, DbProtocolStatus from, DbProtocolStatus to)
{
auto iter = m_streams.find(connection);
if (iter != m_streams.end()) {
@ -42,7 +42,7 @@ void EQ::Net::EQStreamManager::DaybreakConnectionStateChange(std::shared_ptr<Day
}
}
void EQ::Net::EQStreamManager::DaybreakPacketRecv(std::shared_ptr<DaybreakConnection> connection, const Packet &p)
void EQ::Net::EQStreamManager::ReliableStreamPacketRecv(std::shared_ptr<ReliableStreamConnection> connection, const Packet &p)
{
auto iter = m_streams.find(connection);
if (iter != m_streams.end()) {
@ -53,7 +53,7 @@ void EQ::Net::EQStreamManager::DaybreakPacketRecv(std::shared_ptr<DaybreakConnec
}
}
EQ::Net::EQStream::EQStream(EQStreamManagerInterface *owner, std::shared_ptr<DaybreakConnection> connection)
EQ::Net::EQStream::EQStream(EQStreamManagerInterface *owner, std::shared_ptr<ReliableStreamConnection> connection)
{
m_owner = owner;
m_connection = connection;
@ -235,7 +235,7 @@ EQStreamState EQ::Net::EQStream::GetState() {
EQ::Net::EQStream::Stats EQ::Net::EQStream::GetStats() const
{
Stats ret;
ret.DaybreakStats = m_connection->GetStats();
ret.ReliableStreamStats = m_connection->GetStats();
for (int i = 0; i < _maxEmuOpcode; ++i) {
ret.RecvCount[i] = 0;

View File

@ -3,7 +3,7 @@
#include "../eq_packet.h"
#include "../eq_stream_intf.h"
#include "../opcodemgr.h"
#include "daybreak_connection.h"
#include "reliable_stream_connection.h"
#include <vector>
#include <deque>
#include <unordered_map>
@ -23,21 +23,21 @@ namespace EQ
void OnNewConnection(std::function<void(std::shared_ptr<EQStream>)> func) { m_on_new_connection = func; }
void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
private:
DaybreakConnectionManager m_daybreak;
ReliableStreamConnectionManager m_reliable_stream;
std::function<void(std::shared_ptr<EQStream>)> m_on_new_connection;
std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
std::map<std::shared_ptr<DaybreakConnection>, std::shared_ptr<EQStream>> m_streams;
std::map<std::shared_ptr<ReliableStreamConnection>, std::shared_ptr<EQStream>> m_streams;
void DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection);
void DaybreakConnectionStateChange(std::shared_ptr<DaybreakConnection> connection, DbProtocolStatus from, DbProtocolStatus to);
void DaybreakPacketRecv(std::shared_ptr<DaybreakConnection> connection, const Packet &p);
void ReliableStreamNewConnection(std::shared_ptr<ReliableStreamConnection> connection);
void ReliableStreamConnectionStateChange(std::shared_ptr<ReliableStreamConnection> connection, DbProtocolStatus from, DbProtocolStatus to);
void ReliableStreamPacketRecv(std::shared_ptr<ReliableStreamConnection> connection, const Packet &p);
friend class EQStream;
};
class EQStream : public EQStreamInterface
{
public:
EQStream(EQStreamManagerInterface *parent, std::shared_ptr<DaybreakConnection> connection);
EQStream(EQStreamManagerInterface *parent, std::shared_ptr<ReliableStreamConnection> connection);
~EQStream();
virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req = true);
@ -67,7 +67,7 @@ namespace EQ
virtual EQStreamManagerInterface* GetManager() const;
private:
EQStreamManagerInterface *m_owner;
std::shared_ptr<DaybreakConnection> m_connection;
std::shared_ptr<ReliableStreamConnection> m_connection;
OpcodeManager **m_opcode_manager;
std::deque<std::unique_ptr<EQ::Net::Packet>> m_packet_queue;
std::unordered_map<int, int> m_packet_recv_count;

View File

@ -1,4 +1,4 @@
#include "daybreak_connection.h"
#include "reliable_stream_connection.h"
#include "../event/event_loop.h"
#include "../data_verification.h"
#include "crc32.h"
@ -12,7 +12,7 @@ constexpr size_t MAX_CLIENT_RECV_BYTES_PER_WINDOW = 140 * 1024;
// buffer pools
SendBufferPool send_buffer_pool;
EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager()
EQ::Net::ReliableStreamConnectionManager::ReliableStreamConnectionManager()
{
m_attached = nullptr;
memset(&m_timer, 0, sizeof(uv_timer_t));
@ -21,7 +21,7 @@ EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager()
Attach(EQ::EventLoop::Get().Handle());
}
EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager(const DaybreakConnectionManagerOptions &opts)
EQ::Net::ReliableStreamConnectionManager::ReliableStreamConnectionManager(const ReliableStreamConnectionManagerOptions &opts)
{
m_attached = nullptr;
m_options = opts;
@ -31,12 +31,12 @@ EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager(const DaybreakConn
Attach(EQ::EventLoop::Get().Handle());
}
EQ::Net::DaybreakConnectionManager::~DaybreakConnectionManager()
EQ::Net::ReliableStreamConnectionManager::~ReliableStreamConnectionManager()
{
Detach();
}
void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
void EQ::Net::ReliableStreamConnectionManager::Attach(uv_loop_t *loop)
{
if (!m_attached) {
uv_timer_init(loop, &m_timer);
@ -45,7 +45,7 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
auto update_rate = (uint64_t)(1000.0 / m_options.tic_rate_hertz);
uv_timer_start(&m_timer, [](uv_timer_t *handle) {
DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data;
ReliableStreamConnectionManager *c = (ReliableStreamConnectionManager*)handle->data;
c->UpdateDataBudget();
c->Process();
c->ProcessResend();
@ -71,7 +71,7 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
buf->len = 65536;
},
[](uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) {
DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data;
ReliableStreamConnectionManager *c = (ReliableStreamConnectionManager*)handle->data;
if (nread < 0 || addr == nullptr) {
return;
}
@ -90,7 +90,7 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
}
}
void EQ::Net::DaybreakConnectionManager::Detach()
void EQ::Net::ReliableStreamConnectionManager::Detach()
{
if (m_attached) {
uv_udp_recv_stop(&m_socket);
@ -99,11 +99,11 @@ void EQ::Net::DaybreakConnectionManager::Detach()
}
}
void EQ::Net::DaybreakConnectionManager::Connect(const std::string &addr, int port)
void EQ::Net::ReliableStreamConnectionManager::Connect(const std::string &addr, int port)
{
//todo dns resolution
auto connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, addr, port));
auto connection = std::shared_ptr<ReliableStreamConnection>(new ReliableStreamConnection(this, addr, port));
connection->m_self = connection;
if (m_on_new_connection) {
@ -113,7 +113,7 @@ void EQ::Net::DaybreakConnectionManager::Connect(const std::string &addr, int po
m_connections.emplace(std::make_pair(std::make_pair(addr, port), connection));
}
void EQ::Net::DaybreakConnectionManager::Process()
void EQ::Net::ReliableStreamConnectionManager::Process()
{
auto now = Clock::now();
auto iter = m_connections.begin();
@ -177,7 +177,7 @@ void EQ::Net::DaybreakConnectionManager::Process()
}
}
void EQ::Net::DaybreakConnectionManager::UpdateDataBudget()
void EQ::Net::ReliableStreamConnectionManager::UpdateDataBudget()
{
auto outgoing_data_rate = m_options.outgoing_data_rate;
if (outgoing_data_rate <= 0.0) {
@ -196,7 +196,7 @@ void EQ::Net::DaybreakConnectionManager::UpdateDataBudget()
}
}
void EQ::Net::DaybreakConnectionManager::ProcessResend()
void EQ::Net::ReliableStreamConnectionManager::ProcessResend()
{
auto iter = m_connections.begin();
while (iter != m_connections.end()) {
@ -217,15 +217,15 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend()
}
}
void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoint, int port, const char *data, size_t size)
void EQ::Net::ReliableStreamConnectionManager::ProcessPacket(const std::string &endpoint, int port, const char *data, size_t size)
{
if (m_options.simulated_in_packet_loss && m_options.simulated_in_packet_loss >= m_rand.Int(0, 100)) {
return;
}
if (size < DaybreakHeader::size()) {
if (size < ReliableStreamHeader::size()) {
if (m_on_error_message) {
m_on_error_message(fmt::format("Packet of size {0} which is less than {1}", size, DaybreakHeader::size()));
m_on_error_message(fmt::format("Packet of size {0} which is less than {1}", size, ReliableStreamHeader::size()));
}
return;
}
@ -239,9 +239,9 @@ void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoi
else {
if (data[0] == 0 && data[1] == OP_SessionRequest) {
StaticPacket p((void*)data, size);
auto request = p.GetSerialize<DaybreakConnect>(0);
auto request = p.GetSerialize<ReliableStreamConnect>(0);
connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, request, endpoint, port));
connection = std::shared_ptr<ReliableStreamConnection>(new ReliableStreamConnection(this, request, endpoint, port));
connection->m_self = connection;
if (m_on_new_connection) {
@ -262,7 +262,7 @@ void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoi
}
}
std::shared_ptr<EQ::Net::DaybreakConnection> EQ::Net::DaybreakConnectionManager::FindConnectionByEndpoint(std::string addr, int port)
std::shared_ptr<EQ::Net::ReliableStreamConnection> EQ::Net::ReliableStreamConnectionManager::FindConnectionByEndpoint(std::string addr, int port)
{
auto p = std::make_pair(addr, port);
auto iter = m_connections.find(p);
@ -273,9 +273,9 @@ std::shared_ptr<EQ::Net::DaybreakConnection> EQ::Net::DaybreakConnectionManager:
return nullptr;
}
void EQ::Net::DaybreakConnectionManager::SendDisconnect(const std::string &addr, int port)
void EQ::Net::ReliableStreamConnectionManager::SendDisconnect(const std::string &addr, int port)
{
DaybreakDisconnect header;
ReliableStreamDisconnect header;
header.zero = 0;
header.opcode = OP_OutOfSession;
header.connect_code = 0;
@ -300,7 +300,7 @@ void EQ::Net::DaybreakConnectionManager::SendDisconnect(const std::string &addr,
}
//new connection made as server
EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, const DaybreakConnect &connect, const std::string &endpoint, int port)
EQ::Net::ReliableStreamConnection::ReliableStreamConnection(ReliableStreamConnectionManager *owner, const ReliableStreamConnect &connect, const std::string &endpoint, int port)
{
m_owner = owner;
m_last_send = Clock::now();
@ -327,7 +327,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
}
//new connection made as client
EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, const std::string &endpoint, int port)
EQ::Net::ReliableStreamConnection::ReliableStreamConnection(ReliableStreamConnectionManager *owner, const std::string &endpoint, int port)
{
m_owner = owner;
m_last_send = Clock::now();
@ -349,11 +349,11 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_outgoing_budget = owner->m_options.outgoing_data_rate;
}
EQ::Net::DaybreakConnection::~DaybreakConnection()
EQ::Net::ReliableStreamConnection::~ReliableStreamConnection()
{
}
void EQ::Net::DaybreakConnection::Close()
void EQ::Net::ReliableStreamConnection::Close()
{
if (m_status != StatusDisconnected && m_status != StatusDisconnecting) {
FlushBuffer();
@ -367,17 +367,17 @@ void EQ::Net::DaybreakConnection::Close()
ChangeStatus(StatusDisconnecting);
}
void EQ::Net::DaybreakConnection::QueuePacket(Packet &p)
void EQ::Net::ReliableStreamConnection::QueuePacket(Packet &p)
{
QueuePacket(p, 0, true);
}
void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream)
void EQ::Net::ReliableStreamConnection::QueuePacket(Packet &p, int stream)
{
QueuePacket(p, stream, true);
}
void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream, bool reliable)
void EQ::Net::ReliableStreamConnection::QueuePacket(Packet &p, int stream, bool reliable)
{
if (*(char*)p.Data() == 0) {
DynamicPacket packet;
@ -390,21 +390,21 @@ void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream, bool reliab
InternalQueuePacket(p, stream, reliable);
}
EQ::Net::DaybreakConnectionStats EQ::Net::DaybreakConnection::GetStats()
EQ::Net::ReliableStreamConnectionStats EQ::Net::ReliableStreamConnection::GetStats()
{
EQ::Net::DaybreakConnectionStats ret = m_stats;
EQ::Net::ReliableStreamConnectionStats ret = m_stats;
ret.datarate_remaining = m_outgoing_budget;
ret.avg_ping = m_rolling_ping;
return ret;
}
void EQ::Net::DaybreakConnection::ResetStats()
void EQ::Net::ReliableStreamConnection::ResetStats()
{
m_stats.Reset();
}
void EQ::Net::DaybreakConnection::Process()
void EQ::Net::ReliableStreamConnection::Process()
{
try {
auto now = Clock::now();
@ -422,7 +422,7 @@ void EQ::Net::DaybreakConnection::Process()
}
}
void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
void EQ::Net::ReliableStreamConnection::ProcessPacket(Packet &p)
{
m_last_recv = Clock::now();
m_stats.recv_packets++;
@ -458,13 +458,13 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
switch (m_encode_passes[i]) {
case EncodeCompression:
if(temp.GetInt8(0) == 0)
Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
Decompress(temp, ReliableStreamHeader::size(), temp.Length() - ReliableStreamHeader::size());
else
Decompress(temp, 1, temp.Length() - 1);
break;
case EncodeXOR:
if (temp.GetInt8(0) == 0)
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
Decode(temp, ReliableStreamHeader::size(), temp.Length() - ReliableStreamHeader::size());
else
Decode(temp, 1, temp.Length() - 1);
break;
@ -483,7 +483,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
switch (m_encode_passes[i]) {
case EncodeXOR:
if (temp.GetInt8(0) == 0)
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
Decode(temp, ReliableStreamHeader::size(), temp.Length() - ReliableStreamHeader::size());
else
Decode(temp, 1, temp.Length() - 1);
break;
@ -502,7 +502,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
}
}
void EQ::Net::DaybreakConnection::ProcessQueue()
void EQ::Net::ReliableStreamConnection::ProcessQueue()
{
for (int i = 0; i < 4; ++i) {
auto stream = &m_streams[i];
@ -521,7 +521,7 @@ void EQ::Net::DaybreakConnection::ProcessQueue()
}
}
void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq)
void EQ::Net::ReliableStreamConnection::RemoveFromQueue(int stream, uint16_t seq)
{
auto s = &m_streams[stream];
auto iter = s->packet_queue.find(seq);
@ -532,7 +532,7 @@ void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq)
}
}
void EQ::Net::DaybreakConnection::AddToQueue(int stream, uint16_t seq, const Packet &p)
void EQ::Net::ReliableStreamConnection::AddToQueue(int stream, uint16_t seq, const Packet &p)
{
auto s = &m_streams[stream];
auto iter = s->packet_queue.find(seq);
@ -544,7 +544,7 @@ void EQ::Net::DaybreakConnection::AddToQueue(int stream, uint16_t seq, const Pac
}
}
void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
void EQ::Net::ReliableStreamConnection::ProcessDecodedPacket(const Packet &p)
{
if (p.GetInt8(0) == 0) {
if (p.Length() < 2) {
@ -628,13 +628,13 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
case OP_SessionRequest:
{
if (m_status == StatusConnected) {
auto request = p.GetSerialize<DaybreakConnect>(0);
auto request = p.GetSerialize<ReliableStreamConnect>(0);
if (NetworkToHost(request.connect_code) != m_connect_code) {
return;
}
DaybreakConnectReply reply;
ReliableStreamConnectReply reply;
reply.zero = 0;
reply.opcode = OP_SessionResponse;
reply.connect_code = HostToNetwork(m_connect_code);
@ -656,13 +656,13 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
case OP_SessionResponse:
{
if (m_status == StatusConnecting) {
auto reply = p.GetSerialize<DaybreakConnectReply>(0);
auto reply = p.GetSerialize<ReliableStreamConnectReply>(0);
if (m_connect_code == reply.connect_code) {
m_encode_key = reply.encode_key;
m_crc_bytes = reply.crc_bytes;
m_encode_passes[0] = (DaybreakEncodeType)reply.encode_pass1;
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
m_encode_passes[0] = (ReliableStreamEncodeType)reply.encode_pass1;
m_encode_passes[1] = (ReliableStreamEncodeType)reply.encode_pass2;
m_max_packet_size = reply.max_packet_size;
ChangeStatus(StatusConnected);
@ -686,7 +686,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
return;
}
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
auto header = p.GetSerialize<ReliableStreamReliableHeader>(0);
auto sequence = NetworkToHost(header.sequence);
auto stream_id = header.opcode - OP_Packet;
auto stream = &m_streams[stream_id];
@ -703,7 +703,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
RemoveFromQueue(stream_id, sequence);
SendAck(stream_id, stream->sequence_in);
stream->sequence_in++;
StaticPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
StaticPacket next((char*)p.Data() + ReliableStreamReliableHeader::size(), p.Length() - ReliableStreamReliableHeader::size());
ProcessDecodedPacket(next);
}
@ -715,7 +715,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
case OP_Fragment3:
case OP_Fragment4:
{
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
auto header = p.GetSerialize<ReliableStreamReliableHeader>(0);
auto sequence = NetworkToHost(header.sequence);
auto stream_id = header.opcode - OP_Fragment;
auto stream = &m_streams[stream_id];
@ -735,22 +735,22 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
stream->sequence_in++;
if (stream->fragment_total_bytes == 0) {
auto fragheader = p.GetSerialize<DaybreakReliableFragmentHeader>(0);
auto fragheader = p.GetSerialize<ReliableStreamReliableFragmentHeader>(0);
stream->fragment_total_bytes = NetworkToHost(fragheader.total_size);
stream->fragment_current_bytes = 0;
stream->fragment_packet.Reserve(stream->fragment_total_bytes);
stream->fragment_packet.PutData(
stream->fragment_current_bytes,
(char*)p.Data() + DaybreakReliableFragmentHeader::size(), p.Length() - DaybreakReliableFragmentHeader::size());
(char*)p.Data() + ReliableStreamReliableFragmentHeader::size(), p.Length() - ReliableStreamReliableFragmentHeader::size());
stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableFragmentHeader::size());
stream->fragment_current_bytes += (uint32_t)(p.Length() - ReliableStreamReliableFragmentHeader::size());
}
else {
stream->fragment_packet.PutData(
stream->fragment_current_bytes,
(char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
(char*)p.Data() + ReliableStreamReliableHeader::size(), p.Length() - ReliableStreamReliableHeader::size());
stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableHeader::size());
stream->fragment_current_bytes += (uint32_t)(p.Length() - ReliableStreamReliableHeader::size());
if (stream->fragment_current_bytes >= stream->fragment_total_bytes) {
ProcessDecodedPacket(stream->fragment_packet);
@ -769,7 +769,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
case OP_Ack3:
case OP_Ack4:
{
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
auto header = p.GetSerialize<ReliableStreamReliableHeader>(0);
auto sequence = NetworkToHost(header.sequence);
auto stream_id = header.opcode - OP_Ack;
Ack(stream_id, sequence);
@ -781,7 +781,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
case OP_OutOfOrderAck3:
case OP_OutOfOrderAck4:
{
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
auto header = p.GetSerialize<ReliableStreamReliableHeader>(0);
auto sequence = NetworkToHost(header.sequence);
auto stream_id = header.opcode - OP_OutOfOrderAck;
OutOfOrderAck(stream_id, sequence);
@ -815,13 +815,13 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
}
case OP_SessionStatRequest:
{
auto request = p.GetSerialize<DaybreakSessionStatRequest>(0);
auto request = p.GetSerialize<ReliableStreamSessionStatRequest>(0);
m_stats.sync_remote_sent_packets = EQ::Net::NetworkToHost(request.packets_sent);
m_stats.sync_remote_recv_packets = EQ::Net::NetworkToHost(request.packets_recv);
m_stats.sync_sent_packets = m_stats.sent_packets;
m_stats.sync_recv_packets = m_stats.recv_packets;
DaybreakSessionStatResponse response;
ReliableStreamSessionStatResponse response;
response.zero = 0;
response.opcode = OP_SessionStatResponse;
response.timestamp = request.timestamp;
@ -836,7 +836,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
break;
}
case OP_SessionStatResponse: {
auto response = p.GetSerialize<DaybreakSessionStatResponse>(0);
auto response = p.GetSerialize<ReliableStreamSessionStatResponse>(0);
m_stats.sync_remote_sent_packets = EQ::Net::NetworkToHost(response.server_sent);
m_stats.sync_remote_recv_packets = EQ::Net::NetworkToHost(response.server_recv);
m_stats.sync_sent_packets = m_stats.sent_packets;
@ -858,7 +858,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
}
}
bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
bool EQ::Net::ReliableStreamConnection::ValidateCRC(Packet &p)
{
if (m_crc_bytes == 0U) {
return true;
@ -892,7 +892,7 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
return false;
}
void EQ::Net::DaybreakConnection::AppendCRC(Packet &p)
void EQ::Net::ReliableStreamConnection::AppendCRC(Packet &p)
{
if (m_crc_bytes == 0U) {
return;
@ -911,7 +911,7 @@ void EQ::Net::DaybreakConnection::AppendCRC(Packet &p)
}
}
void EQ::Net::DaybreakConnection::ChangeStatus(DbProtocolStatus new_status)
void EQ::Net::ReliableStreamConnection::ChangeStatus(DbProtocolStatus new_status)
{
if (m_owner->m_on_connection_state_change) {
if (auto self = m_self.lock()) {
@ -922,7 +922,7 @@ void EQ::Net::DaybreakConnection::ChangeStatus(DbProtocolStatus new_status)
m_status = new_status;
}
bool EQ::Net::DaybreakConnection::PacketCanBeEncoded(Packet &p) const
bool EQ::Net::ReliableStreamConnection::PacketCanBeEncoded(Packet &p) const
{
if (p.Length() < 2) {
return false;
@ -941,7 +941,7 @@ bool EQ::Net::DaybreakConnection::PacketCanBeEncoded(Packet &p) const
return true;
}
void EQ::Net::DaybreakConnection::Decode(Packet &p, size_t offset, size_t length)
void EQ::Net::ReliableStreamConnection::Decode(Packet &p, size_t offset, size_t length)
{
int key = m_encode_key;
char *buffer = (char*)p.Data() + offset;
@ -961,7 +961,7 @@ void EQ::Net::DaybreakConnection::Decode(Packet &p, size_t offset, size_t length
}
}
void EQ::Net::DaybreakConnection::Encode(Packet &p, size_t offset, size_t length)
void EQ::Net::ReliableStreamConnection::Encode(Packet &p, size_t offset, size_t length)
{
int key = m_encode_key;
char *buffer = (char*)p.Data() + offset;
@ -1050,7 +1050,7 @@ uint32_t Deflate(const uint8_t* in, uint32_t in_len, uint8_t* out, uint32_t out_
}
}
void EQ::Net::DaybreakConnection::Decompress(Packet &p, size_t offset, size_t length)
void EQ::Net::ReliableStreamConnection::Decompress(Packet &p, size_t offset, size_t length)
{
if (length < 2) {
return;
@ -1075,7 +1075,7 @@ void EQ::Net::DaybreakConnection::Decompress(Packet &p, size_t offset, size_t le
p.PutData(offset, new_buffer, new_length);
}
void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t length)
void EQ::Net::ReliableStreamConnection::Compress(Packet &p, size_t offset, size_t length)
{
static thread_local uint8_t new_buffer[2048] = { 0 };
uint8_t *buffer = (uint8_t*)p.Data() + offset;
@ -1097,14 +1097,14 @@ void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t leng
p.PutData(offset, new_buffer, new_length);
}
void EQ::Net::DaybreakConnection::ProcessResend()
void EQ::Net::ReliableStreamConnection::ProcessResend()
{
for (int i = 0; i < 4; ++i) {
ProcessResend(i);
}
}
void EQ::Net::DaybreakConnection::ProcessResend(int stream)
void EQ::Net::ReliableStreamConnection::ProcessResend(int stream)
{
if (m_status == DbProtocolStatus::StatusDisconnected) {
return;
@ -1201,7 +1201,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
auto &sp = e.second;
auto &p = sp.packet;
if (p.Length() >= DaybreakHeader::size()) {
if (p.Length() >= ReliableStreamHeader::size()) {
if (p.GetInt8(0) == 0 && p.GetInt8(1) >= OP_Fragment && p.GetInt8(1) <= OP_Fragment4) {
m_stats.resent_fragments++;
}
@ -1232,7 +1232,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
m_last_ack = now;
}
void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
void EQ::Net::ReliableStreamConnection::Ack(int stream, uint16_t seq)
{
auto now = Clock::now();
auto s = &m_streams[stream];
@ -1259,7 +1259,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
m_last_ack = now;
}
void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq)
void EQ::Net::ReliableStreamConnection::OutOfOrderAck(int stream, uint16_t seq)
{
auto now = Clock::now();
auto s = &m_streams[stream];
@ -1279,15 +1279,15 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq)
m_last_ack = now;
}
void EQ::Net::DaybreakConnection::UpdateDataBudget(double budget_add)
void EQ::Net::ReliableStreamConnection::UpdateDataBudget(double budget_add)
{
auto outgoing_data_rate = m_owner->m_options.outgoing_data_rate;
m_outgoing_budget = EQ::ClampUpper(m_outgoing_budget + budget_add, outgoing_data_rate);
}
void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq)
void EQ::Net::ReliableStreamConnection::SendAck(int stream_id, uint16_t seq)
{
DaybreakReliableHeader ack;
ReliableStreamReliableHeader ack;
ack.zero = 0;
ack.opcode = OP_Ack + stream_id;
ack.sequence = HostToNetwork(seq);
@ -1298,9 +1298,9 @@ void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq)
InternalBufferedSend(p);
}
void EQ::Net::DaybreakConnection::SendOutOfOrderAck(int stream_id, uint16_t seq)
void EQ::Net::ReliableStreamConnection::SendOutOfOrderAck(int stream_id, uint16_t seq)
{
DaybreakReliableHeader ack;
ReliableStreamReliableHeader ack;
ack.zero = 0;
ack.opcode = OP_OutOfOrderAck + stream_id;
ack.sequence = HostToNetwork(seq);
@ -1311,9 +1311,9 @@ void EQ::Net::DaybreakConnection::SendOutOfOrderAck(int stream_id, uint16_t seq)
InternalBufferedSend(p);
}
void EQ::Net::DaybreakConnection::SendDisconnect()
void EQ::Net::ReliableStreamConnection::SendDisconnect()
{
DaybreakDisconnect disconnect;
ReliableStreamDisconnect disconnect;
disconnect.zero = 0;
disconnect.opcode = OP_SessionDisconnect;
disconnect.connect_code = HostToNetwork(m_connect_code);
@ -1322,7 +1322,7 @@ void EQ::Net::DaybreakConnection::SendDisconnect()
InternalSend(out);
}
void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p)
void EQ::Net::ReliableStreamConnection::InternalBufferedSend(Packet &p)
{
if (p.Length() > 0xFFU) {
FlushBuffer();
@ -1331,7 +1331,7 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p)
}
//we could add this packet to a combined
size_t raw_size = DaybreakHeader::size() + (size_t)m_crc_bytes + m_buffered_packets_length + m_buffered_packets.size() + 1 + p.Length();
size_t raw_size = ReliableStreamHeader::size() + (size_t)m_crc_bytes + m_buffered_packets_length + m_buffered_packets.size() + 1 + p.Length();
if (raw_size > m_max_packet_size) {
FlushBuffer();
}
@ -1346,9 +1346,9 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p)
}
}
void EQ::Net::DaybreakConnection::SendConnect()
void EQ::Net::ReliableStreamConnection::SendConnect()
{
DaybreakConnect connect;
ReliableStreamConnect connect;
connect.zero = 0;
connect.opcode = OP_SessionRequest;
connect.protocol_version = HostToNetwork(3U);
@ -1361,9 +1361,9 @@ void EQ::Net::DaybreakConnection::SendConnect()
InternalSend(p);
}
void EQ::Net::DaybreakConnection::SendKeepAlive()
void EQ::Net::ReliableStreamConnection::SendKeepAlive()
{
DaybreakHeader keep_alive;
ReliableStreamHeader keep_alive;
keep_alive.zero = 0;
keep_alive.opcode = OP_KeepAlive;
@ -1373,7 +1373,7 @@ void EQ::Net::DaybreakConnection::SendKeepAlive()
InternalSend(p);
}
void EQ::Net::DaybreakConnection::InternalSend(Packet &p) {
void EQ::Net::ReliableStreamConnection::InternalSend(Packet &p) {
if (m_owner->m_options.outgoing_data_rate > 0.0) {
auto new_budget = m_outgoing_budget - (p.Length() / 1024.0);
if (new_budget <= 0.0) {
@ -1409,14 +1409,14 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p) {
switch (m_encode_passe) {
case EncodeCompression:
if (out.GetInt8(0) == 0) {
Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
Compress(out, ReliableStreamHeader::size(), out.Length() - ReliableStreamHeader::size());
} else {
Compress(out, 1, out.Length() - 1);
}
break;
case EncodeXOR:
if (out.GetInt8(0) == 0) {
Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
Encode(out, ReliableStreamHeader::size(), out.Length() - ReliableStreamHeader::size());
} else {
Encode(out, 1, out.Length() - 1);
}
@ -1466,7 +1466,7 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p) {
}
}
void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, bool reliable)
void EQ::Net::ReliableStreamConnection::InternalQueuePacket(Packet &p, int stream_id, bool reliable)
{
if (!reliable) {
auto max_raw_size = 0xFFU - m_crc_bytes;
@ -1480,23 +1480,23 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
}
auto stream = &m_streams[stream_id];
auto max_raw_size = m_max_packet_size - m_crc_bytes - DaybreakReliableHeader::size() - 1; // -1 for compress flag
auto max_raw_size = m_max_packet_size - m_crc_bytes - ReliableStreamReliableHeader::size() - 1; // -1 for compress flag
size_t length = p.Length();
if (length > max_raw_size) {
DaybreakReliableFragmentHeader first_header;
ReliableStreamReliableFragmentHeader first_header;
first_header.reliable.zero = 0;
first_header.reliable.opcode = OP_Fragment + stream_id;
first_header.reliable.sequence = HostToNetwork(stream->sequence_out);
first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length);
size_t used = 0;
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size() - 1; // -1 for compress flag
size_t sublen = m_max_packet_size - m_crc_bytes - ReliableStreamReliableFragmentHeader::size() - 1; // -1 for compress flag
DynamicPacket first_packet;
first_packet.PutSerialize(0, first_header);
first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen);
first_packet.PutData(ReliableStreamReliableFragmentHeader::size(), (char*)p.Data() + used, sublen);
used += sublen;
DaybreakSentPacket sent;
ReliableStreamSentPacket sent;
sent.packet.PutPacket(0, first_packet);
sent.last_sent = Clock::now();
sent.first_sent = Clock::now();
@ -1513,22 +1513,22 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
while (used < length) {
auto left = length - used;
DynamicPacket packet;
DaybreakReliableHeader header;
ReliableStreamReliableHeader header;
header.zero = 0;
header.opcode = OP_Fragment + stream_id;
header.sequence = HostToNetwork(stream->sequence_out);
packet.PutSerialize(0, header);
if (left > max_raw_size) {
packet.PutData(DaybreakReliableHeader::size(), (char*)p.Data() + used, max_raw_size);
packet.PutData(ReliableStreamReliableHeader::size(), (char*)p.Data() + used, max_raw_size);
used += max_raw_size;
}
else {
packet.PutData(DaybreakReliableHeader::size(), (char*)p.Data() + used, left);
packet.PutData(ReliableStreamReliableHeader::size(), (char*)p.Data() + used, left);
used += left;
}
DaybreakSentPacket sent;
ReliableStreamSentPacket sent;
sent.packet.PutPacket(0, packet);
sent.last_sent = Clock::now();
sent.first_sent = Clock::now();
@ -1545,14 +1545,14 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
}
else {
DynamicPacket packet;
DaybreakReliableHeader header;
ReliableStreamReliableHeader header;
header.zero = 0;
header.opcode = OP_Packet + stream_id;
header.sequence = HostToNetwork(stream->sequence_out);
packet.PutSerialize(0, header);
packet.PutPacket(DaybreakReliableHeader::size(), p);
packet.PutPacket(ReliableStreamReliableHeader::size(), p);
DaybreakSentPacket sent;
ReliableStreamSentPacket sent;
sent.packet.PutPacket(0, packet);
sent.last_sent = Clock::now();
sent.first_sent = Clock::now();
@ -1568,7 +1568,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
}
}
void EQ::Net::DaybreakConnection::FlushBuffer()
void EQ::Net::ReliableStreamConnection::FlushBuffer()
{
if (m_buffered_packets.empty()) {
return;
@ -1595,7 +1595,7 @@ void EQ::Net::DaybreakConnection::FlushBuffer()
m_buffered_packets_length = 0;
}
EQ::Net::SequenceOrder EQ::Net::DaybreakConnection::CompareSequence(uint16_t expected, uint16_t actual) const
EQ::Net::SequenceOrder EQ::Net::ReliableStreamConnection::CompareSequence(uint16_t expected, uint16_t actual) const
{
int diff = (int)actual - (int)expected;

View File

@ -2,8 +2,8 @@
#include "../random.h"
#include "packet.h"
#include "daybreak_structs.h"
#include "daybreak_pooling.h"
#include "reliable_stream_structs.h"
#include "reliable_stream_pooling.h"
#include <uv.h>
#include <chrono>
#include <functional>
@ -16,7 +16,7 @@ namespace EQ
{
namespace Net
{
enum DaybreakProtocolOpcode
enum ReliableStreamProtocolOpcode
{
OP_Padding = 0x00,
OP_SessionRequest = 0x01,
@ -55,7 +55,7 @@ namespace EQ
StatusDisconnected
};
enum DaybreakEncodeType
enum ReliableStreamEncodeType
{
EncodeNone = 0,
EncodeCompression = 1,
@ -72,9 +72,9 @@ namespace EQ
typedef std::chrono::steady_clock::time_point Timestamp;
typedef std::chrono::steady_clock Clock;
struct DaybreakConnectionStats
struct ReliableStreamConnectionStats
{
DaybreakConnectionStats() {
ReliableStreamConnectionStats() {
recv_bytes = 0;
sent_bytes = 0;
recv_packets = 0;
@ -134,14 +134,14 @@ namespace EQ
uint64_t bytes_before_encode;
};
class DaybreakConnectionManager;
class DaybreakConnection;
class DaybreakConnection
class ReliableStreamConnectionManager;
class ReliableStreamConnection;
class ReliableStreamConnection
{
public:
DaybreakConnection(DaybreakConnectionManager *owner, const DaybreakConnect &connect, const std::string &endpoint, int port);
DaybreakConnection(DaybreakConnectionManager *owner, const std::string &endpoint, int port);
~DaybreakConnection();
ReliableStreamConnection(ReliableStreamConnectionManager *owner, const ReliableStreamConnect &connect, const std::string &endpoint, int port);
ReliableStreamConnection(ReliableStreamConnectionManager *owner, const std::string &endpoint, int port);
~ReliableStreamConnection();
const std::string& RemoteEndpoint() const { return m_endpoint; }
int RemotePort() const { return m_port; }
@ -151,23 +151,23 @@ namespace EQ
void QueuePacket(Packet &p, int stream);
void QueuePacket(Packet &p, int stream, bool reliable);
DaybreakConnectionStats GetStats();
ReliableStreamConnectionStats GetStats();
void ResetStats();
size_t GetRollingPing() const { return m_rolling_ping; }
DbProtocolStatus GetStatus() const { return m_status; }
const DaybreakEncodeType* GetEncodePasses() const { return m_encode_passes; }
const DaybreakConnectionManager* GetManager() const { return m_owner; }
DaybreakConnectionManager* GetManager() { return m_owner; }
const ReliableStreamEncodeType* GetEncodePasses() const { return m_encode_passes; }
const ReliableStreamConnectionManager* GetManager() const { return m_owner; }
ReliableStreamConnectionManager* GetManager() { return m_owner; }
private:
DaybreakConnectionManager *m_owner;
ReliableStreamConnectionManager *m_owner;
std::string m_endpoint;
int m_port;
uint32_t m_connect_code;
uint32_t m_encode_key;
uint32_t m_max_packet_size;
uint32_t m_crc_bytes;
DaybreakEncodeType m_encode_passes[2];
ReliableStreamEncodeType m_encode_passes[2];
Timestamp m_last_send;
Timestamp m_last_recv;
@ -176,7 +176,7 @@ namespace EQ
std::list<DynamicPacket> m_buffered_packets;
size_t m_buffered_packets_length;
std::unique_ptr<char[]> m_combined;
DaybreakConnectionStats m_stats;
ReliableStreamConnectionStats m_stats;
Timestamp m_last_session_stats;
size_t m_rolling_ping;
Timestamp m_close_time;
@ -188,7 +188,7 @@ namespace EQ
bool m_acked_since_last_resend = false;
Timestamp m_last_ack;
struct DaybreakSentPacket
struct ReliableStreamSentPacket
{
DynamicPacket packet;
Timestamp last_sent;
@ -197,9 +197,9 @@ namespace EQ
size_t resend_delay;
};
struct DaybreakStream
struct ReliableStream
{
DaybreakStream() {
ReliableStream() {
sequence_in = 0;
sequence_out = 0;
fragment_current_bytes = 0;
@ -214,11 +214,11 @@ namespace EQ
uint32_t fragment_current_bytes;
uint32_t fragment_total_bytes;
std::map<uint16_t, DaybreakSentPacket> sent_packets;
std::map<uint16_t, ReliableStreamSentPacket> sent_packets;
};
DaybreakStream m_streams[4];
std::weak_ptr<DaybreakConnection> m_self;
ReliableStream m_streams[4];
std::weak_ptr<ReliableStreamConnection> m_self;
void Process();
void ProcessPacket(Packet &p);
@ -251,12 +251,12 @@ namespace EQ
void FlushBuffer();
SequenceOrder CompareSequence(uint16_t expected, uint16_t actual) const;
friend class DaybreakConnectionManager;
friend class ReliableStreamConnectionManager;
};
struct DaybreakConnectionManagerOptions
struct ReliableStreamConnectionManagerOptions
{
DaybreakConnectionManagerOptions() {
ReliableStreamConnectionManagerOptions() {
max_connection_count = 0;
keepalive_delay_ms = 9000;
resend_delay_ms = 30;
@ -268,8 +268,8 @@ namespace EQ
connect_stale_ms = 5000;
crc_length = 2;
max_packet_size = 512;
encode_passes[0] = DaybreakEncodeType::EncodeNone;
encode_passes[1] = DaybreakEncodeType::EncodeNone;
encode_passes[0] = ReliableStreamEncodeType::EncodeNone;
encode_passes[1] = ReliableStreamEncodeType::EncodeNone;
port = 0;
hold_size = 512;
hold_length_ms = 50;
@ -299,28 +299,28 @@ namespace EQ
double tic_rate_hertz;
size_t resend_timeout;
size_t connection_close_time;
DaybreakEncodeType encode_passes[2];
ReliableStreamEncodeType encode_passes[2];
int port;
double outgoing_data_rate;
};
class DaybreakConnectionManager
class ReliableStreamConnectionManager
{
public:
DaybreakConnectionManager();
DaybreakConnectionManager(const DaybreakConnectionManagerOptions &opts);
~DaybreakConnectionManager();
ReliableStreamConnectionManager();
ReliableStreamConnectionManager(const ReliableStreamConnectionManagerOptions &opts);
~ReliableStreamConnectionManager();
void Connect(const std::string &addr, int port);
void Process();
void UpdateDataBudget();
void ProcessResend();
void OnNewConnection(std::function<void(std::shared_ptr<DaybreakConnection>)> func) { m_on_new_connection = func; }
void OnConnectionStateChange(std::function<void(std::shared_ptr<DaybreakConnection>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
void OnPacketRecv(std::function<void(std::shared_ptr<DaybreakConnection>, const Packet &)> func) { m_on_packet_recv = func; }
void OnNewConnection(std::function<void(std::shared_ptr<ReliableStreamConnection>)> func) { m_on_new_connection = func; }
void OnConnectionStateChange(std::function<void(std::shared_ptr<ReliableStreamConnection>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
void OnPacketRecv(std::function<void(std::shared_ptr<ReliableStreamConnection>, const Packet &)> func) { m_on_packet_recv = func; }
void OnErrorMessage(std::function<void(const std::string&)> func) { m_on_error_message = func; }
DaybreakConnectionManagerOptions& GetOptions() { return m_options; }
ReliableStreamConnectionManagerOptions& GetOptions() { return m_options; }
private:
void Attach(uv_loop_t *loop);
void Detach();
@ -329,18 +329,18 @@ namespace EQ
uv_timer_t m_timer;
uv_udp_t m_socket;
uv_loop_t *m_attached;
DaybreakConnectionManagerOptions m_options;
std::function<void(std::shared_ptr<DaybreakConnection>)> m_on_new_connection;
std::function<void(std::shared_ptr<DaybreakConnection>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
std::function<void(std::shared_ptr<DaybreakConnection>, const Packet&)> m_on_packet_recv;
ReliableStreamConnectionManagerOptions m_options;
std::function<void(std::shared_ptr<ReliableStreamConnection>)> m_on_new_connection;
std::function<void(std::shared_ptr<ReliableStreamConnection>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
std::function<void(std::shared_ptr<ReliableStreamConnection>, const Packet&)> m_on_packet_recv;
std::function<void(const std::string&)> m_on_error_message;
std::map<std::pair<std::string, int>, std::shared_ptr<DaybreakConnection>> m_connections;
std::map<std::pair<std::string, int>, std::shared_ptr<ReliableStreamConnection>> m_connections;
void ProcessPacket(const std::string &endpoint, int port, const char *data, size_t size);
std::shared_ptr<DaybreakConnection> FindConnectionByEndpoint(std::string addr, int port);
std::shared_ptr<ReliableStreamConnection> FindConnectionByEndpoint(std::string addr, int port);
void SendDisconnect(const std::string &addr, int port);
friend class DaybreakConnection;
friend class ReliableStreamConnection;
};
}
}

View File

@ -8,7 +8,7 @@ namespace EQ
{
namespace Net
{
struct DaybreakHeader
struct ReliableStreamHeader
{
static size_t size() { return 2; }
uint8_t zero;
@ -22,7 +22,7 @@ namespace EQ
}
};
struct DaybreakConnect
struct ReliableStreamConnect
{
static size_t size() { return 14; }
uint8_t zero;
@ -42,7 +42,7 @@ namespace EQ
}
};
struct DaybreakConnectReply
struct ReliableStreamConnectReply
{
static size_t size() { return 17; }
uint8_t zero;
@ -68,7 +68,7 @@ namespace EQ
}
};
struct DaybreakDisconnect
struct ReliableStreamDisconnect
{
static size_t size() { return 8; }
uint8_t zero;
@ -84,7 +84,7 @@ namespace EQ
}
};
struct DaybreakReliableHeader
struct ReliableStreamReliableHeader
{
static size_t size() { return 4; }
uint8_t zero;
@ -100,10 +100,10 @@ namespace EQ
}
};
struct DaybreakReliableFragmentHeader
struct ReliableStreamReliableFragmentHeader
{
static size_t size() { return 4 + DaybreakReliableHeader::size(); }
DaybreakReliableHeader reliable;
static size_t size() { return 4 + ReliableStreamReliableHeader::size(); }
ReliableStreamReliableHeader reliable;
uint32_t total_size;
template <class Archive>
@ -114,7 +114,7 @@ namespace EQ
}
};
struct DaybreakSessionStatRequest
struct ReliableStreamSessionStatRequest
{
static size_t size() { return 40; }
uint8_t zero;
@ -144,7 +144,7 @@ namespace EQ
}
};
struct DaybreakSessionStatResponse
struct ReliableStreamSessionStatResponse
{
static size_t size() { return 40; }
uint8_t zero;

View File

@ -6481,7 +6481,7 @@ namespace RoF2
hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0);
hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber());
hdr.parcel_item_id = packet_type == ItemPacketParcel ? inst->GetID() : 0;
if (item->EvolvingItem) {
if (item->EvolvingItem && packet_type != ItemPacketParcel && packet_type != ItemPacketMerchant) {
hdr.instance_id = inst->GetEvolveUniqueID() & 0xFFFFFFFF; //lower dword
hdr.parcel_item_id = inst->GetEvolveUniqueID() >> 32; //upper dword
}
@ -6500,6 +6500,7 @@ namespace RoF2
if (item->EvolvingItem > 0) {
RoF2::structs::EvolvingItem_Struct evotop;
inst->CalculateEvolveProgression();
evotop.final_item_id = inst->GetEvolveFinalItemID();
evotop.evolve_level = item->EvolvingLevel;

View File

@ -1059,7 +1059,7 @@ namespace Titanium
OUT(spawnid);
OUT_str(charname);
if (emu->race > 473)
if (emu->race > 474)
eq->race = 1;
else
OUT(race);
@ -1840,7 +1840,7 @@ namespace Titanium
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
eq->Race[char_index] = emu_cse->Race;
if (eq->Race[char_index] > 473)
if (eq->Race[char_index] > 474)
eq->Race[char_index] = 1;
for (int index = 0; index < EQ::textures::materialCount; ++index) {
@ -2421,7 +2421,7 @@ namespace Titanium
strcpy(eq->title, emu->title);
// eq->unknown0274 = emu->unknown0274;
eq->helm = emu->helm;
if (emu->race > 473)
if (emu->race > 474)
eq->race = 1;
else
eq->race = emu->race;

File diff suppressed because it is too large Load Diff

View File

@ -21,103 +21,7 @@
#include "../common/types.h"
#include <string>
namespace Gender {
constexpr uint8 Male = 0;
constexpr uint8 Female = 1;
constexpr uint8 Neuter = 2;
}
//theres a big list straight from the client below.
#define HUMAN 1
#define BARBARIAN 2
#define ERUDITE 3
#define WOOD_ELF 4
#define HIGH_ELF 5
#define DARK_ELF 6
#define HALF_ELF 7
#define DWARF 8
#define TROLL 9
#define OGRE 10
#define HALFLING 11
#define GNOME 12
#define WEREWOLF 14
#define WOLF 42
#define BEAR 43
#define SKELETON 60
#define TIGER 63
#define ELEMENTAL 75
#define ALLIGATOR 91
#define OGGOK_CITIZEN 93
#define EYE_OF_ZOMM 108
#define WOLF_ELEMENTAL 120
#define INVISIBLE_MAN 127
#define IKSAR 128
#define VAHSHIR 130
#define CONTROLLED_BOAT 141
#define MINOR_ILL_OBJ 142
#define TREE 143
#define IKSAR_SKELETON 161
#define FROGLOK 330
// TODO: check all clients for (BYTE) usage of '/who all' class and remove FROGLOK2, if possible (330 - 74 = 256 .. WORD->BYTE conversion loss...)
#define FROGLOK2 74 // Not sure why /who all reports race as 74 for frogloks
#define FAIRY 473
#define DRAKKIN 522 // 32768
#define EMU_RACE_NPC 131069 // was 65533
#define EMU_RACE_PET 131070 // was 65534
#define EMU_RACE_UNKNOWN 131071 // was 65535
// player race values
#define PLAYER_RACE_UNKNOWN 0
#define PLAYER_RACE_HUMAN 1
#define PLAYER_RACE_BARBARIAN 2
#define PLAYER_RACE_ERUDITE 3
#define PLAYER_RACE_WOOD_ELF 4
#define PLAYER_RACE_HIGH_ELF 5
#define PLAYER_RACE_DARK_ELF 6
#define PLAYER_RACE_HALF_ELF 7
#define PLAYER_RACE_DWARF 8
#define PLAYER_RACE_TROLL 9
#define PLAYER_RACE_OGRE 10
#define PLAYER_RACE_HALFLING 11
#define PLAYER_RACE_GNOME 12
#define PLAYER_RACE_IKSAR 13
#define PLAYER_RACE_VAHSHIR 14
#define PLAYER_RACE_FROGLOK 15
#define PLAYER_RACE_DRAKKIN 16
#define PLAYER_RACE_COUNT 16
#define PLAYER_RACE_EMU_NPC 17
#define PLAYER_RACE_EMU_PET 18
#define PLAYER_RACE_EMU_COUNT 19
// player race bits
#define PLAYER_RACE_UNKNOWN_BIT 0
#define PLAYER_RACE_HUMAN_BIT 1
#define PLAYER_RACE_BARBARIAN_BIT 2
#define PLAYER_RACE_ERUDITE_BIT 4
#define PLAYER_RACE_WOOD_ELF_BIT 8
#define PLAYER_RACE_HIGH_ELF_BIT 16
#define PLAYER_RACE_DARK_ELF_BIT 32
#define PLAYER_RACE_HALF_ELF_BIT 64
#define PLAYER_RACE_DWARF_BIT 128
#define PLAYER_RACE_TROLL_BIT 256
#define PLAYER_RACE_OGRE_BIT 512
#define PLAYER_RACE_HALFLING_BIT 1024
#define PLAYER_RACE_GNOME_BIT 2048
#define PLAYER_RACE_IKSAR_BIT 4096
#define PLAYER_RACE_VAHSHIR_BIT 8192
#define PLAYER_RACE_FROGLOK_BIT 16384
#define PLAYER_RACE_DRAKKIN_BIT 32768
#define PLAYER_RACE_ALL_MASK 65535
const char* GetRaceIDName(uint16 race_id);
const char* GetPlayerRaceName(uint32 player_race_value);
const char* GetGenderName(uint32 gender_id);
bool IsPlayerRace(uint16 race_id);
@ -127,25 +31,13 @@ uint32 GetPlayerRaceValue(uint16 race_id);
uint16 GetPlayerRaceBit(uint16 race_id);
uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value);
uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit);
float GetRaceGenderDefaultHeight(int race, int gender);
// player race-/gender-based model feature validators
namespace PlayerAppearance
{
bool IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin = true);
bool IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin = true);
bool IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin = true);
bool IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin = true);
bool IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin = true);
bool IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin = true);
bool IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin = true);
bool IsValidHead(uint16 race_id, uint8 gender_id, uint8 head_value, bool use_luclin = true);
bool IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin = true);
bool IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin = true);
bool IsValidTexture(uint16 race_id, uint8 gender_id, uint8 texture_value, bool use_luclin = true);
bool IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin = true);
namespace Gender {
constexpr uint8 Male = 0;
constexpr uint8 Female = 1;
constexpr uint8 Neuter = 2;
}
namespace Race {
@ -884,8 +776,92 @@ namespace Race {
constexpr uint16 Pegasus3 = 732;
constexpr uint16 InteractiveObject = 2250;
constexpr uint16 Node = 2254;
}
constexpr uint16 ALL_RACES_BITMASK = 65535;
namespace RaceBitmask {
constexpr uint16 Unknown = 0;
constexpr uint16 Human = 1;
constexpr uint16 Barbarian = 2;
constexpr uint16 Erudite = 4;
constexpr uint16 WoodElf = 8;
constexpr uint16 HighElf = 16;
constexpr uint16 DarkElf = 32;
constexpr uint16 HalfElf = 64;
constexpr uint16 Dwarf = 128;
constexpr uint16 Troll = 256;
constexpr uint16 Ogre = 512;
constexpr uint16 Halfling = 1024;
constexpr uint16 Gnome = 2048;
constexpr uint16 Iksar = 4096;
constexpr uint16 VahShir = 8192;
constexpr uint16 Froglok = 16384;
constexpr uint16 Drakkin = 32768;
constexpr uint16 All = 65535;
}
namespace RaceIndex {
constexpr uint16 Human = 1;
constexpr uint16 Barbarian = 2;
constexpr uint16 Erudite = 3;
constexpr uint16 WoodElf = 4;
constexpr uint16 HighElf = 5;
constexpr uint16 DarkElf = 6;
constexpr uint16 HalfElf = 7;
constexpr uint16 Dwarf = 8;
constexpr uint16 Troll = 9;
constexpr uint16 Ogre = 10;
constexpr uint16 Halfling = 11;
constexpr uint16 Gnome = 12;
constexpr uint16 Iksar = 13;
constexpr uint16 VahShir = 14;
constexpr uint16 Froglok = 15;
constexpr uint16 Drakkin = 16;
}
namespace RaceAppearance {
bool IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin = true);
bool IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin = true);
bool IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin = true);
bool IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin = true);
bool IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin = true);
bool IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin = true);
bool IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin = true);
bool IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin = true);
bool IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin = true);
bool IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin = true);
constexpr int HumanMale = (Race::Human << 8) | Gender::Male;
constexpr int HumanFemale = (Race::Human << 8) | Gender::Female;
constexpr int BarbarianMale = (Race::Barbarian << 8) | Gender::Male;
constexpr int BarbarianFemale = (Race::Barbarian << 8) | Gender::Female;
constexpr int EruditeMale = (Race::Erudite << 8) | Gender::Male;
constexpr int EruditeFemale = (Race::Erudite << 8) | Gender::Female;
constexpr int WoodElfMale = (Race::WoodElf << 8) | Gender::Male;
constexpr int WoodElfFemale = (Race::WoodElf << 8) | Gender::Female;
constexpr int HighElfMale = (Race::HighElf << 8) | Gender::Male;
constexpr int HighElfFemale = (Race::HighElf << 8) | Gender::Female;
constexpr int DarkElfMale = (Race::DarkElf << 8) | Gender::Male;
constexpr int DarkElfFemale = (Race::DarkElf << 8) | Gender::Female;
constexpr int HalfElfMale = (Race::HalfElf << 8) | Gender::Male;
constexpr int HalfElfFemale = (Race::HalfElf << 8) | Gender::Female;
constexpr int DwarfMale = (Race::Dwarf << 8) | Gender::Male;
constexpr int DwarfFemale = (Race::Dwarf << 8) | Gender::Female;
constexpr int TrollMale = (Race::Troll << 8) | Gender::Male;
constexpr int TrollFemale = (Race::Troll << 8) | Gender::Female;
constexpr int OgreMale = (Race::Ogre << 8) | Gender::Male;
constexpr int OgreFemale = (Race::Ogre << 8) | Gender::Female;
constexpr int HalflingMale = (Race::Halfling << 8) | Gender::Male;
constexpr int HalflingFemale = (Race::Halfling << 8) | Gender::Female;
constexpr int GnomeMale = (Race::Gnome << 8) | Gender::Male;
constexpr int GnomeFemale = (Race::Gnome << 8) | Gender::Female;
constexpr int IksarMale = (Race::Iksar << 8) | Gender::Male;
constexpr int IksarFemale = (Race::Iksar << 8) | Gender::Female;
constexpr int VahShirMale = (Race::VahShir << 8) | Gender::Male;
constexpr int VahShirFemale = (Race::VahShir << 8) | Gender::Female;
constexpr int FroglokMale = (Race::Froglok2 << 8) | Gender::Male;
constexpr int FroglokFemale = (Race::Froglok2 << 8) | Gender::Female;
constexpr int DrakkinMale = (Race::Drakkin << 8) | Gender::Male;
constexpr int DrakkinFemale = (Race::Drakkin << 8) | Gender::Female;
}
#endif

View File

@ -30,6 +30,7 @@ public:
uint32_t aug_slot_5;
uint32_t aug_slot_6;
uint32_t quantity;
uint32_t evolve_amount;
};
static std::string PrimaryKey()
@ -51,6 +52,7 @@ public:
"aug_slot_5",
"aug_slot_6",
"quantity",
"evolve_amount",
};
}
@ -68,6 +70,7 @@ public:
"aug_slot_5",
"aug_slot_6",
"quantity",
"evolve_amount",
};
}
@ -108,17 +111,18 @@ public:
{
CharacterParcelsContainers e{};
e.id = 0;
e.parcels_id = 0;
e.slot_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.quantity = 0;
e.id = 0;
e.parcels_id = 0;
e.slot_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.quantity = 0;
e.evolve_amount = 0;
return e;
}
@ -155,17 +159,18 @@ public:
if (results.RowCount() == 1) {
CharacterParcelsContainers e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
return e;
}
@ -209,6 +214,7 @@ public:
v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_5));
v.push_back(columns[9] + " = " + std::to_string(e.aug_slot_6));
v.push_back(columns[10] + " = " + std::to_string(e.quantity));
v.push_back(columns[11] + " = " + std::to_string(e.evolve_amount));
auto results = db.QueryDatabase(
fmt::format(
@ -241,6 +247,7 @@ public:
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
auto results = db.QueryDatabase(
fmt::format(
@ -281,6 +288,7 @@ public:
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@ -314,17 +322,18 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcelsContainers e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@ -349,17 +358,18 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcelsContainers e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.parcels_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.slot_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_1 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_2 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_3 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_4 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_5 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.aug_slot_6 = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@ -445,6 +455,7 @@ public:
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
auto results = db.QueryDatabase(
fmt::format(
@ -478,6 +489,7 @@ public:
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}

View File

@ -30,6 +30,7 @@ public:
uint32_t aug_slot_6;
uint32_t slot_id;
uint32_t quantity;
uint32_t evolve_amount;
std::string from_name;
std::string note;
time_t sent_date;
@ -54,6 +55,7 @@ public:
"aug_slot_6",
"slot_id",
"quantity",
"evolve_amount",
"from_name",
"note",
"sent_date",
@ -74,6 +76,7 @@ public:
"aug_slot_6",
"slot_id",
"quantity",
"evolve_amount",
"from_name",
"note",
"UNIX_TIMESTAMP(sent_date)",
@ -117,20 +120,21 @@ public:
{
CharacterParcels e{};
e.id = 0;
e.char_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.slot_id = 0;
e.quantity = 0;
e.from_name = "";
e.note = "";
e.sent_date = 0;
e.id = 0;
e.char_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.slot_id = 0;
e.quantity = 0;
e.evolve_amount = 0;
e.from_name = "";
e.note = "";
e.sent_date = 0;
return e;
}
@ -167,20 +171,21 @@ public:
if (results.RowCount() == 1) {
CharacterParcels e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.from_name = row[11] ? row[11] : "";
e.note = row[12] ? row[12] : "";
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.from_name = row[12] ? row[12] : "";
e.note = row[13] ? row[13] : "";
e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
return e;
}
@ -224,9 +229,10 @@ public:
v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_6));
v.push_back(columns[9] + " = " + std::to_string(e.slot_id));
v.push_back(columns[10] + " = " + std::to_string(e.quantity));
v.push_back(columns[11] + " = '" + Strings::Escape(e.from_name) + "'");
v.push_back(columns[12] + " = '" + Strings::Escape(e.note) + "'");
v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
v.push_back(columns[11] + " = " + std::to_string(e.evolve_amount));
v.push_back(columns[12] + " = '" + Strings::Escape(e.from_name) + "'");
v.push_back(columns[13] + " = '" + Strings::Escape(e.note) + "'");
v.push_back(columns[14] + " = FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
@ -259,6 +265,7 @@ public:
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
@ -302,6 +309,7 @@ public:
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
@ -338,20 +346,21 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcels e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.from_name = row[11] ? row[11] : "";
e.note = row[12] ? row[12] : "";
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.from_name = row[12] ? row[12] : "";
e.note = row[13] ? row[13] : "";
e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@ -376,20 +385,21 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterParcels e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.from_name = row[11] ? row[11] : "";
e.note = row[12] ? row[12] : "";
e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10);
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.slot_id = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.quantity = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.evolve_amount = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.from_name = row[12] ? row[12] : "";
e.note = row[13] ? row[13] : "";
e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@ -475,6 +485,7 @@ public:
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");
@ -511,6 +522,7 @@ public:
v.push_back(std::to_string(e.aug_slot_6));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.quantity));
v.push_back(std::to_string(e.evolve_amount));
v.push_back("'" + Strings::Escape(e.from_name) + "'");
v.push_back("'" + Strings::Escape(e.note) + "'");
v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")");

View File

@ -70,6 +70,7 @@ public:
int32_t endurance_regen;
int32_t shielding;
int32_t spell_damage;
int32_t heal_amount;
int32_t spell_shielding;
int32_t strikethrough;
int32_t stun_resist;
@ -154,6 +155,7 @@ public:
"endurance_regen",
"shielding",
"spell_damage",
"heal_amount",
"spell_shielding",
"strikethrough",
"stun_resist",
@ -234,6 +236,7 @@ public:
"endurance_regen",
"shielding",
"spell_damage",
"heal_amount",
"spell_shielding",
"strikethrough",
"stun_resist",
@ -348,6 +351,7 @@ public:
e.endurance_regen = 0;
e.shielding = 0;
e.spell_damage = 0;
e.heal_amount = 0;
e.spell_shielding = 0;
e.strikethrough = 0;
e.stun_resist = 0;
@ -458,29 +462,30 @@ public:
e.endurance_regen = row[48] ? static_cast<int32_t>(atoi(row[48])) : 0;
e.shielding = row[49] ? static_cast<int32_t>(atoi(row[49])) : 0;
e.spell_damage = row[50] ? static_cast<int32_t>(atoi(row[50])) : 0;
e.spell_shielding = row[51] ? static_cast<int32_t>(atoi(row[51])) : 0;
e.strikethrough = row[52] ? static_cast<int32_t>(atoi(row[52])) : 0;
e.stun_resist = row[53] ? static_cast<int32_t>(atoi(row[53])) : 0;
e.backstab = row[54] ? static_cast<int32_t>(atoi(row[54])) : 0;
e.wind = row[55] ? static_cast<int32_t>(atoi(row[55])) : 0;
e.brass = row[56] ? static_cast<int32_t>(atoi(row[56])) : 0;
e.string = row[57] ? static_cast<int32_t>(atoi(row[57])) : 0;
e.percussion = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.singing = row[59] ? static_cast<int32_t>(atoi(row[59])) : 0;
e.baking = row[60] ? static_cast<int32_t>(atoi(row[60])) : 0;
e.alchemy = row[61] ? static_cast<int32_t>(atoi(row[61])) : 0;
e.tailoring = row[62] ? static_cast<int32_t>(atoi(row[62])) : 0;
e.blacksmithing = row[63] ? static_cast<int32_t>(atoi(row[63])) : 0;
e.fletching = row[64] ? static_cast<int32_t>(atoi(row[64])) : 0;
e.brewing = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.jewelry = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.pottery = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.research = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.alcohol = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.fishing = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.tinkering = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.created_at = strtoll(row[72] ? row[72] : "-1", nullptr, 10);
e.updated_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10);
e.heal_amount = row[51] ? static_cast<int32_t>(atoi(row[51])) : 0;
e.spell_shielding = row[52] ? static_cast<int32_t>(atoi(row[52])) : 0;
e.strikethrough = row[53] ? static_cast<int32_t>(atoi(row[53])) : 0;
e.stun_resist = row[54] ? static_cast<int32_t>(atoi(row[54])) : 0;
e.backstab = row[55] ? static_cast<int32_t>(atoi(row[55])) : 0;
e.wind = row[56] ? static_cast<int32_t>(atoi(row[56])) : 0;
e.brass = row[57] ? static_cast<int32_t>(atoi(row[57])) : 0;
e.string = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.percussion = row[59] ? static_cast<int32_t>(atoi(row[59])) : 0;
e.singing = row[60] ? static_cast<int32_t>(atoi(row[60])) : 0;
e.baking = row[61] ? static_cast<int32_t>(atoi(row[61])) : 0;
e.alchemy = row[62] ? static_cast<int32_t>(atoi(row[62])) : 0;
e.tailoring = row[63] ? static_cast<int32_t>(atoi(row[63])) : 0;
e.blacksmithing = row[64] ? static_cast<int32_t>(atoi(row[64])) : 0;
e.fletching = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.brewing = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.jewelry = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.pottery = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.research = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.alcohol = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.fishing = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.tinkering = row[72] ? static_cast<int32_t>(atoi(row[72])) : 0;
e.created_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10);
e.updated_at = strtoll(row[74] ? row[74] : "-1", nullptr, 10);
return e;
}
@ -565,29 +570,30 @@ public:
v.push_back(columns[48] + " = " + std::to_string(e.endurance_regen));
v.push_back(columns[49] + " = " + std::to_string(e.shielding));
v.push_back(columns[50] + " = " + std::to_string(e.spell_damage));
v.push_back(columns[51] + " = " + std::to_string(e.spell_shielding));
v.push_back(columns[52] + " = " + std::to_string(e.strikethrough));
v.push_back(columns[53] + " = " + std::to_string(e.stun_resist));
v.push_back(columns[54] + " = " + std::to_string(e.backstab));
v.push_back(columns[55] + " = " + std::to_string(e.wind));
v.push_back(columns[56] + " = " + std::to_string(e.brass));
v.push_back(columns[57] + " = " + std::to_string(e.string));
v.push_back(columns[58] + " = " + std::to_string(e.percussion));
v.push_back(columns[59] + " = " + std::to_string(e.singing));
v.push_back(columns[60] + " = " + std::to_string(e.baking));
v.push_back(columns[61] + " = " + std::to_string(e.alchemy));
v.push_back(columns[62] + " = " + std::to_string(e.tailoring));
v.push_back(columns[63] + " = " + std::to_string(e.blacksmithing));
v.push_back(columns[64] + " = " + std::to_string(e.fletching));
v.push_back(columns[65] + " = " + std::to_string(e.brewing));
v.push_back(columns[66] + " = " + std::to_string(e.jewelry));
v.push_back(columns[67] + " = " + std::to_string(e.pottery));
v.push_back(columns[68] + " = " + std::to_string(e.research));
v.push_back(columns[69] + " = " + std::to_string(e.alcohol));
v.push_back(columns[70] + " = " + std::to_string(e.fishing));
v.push_back(columns[71] + " = " + std::to_string(e.tinkering));
v.push_back(columns[72] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
v.push_back(columns[73] + " = FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")");
v.push_back(columns[51] + " = " + std::to_string(e.heal_amount));
v.push_back(columns[52] + " = " + std::to_string(e.spell_shielding));
v.push_back(columns[53] + " = " + std::to_string(e.strikethrough));
v.push_back(columns[54] + " = " + std::to_string(e.stun_resist));
v.push_back(columns[55] + " = " + std::to_string(e.backstab));
v.push_back(columns[56] + " = " + std::to_string(e.wind));
v.push_back(columns[57] + " = " + std::to_string(e.brass));
v.push_back(columns[58] + " = " + std::to_string(e.string));
v.push_back(columns[59] + " = " + std::to_string(e.percussion));
v.push_back(columns[60] + " = " + std::to_string(e.singing));
v.push_back(columns[61] + " = " + std::to_string(e.baking));
v.push_back(columns[62] + " = " + std::to_string(e.alchemy));
v.push_back(columns[63] + " = " + std::to_string(e.tailoring));
v.push_back(columns[64] + " = " + std::to_string(e.blacksmithing));
v.push_back(columns[65] + " = " + std::to_string(e.fletching));
v.push_back(columns[66] + " = " + std::to_string(e.brewing));
v.push_back(columns[67] + " = " + std::to_string(e.jewelry));
v.push_back(columns[68] + " = " + std::to_string(e.pottery));
v.push_back(columns[69] + " = " + std::to_string(e.research));
v.push_back(columns[70] + " = " + std::to_string(e.alcohol));
v.push_back(columns[71] + " = " + std::to_string(e.fishing));
v.push_back(columns[72] + " = " + std::to_string(e.tinkering));
v.push_back(columns[73] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
v.push_back(columns[74] + " = FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
@ -660,6 +666,7 @@ public:
v.push_back(std::to_string(e.endurance_regen));
v.push_back(std::to_string(e.shielding));
v.push_back(std::to_string(e.spell_damage));
v.push_back(std::to_string(e.heal_amount));
v.push_back(std::to_string(e.spell_shielding));
v.push_back(std::to_string(e.strikethrough));
v.push_back(std::to_string(e.stun_resist));
@ -763,6 +770,7 @@ public:
v.push_back(std::to_string(e.endurance_regen));
v.push_back(std::to_string(e.shielding));
v.push_back(std::to_string(e.spell_damage));
v.push_back(std::to_string(e.heal_amount));
v.push_back(std::to_string(e.spell_shielding));
v.push_back(std::to_string(e.strikethrough));
v.push_back(std::to_string(e.stun_resist));
@ -870,29 +878,30 @@ public:
e.endurance_regen = row[48] ? static_cast<int32_t>(atoi(row[48])) : 0;
e.shielding = row[49] ? static_cast<int32_t>(atoi(row[49])) : 0;
e.spell_damage = row[50] ? static_cast<int32_t>(atoi(row[50])) : 0;
e.spell_shielding = row[51] ? static_cast<int32_t>(atoi(row[51])) : 0;
e.strikethrough = row[52] ? static_cast<int32_t>(atoi(row[52])) : 0;
e.stun_resist = row[53] ? static_cast<int32_t>(atoi(row[53])) : 0;
e.backstab = row[54] ? static_cast<int32_t>(atoi(row[54])) : 0;
e.wind = row[55] ? static_cast<int32_t>(atoi(row[55])) : 0;
e.brass = row[56] ? static_cast<int32_t>(atoi(row[56])) : 0;
e.string = row[57] ? static_cast<int32_t>(atoi(row[57])) : 0;
e.percussion = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.singing = row[59] ? static_cast<int32_t>(atoi(row[59])) : 0;
e.baking = row[60] ? static_cast<int32_t>(atoi(row[60])) : 0;
e.alchemy = row[61] ? static_cast<int32_t>(atoi(row[61])) : 0;
e.tailoring = row[62] ? static_cast<int32_t>(atoi(row[62])) : 0;
e.blacksmithing = row[63] ? static_cast<int32_t>(atoi(row[63])) : 0;
e.fletching = row[64] ? static_cast<int32_t>(atoi(row[64])) : 0;
e.brewing = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.jewelry = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.pottery = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.research = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.alcohol = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.fishing = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.tinkering = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.created_at = strtoll(row[72] ? row[72] : "-1", nullptr, 10);
e.updated_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10);
e.heal_amount = row[51] ? static_cast<int32_t>(atoi(row[51])) : 0;
e.spell_shielding = row[52] ? static_cast<int32_t>(atoi(row[52])) : 0;
e.strikethrough = row[53] ? static_cast<int32_t>(atoi(row[53])) : 0;
e.stun_resist = row[54] ? static_cast<int32_t>(atoi(row[54])) : 0;
e.backstab = row[55] ? static_cast<int32_t>(atoi(row[55])) : 0;
e.wind = row[56] ? static_cast<int32_t>(atoi(row[56])) : 0;
e.brass = row[57] ? static_cast<int32_t>(atoi(row[57])) : 0;
e.string = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.percussion = row[59] ? static_cast<int32_t>(atoi(row[59])) : 0;
e.singing = row[60] ? static_cast<int32_t>(atoi(row[60])) : 0;
e.baking = row[61] ? static_cast<int32_t>(atoi(row[61])) : 0;
e.alchemy = row[62] ? static_cast<int32_t>(atoi(row[62])) : 0;
e.tailoring = row[63] ? static_cast<int32_t>(atoi(row[63])) : 0;
e.blacksmithing = row[64] ? static_cast<int32_t>(atoi(row[64])) : 0;
e.fletching = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.brewing = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.jewelry = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.pottery = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.research = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.alcohol = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.fishing = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.tinkering = row[72] ? static_cast<int32_t>(atoi(row[72])) : 0;
e.created_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10);
e.updated_at = strtoll(row[74] ? row[74] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@ -968,29 +977,30 @@ public:
e.endurance_regen = row[48] ? static_cast<int32_t>(atoi(row[48])) : 0;
e.shielding = row[49] ? static_cast<int32_t>(atoi(row[49])) : 0;
e.spell_damage = row[50] ? static_cast<int32_t>(atoi(row[50])) : 0;
e.spell_shielding = row[51] ? static_cast<int32_t>(atoi(row[51])) : 0;
e.strikethrough = row[52] ? static_cast<int32_t>(atoi(row[52])) : 0;
e.stun_resist = row[53] ? static_cast<int32_t>(atoi(row[53])) : 0;
e.backstab = row[54] ? static_cast<int32_t>(atoi(row[54])) : 0;
e.wind = row[55] ? static_cast<int32_t>(atoi(row[55])) : 0;
e.brass = row[56] ? static_cast<int32_t>(atoi(row[56])) : 0;
e.string = row[57] ? static_cast<int32_t>(atoi(row[57])) : 0;
e.percussion = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.singing = row[59] ? static_cast<int32_t>(atoi(row[59])) : 0;
e.baking = row[60] ? static_cast<int32_t>(atoi(row[60])) : 0;
e.alchemy = row[61] ? static_cast<int32_t>(atoi(row[61])) : 0;
e.tailoring = row[62] ? static_cast<int32_t>(atoi(row[62])) : 0;
e.blacksmithing = row[63] ? static_cast<int32_t>(atoi(row[63])) : 0;
e.fletching = row[64] ? static_cast<int32_t>(atoi(row[64])) : 0;
e.brewing = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.jewelry = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.pottery = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.research = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.alcohol = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.fishing = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.tinkering = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.created_at = strtoll(row[72] ? row[72] : "-1", nullptr, 10);
e.updated_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10);
e.heal_amount = row[51] ? static_cast<int32_t>(atoi(row[51])) : 0;
e.spell_shielding = row[52] ? static_cast<int32_t>(atoi(row[52])) : 0;
e.strikethrough = row[53] ? static_cast<int32_t>(atoi(row[53])) : 0;
e.stun_resist = row[54] ? static_cast<int32_t>(atoi(row[54])) : 0;
e.backstab = row[55] ? static_cast<int32_t>(atoi(row[55])) : 0;
e.wind = row[56] ? static_cast<int32_t>(atoi(row[56])) : 0;
e.brass = row[57] ? static_cast<int32_t>(atoi(row[57])) : 0;
e.string = row[58] ? static_cast<int32_t>(atoi(row[58])) : 0;
e.percussion = row[59] ? static_cast<int32_t>(atoi(row[59])) : 0;
e.singing = row[60] ? static_cast<int32_t>(atoi(row[60])) : 0;
e.baking = row[61] ? static_cast<int32_t>(atoi(row[61])) : 0;
e.alchemy = row[62] ? static_cast<int32_t>(atoi(row[62])) : 0;
e.tailoring = row[63] ? static_cast<int32_t>(atoi(row[63])) : 0;
e.blacksmithing = row[64] ? static_cast<int32_t>(atoi(row[64])) : 0;
e.fletching = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.brewing = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.jewelry = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.pottery = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.research = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.alcohol = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.fishing = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.tinkering = row[72] ? static_cast<int32_t>(atoi(row[72])) : 0;
e.created_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10);
e.updated_at = strtoll(row[74] ? row[74] : "-1", nullptr, 10);
all_entries.push_back(e);
}
@ -1116,6 +1126,7 @@ public:
v.push_back(std::to_string(e.endurance_regen));
v.push_back(std::to_string(e.shielding));
v.push_back(std::to_string(e.spell_damage));
v.push_back(std::to_string(e.heal_amount));
v.push_back(std::to_string(e.spell_shielding));
v.push_back(std::to_string(e.strikethrough));
v.push_back(std::to_string(e.stun_resist));
@ -1212,6 +1223,7 @@ public:
v.push_back(std::to_string(e.endurance_regen));
v.push_back(std::to_string(e.shielding));
v.push_back(std::to_string(e.spell_damage));
v.push_back(std::to_string(e.heal_amount));
v.push_back(std::to_string(e.spell_shielding));
v.push_back(std::to_string(e.strikethrough));
v.push_back(std::to_string(e.stun_resist));

View File

@ -191,6 +191,22 @@ public:
return character_ids;
}
static uint32_t GetTotalTimePlayed(Database& db, uint32_t account_id)
{
auto query = fmt::format(
"SELECT SUM(time_played) FROM `character_data` WHERE `account_id` = {}",
account_id
);
auto results = db.QueryDatabase(query);
if (!results.Success()) {
return 0;
}
auto row = results.begin();
return Strings::ToUnsignedInt(row[0]);
}
};
#endif //EQEMU_CHARACTER_DATA_REPOSITORY_H

View File

@ -49,6 +49,7 @@ public:
// these are the base definitions for command_subsettings and can be over-ridden by the database
std::vector<CommandSubsettingsRepository::CommandSubsettings> static_records = {
{.parent_command = "find", .sub_command = "aa", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaa"},
{.parent_command = "find", .sub_command = "account", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaccount"},
{.parent_command = "find", .sub_command = "body_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findbodytype"},
{.parent_command = "find", .sub_command = "bug_category", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findbugcategory"},
{.parent_command = "find", .sub_command = "character", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcharacter"},

View File

@ -619,7 +619,7 @@ RULE_INT(Combat, SneakPullAssistRange, 400, "Modified range of assist for sneak
RULE_BOOL(Combat, Classic2HBAnimation, false, "2HB will use the 2 hand piercing animation instead of the overhead slashing animation")
RULE_BOOL(Combat, ArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption")
RULE_BOOL(Combat, ThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption")
RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SE_RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.")
RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SpellEffect::RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.")
RULE_INT(Combat, FrontalStunImmunityClasses, 0, "Bitmask for Classes than have frontal stun immunity, No Races (0) by default.")
RULE_BOOL(Combat, NPCsUseFrontalStunImmunityClasses, false, "Enable or disable NPCs using frontal stun immunity Classes from Combat:FrontalStunImmunityClasses, false by default.")
RULE_INT(Combat, FrontalStunImmunityRaces, 512, "Bitmask for Races than have frontal stun immunity, Ogre (512) only by default.")

View File

@ -51,19 +51,10 @@
#include "repositories/inventory_repository.h"
#include "repositories/books_repository.h"
#include "repositories/sharedbank_repository.h"
namespace ItemField
{
enum {
source = 0,
#define F(x) x,
#include "item_fieldlist.h"
#undef F
updated,
minstatus,
comment,
};
}
#include "repositories/character_inspect_messages_repository.h"
#include "repositories/spells_new_repository.h"
#include "repositories/damageshieldtypes_repository.h"
#include "repositories/items_repository.h"
SharedDatabase::SharedDatabase()
: Database()
@ -131,66 +122,41 @@ bool SharedDatabase::SetGMFlymode(uint32 account_id, uint8 flymode)
return a.id > 0;
}
uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
uint32 EntitledTime = 0;
const std::string query = StringFormat("SELECT `time_played` FROM `character_data` WHERE `account_id` = %u", AccountID);
auto results = QueryDatabase(query);
for (auto& row = results.begin(); row != results.end(); ++row) {
EntitledTime += Strings::ToUnsignedInt(row[0]);
}
return EntitledTime;
}
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
void SharedDatabase::SetMailKey(uint32 character_id, uint32 ip_address, uint32 mail_key)
{
char mail_key[17];
std::string full_mail_key;
if (RuleB(Chat, EnableMailKeyIPVerification) == true) {
sprintf(mail_key, "%08X%08X", IPAddress, MailKey);
}
else {
sprintf(mail_key, "%08X", MailKey);
if (RuleB(Chat, EnableMailKeyIPVerification)) {
full_mail_key = fmt::format("{:08X}{:08X}", ip_address, mail_key);
} else {
full_mail_key = fmt::format("{:08X}", mail_key);
}
const std::string query = StringFormat(
"UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
mail_key, CharID
);
auto e = CharacterDataRepository::FindOne(*this, character_id);
if (!e.id) {
LogError("Failed to find character_id [{}] when setting mailkey", character_id);
return;
}
const auto results = QueryDatabase(query);
if (!results.Success()) {
LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, mail_key, results.ErrorMessage().c_str());
e.mailkey = full_mail_key;
if (!CharacterDataRepository::UpdateOne(*this, e)) {
LogError("Failed to set mailkey to [{}] for character_id [{}]", full_mail_key, character_id);
}
}
SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id)
SharedDatabase::MailKeys SharedDatabase::GetMailKey(uint32 character_id)
{
const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", character_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return MailKeys{};
auto e = CharacterDataRepository::FindOne(*this, character_id);
if (!e.id) {
return MailKeys{ };
}
if (!results.RowCount()) {
Log(Logs::General,
Logs::ClientLogin,
"Error: Mailkey for character id [%i] does not exist or could not be found",
character_id
);
return MailKeys{};
}
auto &row = results.begin();
if (row != results.end()) {
std::string mail_key = row[0];
return MailKeys{
.mail_key = mail_key.substr(8),
.mail_key_full = mail_key
};
}
return MailKeys{};
return MailKeys{
.mail_key = e.mailkey.substr(8),
.mail_key_full = e.mailkey
};
}
bool SharedDatabase::SaveCursor(
@ -457,27 +423,20 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id)
);
}
int32 SharedDatabase::GetSharedPlatinum(uint32 account_id)
{
const auto query = fmt::format("SELECT sharedplat FROM account WHERE id = {}", account_id);
auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
return 0;
}
const auto& e = AccountRepository::FindOne(*this, account_id);
auto row = results.begin();
return Strings::ToInt(row[0]);
return e.sharedplat;
}
bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
const std::string query = StringFormat("UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id);
const auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
bool SharedDatabase::AddSharedPlatinum(uint32 account_id, int amount)
{
auto e = AccountRepository::FindOne(*this, account_id);
return true;
e.sharedplat += amount;
return AccountRepository::UpdateOne(*this, e);
}
bool SharedDatabase::SetStartingItems(
@ -944,27 +903,10 @@ void SharedDatabase::ClearOldRecastTimestamps(uint32 char_id)
);
}
void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id)
void SharedDatabase::GetItemsCount(int32& item_count, uint32& max_id)
{
item_count = -1;
max_id = 0;
const std::string query = "SELECT MAX(id), count(*) FROM items";
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
if (results.RowCount() == 0)
return;
auto& row = results.begin();
if (row[0])
max_id = Strings::ToUnsignedInt(row[0]);
if (row[1])
item_count = Strings::ToUnsignedInt(row[1]);
max_id = ItemsRepository::GetMaxId(*this);
item_count = ItemsRepository::Count(*this);
}
bool SharedDatabase::LoadItems(const std::string &prefix) {
@ -994,14 +936,14 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
std::string variable_buffer;
bool disable_attuneable = RuleB(Items, DisableAttuneable);
bool disable_bard_focus_effects = RuleB(Items, DisableBardFocusEffects);
bool disable_lore = RuleB(Items, DisableLore);
bool disable_no_drop = RuleB(Items, DisableNoDrop);
bool disable_no_pet = RuleB(Items, DisableNoPet);
bool disable_no_rent = RuleB(Items, DisableNoRent);
bool disable_no_transfer = RuleB(Items, DisableNoTransfer);
bool disable_potion_belt = RuleB(Items, DisablePotionBelt);
bool disable_attuneable = RuleB(Items, DisableAttuneable);
bool disable_bard_focus_effects = RuleB(Items, DisableBardFocusEffects);
bool disable_lore = RuleB(Items, DisableLore);
bool disable_no_drop = RuleB(Items, DisableNoDrop);
bool disable_no_pet = RuleB(Items, DisableNoPet);
bool disable_no_rent = RuleB(Items, DisableNoRent);
bool disable_no_transfer = RuleB(Items, DisableNoTransfer);
bool disable_potion_belt = RuleB(Items, DisablePotionBelt);
bool disable_spell_focus_effects = RuleB(Items, DisableSpellFocusEffects);
// Old Variable Code
@ -1032,206 +974,204 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
EQ::ItemData item;
const std::string query = "SELECT source,"
#define F(x) "`"#x"`,"
#include "item_fieldlist.h"
#undef F
"updated, minstatus, comment FROM items ORDER BY id";
auto results = QueryDatabase(query);
if (!results.Success()) {
const auto& l = ItemsRepository::All(*this);
if (l.empty()) {
return;
}
for (auto& row = results.begin(); row != results.end(); ++row) {
for (const auto& e : l) {
memset(&item, 0, sizeof(EQ::ItemData));
// Unique Identifier
item.ID = Strings::ToUnsignedInt(row[ItemField::id]);
item.ID = e.id;
// Minimum Status
item.MinStatus = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::minstatus]));
item.MinStatus = static_cast<uint8>(e.minstatus);
// Name, Lore, and Comment
strn0cpy(item.Name, row[ItemField::name], sizeof(item.Name));
strn0cpy(item.Lore, row[ItemField::lore], sizeof(item.Lore));
strn0cpy(item.Comment, row[ItemField::comment], sizeof(item.Comment));
strn0cpy(item.Name, e.Name.c_str(), sizeof(item.Name));
strn0cpy(item.Lore, e.lore.c_str(), sizeof(item.Lore));
strn0cpy(item.Comment, e.comment.c_str(), sizeof(item.Comment));
// Flags
item.ArtifactFlag = Strings::ToBool(row[ItemField::artifactflag]);
item.Attuneable = !disable_attuneable && Strings::ToBool(row[ItemField::attuneable]);
item.BenefitFlag = Strings::ToBool(row[ItemField::benefitflag]);
item.FVNoDrop = Strings::ToBool(row[ItemField::fvnodrop]);
item.Magic = Strings::ToBool(row[ItemField::magic]);
item.NoDrop = disable_no_drop ? static_cast<uint8>(255) : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::nodrop]));
item.NoPet = !disable_no_pet && Strings::ToBool(row[ItemField::nopet]);
item.NoRent = disable_no_rent ? static_cast<uint8>(255) : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::norent]));
item.NoTransfer = !disable_no_transfer && Strings::ToBool(row[ItemField::notransfer]);
item.PendingLoreFlag = Strings::ToBool(row[ItemField::pendingloreflag]);
item.QuestItemFlag = Strings::ToBool(row[ItemField::questitemflag]);
item.Stackable = Strings::ToBool(row[ItemField::stackable]);
item.Tradeskills = Strings::ToBool(row[ItemField::tradeskills]);
item.SummonedFlag = Strings::ToBool(row[ItemField::summonedflag]);
item.ArtifactFlag = e.artifactflag;
item.Attuneable = !disable_attuneable && e.attuneable;
item.BenefitFlag = e.benefitflag;
item.FVNoDrop = e.fvnodrop;
item.Magic = e.magic;
item.NoDrop = disable_no_drop ? std::numeric_limits<uint8>::max() : e.nodrop;
item.NoPet = !disable_no_pet && e.nopet;
item.NoRent = disable_no_rent ? std::numeric_limits<uint8>::max() : e.norent;
item.NoTransfer = !disable_no_transfer && e.notransfer;
item.PendingLoreFlag = e.pendingloreflag;
item.QuestItemFlag = e.questitemflag;
item.Stackable = e.stackable;
item.Tradeskills = e.tradeskills;
item.SummonedFlag = e.summonedflag;
// Lore
item.LoreGroup = disable_lore ? 0 : Strings::ToInt(row[ItemField::loregroup]);
item.LoreFlag = !disable_lore && item.LoreGroup != 0;
item.LoreGroup = disable_lore ? 0 : e.loregroup;
item.LoreFlag = !disable_lore && item.LoreGroup != 0;
// Type
item.AugType = Strings::ToUnsignedInt(row[ItemField::augtype]);
item.ItemType = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::itemtype]));
item.SubType = Strings::ToInt(row[ItemField::subtype]);
item.AugType = e.augtype;
item.ItemType = static_cast<uint8>(e.itemtype);
item.SubType = e.subtype;
// Miscellaneous
item.ExpendableArrow = static_cast<uint16>(Strings::ToUnsignedInt(row[ItemField::expendablearrow]));
item.Light = static_cast<int8>(Strings::ToInt(row[ItemField::light]));
item.MaxCharges = static_cast<int16>(Strings::ToInt(row[ItemField::maxcharges]));
item.Size = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::size]));
item.StackSize = static_cast<int16>(Strings::ToInt(row[ItemField::stacksize]));
item.Weight = Strings::ToInt(row[ItemField::weight]);
item.ExpendableArrow = e.expendablearrow;
item.Light = EQ::Clamp(e.light, -128, 127);
item.MaxCharges = e.maxcharges;
item.Size = static_cast<uint8>(e.size);
item.StackSize = e.stacksize;
item.Weight = e.weight;
// Potion Belt
item.PotionBelt = !disable_potion_belt && Strings::ToBool(row[ItemField::potionbelt]);
item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::potionbeltslots]));
item.PotionBelt = !disable_potion_belt && e.potionbelt;
item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast<uint8>(e.potionbeltslots);
// Merchant
item.Favor = Strings::ToUnsignedInt(row[ItemField::favor]);
item.GuildFavor = Strings::ToUnsignedInt(row[ItemField::guildfavor]);
item.Price = Strings::ToUnsignedInt(row[ItemField::price]);
item.SellRate = Strings::ToFloat(row[ItemField::sellrate]);
item.Favor = e.favor;
item.GuildFavor = e.guildfavor;
item.Price = e.price;
item.SellRate = e.sellrate;
// Display
item.Color = Strings::ToUnsignedInt(row[ItemField::color]);
item.EliteMaterial = Strings::ToUnsignedInt(row[ItemField::elitematerial]);
item.HerosForgeModel = Strings::ToUnsignedInt(row[ItemField::herosforgemodel]);
item.Icon = Strings::ToUnsignedInt(row[ItemField::icon]);
strn0cpy(item.IDFile, row[ItemField::idfile], sizeof(item.IDFile));
item.Material = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::material]));
item.Color = e.color;
item.EliteMaterial = e.elitematerial;
item.HerosForgeModel = e.herosforgemodel;
item.Icon = e.icon;
strn0cpy(item.IDFile, e.idfile.c_str(), sizeof(item.IDFile));
item.Material = e.material;
// Resists
item.CR = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::cr]), -128, 127));
item.DR = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::dr]), -128, 127));
item.FR = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::fr]), -128, 127));
item.MR = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::mr]), -128, 127));
item.PR = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::pr]), -128, 127));
item.SVCorruption = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::svcorruption]), -128, 127));
item.CR = EQ::Clamp(e.cr, -128, 127);
item.DR = EQ::Clamp(e.dr, -128, 127);
item.FR = EQ::Clamp(e.fr, -128, 127);
item.MR = EQ::Clamp(e.mr, -128, 127);
item.PR = EQ::Clamp(e.pr, -128, 127);
item.SVCorruption = EQ::Clamp(e.svcorruption, -128, 127);
// Heroic Resists
item.HeroicCR = Strings::ToInt(row[ItemField::heroic_cr]);
item.HeroicDR = Strings::ToInt(row[ItemField::heroic_dr]);
item.HeroicFR = Strings::ToInt(row[ItemField::heroic_fr]);
item.HeroicMR = Strings::ToInt(row[ItemField::heroic_mr]);
item.HeroicPR = Strings::ToInt(row[ItemField::heroic_pr]);
item.HeroicSVCorrup = Strings::ToInt(row[ItemField::heroic_svcorrup]);
item.HeroicCR = e.heroic_cr;
item.HeroicDR = e.heroic_dr;
item.HeroicFR = e.heroic_fr;
item.HeroicMR = e.heroic_mr;
item.HeroicPR = e.heroic_pr;
item.HeroicSVCorrup = e.heroic_svcorrup;
// Stats
item.AAgi = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::aagi]), -128, 127));
item.ACha = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::acha]), -128, 127));
item.ADex = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::adex]), -128, 127));
item.AInt = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::aint]), -128, 127));
item.ASta = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::asta]), -128, 127));
item.AStr = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::astr]), -128, 127));
item.AWis = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::awis]), -128, 127));
item.AAgi = EQ::Clamp(e.aagi, -128, 127);
item.ACha = EQ::Clamp(e.acha, -128, 127);
item.ADex = EQ::Clamp(e.adex, -128, 127);
item.AInt = EQ::Clamp(e.aint, -128, 127);
item.ASta = EQ::Clamp(e.asta, -128, 127);
item.AStr = EQ::Clamp(e.astr, -128, 127);
item.AWis = EQ::Clamp(e.awis, -128, 127);
// Heroic Stats
item.HeroicAgi = Strings::ToInt(row[ItemField::heroic_agi]);
item.HeroicCha = Strings::ToInt(row[ItemField::heroic_cha]);
item.HeroicDex = Strings::ToInt(row[ItemField::heroic_dex]);
item.HeroicInt = Strings::ToInt(row[ItemField::heroic_int]);
item.HeroicSta = Strings::ToInt(row[ItemField::heroic_sta]);
item.HeroicStr = Strings::ToInt(row[ItemField::heroic_str]);
item.HeroicWis = Strings::ToInt(row[ItemField::heroic_wis]);
item.HeroicAgi = e.heroic_agi;
item.HeroicCha = e.heroic_cha;
item.HeroicDex = e.heroic_dex;
item.HeroicInt = e.heroic_int;
item.HeroicSta = e.heroic_sta;
item.HeroicStr = e.heroic_str;
item.HeroicWis = e.heroic_wis;
// Health, Mana, and Endurance
item.HP = Strings::ToInt(row[ItemField::hp]);
item.Regen = Strings::ToInt(row[ItemField::regen]);
item.Mana = Strings::ToInt(row[ItemField::mana]);
item.ManaRegen = Strings::ToInt(row[ItemField::manaregen]);
item.Endur = Strings::ToInt(row[ItemField::endur]);
item.EnduranceRegen = Strings::ToInt(row[ItemField::enduranceregen]);
item.HP = e.hp;
item.Regen = e.regen;
item.Mana = e.mana;
item.ManaRegen = e.manaregen;
item.Endur = e.endur;
item.EnduranceRegen = e.enduranceregen;
// Bane Damage
item.BaneDmgAmt = Strings::ToInt(row[ItemField::banedmgamt]);
item.BaneDmgBody = Strings::ToUnsignedInt(row[ItemField::banedmgbody]);
item.BaneDmgRace = Strings::ToUnsignedInt(row[ItemField::banedmgrace]);
item.BaneDmgRaceAmt = Strings::ToUnsignedInt(row[ItemField::banedmgraceamt]);
item.BaneDmgAmt = e.banedmgamt;
item.BaneDmgBody = e.banedmgbody;
item.BaneDmgRace = e.banedmgrace;
item.BaneDmgRaceAmt = e.banedmgraceamt;
// Elemental Damage
item.ElemDmgType = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::elemdmgtype]));
item.ElemDmgAmt = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::elemdmgamt]));
item.ElemDmgType = static_cast<uint8>(e.elemdmgtype);
item.ElemDmgAmt = static_cast<uint8>(e.elemdmgamt);
// Combat
item.BackstabDmg = Strings::ToUnsignedInt(row[ItemField::backstabdmg]);
item.Damage = Strings::ToUnsignedInt(row[ItemField::damage]);
item.Delay = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::delay]));
item.Range = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::range]));
item.BackstabDmg = e.backstabdmg;
item.Damage = e.damage;
item.Delay = static_cast<uint8>(e.delay);
item.Range = static_cast<uint8>(e.range_);
// Combat Stats
item.AC = Strings::ToInt(row[ItemField::ac]);
item.Accuracy = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::accuracy]), -128, 127));
item.Attack = Strings::ToInt(row[ItemField::attack]);
item.Avoidance = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::avoidance]), -128, 127));
item.Clairvoyance = Strings::ToUnsignedInt(row[ItemField::clairvoyance]);
item.CombatEffects = Strings::IsNumber(row[ItemField::combateffects]) ? static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::combateffects]), -128, 127)) : 0;
item.DamageShield = Strings::ToInt(row[ItemField::damageshield]);
item.DotShielding = Strings::ToInt(row[ItemField::dotshielding]);
item.DSMitigation = Strings::ToUnsignedInt(row[ItemField::dsmitigation]);
item.Haste = Strings::ToInt(row[ItemField::haste]);
item.HealAmt = Strings::ToInt(row[ItemField::healamt]);
item.Purity = Strings::ToUnsignedInt(row[ItemField::purity]);
item.Shielding = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::shielding]), -128, 127));
item.SpellDmg = Strings::ToInt(row[ItemField::spelldmg]);
item.SpellShield = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::spellshield]), -128, 127));
item.StrikeThrough = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::strikethrough]), -128, 127));
item.StunResist = static_cast<int8>(EQ::Clamp(Strings::ToInt(row[ItemField::stunresist]), -128, 127));
item.AC = e.ac;
item.Accuracy = EQ::Clamp(e.accuracy, -128, 127);
item.Attack = e.attack;
item.Avoidance = EQ::Clamp(e.avoidance, -128, 127);
item.Clairvoyance = e.clairvoyance;
item.CombatEffects = Strings::IsNumber(e.combateffects) ? static_cast<int8>(EQ::Clamp(Strings::ToInt(e.combateffects), -128, 127)) : 0;
item.DamageShield = e.damageshield;
item.DotShielding = e.dotshielding;
item.DSMitigation = e.dsmitigation;
item.Haste = e.haste;
item.HealAmt = e.healamt;
item.Purity = e.purity;
item.Shielding = EQ::Clamp(e.shielding, -128, 127);
item.SpellDmg = e.spelldmg;
item.SpellShield = EQ::Clamp(e.spellshield, -128, 127);
item.StrikeThrough = EQ::Clamp(e.strikethrough, -128, 127);
item.StunResist = EQ::Clamp(e.stunresist, -128, 127);
// Restrictions
item.AugRestrict = Strings::ToUnsignedInt(row[ItemField::augrestrict]);
item.Classes = Strings::ToUnsignedInt(row[ItemField::classes]);
item.Deity = Strings::ToUnsignedInt(row[ItemField::deity]);
item.ItemClass = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::itemclass]));
item.Races = Strings::ToUnsignedInt(row[ItemField::races]);
item.RecLevel = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::reclevel]));
item.RecSkill = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::recskill]));
item.ReqLevel = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::reqlevel]));
item.Slots = Strings::ToUnsignedInt(row[ItemField::slots]);
item.AugRestrict = e.augrestrict;
item.Classes = e.classes;
item.Deity = e.deity;
item.ItemClass = static_cast<uint8>(e.itemclass);
item.Races = e.races;
item.RecLevel = static_cast<uint8>(e.reclevel);
item.RecSkill = static_cast<uint8>(e.recskill);
item.ReqLevel = static_cast<uint8>(e.reqlevel);
item.Slots = e.slots;
// Skill Modifier
item.SkillModValue = Strings::ToInt(row[ItemField::skillmodvalue]);
item.SkillModMax = Strings::ToInt(row[ItemField::skillmodmax]);
item.SkillModType = Strings::ToUnsignedInt(row[ItemField::skillmodtype]);
item.SkillModValue = e.skillmodvalue;
item.SkillModMax = e.skillmodmax;
item.SkillModType = e.skillmodtype;
// Extra Damage Skill
item.ExtraDmgSkill = Strings::ToInt(row[ItemField::extradmgskill]);
item.ExtraDmgAmt = Strings::ToInt(row[ItemField::extradmgamt]);
item.ExtraDmgSkill = e.extradmgskill;
item.ExtraDmgAmt = e.extradmgamt;
// Bard
item.BardType = Strings::ToUnsignedInt(row[ItemField::bardtype]);
item.BardValue = Strings::ToInt(row[ItemField::bardvalue]);
item.BardType = e.bardtype;
item.BardValue = e.bardvalue;
// Faction
item.FactionAmt1 = Strings::ToInt(row[ItemField::factionamt1]);
item.FactionMod1 = Strings::ToInt(row[ItemField::factionmod1]);
item.FactionAmt2 = Strings::ToInt(row[ItemField::factionamt2]);
item.FactionMod2 = Strings::ToInt(row[ItemField::factionmod2]);
item.FactionAmt3 = Strings::ToInt(row[ItemField::factionamt3]);
item.FactionMod3 = Strings::ToInt(row[ItemField::factionmod3]);
item.FactionAmt4 = Strings::ToInt(row[ItemField::factionamt4]);
item.FactionMod4 = Strings::ToInt(row[ItemField::factionmod4]);
item.FactionAmt1 = e.factionamt1;
item.FactionMod1 = e.factionmod1;
item.FactionAmt2 = e.factionamt2;
item.FactionMod2 = e.factionmod2;
item.FactionAmt3 = e.factionamt3;
item.FactionMod3 = e.factionmod3;
item.FactionAmt4 = e.factionamt4;
item.FactionMod4 = e.factionmod4;
// Augment
item.AugDistiller = Strings::ToUnsignedInt(row[ItemField::augdistiller]);
item.AugSlotType[0] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot1type]));
item.AugSlotVisible[0] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot1visible]));
item.AugSlotType[1] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot2type]));
item.AugSlotVisible[1] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot2visible]));
item.AugSlotType[2] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot3type]));
item.AugSlotVisible[2] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot3visible]));
item.AugSlotType[3] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot4type]));
item.AugSlotVisible[3] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot4visible]));
item.AugSlotType[4] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot5type]));
item.AugSlotVisible[4] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot5visible]));
item.AugSlotType[5] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot6type]));
item.AugSlotVisible[5] = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::augslot6visible]));
// Augment Distiller
item.AugDistiller = e.augdistiller;
// Augment Slots
item.AugSlotType[0] = static_cast<uint8>(e.augslot1type);
item.AugSlotVisible[0] = static_cast<uint8>(e.augslot1visible);
item.AugSlotType[1] = static_cast<uint8>(e.augslot2type);
item.AugSlotVisible[1] = static_cast<uint8>(e.augslot2visible);
item.AugSlotType[2] = static_cast<uint8>(e.augslot3type);
item.AugSlotVisible[2] = static_cast<uint8>(e.augslot3visible);
item.AugSlotType[3] = static_cast<uint8>(e.augslot4type);
item.AugSlotVisible[3] = static_cast<uint8>(e.augslot4visible);
item.AugSlotType[4] = static_cast<uint8>(e.augslot5type);
item.AugSlotVisible[4] = static_cast<uint8>(e.augslot5visible);
item.AugSlotType[5] = static_cast<uint8>(e.augslot6type);
item.AugSlotVisible[5] = static_cast<uint8>(e.augslot6visible);
// Augment Unknowns
for (uint8 i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) {
@ -1239,79 +1179,79 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
}
// LDoN
item.LDoNTheme = Strings::ToUnsignedInt(row[ItemField::ldontheme]);
item.LDoNPrice = Strings::ToUnsignedInt(row[ItemField::ldonprice]);
item.LDoNSellBackRate = Strings::ToUnsignedInt(row[ItemField::ldonsellbackrate]);
item.LDoNSold = Strings::ToUnsignedInt(row[ItemField::ldonsold]);
item.PointType = Strings::ToUnsignedInt(row[ItemField::pointtype]);
item.LDoNTheme = e.ldontheme;
item.LDoNPrice = e.ldonprice;
item.LDoNSellBackRate = e.ldonsellbackrate;
item.LDoNSold = e.ldonsold;
item.PointType = e.pointtype;
// Bag
item.BagSize = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::bagsize]));
item.BagSlots = static_cast<uint8>(EQ::Clamp(Strings::ToInt(row[ItemField::bagslots]), 0, static_cast<int>(EQ::invbag::SLOT_COUNT)));
item.BagType = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::bagtype]));
item.BagWR = static_cast<uint8>(EQ::Clamp(Strings::ToInt(row[ItemField::bagwr]), 0, 100));
item.BagSize = static_cast<uint8>(e.bagsize);
item.BagSlots = EQ::Clamp(e.bagslots, 0, static_cast<int>(EQ::invbag::SLOT_COUNT));
item.BagType = static_cast<uint8>(e.bagtype);
item.BagWR = EQ::Clamp(e.bagwr, 0, 100);
// Bard Effect
item.Bard.Effect = disable_bard_focus_effects ? 0 : Strings::ToInt(row[ItemField::bardeffect]);
item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::bardtype]));
item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::bardlevel]));
item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::bardlevel2]));
item.Bard.Effect = disable_bard_focus_effects ? 0 : e.bardeffect;
item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast<uint8>(e.bardtype);
item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast<uint8>(e.bardlevel);
item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast<uint8>(e.bardlevel2);
// Book
item.Book = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::book]));
item.BookType = Strings::ToUnsignedInt(row[ItemField::booktype]);
item.Book = static_cast<uint8>(e.book);
item.BookType = e.booktype;
// Click Effect
item.CastTime = Strings::ToUnsignedInt(row[ItemField::casttime]);
item.CastTime_ = Strings::ToInt(row[ItemField::casttime_]);
item.Click.Effect = Strings::ToInt(row[ItemField::clickeffect]);
item.Click.Type = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::clicktype]));
item.Click.Level = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::clicklevel]));
item.Click.Level2 = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::clicklevel2]));
strn0cpy(item.ClickName, row[ItemField::clickname], sizeof(item.ClickName));
item.RecastDelay = Strings::ToUnsignedInt(row[ItemField::recastdelay]);
item.RecastType = Strings::ToInt(row[ItemField::recasttype]);
item.CastTime = e.casttime;
item.CastTime_ = e.casttime_;
item.Click.Effect = e.clickeffect;
item.Click.Type = static_cast<uint8>(e.clicktype);
item.Click.Level = static_cast<uint8>(e.clicklevel);
item.Click.Level2 = static_cast<uint8>(e.clicklevel2);
strn0cpy(item.ClickName, e.clickname.c_str(), sizeof(item.ClickName));
item.RecastDelay = e.recastdelay;
item.RecastType = e.recasttype;
// Focus Effect
item.Focus.Effect = disable_spell_focus_effects ? 0 : Strings::ToInt(row[ItemField::focuseffect]);
item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::focustype]));
item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::focuslevel]));
item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::focuslevel2]));
strn0cpy(item.FocusName, disable_spell_focus_effects ? "" : row[ItemField::focusname], sizeof(item.FocusName));
item.Focus.Effect = disable_spell_focus_effects ? 0 : e.focuseffect;
item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast<uint8>(e.focustype);
item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast<uint8>(e.focuslevel);
item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast<uint8>(e.focuslevel2);
strn0cpy(item.FocusName, disable_spell_focus_effects ? "" : e.focusname.c_str(), sizeof(item.FocusName));
// Proc Effect
item.Proc.Effect = Strings::ToInt(row[ItemField::proceffect]);
item.Proc.Type = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::proctype]));
item.Proc.Level = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::proclevel]));
item.Proc.Level2 = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::proclevel2]));
strn0cpy(item.ProcName, row[ItemField::procname], sizeof(item.ProcName));
item.ProcRate = Strings::ToInt(row[ItemField::procrate]);
item.Proc.Effect = e.proceffect;
item.Proc.Type = static_cast<uint8>(e.proctype);
item.Proc.Level = static_cast<uint8>(e.proclevel);
item.Proc.Level2 = static_cast<uint8>(e.proclevel2);
strn0cpy(item.ProcName, e.procname.c_str(), sizeof(item.ProcName));
item.ProcRate = e.procrate;
// Scroll Effect
item.Scroll.Effect = Strings::ToInt(row[ItemField::scrolleffect]);
item.Scroll.Type = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::scrolltype]));
item.Scroll.Level = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::scrolllevel]));
item.Scroll.Level2 = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::scrolllevel2]));
strn0cpy(item.ScrollName, row[ItemField::scrollname], sizeof(item.ScrollName));
item.Scroll.Effect = e.scrolleffect;
item.Scroll.Type = static_cast<uint8>(e.scrolltype);
item.Scroll.Level = static_cast<uint8>(e.scrolllevel);
item.Scroll.Level2 = static_cast<uint8>(e.scrolllevel2);
strn0cpy(item.ScrollName, e.scrollname.c_str(), sizeof(item.ScrollName));
// Worn Effect
item.Worn.Effect = Strings::ToInt(row[ItemField::worneffect]);
item.Worn.Type = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::worntype]));
item.Worn.Level = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::wornlevel]));
item.Worn.Level2 = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::wornlevel2]));
strn0cpy(item.WornName, row[ItemField::wornname], sizeof(item.WornName));
item.Worn.Effect = e.worneffect;
item.Worn.Type = static_cast<uint8>(e.worntype);
item.Worn.Level = static_cast<uint8>(e.wornlevel);
item.Worn.Level2 = static_cast<uint8>(e.wornlevel2);
strn0cpy(item.WornName, e.wornname.c_str(), sizeof(item.WornName));
// Evolving Item
item.EvolvingID = Strings::ToUnsignedInt(row[ItemField::evoid]);
item.EvolvingItem = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::evoitem]));
item.EvolvingLevel = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::evolvinglevel]));
item.EvolvingMax = static_cast<uint8>(Strings::ToUnsignedInt(row[ItemField::evomax]));
item.EvolvingID = e.evoid;
item.EvolvingItem = static_cast<uint8>(e.evoitem);
item.EvolvingLevel = static_cast<uint8>(e.evolvinglevel);
item.EvolvingMax = static_cast<uint8>(e.evomax);
// Scripting
item.CharmFileID = Strings::IsNumber(row[ItemField::charmfileid]) ? Strings::ToUnsignedInt(row[ItemField::charmfileid]) : 0;
strn0cpy(item.CharmFile, row[ItemField::charmfile], sizeof(item.CharmFile));
strn0cpy(item.Filename, row[ItemField::filename], sizeof(item.Filename));
item.ScriptFileID = Strings::ToUnsignedInt(row[ItemField::scriptfileid]);
item.CharmFileID = Strings::IsNumber(e.charmfileid) ? Strings::ToUnsignedInt(e.charmfileid) : 0;
strn0cpy(item.CharmFile, e.charmfile.c_str(), sizeof(item.CharmFile));
strn0cpy(item.Filename, e.filename.c_str(), sizeof(item.Filename));
item.ScriptFileID = e.scriptfileid;
try {
hash.insert(item.ID, item);
@ -1673,20 +1613,17 @@ bool SharedDatabase::GetCommandSubSettings(std::vector<CommandSubsettingsReposit
return true;
}
void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) {
const std::string query = StringFormat("SELECT `spellid`, `type` FROM `damageshieldtypes` WHERE `spellid` > 0 "
"AND `spellid` <= %i", iMaxSpellID);
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* s)
{
const auto& l = DamageshieldtypesRepository::All(*this);
for(auto& row = results.begin(); row != results.end(); ++row) {
const int spellID = Strings::ToInt(row[0]);
if((spellID > 0) && (spellID <= iMaxSpellID))
sp[spellID].damage_shield_type = Strings::ToUnsignedInt(row[1]);
}
if (l.empty()) {
return;
}
for (const auto& e : l) {
s[e.spellid].damage_shield_type = e.type;
}
}
const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) {
@ -1903,21 +1840,32 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
sp[tempid].damage_shield_type = 0;
}
LoadDamageShieldTypes(sp, max_spells);
LoadDamageShieldTypes(sp);
}
void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) {
const std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id);
auto results = QueryDatabase(query);
memset(message, '\0', sizeof(InspectMessage_Struct));
for (auto& row = results.begin(); row != results.end(); ++row) {
memcpy(message, row[0], sizeof(InspectMessage_Struct));
void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* s)
{
const auto& e = CharacterInspectMessagesRepository::FindOne(*this, character_id);
memset(s, '\0', sizeof(InspectMessage_Struct));
if (!e.id) {
return;
}
memcpy(s, e.inspect_message.c_str(), sizeof(InspectMessage_Struct));
}
void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) {
const std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, Strings::Escape(message->text).c_str());
auto results = QueryDatabase(query);
void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* s)
{
auto e = CharacterInspectMessagesRepository::NewEntity();
e.id = character_id;
e.inspect_message = s->text;
if (!CharacterInspectMessagesRepository::ReplaceOne(*this, e)) {
LogError("Failed to save character inspect message of [{}] for character_id [{}]", s->text, character_id);
}
}
uint32 SharedDatabase::GetSpellsCount()
@ -1938,18 +1886,7 @@ uint32 SharedDatabase::GetSpellsCount()
uint32 SharedDatabase::GetItemsCount()
{
auto results = QueryDatabase("SELECT count(*) FROM items");
if (!results.Success() || !results.RowCount()) {
return 0;
}
auto& row = results.begin();
if (row[0]) {
return Strings::ToUnsignedInt(row[0]);
}
return 0;
return ItemsRepository::Count(*this);
}
void SharedDatabase::SetSharedItemsCount(uint32 shared_items_count)

View File

@ -76,21 +76,20 @@ public:
uint8 GetGMSpeed(uint32 account_id);
bool SetHideMe(uint32 account_id, uint8 hideme);
int DeleteStalePlayerCorpses();
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct *message);
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct *message);
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* s);
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* s);
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
bool UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected);
bool UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned);
bool GetCommandSubSettings(std::vector<CommandSubsettingsRepository::CommandSubsettings> &command_subsettings);
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
bool SetGMInvul(uint32 account_id, bool gminvul);
bool SetGMFlymode(uint32 account_id, uint8 flymode);
void SetMailKey(int CharID, int IPAddress, int MailKey);
void SetMailKey(uint32 character_id, uint32 ip_address, uint32 mail_key);
struct MailKeys {
std::string mail_key;
std::string mail_key_full;
};
MailKeys GetMailKey(int character_id);
MailKeys GetMailKey(uint32 character_id);
bool SaveCursor(
uint32 char_id,
std::list<EQ::ItemInstance *>::const_iterator &start,
@ -104,7 +103,7 @@ public:
bool VerifyInventory(uint32 account_id, int16 slot_id, const EQ::ItemInstance *inst);
bool GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is_charid);
int32 GetSharedPlatinum(uint32 account_id);
bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add);
bool AddSharedPlatinum(uint32 account_id, int amount);
bool GetInventory(Client* c);
bool GetInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv); // deprecated
std::map<uint32, uint32> GetItemRecastTimestamps(uint32 char_id);
@ -158,7 +157,7 @@ public:
);
EQ::ItemInstance *CreateBaseItem(const EQ::ItemData *item, int16 charges = 0);
void GetItemsCount(int32 &item_count, uint32 &max_id);
void GetItemsCount(int32& item_count, uint32& max_id);
void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id);
bool LoadItems(const std::string &prefix);
const EQ::ItemData *IterateItems(uint32 *id) const;
@ -173,7 +172,7 @@ public:
int GetMaxSpellID();
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
void LoadSpells(void *data, int max_spells);
void LoadDamageShieldTypes(SPDat_Spell_Struct *sp, int32 iMaxSpellID);
void LoadDamageShieldTypes(SPDat_Spell_Struct* s);
uint32 GetSharedSpellsCount() { return m_shared_spells_count; }
uint32 GetSpellsCount();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -313,6 +313,12 @@ std::string Strings::Commify(const std::string &number)
auto string_length = static_cast<int>(number.length());
if (string_length == 3) {
return number;
} else if (string_length == 4 && number.starts_with("-")) {
return number;
}
int i = 0;
for (i = string_length - 3; i >= 0; i -= 3) {
if (i > 0) {

View File

@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "23.9.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "23.10.3-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9326
#define CURRENT_BINARY_DATABASE_VERSION 9328
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
#define CUSTOM_BINARY_DATABASE_VERSION 0

View File

@ -33,7 +33,7 @@ EverQuest::EverQuest(const std::string &host, int port, const std::string &user,
}
else {
m_host = addr;
m_login_connection_manager.reset(new EQ::Net::DaybreakConnectionManager());
m_login_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager());
m_login_connection_manager->OnNewConnection(std::bind(&EverQuest::LoginOnNewConnection, this, std::placeholders::_1));
m_login_connection_manager->OnConnectionStateChange(std::bind(&EverQuest::LoginOnStatusChangeReconnectEnabled, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
@ -48,13 +48,13 @@ EverQuest::~EverQuest()
{
}
void EverQuest::LoginOnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection)
void EverQuest::LoginOnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection)
{
m_login_connection = connection;
Log.OutF(Logs::General, Logs::Headless_Client, "Connecting...");
}
void EverQuest::LoginOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void EverQuest::LoginOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusConnected) {
Log.OutF(Logs::General, Logs::Headless_Client, "Login connected.");
@ -70,14 +70,14 @@ void EverQuest::LoginOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::Day
}
}
void EverQuest::LoginOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void EverQuest::LoginOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusDisconnected) {
m_login_connection.reset();
}
}
void EverQuest::LoginOnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet & p)
void EverQuest::LoginOnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet & p)
{
auto opcode = p.GetUInt16(0);
switch (opcode) {
@ -251,20 +251,20 @@ void EverQuest::LoginDisableReconnect()
void EverQuest::ConnectToWorld()
{
m_world_connection_manager.reset(new EQ::Net::DaybreakConnectionManager());
m_world_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager());
m_world_connection_manager->OnNewConnection(std::bind(&EverQuest::WorldOnNewConnection, this, std::placeholders::_1));
m_world_connection_manager->OnConnectionStateChange(std::bind(&EverQuest::WorldOnStatusChangeReconnectEnabled, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_world_connection_manager->OnPacketRecv(std::bind(&EverQuest::WorldOnPacketRecv, this, std::placeholders::_1, std::placeholders::_2));
m_world_connection_manager->Connect(m_host, 9000);
}
void EverQuest::WorldOnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection)
void EverQuest::WorldOnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection)
{
m_world_connection = connection;
Log.OutF(Logs::General, Logs::Headless_Client, "Connecting to world...");
}
void EverQuest::WorldOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void EverQuest::WorldOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusConnected) {
Log.OutF(Logs::General, Logs::Headless_Client, "World connected.");
@ -278,14 +278,14 @@ void EverQuest::WorldOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::Day
}
}
void EverQuest::WorldOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void EverQuest::WorldOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusDisconnected) {
m_world_connection.reset();
}
}
void EverQuest::WorldOnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet & p)
void EverQuest::WorldOnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet & p)
{
auto opcode = p.GetUInt16(0);
switch (opcode) {

26
hc/eq.h
View File

@ -1,7 +1,7 @@
#pragma once
#include "../common/eqemu_logsys.h"
#include "../common/net/daybreak_connection.h"
#include "../common/net/reliable_stream_connection.h"
#include "../common/event/timer.h"
#include <openssl/des.h>
#include <string>
@ -26,10 +26,10 @@ public:
private:
//Login
void LoginOnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection);
void LoginOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void LoginOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void LoginOnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p);
void LoginOnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection);
void LoginOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void LoginOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void LoginOnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p);
void LoginSendSessionReady();
void LoginSendLogin();
@ -41,25 +41,25 @@ private:
void LoginDisableReconnect();
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_login_connection_manager;
std::shared_ptr<EQ::Net::DaybreakConnection> m_login_connection;
std::unique_ptr<EQ::Net::ReliableStreamConnectionManager> m_login_connection_manager;
std::shared_ptr<EQ::Net::ReliableStreamConnection> m_login_connection;
std::map<uint32_t, WorldServer> m_world_servers;
//World
void ConnectToWorld();
void WorldOnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection);
void WorldOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void WorldOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void WorldOnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p);
void WorldOnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection);
void WorldOnStatusChangeReconnectEnabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void WorldOnStatusChangeReconnectDisabled(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void WorldOnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p);
void WorldSendClientAuth();
void WorldSendEnterWorld(const std::string &character);
void WorldProcessCharacterSelect(const EQ::Net::Packet &p);
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_world_connection_manager;
std::shared_ptr<EQ::Net::DaybreakConnection> m_world_connection;
std::unique_ptr<EQ::Net::ReliableStreamConnectionManager> m_world_connection_manager;
std::shared_ptr<EQ::Net::ReliableStreamConnection> m_world_connection;
//Variables
std::string m_host;

View File

@ -26,7 +26,7 @@ LoginConnection::LoginConnection(const std::string &username, const std::string
m_host_port = host_port;
m_server = server;
m_connection_manager.reset(new EQ::Net::DaybreakConnectionManager());
m_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager());
m_connection_manager->OnNewConnection(std::bind(&LoginConnection::OnNewConnection, this, std::placeholders::_1));
m_connection_manager->OnConnectionStateChange(std::bind(&LoginConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
@ -39,13 +39,13 @@ LoginConnection::~LoginConnection()
{
}
void LoginConnection::OnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection)
void LoginConnection::OnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection)
{
m_connection = connection;
Log.OutF(Logs::General, Logs::Headless_Client, "Connecting...");
}
void LoginConnection::OnStatusChangeActive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void LoginConnection::OnStatusChangeActive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusConnected) {
Log.OutF(Logs::General, Logs::Headless_Client, "Login connected.");
@ -61,7 +61,7 @@ void LoginConnection::OnStatusChangeActive(std::shared_ptr<EQ::Net::DaybreakConn
}
}
void LoginConnection::OnStatusChangeInactive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void LoginConnection::OnStatusChangeInactive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusDisconnected) {
m_key.clear();
@ -70,7 +70,7 @@ void LoginConnection::OnStatusChangeInactive(std::shared_ptr<EQ::Net::DaybreakCo
}
}
void LoginConnection::OnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p)
void LoginConnection::OnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p)
{
auto opcode = p.GetUInt16(0);
switch (opcode) {

View File

@ -1,6 +1,6 @@
#pragma once
#include "../common/net/daybreak_connection.h"
#include "../common/net/reliable_stream_connection.h"
#include "../common/event/timer.h"
#include <map>
@ -23,10 +23,10 @@ public:
~LoginConnection();
private:
void OnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection);
void OnStatusChangeActive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnStatusChangeInactive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p);
void OnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection);
void OnStatusChangeActive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnStatusChangeInactive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p);
void Kill();
void Start();
@ -38,8 +38,8 @@ private:
void ProcessServerPacketList(const EQ::Net::Packet &p);
void ProcessServerPlayResponse(const EQ::Net::Packet &p);
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_connection_manager;
std::shared_ptr<EQ::Net::DaybreakConnection> m_connection;
std::unique_ptr<EQ::Net::ReliableStreamConnectionManager> m_connection_manager;
std::shared_ptr<EQ::Net::ReliableStreamConnection> m_connection;
bool m_connecting;
std::unique_ptr<EQ::Timer> m_connect_timer;

View File

@ -8,7 +8,7 @@ WorldConnection::WorldConnection(const std::string &key, uint32_t dbid, const st
m_key = key;
m_dbid = dbid;
m_connection_manager.reset(new EQ::Net::DaybreakConnectionManager());
m_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager());
m_connection_manager->OnNewConnection(std::bind(&WorldConnection::OnNewConnection, this, std::placeholders::_1));
m_connection_manager->OnConnectionStateChange(std::bind(&WorldConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection_manager->OnPacketRecv(std::bind(&WorldConnection::OnPacketRecv, this, std::placeholders::_1, std::placeholders::_2));
@ -18,13 +18,13 @@ WorldConnection::WorldConnection(const std::string &key, uint32_t dbid, const st
WorldConnection::~WorldConnection() {
}
void WorldConnection::OnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection)
void WorldConnection::OnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection)
{
m_connection = connection;
Log.OutF(Logs::General, Logs::Headless_Client, "Connecting to world...");
}
void WorldConnection::OnStatusChangeActive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void WorldConnection::OnStatusChangeActive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusConnected) {
Log.OutF(Logs::General, Logs::Headless_Client, "World connected.");
@ -38,14 +38,14 @@ void WorldConnection::OnStatusChangeActive(std::shared_ptr<EQ::Net::DaybreakConn
}
}
void WorldConnection::OnStatusChangeInactive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
void WorldConnection::OnStatusChangeInactive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to)
{
if (to == EQ::Net::StatusDisconnected) {
m_connection.reset();
}
}
void WorldConnection::OnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p)
void WorldConnection::OnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p)
{
auto opcode = p.GetUInt16(0);
Log.OutF(Logs::General, Logs::Headless_Client, "Packet in:\n{0}", p.ToString());

View File

@ -1,6 +1,6 @@
#pragma once
#include "../common/net/daybreak_connection.h"
#include "../common/net/reliable_stream_connection.h"
#include "../common/event/timer.h"
#include <map>
@ -10,17 +10,17 @@ public:
WorldConnection(const std::string &key, uint32_t dbid, const std::string &host);
~WorldConnection();
private:
void OnNewConnection(std::shared_ptr<EQ::Net::DaybreakConnection> connection);
void OnStatusChangeActive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnStatusChangeInactive(std::shared_ptr<EQ::Net::DaybreakConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnPacketRecv(std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p);
void OnNewConnection(std::shared_ptr<EQ::Net::ReliableStreamConnection> connection);
void OnStatusChangeActive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnStatusChangeInactive(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to);
void OnPacketRecv(std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p);
void Kill();
void Start();
void SendClientAuth();
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_connection_manager;
std::shared_ptr<EQ::Net::DaybreakConnection> m_connection;
std::unique_ptr<EQ::Net::ReliableStreamConnectionManager> m_connection_manager;
std::shared_ptr<EQ::Net::ReliableStreamConnection> m_connection;
bool m_connecting;
std::unique_ptr<EQ::Timer> m_connect_timer;

View File

@ -124,18 +124,18 @@ uint64 AccountManagement::CheckExternalLoginserverUserCredentials(LoginAccountCo
bool running = true;
uint32 ret = 0;
EQ::Net::DaybreakConnectionManager mgr;
std::shared_ptr<EQ::Net::DaybreakConnection> conn;
EQ::Net::ReliableStreamConnectionManager mgr;
std::shared_ptr<EQ::Net::ReliableStreamConnection> conn;
mgr.OnNewConnection(
[&](std::shared_ptr<EQ::Net::DaybreakConnection> connection) {
[&](std::shared_ptr<EQ::Net::ReliableStreamConnection> connection) {
conn = connection;
}
);
mgr.OnConnectionStateChange(
[&](
std::shared_ptr<EQ::Net::DaybreakConnection> conn,
std::shared_ptr<EQ::Net::ReliableStreamConnection> conn,
EQ::Net::DbProtocolStatus from,
EQ::Net::DbProtocolStatus to
) {
@ -152,7 +152,7 @@ uint64 AccountManagement::CheckExternalLoginserverUserCredentials(LoginAccountCo
);
mgr.OnPacketRecv(
[&](std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p) {
[&](std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p) {
auto opcode = p.GetUInt16(0);
switch (opcode) {
case 0x0017: //OP_ChatMessage
@ -250,18 +250,18 @@ uint64 AccountManagement::HealthCheckUserLogin()
bool running = true;
uint64 ret = 0;
EQ::Net::DaybreakConnectionManager mgr;
std::shared_ptr<EQ::Net::DaybreakConnection> c;
EQ::Net::ReliableStreamConnectionManager mgr;
std::shared_ptr<EQ::Net::ReliableStreamConnection> c;
mgr.OnNewConnection(
[&](std::shared_ptr<EQ::Net::DaybreakConnection> connection) {
[&](std::shared_ptr<EQ::Net::ReliableStreamConnection> connection) {
c = connection;
}
);
mgr.OnConnectionStateChange(
[&](
std::shared_ptr<EQ::Net::DaybreakConnection> conn,
std::shared_ptr<EQ::Net::ReliableStreamConnection> conn,
EQ::Net::DbProtocolStatus from,
EQ::Net::DbProtocolStatus to
) {
@ -278,7 +278,7 @@ uint64 AccountManagement::HealthCheckUserLogin()
);
mgr.OnPacketRecv(
[&](std::shared_ptr<EQ::Net::DaybreakConnection> conn, const EQ::Net::Packet &p) {
[&](std::shared_ptr<EQ::Net::ReliableStreamConnection> conn, const EQ::Net::Packet &p) {
auto opcode = p.GetUInt16(0);
switch (opcode) {
case 0x0017: //OP_ChatMessage

View File

@ -6,7 +6,7 @@
#include "../common/random.h"
#include "../common/eq_stream_intf.h"
#include "../common/net/dns.h"
#include "../common/net/daybreak_connection.h"
#include "../common/net/reliable_stream_connection.h"
#include "login_types.h"
#include "../common/repositories/login_accounts_repository.h"
#include <memory>
@ -54,8 +54,8 @@ private:
unsigned int m_selected_play_server_id;
unsigned int m_play_sequence_id;
std::string m_key;
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_login_connection_manager;
std::shared_ptr<EQ::Net::DaybreakConnection> m_login_connection;
std::unique_ptr<EQ::Net::ReliableStreamConnectionManager> m_login_connection_manager;
std::shared_ptr<EQ::Net::ReliableStreamConnection> m_login_connection;
LoginBaseMessage m_login_base_message;
std::string m_stored_username;
std::string m_stored_password;

View File

@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "23.9.0",
"version": "23.10.3",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"

View File

@ -35,4 +35,4 @@ IF(UNIX)
ADD_DEFINITIONS(-fPIC)
ENDIF(UNIX)
SET(LIBRARY_OUTPUT_PATH ../../Bin)
SET(LIBRARY_OUTPUT_PATH ../../bin)

View File

@ -469,11 +469,11 @@ static void ProcessCommandIgnore(Client *c, std::string Ignoree) {
Clientlist::Clientlist(int ChatPort) {
EQStreamManagerInterfaceOptions chat_opts(ChatPort, false, false);
chat_opts.opcode_size = 1;
chat_opts.daybreak_options.stale_connection_ms = 600000;
chat_opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
chat_opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
chat_opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
chat_opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS);
chat_opts.reliable_stream_options.stale_connection_ms = 600000;
chat_opts.reliable_stream_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
chat_opts.reliable_stream_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
chat_opts.reliable_stream_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
chat_opts.reliable_stream_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS);
chatsf = new EQ::Net::EQStreamManager(chat_opts);

View File

@ -1,8 +1,6 @@
module should-release
go 1.23.0
toolchain go1.23.5
go 1.24.0
require (
github.com/google/go-github/v41 v41.0.0
@ -11,5 +9,5 @@ require (
require (
github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/crypto v0.45.0 // indirect
)

View File

@ -10,8 +10,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=

View File

@ -985,7 +985,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
safe_delete(outapp);
// set mailkey - used for duration of character session
int mail_key = EQ::Random::Instance()->Int(1, INT_MAX);
uint32 mail_key = EQ::Random::Instance()->Int(1, INT_MAX);
database.SetMailKey(charid, GetIP(), mail_key);
if (UCSServerAvailable_) {
@ -1019,8 +1019,16 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
break;
}
std::string ucs_addr = config->GetUCSHost();
if (cle && cle->IsLocalClient()) {
const char* local_addr = config->LocalAddress.c_str();
if (local_addr[0]) {
ucs_addr = local_addr;
}
}
buffer = fmt::format("{},{},{}.{},{}{:08X}",
config->GetUCSHost(),
ucs_addr,
config->GetUCSPort(),
config->ShortName,
GetCharName(),
@ -1046,7 +1054,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
}
buffer = fmt::format("{},{},{}.{},{}{:08X}",
config->GetUCSHost(),
ucs_addr,
config->GetUCSPort(),
config->ShortName,
GetCharName(),
@ -2076,10 +2084,10 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
classtemp = cc->class_ - 1;
racetemp = cc->race - 1;
// these have non sequential race numbers so they need to be mapped
if (cc->race == FROGLOK) racetemp = 14;
if (cc->race == VAHSHIR) racetemp = 13;
if (cc->race == IKSAR) racetemp = 12;
if (cc->race == DRAKKIN) racetemp = 15;
if (cc->race == Race::Froglok2) racetemp = 14;
if (cc->race == Race::VahShir) racetemp = 13;
if (cc->race == Race::Iksar) racetemp = 12;
if (cc->race == Race::Drakkin) racetemp = 15;
// if out of range looking it up in the table would crash stuff
// so we return from these
@ -2186,43 +2194,43 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp )
{
switch( pp->race )
{
case BARBARIAN:
case DWARF:
case ERUDITE:
case HALF_ELF:
case HIGH_ELF:
case HUMAN:
case OGRE:
case TROLL:
case DRAKKIN: //Drakkin are supposed to get a starting AA Skill
case Race::Barbarian:
case Race::Dwarf:
case Race::Erudite:
case Race::HalfElf:
case Race::HighElf:
case Race::Human:
case Race::Ogre:
case Race::Troll:
case Race::Drakkin: //Drakkin are supposed to get a starting AA Skill
{
// No Race Specific Skills
break;
}
case DARK_ELF:
case Race::DarkElf:
{
pp->skills[EQ::skills::SkillHide] = 50;
break;
}
case FROGLOK:
case Race::Froglok2:
{
if (RuleI(Skills, SwimmingStartValue) < 125) {
pp->skills[EQ::skills::SkillSwimming] = 125;
}
break;
}
case GNOME:
case Race::Gnome:
{
pp->skills[EQ::skills::SkillTinkering] = 50;
break;
}
case HALFLING:
case Race::Halfling:
{
pp->skills[EQ::skills::SkillHide] = 50;
pp->skills[EQ::skills::SkillSneak] = 50;
break;
}
case IKSAR:
case Race::Iksar:
{
pp->skills[EQ::skills::SkillForage] = 50;
if (RuleI(Skills, SwimmingStartValue) < 100) {
@ -2230,13 +2238,13 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp )
}
break;
}
case WOOD_ELF:
case Race::WoodElf:
{
pp->skills[EQ::skills::SkillForage] = 50;
pp->skills[EQ::skills::SkillHide] = 50;
break;
}
case VAHSHIR:
case Race::VahShir:
{
pp->skills[EQ::skills::SkillSafeFall] = 50;
pp->skills[EQ::skills::SkillSneak] = 50;

View File

@ -281,62 +281,107 @@ ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) {
return nullptr;
}
void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) {
void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* search_criteria)
{
LinkedListIterator<ClientListEntry*> iterator(clientlist);
int x = 0, y = 0;
int namestrlen = iName == 0 ? 0 : strlen(iName);
bool addnewline = false;
char newline[3];
if (connection->IsConsole())
strcpy(newline, "\r\n");
else
strcpy(newline, "^");
auto out = fmt::memory_buffer();
int found_count = 0;
int total_count = 0;
int name_length = search_criteria ? strlen(search_criteria) : 0;
const char* new_line = connection->IsConsole() ? "\r\n" : "^";
bool add_new_line = false;
std::string message;
iterator.Reset();
while(iterator.MoreElements()) {
while (iterator.MoreElements()) {
ClientListEntry* cle = iterator.GetData();
if (admin >= cle->Admin() && (iName == 0 || namestrlen == 0 || strncasecmp(cle->name(), iName, namestrlen) == 0 || strncasecmp(cle->AccountName(), iName, namestrlen) == 0 || strncasecmp(cle->LSName(), iName, namestrlen) == 0)) {
struct in_addr in;
in.s_addr = cle->GetIP();
if (addnewline) {
fmt::format_to(std::back_inserter(out), fmt::runtime(newline));
struct in_addr in;
in.s_addr = cle->GetIP();
if (
admin >= cle->Admin() &&
(
!search_criteria ||
Strings::Contains(std::string(inet_ntoa(in)), search_criteria) ||
Strings::Contains(cle->name(), search_criteria) == 0 ||
Strings::Contains(cle->AccountName(), search_criteria) == 0 ||
Strings::Contains(cle->LSName(), search_criteria) == 0
)
) {
if (add_new_line) {
message += new_line;
}
fmt::format_to(std::back_inserter(out), "ID: {} Acc# {} AccName: {} IP: {}", cle->GetID(), cle->AccountID(), cle->AccountName(), inet_ntoa(in));
fmt::format_to(std::back_inserter(out), "{} Stale: {} Online: {} Admin: {}", newline, cle->GetStaleCounter(), static_cast<int>(cle->Online()), cle->Admin());
if (cle->LSID())
fmt::format_to(std::back_inserter(out), "{} LSID: {} LSName: {} WorldAdmin: {}", newline, cle->LSID(), cle->LSName(), cle->WorldAdmin());
if (cle->CharID())
fmt::format_to(std::back_inserter(out), "{} CharID: {} CharName: {} Zone: {} ({})", newline, cle->CharID(), cle->name(), ZoneName(cle->zone()), cle->zone());
if (out.size() >= 3072) {
message += fmt::format(
"Account: {} ({}) | IP: {} | Admin: {}",
cle->AccountName(),
cle->AccountID(),
inet_ntoa(in),
cle->Admin()
);
if (cle->CharID()) {
message += fmt::format(
"{}Character: {} ({}) | Zone: {} ({})",
new_line,
cle->name(),
cle->CharID(),
ZoneLongName(cle->zone()),
cle->zone()
);
}
if (message.size() >= 3072) {
connection->SendEmoteMessageRaw(
to,
0,
AccountStatus::Player,
Chat::NPCQuestSay,
out.data()
message.c_str()
);
addnewline = false;
out.clear();
message.clear();
add_new_line = false;
} else {
addnewline = true;
add_new_line = true;
}
y++;
found_count++;
}
iterator.Advance();
x++;
total_count++;
}
fmt::format_to(std::back_inserter(out), "{}{} CLEs in memory. {} CLEs listed. numplayers = {}.", newline, x, y, numplayers);
message += fmt::format(
"{}{}Player Count: {}",
new_line,
(
found_count != total_count ?
fmt::format(
"Total: {} CLE{} | Found: {} CLE{} | ",
total_count,
(total_count != 1 ? "s" : ""),
found_count,
(found_count != 1 ? "s" : "")
) :
""
),
numplayers
);
connection->SendEmoteMessageRaw(
to,
0,
AccountStatus::Player,
Chat::NPCQuestSay,
out.data()
message.c_str()
);
}
void ClientList::CLEAdd(
uint32 login_server_id,
const char *login_server_name,
@ -598,7 +643,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
whomlen = strlen(whom->whom);
if (whom->wrace == 0x001A) { // 0x001A is the old Froglok race number and is sent by the client for /who all froglok
whom->wrace = FROGLOK; // This is what EQEmu uses for the Froglok Race number.
whom->wrace = Race::Froglok2; // This is what EQEmu uses for the Froglok Race number.
}
}

View File

@ -45,7 +45,7 @@ public:
void SendClientVersionSummary(const char *Name);
void SendLFGMatches(ServerLFGMatchesRequest_Struct *LFGMatchesRequest);
void ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* whom, WorldTCPConnection* connection);
void SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName = 0);
void SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* search_criteria = 0);
bool SendPacket(const char* to, ServerPacket* pack);

View File

@ -333,11 +333,11 @@ int main(int argc, char **argv)
WorldBoot::CheckForPossibleConfigurationIssues();
EQStreamManagerInterfaceOptions opts(9000, false, false);
opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS);
opts.daybreak_options.outgoing_data_rate = RuleR(Network, ClientDataRate);
opts.reliable_stream_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
opts.reliable_stream_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
opts.reliable_stream_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
opts.reliable_stream_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS);
opts.reliable_stream_options.outgoing_data_rate = RuleR(Network, ClientDataRate);
EQ::Net::EQStreamManager eqsm(opts);

View File

@ -82,7 +82,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
for (int x = 0; x < MAX_SWARM_PETS; x++)
{
if (spells[spell_id].effect_id[x] == SE_TemporaryPets)
if (spells[spell_id].effect_id[x] == SpellEffect::TemporaryPets)
{
pet.count = spells[spell_id].base_value[x];
pet.duration = spells[spell_id].max_value[x];
@ -1376,7 +1376,7 @@ int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) {
}
for(auto &effect : rank->effects) {
if(effect.effect_id == SE_HastenedAASkill && effect.limit_value == ability_in->id) {
if(effect.effect_id == SpellEffect::HastenedAASkill && effect.limit_value == ability_in->id) {
total_reduction += effect.base_value;
}
}
@ -1619,7 +1619,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank)
auto race = GetPlayerRaceValue(GetBaseRace());
race = race > PLAYER_RACE_COUNT ? Race::Human : race;
race = race > RaceIndex::Drakkin ? Race::Human : race;
if (!(a->races & (1 << (race - 1)))) {
return false;
@ -1949,7 +1949,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab
Instructions for how to make the AA - assuming a basic level of knowledge of how AA's work.
- aa_abilities table : Create new ability with a hotkey, type 3, zero charges
- aa_ranks table : [Disabled rank] First rank, should have a cost > 0 (this is what you buy), Set hotkeys, MUST SET A SPELL CONTAINING EFFECT SE_Buy_AA_Rank(SPA 472), set a short recast timer.
- aa_ranks table : [Disabled rank] First rank, should have a cost > 0 (this is what you buy), Set hotkeys, MUST SET A SPELL CONTAINING EFFECT SpellEffect::Buy_AA_Rank(SPA 472), set a short recast timer.
[Enabled rank] Second rank, should have a cost = 0, Set hotkeys, Set any valid spell ID you want (it has to exist but does nothing), set a short recast timer.
*Recommend if doing custom, just make the hotkey titled 'Toggle <Ability Name>' and use for both.
@ -1969,7 +1969,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab
*/
bool enable_next_rank = IsEffectInSpell(rank.spell, SE_Buy_AA_Rank);
bool enable_next_rank = IsEffectInSpell(rank.spell, SpellEffect::Buy_AA_Rank);
if (enable_next_rank) {
@ -1980,7 +1980,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab
AA::Rank *rank_next = zone->GetAlternateAdvancementRank(rank.next_id);
//Add checks for any special cases for toggle.
if (rank_next && IsEffectinAlternateAdvancementRankEffects(*rank_next, SE_Weapon_Stance)) {
if (rank_next && IsEffectinAlternateAdvancementRankEffects(*rank_next, SpellEffect::Weapon_Stance)) {
weaponstance.aabonus_enabled = true;
ApplyWeaponsStance();
}
@ -1994,7 +1994,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab
Message(Chat::Spells, "You disable an ability."); //Message live gives you. Should come from spell.
//Add checks for any special cases for toggle.
if (IsEffectinAlternateAdvancementRankEffects(rank, SE_Weapon_Stance)) {
if (IsEffectinAlternateAdvancementRankEffects(rank, SpellEffect::Weapon_Stance)) {
weaponstance.aabonus_enabled = false;
BuffFadeBySpellID(weaponstance.aabonus_buff_spell_id);
}
@ -2005,8 +2005,8 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab
bool Client::UseTogglePassiveHotkey(const AA::Rank &rank) {
/*
Disabled rank needs a rank spell containing the SE_Buy_AA_Rank effect to return true.
Enabled rank checks to see if the prior rank contains a rank spell with SE_Buy_AA_Rank, if so true.
Disabled rank needs a rank spell containing the SpellEffect::Buy_AA_Rank effect to return true.
Enabled rank checks to see if the prior rank contains a rank spell with SpellEffect::Buy_AA_Rank, if so true.
Note: On live the enabled rank is Expendable with Charge 1.
@ -2014,13 +2014,13 @@ bool Client::UseTogglePassiveHotkey(const AA::Rank &rank) {
*/
if (IsEffectInSpell(rank.spell, SE_Buy_AA_Rank)) {//Checked when is Disabled.
if (IsEffectInSpell(rank.spell, SpellEffect::Buy_AA_Rank)) {//Checked when is Disabled.
return true;
}
else if (rank.prev_id != -1) {//Check when effect is Enabled.
AA::Rank *rank_prev = zone->GetAlternateAdvancementRank(rank.prev_id);
if (rank_prev && IsEffectInSpell(rank_prev->spell, SE_Buy_AA_Rank)) {
if (rank_prev && IsEffectInSpell(rank_prev->spell, SpellEffect::Buy_AA_Rank)) {
return true;
}
}

View File

@ -1377,132 +1377,132 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool is_proc)
for (int o = 0; o < EFFECT_COUNT; o++) {
switch (spells[spell_id].effect_id[o]) {
case SE_CurrentHPOnce:
case SE_CurrentHP: {
case SpellEffect::CurrentHPOnce:
case SpellEffect::CurrentHP: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if(val < 0) {
aggro_amount -= val;
}
break;
}
case SE_MovementSpeed: {
case SpellEffect::MovementSpeed: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) {
aggro_amount += default_aggro;
}
break;
}
case SE_AttackSpeed:
case SE_AttackSpeed2:
case SE_AttackSpeed3: {
case SpellEffect::AttackSpeed:
case SpellEffect::AttackSpeed2:
case SpellEffect::AttackSpeed3: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 100) {
aggro_amount += default_aggro;
}
break;
}
case SE_Stun:
case SE_Blind:
case SE_Mez:
case SE_Charm:
case SE_Fear:
case SE_Fearstun:
case SpellEffect::Stun:
case SpellEffect::Blind:
case SpellEffect::Mez:
case SpellEffect::Charm:
case SpellEffect::Fear:
case SpellEffect::Fearstun:
aggro_amount += default_aggro;
break;
case SE_Root:
case SpellEffect::Root:
aggro_amount += 10;
break;
case SE_ACv2:
case SE_ArmorClass: {
case SpellEffect::ACv2:
case SpellEffect::ArmorClass: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) {
aggro_amount += default_aggro;
}
break;
}
case SE_ATK:
case SE_ResistMagic:
case SE_ResistFire:
case SE_ResistCold:
case SE_ResistPoison:
case SE_ResistDisease:
case SE_STR:
case SE_STA:
case SE_DEX:
case SE_AGI:
case SE_INT:
case SE_WIS:
case SE_CHA: {
case SpellEffect::ATK:
case SpellEffect::ResistMagic:
case SpellEffect::ResistFire:
case SpellEffect::ResistCold:
case SpellEffect::ResistPoison:
case SpellEffect::ResistDisease:
case SpellEffect::STR:
case SpellEffect::STA:
case SpellEffect::DEX:
case SpellEffect::AGI:
case SpellEffect::INT:
case SpellEffect::WIS:
case SpellEffect::CHA: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) {
aggro_amount += 10;
}
break;
}
case SE_ResistAll: {
case SpellEffect::ResistAll: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) {
aggro_amount += 50;
}
break;
}
case SE_AllStats: {
case SpellEffect::AllStats: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) {
aggro_amount += 70;
}
break;
}
case SE_BardAEDot:
case SpellEffect::BardAEDot:
aggro_amount += 10;
break;
case SE_SpinTarget:
case SE_Amnesia:
case SE_Silence:
case SE_Destroy:
case SpellEffect::SpinTarget:
case SpellEffect::Amnesia:
case SpellEffect::Silence:
case SpellEffect::Destroy:
aggro_amount += default_aggro;
break;
// unsure -- leave them this for now
case SE_Harmony:
case SE_CastingLevel:
case SE_MeleeMitigation:
case SE_CriticalHitChance:
case SE_AvoidMeleeChance:
case SE_RiposteChance:
case SE_DodgeChance:
case SE_ParryChance:
case SE_DualWieldChance:
case SE_DoubleAttackChance:
case SE_MeleeSkillCheck:
case SE_HitChance:
case SE_DamageModifier:
case SE_MinDamageModifier:
case SE_IncreaseBlockChance:
case SE_Accuracy:
case SE_DamageShield:
case SE_SpellDamageShield:
case SE_ReverseDS: {
case SpellEffect::Harmony:
case SpellEffect::CastingLevel:
case SpellEffect::MeleeMitigation:
case SpellEffect::CriticalHitChance:
case SpellEffect::AvoidMeleeChance:
case SpellEffect::RiposteChance:
case SpellEffect::DodgeChance:
case SpellEffect::ParryChance:
case SpellEffect::DualWieldChance:
case SpellEffect::DoubleAttackChance:
case SpellEffect::MeleeSkillCheck:
case SpellEffect::HitChance:
case SpellEffect::DamageModifier:
case SpellEffect::MinDamageModifier:
case SpellEffect::IncreaseBlockChance:
case SpellEffect::Accuracy:
case SpellEffect::DamageShield:
case SpellEffect::SpellDamageShield:
case SpellEffect::ReverseDS: {
aggro_amount += mob_level * 2;
break;
}
// unsure -- leave them this for now
case SE_CurrentMana:
case SE_ManaRegen_v2:
case SE_ManaPool:
case SE_CurrentEndurance: {
case SpellEffect::CurrentMana:
case SpellEffect::ManaRegen_v2:
case SpellEffect::ManaPool:
case SpellEffect::CurrentEndurance: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) {
aggro_amount -= val * 2;
}
break;
}
case SE_CancelMagic:
case SE_DispelDetrimental:
case SE_DispelBeneficial:
case SpellEffect::CancelMagic:
case SpellEffect::DispelDetrimental:
case SpellEffect::DispelBeneficial:
dispel = true;
break;
case SE_ReduceHate:
case SE_InstantHate:
case SpellEffect::ReduceHate:
case SpellEffect::InstantHate:
non_modified_aggro = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
break;
}
@ -1549,8 +1549,8 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib
for (int o = 0; o < EFFECT_COUNT; o++) {
switch (spells[spell_id].effect_id[o]) {
case SE_CurrentHP:
case SE_PercentalHeal:
case SpellEffect::CurrentHP:
case SpellEffect::PercentalHeal:
{
if (heal_possible == 0) {
AggroAmount += 1;
@ -1572,12 +1572,12 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib
AggroAmount += std::max(val, (int64)1);
break;
}
case SE_Rune:
case SpellEffect::Rune:
AggroAmount += CalcSpellEffectValue_formula(spells[spell_id].formula[o],
spells[spell_id].base_value[o], spells[spell_id].max_value[o], GetLevel(), spell_id) * 2;
ignore_default_buff = true;
break;
case SE_HealOverTime:
case SpellEffect::HealOverTime:
AggroAmount += 10;
ignore_default_buff = true;
break;

View File

@ -82,7 +82,7 @@ Json::Value ApiGetPacketStatistics(EQ::Net::WebsocketServerConnection *connectio
auto connection = client->Connection();
auto opts = connection->GetManager()->GetOptions();
auto eqs_stats = connection->GetStats();
auto &stats = eqs_stats.DaybreakStats;
auto &stats = eqs_stats.ReliableStreamStats;
auto now = EQ::Net::Clock::now();
auto sec_since_stats_reset = std::chrono::duration_cast<std::chrono::duration<double>>(
now - stats.created

View File

@ -179,7 +179,7 @@ int Mob::compute_tohit(EQ::skills::SkillType skillinuse)
//SYNC WITH: tune.cpp, mob.h TuneGetTotalToHit
int Mob::GetTotalToHit(EQ::skills::SkillType skill, int chance_mod)
{
if (chance_mod >= 10000) // override for stuff like SE_SkillAttack
if (chance_mod >= 10000) // override for stuff like SpellEffect::SkillAttack
return -1;
// calculate attacker's accuracy
@ -209,7 +209,7 @@ int Mob::GetTotalToHit(EQ::skills::SkillType skill, int chance_mod)
if (atkhit_bonus)
accuracy += round(static_cast<double>(accuracy) * static_cast<double>(atkhit_bonus) * 0.0001);
// 216 Melee Accuracy Amt aka SE_Accuracy -- flat bonus
// 216 Melee Accuracy Amt aka SpellEffect::Accuracy -- flat bonus
accuracy += itembonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] +
aabonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] +
spellbonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] +
@ -224,7 +224,7 @@ int Mob::GetTotalToHit(EQ::skills::SkillType skill, int chance_mod)
if (spellbonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] >= 10000)
return -1;
// 184 Accuracy % aka SE_HitChance -- percentage increase
// 184 Accuracy % aka SpellEffect::HitChance -- percentage increase
auto hit_bonus = itembonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] +
aabonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] +
spellbonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] +
@ -285,7 +285,7 @@ int Mob::compute_defense()
}
//516 SE_AC_Mitigation_Max_Percent
//516 SpellEffect::AC_Mitigation_Max_Percent
auto ac_bonus = itembonuses.AC_Mitigation_Max_Percent + aabonuses.AC_Mitigation_Max_Percent + spellbonuses.AC_Mitigation_Max_Percent;
if (ac_bonus) {
defense += round(static_cast<double>(defense) * static_cast<double>(ac_bonus) * 0.0001);
@ -315,15 +315,15 @@ int Mob::GetTotalDefense()
if (evasion_bonus >= 10000)
return -1;
// 515 SE_AC_Avoidance_Max_Percent
// 515 SpellEffect::AC_Avoidance_Max_Percent
auto ac_aviodance_bonus = itembonuses.AC_Avoidance_Max_Percent + aabonuses.AC_Avoidance_Max_Percent + spellbonuses.AC_Avoidance_Max_Percent;
if (ac_aviodance_bonus)
avoidance += round(static_cast<double>(avoidance) * static_cast<double>(ac_aviodance_bonus) * 0.0001);
// 172 Evasion aka SE_AvoidMeleeChance
// 172 Evasion aka SpellEffect::AvoidMeleeChance
evasion_bonus += itembonuses.AvoidMeleeChanceEffect + aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance
// 215 Pet Avoidance % aka SE_PetAvoidance
// 215 Pet Avoidance % aka SpellEffect::PetAvoidance
evasion_bonus += GetPetAvoidanceBonusFromOwner();
// Evasion is a percentage bonus according to AA descriptions
@ -401,8 +401,8 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
*/
/* Order according to current (SoF+?) dev quotes:
* https://forums.daybreakgames.com/eq/index.php?threads/test-update-06-10-15.223510/page-2#post-3261772
* https://forums.daybreakgames.com/eq/index.php?threads/test-update-06-10-15.223510/page-2#post-3268227
* https://web.archive.org/web/20250816014133/https://forums.everquest.com/index.php?threads/test-update-06-10-15.223510/page-2#post-3261772
* https://web.archive.org/web/20250816014133/https://forums.everquest.com/index.php?threads/test-update-06-10-15.223510/page-2#post-3268227
* Riposte 50, hDEX, must have weapon/fists, doesn't work on archery/throwing
* Block 25, hDEX, works on archery/throwing, behind block done here if back to attacker base1 is chance
* Parry 45, hDEX, doesn't work on throwing/archery, must be facing target
@ -461,7 +461,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
}
/* Heroic Strikethrough Implementation per Dev Quotes (2018):
* https://forums.daybreakgames.com/eq/index.php?threads/illusions-benefit-neza-10-dodge.246757/#post-3622670
* https://web.archive.org/web/20250816014810/https://forums.everquest.com/index.php?threads/illusions-benefit-neza-10-dodge.246757/#post-3622670
* Step1 = HeroicStrikethrough(NPC)
* Step2 = HeroicAgility / 25
* Step3 = MIN( Step1, Step2 )
@ -896,7 +896,7 @@ int Mob::GetClassRaceACBonus()
ac_bonus = 16;
}
if (GetRace() == IKSAR)
if (GetRace() == Race::Iksar)
ac_bonus += EQ::Clamp(static_cast<int>(level), 10, 35);
return ac_bonus;
@ -1917,7 +1917,7 @@ bool Client::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::Skil
dead = true;
if (m_pet && m_pet->IsCharmed()) {
m_pet->BuffFadeByEffect(SE_Charm);
m_pet->BuffFadeByEffect(SpellEffect::Charm);
}
if (GetMerc()) {
@ -3414,7 +3414,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
uint8 Mob::GetWeaponDamageBonus(const EQ::ItemData *weapon, bool offhand)
{
// dev quote with old and new formulas
// https://forums.daybreakgames.com/eq/index.php?threads/test-update-09-17-15.226618/page-5#post-3326194
// https://web.archive.org/web/20250816013618/https://forums.everquest.com/index.php?threads/test-update-09-17-15.226618/page-5#post-3326194
//
// We assume that the level check is done before calling this function and sinister strikes is checked before
// calling for offhand DB
@ -3545,7 +3545,7 @@ int Mob::GetHandToHandDelay(void)
int iksar = 0;
if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 46)
epic = 280;
else if (GetRace() == IKSAR)
else if (GetRace() == Race::Iksar)
iksar = 1;
// the delay bonus from the monk epic scales up to a skill of 280
if (epic >= skill)
@ -3586,8 +3586,8 @@ int Mob::GetHandToHandDelay(void)
return 16;
int level = GetLevel();
if (level > 62)
return GetRace() == IKSAR ? 21 : 20;
return GetRace() == IKSAR ? mnk_iks_delay[level] : mnk_hum_delay[level];
return GetRace() == Race::Iksar ? 21 : 20;
return GetRace() == Race::Iksar ? mnk_iks_delay[level] : mnk_hum_delay[level];
}
else if (GetClass() == Class::Beastlord) {
int level = GetLevel();
@ -3678,7 +3678,7 @@ int64 Mob::ReduceDamage(int64 damage)
return DMG_RUNE;
if (spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] >= 0)
damage = RuneAbsorb(damage, SE_Rune);
damage = RuneAbsorb(damage, SpellEffect::Rune);
if (damage < 1)
return DMG_RUNE;
@ -3805,10 +3805,10 @@ int64 Mob::AffectMagicalDamage(int64 damage, uint16 spell_id, const bool iBuffTi
//Regular runes absorb spell damage (except dots) - Confirmed on live.
if (spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] >= 0)
damage = RuneAbsorb(damage, SE_Rune);
damage = RuneAbsorb(damage, SpellEffect::Rune);
if (spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] && spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_BUFFSLOT] >= 0)
damage = RuneAbsorb(damage, SE_AbsorbMagicAtt);
damage = RuneAbsorb(damage, SpellEffect::AbsorbMagicAtt);
if (damage < 1)
return 0;
@ -4113,11 +4113,11 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
if (IsPet()) {
Mob *owner = GetOwner();
if (owner && owner->IsClient()) {
if (GetPetOrder() == SPO_Sit) {
if (GetPetOrder() == PetOrder::Sit) {
SetPetOrder(GetPreviousPetOrder());
}
// fix GUI sit button to be unpressed and stop sitting regen
owner->CastToClient()->SetPetCommandState(PET_BUTTON_SIT, 0);
owner->CastToClient()->SetPetCommandState(PetButton::Sit, PetButtonState::Off);
SetAppearance(eaStanding);
}
}
@ -4147,12 +4147,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
if (IsClient() && !pet->IsPetStop()) {
// if pet was sitting his new mode is previous setting of
// follow or guard after the battle (live verified)
if (pet->GetPetOrder() == SPO_Sit) {
if (pet->GetPetOrder() == PetOrder::Sit) {
pet->SetPetOrder(pet->GetPreviousPetOrder());
}
// fix GUI sit button to be unpressed and stop sitting regen
CastToClient()->SetPetCommandState(PET_BUTTON_SIT, 0);
CastToClient()->SetPetCommandState(PetButton::Sit, PetButtonState::Off);
pet->SetAppearance(eaStanding);
}
@ -4174,7 +4174,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
damage = ReduceDamage(damage);
LogCombat("Melee Damage reduced to [{}]", damage);
damage = ReduceAllDamage(damage);
TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker);
TryTriggerThreshHold(damage, SpellEffect::TriggerMeleeThreshold, attacker);
CheckNumHitsRemaining(NumHit::IncomingHitSuccess);
}
@ -4199,7 +4199,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.", attacker->GetCleanName());
}
damage = ReduceAllDamage(damage);
TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker);
TryTriggerThreshHold(damage, SpellEffect::TriggerSpellThreshold, attacker);
}
if (IsClient() && CastToClient()->sneaking) {
@ -4314,7 +4314,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
GetCleanName(), /* Message1 */
attacker->GetCleanName() /* Message2 */
);
BuffFadeByEffect(SE_Mez);
BuffFadeByEffect(SpellEffect::Mez);
}
// broken up for readability
@ -4399,12 +4399,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
int bashsave_roll = zone->random.Int(0, 100);
if (bashsave_roll > 98 || bashsave_roll > (55 - stunbash_chance)) {
// did stun -- roll other resists
// SE_FrontalStunResist description says any angle now a days
// SpellEffect::FrontalStunResist description says any angle now a days
int stun_resist2 = spellbonuses.FrontalStunResist + itembonuses.FrontalStunResist +
aabonuses.FrontalStunResist;
if (zone->random.Int(1, 100) > stun_resist2) {
// stun resist 2 failed
// time to check SE_StunResist and mod2 stun resist
// time to check SpellEffect::StunResist and mod2 stun resist
int stun_resist =
spellbonuses.StunResist + itembonuses.StunResist + aabonuses.StunResist;
if (zone->random.Int(0, 100) >= stun_resist) {
@ -5668,7 +5668,7 @@ void Mob::DoRiposte(Mob *defender)
defender->itembonuses.DoubleRiposte;
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
LogCombat("Preforming a double riposted from SE_DoubleRiposte ([{}] percent chance)", DoubleRipChance);
LogCombat("Preforming a double riposted from SpellEffect::DoubleRiposte ([{}] percent chance)", DoubleRipChance);
defender->Attack(this, EQ::invslot::slotPrimary, true);
if (HasDied())
return;
@ -5679,7 +5679,7 @@ void Mob::DoRiposte(Mob *defender)
// Live AA - Double Riposte
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
LogCombat("Preforming a double riposted from SE_GiveDoubleRiposte base1 == 0 ([{}] percent chance)", DoubleRipChance);
LogCombat("Preforming a double riposted from SpellEffect::GiveDoubleRiposte base1 == 0 ([{}] percent chance)", DoubleRipChance);
defender->Attack(this, EQ::invslot::slotPrimary, true);
if (HasDied())
return;
@ -6027,12 +6027,12 @@ void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, b
for (int i = 0; i < EFFECT_COUNT; i++) {
if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) {
if (spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcAttempt || spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcSuccess) {
proc_spell_id = spells[base_spell_id].base_value[i];
ProcMod = static_cast<float>(spells[base_spell_id].limit_value[i]);
}
else if (spells[base_spell_id].effect_id[i] == SE_LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) {
else if (spells[base_spell_id].effect_id[i] == SpellEffect::LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) {
if (CanProc && spells[base_spell_id].base_value[i] == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (zone->random.Roll(final_chance)) {
@ -6071,12 +6071,12 @@ void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, b
ProcMod = 0;
for (int i = 0; i < EFFECT_COUNT; i++) {
if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) {
if (spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcAttempt || spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcSuccess) {
proc_spell_id = spells[base_spell_id].base_value[i];
ProcMod = static_cast<float>(spells[base_spell_id].limit_value[i]);
}
else if (spells[base_spell_id].effect_id[i] == SE_LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) {
else if (spells[base_spell_id].effect_id[i] == SpellEffect::LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) {
if (CanProc && spells[base_spell_id].base_value[i] == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
@ -6133,11 +6133,11 @@ void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, b
limit_value = effect.limit_value;
slot = effect.slot;
if (effect_id == SE_SkillProcAttempt || effect_id == SE_SkillProcSuccess) {
if (effect_id == SpellEffect::SkillProcAttempt || effect_id == SpellEffect::SkillProcSuccess) {
proc_spell_id = base_value;
ProcMod = static_cast<float>(limit_value);
}
else if (effect_id == SE_LimitToSkill && base_value <= EQ::skills::HIGHEST_SKILL) {
else if (effect_id == SpellEffect::LimitToSkill && base_value <= EQ::skills::HIGHEST_SKILL) {
if (CanProc && base_value == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
@ -6300,7 +6300,7 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
int32 Mob::RuneAbsorb(int64 damage, uint16 type)
{
uint32 buff_max = GetMaxTotalSlots();
if (type == SE_Rune) {
if (type == SpellEffect::Rune) {
for (uint32 slot = 0; slot < buff_max; slot++) {
if (slot == spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] && spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)) {
int melee_rune_left = buffs[slot].melee_rune;
@ -6544,7 +6544,7 @@ void Mob::DoShieldDamageOnShielderSpellEffect(Mob* shield_target, int64 hit_dama
return;
}
/*
SPA 463 SE_SHIELD_TARGET
SPA 463 SpellEffect::SHIELD_TARGET
Live description: "Shields your target, taking a percentage of their damage".
Only example spell on live is an NPC who uses it during a raid event "Laurion's Song" expansion. SPA 54492 'Guardian Stance' Described as 100% Melee Shielding
@ -6596,7 +6596,7 @@ void Mob::CommonBreakInvisibleFromCombat()
CancelSneakHide();
if (spellbonuses.NegateIfCombat) {
BuffFadeByEffect(SE_NegateIfCombat);
BuffFadeByEffect(SpellEffect::NegateIfCombat);
}
hidden = false;

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,7 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
SetPullingFlag(false);
SetReturningFlag(false);
SetIsUsingItemClick(false);
m_previous_pet_order = SPO_Guard;
m_previous_pet_order = PetOrder::Guard;
rest_timer.Disable();
m_ping_timer.Disable();
@ -232,7 +232,7 @@ Bot::Bot(
SetPullingFlag(false);
SetReturningFlag(false);
SetIsUsingItemClick(false);
m_previous_pet_order = SPO_Guard;
m_previous_pet_order = PetOrder::Guard;
rest_timer.Disable();
m_ping_timer.Disable();
@ -296,8 +296,8 @@ Bot::Bot(
for (int x1 = 0; x1 < EFFECT_COUNT; x1++) {
switch (spell.effect_id[x1]) {
case SE_IllusionCopy:
case SE_Illusion: {
case SpellEffect::IllusionCopy:
case SpellEffect::Illusion: {
if (GetIllusionBlock()) {
break;
}
@ -317,7 +317,7 @@ Bot::Bot(
);
} else if (spell.base_value[x1] == -2) // WTF IS THIS
{
if (GetRace() == IKSAR || GetRace() == VAHSHIR || GetRace() <= GNOME) {
if (GetRace() == Race::Iksar || GetRace() == Race::VahShir || GetRace() <= Race::Gnome) {
SendIllusionPacket(
AppearanceStruct{
.gender_id = GetGender(),
@ -346,27 +346,27 @@ Bot::Bot(
}
switch (spell.base_value[x1]) {
case OGRE:
case Race::Ogre:
SendAppearancePacket(AppearanceType::Size, 9);
break;
case TROLL:
case Race::Troll:
SendAppearancePacket(AppearanceType::Size, 8);
break;
case VAHSHIR:
case BARBARIAN:
case Race::VahShir:
case Race::Barbarian:
SendAppearancePacket(AppearanceType::Size, 7);
break;
case HALF_ELF:
case WOOD_ELF:
case DARK_ELF:
case FROGLOK:
case Race::HalfElf:
case Race::WoodElf:
case Race::DarkElf:
case Race::Froglok2:
SendAppearancePacket(AppearanceType::Size, 5);
break;
case DWARF:
case Race::Dwarf:
SendAppearancePacket(AppearanceType::Size, 4);
break;
case HALFLING:
case GNOME:
case Race::Halfling:
case Race::Gnome:
SendAppearancePacket(AppearanceType::Size, 3);
break;
default:
@ -375,63 +375,63 @@ Bot::Bot(
}
break;
}
case SE_Silence:
case SpellEffect::Silence:
{
Silence(true);
break;
}
case SE_Amnesia:
case SpellEffect::Amnesia:
{
Amnesia(true);
break;
}
case SE_DivineAura:
case SpellEffect::DivineAura:
{
invulnerable = true;
break;
}
case SE_Invisibility2:
case SE_Invisibility:
case SpellEffect::Invisibility2:
case SpellEffect::Invisibility:
{
invisible = true;
SendAppearancePacket(AppearanceType::Invisibility, 1);
break;
}
case SE_Levitate:
case SpellEffect::Levitate:
{
if (!zone->CanLevitate())
{
SendAppearancePacket(AppearanceType::FlyMode, 0);
BuffFadeByEffect(SE_Levitate);
BuffFadeByEffect(SpellEffect::Levitate);
}
else {
SendAppearancePacket(AppearanceType::FlyMode, 2);
}
break;
}
case SE_InvisVsUndead2:
case SE_InvisVsUndead:
case SpellEffect::InvisVsUndead2:
case SpellEffect::InvisVsUndead:
{
invisible_undead = true;
break;
}
case SE_InvisVsAnimals:
case SpellEffect::InvisVsAnimals:
{
invisible_animals = true;
break;
}
case SE_AddMeleeProc:
case SE_WeaponProc:
case SpellEffect::AddMeleeProc:
case SpellEffect::WeaponProc:
{
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel);
break;
}
case SE_DefensiveProc:
case SpellEffect::DefensiveProc:
{
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid);
break;
}
case SE_RangedProc:
case SpellEffect::RangedProc:
{
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid);
break;
@ -457,10 +457,10 @@ Bot::Bot(
int resurrection_sickness_spell_id = (
RuleB(Bots, OldRaceRezEffects) &&
(
GetRace() == BARBARIAN ||
GetRace() == DWARF ||
GetRace() == TROLL ||
GetRace() == OGRE
GetRace() == Race::Barbarian ||
GetRace() == Race::Dwarf ||
GetRace() == Race::Troll ||
GetRace() == Race::Ogre
) ?
RuleI(Bots, OldResurrectionSicknessSpell) :
RuleI(Bots, ResurrectionSicknessSpell)
@ -955,9 +955,9 @@ void Bot::GenerateBaseStats()
float BotSize = GetSize();
switch(GetRace()) {
case HUMAN: // Humans have no race bonus
case Race::Human: // Humans have no race bonus
break;
case BARBARIAN:
case Race::Barbarian:
Strength += 28;
Stamina += 20;
Agility += 7;
@ -968,7 +968,7 @@ void Bot::GenerateBaseStats()
BotSize = 7.0;
ColdResist += 10;
break;
case ERUDITE:
case Race::Erudite:
Strength -= 15;
Stamina -= 5;
Agility -= 5;
@ -979,7 +979,7 @@ void Bot::GenerateBaseStats()
MagicResist += 5;
DiseaseResist -= 5;
break;
case WOOD_ELF:
case Race::WoodElf:
Strength -= 10;
Stamina -= 10;
Agility += 20;
@ -987,7 +987,7 @@ void Bot::GenerateBaseStats()
Wisdom += 5;
BotSize = 5.0;
break;
case HIGH_ELF:
case Race::HighElf:
Strength -= 20;
Stamina -= 10;
Agility += 10;
@ -996,7 +996,7 @@ void Bot::GenerateBaseStats()
Intelligence += 12;
Charisma += 5;
break;
case DARK_ELF:
case Race::DarkElf:
Strength -= 15;
Stamina -= 10;
Agility += 15;
@ -1005,7 +1005,7 @@ void Bot::GenerateBaseStats()
Charisma -= 15;
BotSize = 5.0;
break;
case HALF_ELF:
case Race::HalfElf:
Strength -= 5;
Stamina -= 5;
Agility += 15;
@ -1013,7 +1013,7 @@ void Bot::GenerateBaseStats()
Wisdom -= 15;
BotSize = 5.5;
break;
case DWARF:
case Race::Dwarf:
Strength += 15;
Stamina += 15;
Agility -= 5;
@ -1025,7 +1025,7 @@ void Bot::GenerateBaseStats()
MagicResist -= 5;
PoisonResist += 5;
break;
case TROLL:
case Race::Troll:
Strength += 33;
Stamina += 34;
Agility += 8;
@ -1035,7 +1035,7 @@ void Bot::GenerateBaseStats()
BotSize = 8.0;
FireResist -= 20;
break;
case OGRE:
case Race::Ogre:
Strength += 55;
Stamina += 77;
Agility -= 5;
@ -1045,7 +1045,7 @@ void Bot::GenerateBaseStats()
Charisma -= 38;
BotSize = 9.0;
break;
case HALFLING:
case Race::Halfling:
Strength -= 5;
Agility += 20;
Dexterity += 15;
@ -1056,7 +1056,7 @@ void Bot::GenerateBaseStats()
PoisonResist += 5;
DiseaseResist += 5;
break;
case GNOME:
case Race::Gnome:
Strength -= 15;
Stamina -= 5;
Agility += 10;
@ -1066,7 +1066,7 @@ void Bot::GenerateBaseStats()
Charisma -= 15;
BotSize = 3.0;
break;
case IKSAR:
case Race::Iksar:
Strength -= 5;
Stamina -= 5;
Agility += 15;
@ -1076,7 +1076,7 @@ void Bot::GenerateBaseStats()
MagicResist -= 5;
FireResist -= 5;
break;
case VAHSHIR:
case Race::VahShir:
Strength += 15;
Agility += 15;
Dexterity -= 5;
@ -1087,7 +1087,7 @@ void Bot::GenerateBaseStats()
MagicResist -= 5;
FireResist -= 5;
break;
case FROGLOK:
case Race::Froglok2:
Strength -= 5;
Stamina += 5;
Agility += 25;
@ -1097,7 +1097,7 @@ void Bot::GenerateBaseStats()
MagicResist -= 5;
FireResist -= 5;
break;
case DRAKKIN:
case Race::Drakkin:
Strength -= 5;
Stamina += 5;
Agility += 10;
@ -1140,7 +1140,7 @@ void Bot::GenerateBaseStats()
void Bot::GenerateAppearance() {
// Randomize facial appearance
int iFace = 0;
if (GetRace() == BARBARIAN) // Barbarian w/Tatoo
if (GetRace() == Race::Barbarian) // Barbarian w/Tatoo
{
iFace = zone->random.Int(0, 79);
}
@ -1152,13 +1152,13 @@ void Bot::GenerateAppearance() {
int iHair = 0;
int iBeard = 0;
int iBeardColor = 1;
if (GetRace() == DRAKKIN) {
if (GetRace() == Race::Drakkin) {
iHair = zone->random.Int(0, 8);
iBeard = zone->random.Int(0, 11);
iBeardColor = zone->random.Int(0, 3);
} else if (GetGender()) {
iHair = zone->random.Int(0, 2);
if (GetRace() == DWARF && zone->random.Int(1, 100) < 50) {
if (GetRace() == Race::Dwarf && zone->random.Int(1, 100) < 50) {
iFace += 10;
}
} else {
@ -1168,7 +1168,7 @@ void Bot::GenerateAppearance() {
}
int iHairColor = 0;
if (GetRace() == DRAKKIN) {
if (GetRace() == Race::Drakkin) {
iHairColor = zone->random.Int(0, 3);
} else {
iHairColor = zone->random.Int(0, 19);
@ -1176,7 +1176,7 @@ void Bot::GenerateAppearance() {
auto iEyeColor1 = (uint8)zone->random.Int(0, 9);
uint8 iEyeColor2 = 0;
if (GetRace() == DRAKKIN) {
if (GetRace() == Race::Drakkin) {
iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11);
} else if (zone->random.Int(1, 100) > 96) {
iEyeColor2 = zone->random.Int(0, 9);
@ -1187,7 +1187,7 @@ void Bot::GenerateAppearance() {
int iHeritage = 0;
int iTattoo = 0;
int iDetails = 0;
if (GetRace() == DRAKKIN) {
if (GetRace() == Race::Drakkin) {
iHeritage = zone->random.Int(0, 6);
iTattoo = zone->random.Int(0, 7);
iDetails = zone->random.Int(0, 7);
@ -1527,7 +1527,7 @@ bool Bot::LoadPet()
auto my_buffs = GetBuffs();
if (buffs_max && my_buffs) {
for (int index = 0; index < buffs_max; ++index) {
if (IsEffectInSpell(my_buffs[index].spellid, SE_Familiar)) {
if (IsEffectInSpell(my_buffs[index].spellid, SpellEffect::Familiar)) {
MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone);
return true;
}
@ -2313,7 +2313,7 @@ void Bot::AI_Process()
bot_owner->SetBotPulling(false);
if (GetPet()) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
GetPet()->CastToNPC()->SaveGuardSpot(true);
}
@ -2569,7 +2569,7 @@ void Bot::DoOutOfCombatChecks(Client* bot_owner, Mob* follow_mob, float leash_di
bot_owner->SetBotPulling(false);
if (GetPet()) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
GetPet()->CastToNPC()->SaveGuardSpot(true);
}
}
@ -3198,7 +3198,7 @@ bool Bot::IsValidTarget(
bot_owner->SetBotPulling(false);
if (GetPet()) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
GetPet()->CastToNPC()->SaveGuardSpot(true);
}
}
@ -3233,7 +3233,7 @@ Mob* Bot::GetBotTarget(Client* bot_owner)
bot_owner->SetBotPulling(false);
if (GetPet()) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
GetPet()->CastToNPC()->SaveGuardSpot(true);
}
}
@ -3269,7 +3269,7 @@ bool Bot::ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_dist
bot_owner->SetBotPulling(false);
if (GetPet()) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
GetPet()->CastToNPC()->SaveGuardSpot(true);
if (HasControllablePet(BotAnimEmpathy::BackOff)) {
@ -3313,7 +3313,7 @@ bool Bot::PullingFlagChecks(Client* bot_owner) {
bot_owner->SetBotPulling(false);
if (GetPet()) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
GetPet()->CastToNPC()->SaveGuardSpot(true);
}
@ -3494,7 +3494,7 @@ Client* Bot::SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint
void Bot::SetOwnerTarget(Client* bot_owner) {
if (GetPet() && (PULLING_BOT || RETURNING_BOT)) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
}
SetAttackFlag(false);
@ -3533,7 +3533,7 @@ void Bot::BotPullerProcess(Client* bot_owner, Raid* raid) {
bot_owner->SetBotPulling(false);
if (GetPet()) {
GetPet()->SetPetOrder(SPO_Follow);
GetPet()->SetPetOrder(PetOrder::Follow);
GetPet()->CastToNPC()->SaveGuardSpot(true);
}
@ -3562,7 +3562,7 @@ void Bot::BotPullerProcess(Client* bot_owner, Raid* raid) {
if (HasControllablePet(BotAnimEmpathy::Guard)) {
m_previous_pet_order = GetPet()->GetPetOrder();
GetPet()->CastToNPC()->SaveGuardSpot(GetPosition());
GetPet()->SetPetOrder(SPO_Guard);
GetPet()->SetPetOrder(PetOrder::Guard);
}
}
}
@ -3578,7 +3578,7 @@ void Bot::Depop() {
if (bot_pet) {
if (bot_pet->Charmed()) {
bot_pet->BuffFadeByEffect(SE_Charm);
bot_pet->BuffFadeByEffect(SpellEffect::Charm);
}
else {
bot_pet->Depop();
@ -5404,9 +5404,9 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
case Class::Paladin:
{
bool is_large_race = (
GetBaseRace() == OGRE ||
GetBaseRace() == TROLL ||
GetBaseRace() == BARBARIAN
GetBaseRace() == Race::Ogre ||
GetBaseRace() == Race::Troll ||
GetBaseRace() == Race::Barbarian
);
bool has_bash_skill = GetSkill(EQ::skills::SkillBash) > 0;
bool has_shield_in_secondary =
@ -5974,7 +5974,7 @@ bool Bot::SpellOnTarget(
if (spelltar->IsPet()) {
for (int i = 0; i < EFFECT_COUNT; ++i) {
if (spells[spell_id].effect_id[i] == SE_Illusion) {
if (spells[spell_id].effect_id[i] == SpellEffect::Illusion) {
return false;
}
}
@ -6214,7 +6214,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spe
if (!noGroupSpell) {
for (Mob* m : GetBuffTargets(spellTarget)) {
if (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune)) {
if (IsEffectInSpell(thespell, SpellEffect::AbsorbMagicAtt) || IsEffectInSpell(thespell, SpellEffect::Rune)) {
for (int i = 0; i < m->GetMaxTotalSlots(); i++) {
uint32 buff_count = m->GetMaxTotalSlots();
@ -7831,7 +7831,7 @@ bool Bot::GetNeedsCured(Mob *tar) {
bool need_cured = false;
if (tar) {
if (tar->FindType(SE_PoisonCounter) || tar->FindType(SE_DiseaseCounter) || tar->FindType(SE_CurseCounter) || tar->FindType(SE_CorruptionCounter)) {
if (tar->FindType(SpellEffect::PoisonCounter) || tar->FindType(SpellEffect::DiseaseCounter) || tar->FindType(SpellEffect::CurseCounter) || tar->FindType(SpellEffect::CorruptionCounter)) {
uint32 buff_count = tar->GetMaxTotalSlots();
for (unsigned int j = 0; j < buff_count; j++) {
@ -8616,7 +8616,7 @@ void Bot::Escape()
}
void Bot::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls, bool calculate_speed) {
BuffFadeByEffect(SE_Levitate);
BuffFadeByEffect(SpellEffect::Levitate);
if (CheckLosFN(target_x, target_y, target_z, 6.0f) || ignore_los) {
auto p = new EQApplicationPacket(OP_Fling, sizeof(fling_struct));
auto* f = (fling_struct*) p->pBuffer;
@ -9553,9 +9553,9 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck
if (spells[spell_id].target_type == ST_Self && tar != this) {
if (
!IsEffectInSpell(spell_id, SE_SummonCorpse) ||
!IsEffectInSpell(spell_id, SpellEffect::SummonCorpse) ||
(
IsEffectInSpell(spell_id, SE_SummonCorpse) &&
IsEffectInSpell(spell_id, SpellEffect::SummonCorpse) &&
!RuleB(Bots, AllowCommandedSummonCorpse)
)
) {
@ -9667,7 +9667,7 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck
if (
!zone->CanLevitate() &&
IsEffectInSpell(spell_id, SE_Levitate)
IsEffectInSpell(spell_id, SpellEffect::Levitate)
) {
LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} due to !CanLevitate.'", GetCleanName(), GetSpellName(spell_id));
return false;
@ -9907,8 +9907,8 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) {
spell_type != BotSpellTypes::Succor
) &&
(
IsEffectInSpell(spell_id, SE_Teleport) ||
IsEffectInSpell(spell_id, SE_Succor)
IsEffectInSpell(spell_id, SpellEffect::Teleport) ||
IsEffectInSpell(spell_id, SpellEffect::Succor)
)
) {
LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to Teleport.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName());
@ -9918,7 +9918,7 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) {
if (
tar->IsPet() &&
!RuleB(Bots, CanCastIllusionsOnPets) &&
IsEffectInSpell(spell_id, SE_Illusion)
IsEffectInSpell(spell_id, SpellEffect::Illusion)
) {
LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to PetSE_Illusion.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName());
return false;
@ -9962,13 +9962,13 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) {
tar->IsBot() &&
(tar->GetLevel() >= tar->CastToBot()->GetStopMeleeLevel()) &&
(
IsEffectInSpell(spell_id, SE_AttackSpeed) ||
IsEffectInSpell(spell_id, SE_ReverseDS)
IsEffectInSpell(spell_id, SpellEffect::AttackSpeed) ||
IsEffectInSpell(spell_id, SpellEffect::ReverseDS)
) ||
(
SpellEffectsCount(spell_id) == 1 &&
(
IsEffectInSpell(spell_id, SE_ATK) || IsEffectInSpell(spell_id, SE_STR)
IsEffectInSpell(spell_id, SpellEffect::ATK) || IsEffectInSpell(spell_id, SpellEffect::STR)
)
)
) {
@ -9978,11 +9978,11 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) {
break;
case Archetype::Melee:
if (
IsEffectInSpell(spell_id, SE_IncreaseSpellHaste) ||
IsEffectInSpell(spell_id, SE_ManaPool) ||
IsEffectInSpell(spell_id, SE_CastingLevel) ||
IsEffectInSpell(spell_id, SE_ManaRegen_v2) ||
IsEffectInSpell(spell_id, SE_CurrentMana)
IsEffectInSpell(spell_id, SpellEffect::IncreaseSpellHaste) ||
IsEffectInSpell(spell_id, SpellEffect::ManaPool) ||
IsEffectInSpell(spell_id, SpellEffect::CastingLevel) ||
IsEffectInSpell(spell_id, SpellEffect::ManaRegen_v2) ||
IsEffectInSpell(spell_id, SpellEffect::CurrentMana)
) {
LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to Archetype::Melee.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName());
return false;
@ -9997,8 +9997,8 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) {
// Differences for each type
if (spell_type != BotSpellTypes::InCombatBuff) {
if (
IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) ||
IsEffectInSpell(spell_id, SE_Rune)
IsEffectInSpell(spell_id, SpellEffect::AbsorbMagicAtt) ||
IsEffectInSpell(spell_id, SpellEffect::Rune)
) {
for (int i = 0; i < tar->GetMaxTotalSlots(); i++) {
uint32 buff_count = tar->GetMaxTotalSlots();
@ -10026,14 +10026,14 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) {
tar->IsBot() &&
(tar->GetLevel() >= tar->CastToBot()->GetStopMeleeLevel()) &&
(
IsEffectInSpell(spell_id, SE_AttackSpeed) ||
IsEffectInSpell(spell_id, SE_ReverseDS)
IsEffectInSpell(spell_id, SpellEffect::AttackSpeed) ||
IsEffectInSpell(spell_id, SpellEffect::ReverseDS)
) ||
(
SpellEffectsCount(spell_id) == 1 &&
(
IsEffectInSpell(spell_id, SE_ATK) ||
IsEffectInSpell(spell_id, SE_STR)
IsEffectInSpell(spell_id, SpellEffect::ATK) ||
IsEffectInSpell(spell_id, SpellEffect::STR)
)
)
) {
@ -10043,11 +10043,11 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) {
break;
case Archetype::Melee:
if (
IsEffectInSpell(spell_id, SE_IncreaseSpellHaste) ||
IsEffectInSpell(spell_id, SE_ManaPool) ||
IsEffectInSpell(spell_id, SE_CastingLevel) ||
IsEffectInSpell(spell_id, SE_ManaRegen_v2) ||
IsEffectInSpell(spell_id, SE_CurrentMana)
IsEffectInSpell(spell_id, SpellEffect::IncreaseSpellHaste) ||
IsEffectInSpell(spell_id, SpellEffect::ManaPool) ||
IsEffectInSpell(spell_id, SpellEffect::CastingLevel) ||
IsEffectInSpell(spell_id, SpellEffect::ManaRegen_v2) ||
IsEffectInSpell(spell_id, SpellEffect::CurrentMana)
) {
LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to Archetype::Melee.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName());
return false;
@ -10329,7 +10329,7 @@ bool Bot::IsValidMezTarget(Mob* owner, Mob* npc, uint16 spell_id) {
auto npc_buffs = npc->GetBuffs();
for (int i = 0; i < buff_count; i++) {
if (IsDetrimentalSpell(npc_buffs[i].spellid) && IsEffectInSpell(npc_buffs[i].spellid, SE_CurrentHP)) {
if (IsDetrimentalSpell(npc_buffs[i].spellid) && IsEffectInSpell(npc_buffs[i].spellid, SpellEffect::CurrentHP)) {
return false;
}
}
@ -11684,7 +11684,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
return false;
case BotSpellTypes::Root:
case BotSpellTypes::AERoot:
if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SE_Root)) {
if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::Root)) {
return true;
}
@ -11718,7 +11718,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
return false;
case BotSpellTypes::Pet:
if (IsSummonPetSpell(spell_id) || IsEffectInSpell(spell_id, SE_TemporaryPets)) {
if (IsSummonPetSpell(spell_id) || IsEffectInSpell(spell_id, SpellEffect::TemporaryPets)) {
return true;
}
@ -11732,7 +11732,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
return false;
case BotSpellTypes::Snare:
case BotSpellTypes::AESnare:
if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) {
if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::MovementSpeed)) {
return true;
}
@ -11806,7 +11806,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
return false;
case BotSpellTypes::Resurrect:
if (IsEffectInSpell(spell_id, SE_Revive)) {
if (IsEffectInSpell(spell_id, SpellEffect::Revive)) {
return true;
}
@ -11911,14 +11911,14 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
return false;
case BotSpellTypes::ResistBuffs:
case BotSpellTypes::PetResistBuffs:
if (IsResistanceBuffSpell(spell_id) && !IsEffectInSpell(spell_id, SE_DamageShield)) {
if (IsResistanceBuffSpell(spell_id) && !IsEffectInSpell(spell_id, SpellEffect::DamageShield)) {
return true;
}
return false;
case BotSpellTypes::DamageShields:
case BotSpellTypes::PetDamageShields:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_DamageShield)) {
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::DamageShield)) {
return true;
}
@ -11926,7 +11926,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
case BotSpellTypes::Teleport:
if (
IsBeneficialSpell(spell_id) &&
(IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate))
(IsEffectInSpell(spell_id, SpellEffect::Teleport) || IsEffectInSpell(spell_id, SpellEffect::Translocate))
) {
return true;
}
@ -11942,40 +11942,40 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
case BotSpellTypes::Succor:
if (
IsBeneficialSpell(spell_id) &&
IsEffectInSpell(spell_id, SE_Succor)
IsEffectInSpell(spell_id, SpellEffect::Succor)
) {
return true;
}
return false;
case BotSpellTypes::BindAffinity:
if (IsEffectInSpell(spell_id, SE_BindAffinity)) {
if (IsEffectInSpell(spell_id, SpellEffect::BindAffinity)) {
return true;
}
return false;
case BotSpellTypes::Identify:
if (IsEffectInSpell(spell_id, SE_Identify)) {
if (IsEffectInSpell(spell_id, SpellEffect::Identify)) {
return true;
}
return false;
case BotSpellTypes::Levitate:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_Levitate)) {
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::Levitate)) {
return true;
}
return false;
case BotSpellTypes::Rune:
if (IsBeneficialSpell(spell_id) &&
(IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) || IsEffectInSpell(spell_id, SE_Rune))
(IsEffectInSpell(spell_id, SpellEffect::AbsorbMagicAtt) || IsEffectInSpell(spell_id, SpellEffect::Rune))
) {
return true;
}
return false;
case BotSpellTypes::WaterBreathing:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_WaterBreathing)) {
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::WaterBreathing)) {
return true;
}
@ -11983,7 +11983,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
case BotSpellTypes::Size:
if (
IsBeneficialSpell(spell_id) &&
(IsEffectInSpell(spell_id, SE_ModelSize) || IsEffectInSpell(spell_id, SE_ChangeHeight))
(IsEffectInSpell(spell_id, SpellEffect::ModelSize) || IsEffectInSpell(spell_id, SpellEffect::ChangeHeight))
) {
return true;
}
@ -11991,14 +11991,14 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
return false;
case BotSpellTypes::Invisibility:
if (IsBeneficialSpell(spell_id) &&
(IsEffectInSpell(spell_id, SE_SeeInvis) ||IsInvisibleSpell(spell_id))
(IsEffectInSpell(spell_id, SpellEffect::SeeInvis) ||IsInvisibleSpell(spell_id))
) {
return true;
}
return false;
case BotSpellTypes::MovementSpeed:
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) {
if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::MovementSpeed)) {
return true;
}
@ -12007,10 +12007,10 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
if (
IsBeneficialSpell(spell_id) &&
(
IsEffectInSpell(spell_id, SE_GateToHomeCity) ||
IsEffectInSpell(spell_id, SpellEffect::GateToHomeCity) ||
(
teleport_zone.compare("") &&
(IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate))
(IsEffectInSpell(spell_id, SpellEffect::Teleport) || IsEffectInSpell(spell_id, SpellEffect::Translocate))
)
)
) {
@ -12019,7 +12019,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) {
return false;
case BotSpellTypes::SummonCorpse:
if (IsEffectInSpell(spell_id, SE_SummonCorpse)) {
if (IsEffectInSpell(spell_id, SpellEffect::SummonCorpse)) {
return true;
}
@ -12510,15 +12510,15 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe
break;
case CommandedSubTypes::SeeInvis:
if (IsEffectInSpell(spell_id, SE_SeeInvis)) {
if (IsEffectInSpell(spell_id, SpellEffect::SeeInvis)) {
return true;
}
break;
case CommandedSubTypes::Invis:
if (
IsEffectInSpell(spell_id, SE_Invisibility) ||
IsEffectInSpell(spell_id, SE_Invisibility2)
IsEffectInSpell(spell_id, SpellEffect::Invisibility) ||
IsEffectInSpell(spell_id, SpellEffect::Invisibility2)
) {
return true;
}
@ -12526,8 +12526,8 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe
break;
case CommandedSubTypes::InvisUndead:
if (
IsEffectInSpell(spell_id, SE_InvisVsUndead) ||
IsEffectInSpell(spell_id, SE_InvisVsUndead2)
IsEffectInSpell(spell_id, SpellEffect::InvisVsUndead) ||
IsEffectInSpell(spell_id, SpellEffect::InvisVsUndead2)
) {
return true;
}
@ -12535,8 +12535,8 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe
break;
case CommandedSubTypes::InvisAnimals:
if (
IsEffectInSpell(spell_id, SE_InvisVsAnimals) ||
IsEffectInSpell(spell_id, SE_ImprovedInvisAnimals)
IsEffectInSpell(spell_id, SpellEffect::InvisVsAnimals) ||
IsEffectInSpell(spell_id, SpellEffect::ImprovedInvisAnimals)
) {
return true;
}
@ -12545,13 +12545,13 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe
case CommandedSubTypes::Shrink:
if (
(
IsEffectInSpell(spell_id, SE_ModelSize) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ModelSize), GetLevel()) < 100
IsEffectInSpell(spell_id, SpellEffect::ModelSize) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ModelSize), GetLevel()) < 100
)
||
(
IsEffectInSpell(spell_id, SE_ChangeHeight) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ChangeHeight), GetLevel()) < 100
IsEffectInSpell(spell_id, SpellEffect::ChangeHeight) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ChangeHeight), GetLevel()) < 100
)
) {
return true;
@ -12561,13 +12561,13 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe
case CommandedSubTypes::Grow:
if (
(
IsEffectInSpell(spell_id, SE_ModelSize) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ModelSize), GetLevel()) > 100
IsEffectInSpell(spell_id, SpellEffect::ModelSize) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ModelSize), GetLevel()) > 100
)
||
(
IsEffectInSpell(spell_id, SE_ChangeHeight) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ChangeHeight), GetLevel()) > 100
IsEffectInSpell(spell_id, SpellEffect::ChangeHeight) &&
CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ChangeHeight), GetLevel()) > 100
)
) {
return true;
@ -12577,7 +12577,7 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe
case CommandedSubTypes::Selo:
if (
IsBeneficialSpell(spell_id) &&
IsEffectInSpell(spell_id, SE_MovementSpeed) &&
IsEffectInSpell(spell_id, SpellEffect::MovementSpeed) &&
IsBardSong(spell_id)
) {
return true;
@ -13347,7 +13347,7 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) {
if (!GetSpecialAbility(SpecialAbility::MesmerizeImmunity) && IsMesmerizeSpell(spell_id)) {
// check max level for spell
effect_index = GetSpellEffectIndex(spell_id, SE_Mez);
effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Mez);
assert(effect_index >= 0);
// NPCs get to ignore the max level
if (
@ -13359,13 +13359,13 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) {
}
// slow and haste spells
if (GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SE_AttackSpeed)) {
if (GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SpellEffect::AttackSpeed)) {
return true;
}
// client vs client fear
if (!GetSpecialAbility(SpecialAbility::FearImmunity) && IsEffectInSpell(spell_id, SE_Fear)) {
effect_index = GetSpellEffectIndex(spell_id, SE_Fear);
if (!GetSpecialAbility(SpecialAbility::FearImmunity) && IsEffectInSpell(spell_id, SpellEffect::Fear)) {
effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Fear);
if (IsClient() && caster->IsClient() && (caster->CastToClient()->GetGM() == false)) {
LogSpells("Clients cannot fear eachother!");
@ -13389,7 +13389,7 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) {
//let npcs cast whatever charm on anyone
if (!caster->IsNPC()) {
// check level limit of charm spell
effect_index = GetSpellEffectIndex(spell_id, SE_Charm);
effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Charm);
assert(effect_index >= 0);
if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0) {
return true;
@ -13400,8 +13400,8 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) {
if (
GetSpecialAbility(SpecialAbility::SnareImmunity) &&
(
IsEffectInSpell(spell_id, SE_Root) ||
IsEffectInSpell(spell_id, SE_MovementSpeed)
IsEffectInSpell(spell_id, SpellEffect::Root) ||
IsEffectInSpell(spell_id, SpellEffect::MovementSpeed)
)
) {
return true;
@ -13456,6 +13456,6 @@ bool Bot::HasControllablePet(uint8 ranks_required) {
}
return GetClass() != Class::Enchanter ||
GetPet()->GetPetType() != petAnimation ||
GetPet()->GetPetType() != PetType::Animation ||
GetAA(aaAnimationEmpathy) >= ranks_required;
}

View File

@ -46,9 +46,9 @@ void bot_command_beard_color(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF)
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != Race::Dwarf)
fail_type = AFT_GenderRace;
else if (!PlayerAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue))
else if (!RaceAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = AFT_Value;
else
my_bot->SetBeardColor(uvalue);
@ -83,9 +83,9 @@ void bot_command_beard_style(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF)
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != Race::Dwarf)
fail_type = AFT_GenderRace;
else if (!PlayerAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue))
else if (!RaceAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = AFT_Value;
else
my_bot->SetBeard(uvalue);
@ -122,9 +122,9 @@ void bot_command_details(Client *c, const Seperator *sep)
uint32 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (my_bot->GetRace() != DRAKKIN)
if (my_bot->GetRace() != Race::Drakkin)
fail_type = AFT_Race;
else if (!PlayerAppearance::IsValidDetail(my_bot->GetRace(), my_bot->GetGender(), uvalue))
else if (!RaceAppearance::IsValidDetail(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = AFT_Value;
else
my_bot->SetDrakkinDetails(uvalue);
@ -281,7 +281,7 @@ void bot_command_eyes(Client *c, const Seperator *sep)
// eye_bias = 2;
auto fail_type = AFT_None;
if (!PlayerAppearance::IsValidEyeColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) {
if (!RaceAppearance::IsValidEyeColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) {
fail_type = AFT_Value;
}
else {
@ -328,12 +328,12 @@ void bot_command_face(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (!PlayerAppearance::IsValidFace(my_bot->GetRace(), my_bot->GetGender(), uvalue)) {
if (!RaceAppearance::IsValidFace(my_bot->GetRace(), my_bot->GetGender(), uvalue)) {
fail_type = AFT_Value;
}
else {
uint8 old_woad = 0;
if (my_bot->GetRace() == BARBARIAN)
if (my_bot->GetRace() == Race::Barbarian)
old_woad = ((my_bot->GetLuclinFace() / 10) * 10);
my_bot->SetLuclinFace((old_woad + uvalue));
}
@ -368,7 +368,7 @@ void bot_command_hair_color(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (!PlayerAppearance::IsValidHairColor(my_bot->GetRace(), my_bot->GetGender(), uvalue))
if (!RaceAppearance::IsValidHairColor(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = AFT_Value;
else
my_bot->SetHairColor(uvalue);
@ -403,7 +403,7 @@ void bot_command_hairstyle(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (!PlayerAppearance::IsValidHair(my_bot->GetRace(), my_bot->GetGender(), uvalue))
if (!RaceAppearance::IsValidHair(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = AFT_Value;
else
my_bot->SetHairStyle(uvalue);
@ -440,9 +440,9 @@ void bot_command_heritage(Client *c, const Seperator *sep)
uint32 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (my_bot->GetRace() != DRAKKIN)
if (my_bot->GetRace() != Race::Drakkin)
fail_type = AFT_Race;
else if (!PlayerAppearance::IsValidHeritage(my_bot->GetRace(), my_bot->GetGender(), uvalue))
else if (!RaceAppearance::IsValidHeritage(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = AFT_Value;
else
my_bot->SetDrakkinHeritage(uvalue);
@ -479,9 +479,9 @@ void bot_command_tattoo(Client *c, const Seperator *sep)
uint32 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (my_bot->GetRace() != DRAKKIN)
if (my_bot->GetRace() != Race::Drakkin)
fail_type = AFT_Race;
else if (!PlayerAppearance::IsValidTattoo(my_bot->GetRace(), my_bot->GetGender(), uvalue))
else if (!RaceAppearance::IsValidTattoo(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = AFT_Value;
else
my_bot->SetDrakkinTattoo(uvalue);
@ -516,10 +516,10 @@ void bot_command_woad(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = AFT_None;
if (my_bot->GetRace() != BARBARIAN) {
if (my_bot->GetRace() != Race::Barbarian) {
fail_type = AFT_Race;
}
else if (!PlayerAppearance::IsValidWoad(my_bot->GetRace(), my_bot->GetGender(), uvalue)) {
else if (!RaceAppearance::IsValidWoad(my_bot->GetRace(), my_bot->GetGender(), uvalue)) {
fail_type = AFT_Value;
}
else {

View File

@ -455,13 +455,13 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
fmt::format("- You must use a value between 1 and {}.", RuleI(Bots, MaxFollowDistance))
};
p.example_format = { fmt::format("{} [reset]/[set [value]] [actionable]", sep->arg[0]) };
p.examples_one = {
"To set all bots to follow at a distance of 25:",
fmt::format("{} set 25 spawned", sep->arg[0])
p.examples_one = {
"To set all bots to follow at a distance of 25:",
fmt::format("{} set 25 spawned", sep->arg[0])
};
p.examples_two = {
"To check the curret following distance of all bots:",
fmt::format("{} current spawned", sep->arg[0])
p.examples_two = {
"To check the curret following distance of all bots:",
fmt::format("{} current spawned", sep->arg[0])
};
p.examples_three =
{
@ -470,10 +470,10 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
"{} reset byclass {}",
sep->arg[0],
Class::Wizard
)
)
};
p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" };
std::string popup_text = c->SendBotCommandHelpWindow(p);
popup_text = DialogueWindow::Table(popup_text);
@ -483,7 +483,7 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
}
const int ab_mask = ActionableBots::ABM_Type2;
uint32 bfd = RuleI(Bots, DefaultFollowDistance);
bool set_flag = false;
bool current_check = false;
@ -862,7 +862,7 @@ void bot_command_report(Client *c, const Seperator *sep)
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
@ -1057,7 +1057,7 @@ void bot_command_stance(Client *c, const Seperator *sep)
BotCommandHelpParams p;
p.description = { "Change a bot's stance to control the way it behaves." };
p.notes =
p.notes =
{
"- Changing a stance will reset all settings to match that stance type.",
"- Any changes made will only save to that stance for future use.",
@ -1122,29 +1122,29 @@ void bot_command_stance(Client *c, const Seperator *sep)
Stance::AEBurn
)
};
p.example_format =
p.example_format =
{ fmt::format( "{} [current | value]", sep->arg[0]) };
p.examples_one =
{
"To set all bots to BurnAE:",
p.examples_one =
{
"To set all bots to BurnAE:",
fmt::format("{} {} spawned {}",
sep->arg[0],
Stance::Aggressive,
Class::ShadowKnight
)
};
p.examples_two =
{
"To set all Shadowknights to Aggressive:",
p.examples_two =
{
"To set all Shadowknights to Aggressive:",
fmt::format("{} {} byclass {}",
sep->arg[0],
Stance::Aggressive,
Class::ShadowKnight
)
};
p.examples_three = {
"To check the current stances of all bots:",
fmt::format("{} current spawned", sep->arg[0])
p.examples_three = {
"To check the current stances of all bots:",
fmt::format("{} current spawned", sep->arg[0])
};
p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" };
@ -1239,7 +1239,7 @@ void bot_command_stance(Client *c, const Seperator *sep)
database.botdb.LoadBotSettings(bot_iter);
if (
(bot_iter->GetClass() == Class::Warrior || bot_iter->GetClass() == Class::Paladin || bot_iter->GetClass() == Class::ShadowKnight) &&
(bot_iter->GetClass() == Class::Warrior || bot_iter->GetClass() == Class::Paladin || bot_iter->GetClass() == Class::ShadowKnight) &&
(bot_iter->GetBotStance() == Stance::Aggressive)
) {
bot_iter->SetTaunting(true);
@ -1255,7 +1255,7 @@ void bot_command_stance(Client *c, const Seperator *sep)
bot_iter->GetPet()->CastToNPC()->SetTaunting(false);
}
}
bot_iter->Save();
++success_count;
}
@ -1431,7 +1431,7 @@ void bot_command_summon(Client *c, const Seperator *sep)
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
@ -1550,7 +1550,7 @@ void bot_command_toggle_ranged(Client *c, const Seperator *sep)
return;
}
std::string arg1 = sep->arg[1];
int ab_arg = 1;
@ -1712,7 +1712,7 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
return;
}
std::string arg1 = sep->arg[1];
int ab_arg = 1;

View File

@ -245,7 +245,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
if (pet_type == 6 && RuleI(Bots, RequiredMagicianEpicPetItemID) > 0) {
bool has_item = bot_iter->HasBotItem(RuleI(Bots, RequiredMagicianEpicPetItemID)) != INVALID_INDEX;
if (!has_item) {
c->Message(
Chat::Say,
@ -257,7 +257,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
);
continue;
}
}
}
if (current_check) {
@ -313,7 +313,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
continue;
}
if (!IsEffectInSpell(s.SpellId, SE_SummonPet)) {
if (!IsEffectInSpell(s.SpellId, SpellEffect::SummonPet)) {
continue;
}
@ -401,7 +401,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
return;
}
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,

View File

@ -40,7 +40,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_targ
) {
return false;
}
if (
!IsCommandedSpell() &&
zone->random.Int(0, 100) > chance
@ -240,7 +240,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_targ
tar->GetCleanName()
).c_str()
);
InterruptSpell();
}
@ -297,7 +297,7 @@ bool Bot::BotCastMez(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spel
if (AIDoSpellCast(s.SpellIndex, tar, s.ManaCost)) {
if (BotSpellTypeUsesTargetSettings(spell_type)) {
SetCastedSpellType(UINT16_MAX);
if (!IsCommandedSpell()) {
SetBotSpellRecastTimer(spell_type, tar, true);
}
@ -384,7 +384,7 @@ bool Bot::BotCastPet(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spel
int familiar_buff_slot = -1;
if (buffs_max && my_buffs) {
for (int index = 0; index < buffs_max; ++index) {
if (IsEffectInSpell(my_buffs[index].spellid, SE_Familiar)) {
if (IsEffectInSpell(my_buffs[index].spellid, SpellEffect::Familiar)) {
MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone);
familiar_buff_slot = index;
break;
@ -445,11 +445,11 @@ bool Bot::BotCastNuke(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spe
}
if (
!tar->GetSpecialAbility(SpecialAbility::StunImmunity) &&
!tar->GetSpecialAbility(SpecialAbility::StunImmunity) &&
(
IsCommandedSpell() ||
IsCommandedSpell() ||
(!tar->IsStunned() && (zone->random.Int(1, 100) <= stun_chance))
)
)
) {
bot_spell = GetBestBotSpellForStunByTargetType(this, ST_TargetOptional, spell_type, IsAEBotSpellType(spell_type), tar);
}
@ -1173,7 +1173,7 @@ BotSpell Bot::GetBestBotSpellForVeryFastHeal(Bot* caster, Mob* tar, uint16 spell
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP);
for (auto bot_spell_list_itr : bot_spell_list) {
if (
@ -1198,7 +1198,7 @@ BotSpell Bot::GetBestBotSpellForFastHeal(Bot* caster, Mob* tar, uint16 spell_typ
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP);
for (auto bot_spell_list_itr : bot_spell_list) {
if (IsFastHealSpell(bot_spell_list_itr.SpellId) && caster->CastChecks(bot_spell_list_itr.SpellId, tar, spell_type)) {
@ -1222,7 +1222,7 @@ BotSpell Bot::GetBestBotSpellForHealOverTime(Bot* caster, Mob* tar, uint16 spell
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_HealOverTime);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::HealOverTime);
for (auto bot_spell_list_itr : bot_spell_list) {
if (IsHealOverTimeSpell(bot_spell_list_itr.SpellId) && caster->CastChecks(bot_spell_list_itr.SpellId, tar, spell_type)) {
@ -1278,7 +1278,7 @@ BotSpell Bot::GetBestBotSpellForRegularSingleTargetHeal(Bot* caster, Mob* tar, u
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP);
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
if (IsRegularSingleTargetHealSpell(bot_spell_list_itr->SpellId) && caster->CastChecks(bot_spell_list_itr->SpellId, tar, spell_type)) {
@ -1302,7 +1302,7 @@ BotSpell Bot::GetFirstBotSpellForSingleTargetHeal(Bot* caster, Mob* tar, uint16
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP);
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
if (IsRegularSingleTargetHealSpell(bot_spell_list_itr->SpellId) && caster->CastChecks(bot_spell_list_itr->SpellId, tar, spell_type)) {
@ -1329,7 +1329,7 @@ BotSpell Bot::GetBestBotSpellForGroupHeal(Bot* caster, Mob* tar, uint16 spell_ty
return result;
}
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP);
int target_count = 0;
int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type);
@ -1367,7 +1367,7 @@ BotSpell Bot::GetBestBotSpellForGroupHealOverTime(Bot* caster, Mob* tar, uint16
return result;
}
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_HealOverTime);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::HealOverTime);
int target_count = 0;
int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type);
@ -1405,7 +1405,7 @@ BotSpell Bot::GetBestBotSpellForGroupCompleteHeal(Bot* caster, Mob* tar, uint16
return result;
}
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CompleteHeal);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CompleteHeal);
int target_count = 0;
int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type);
@ -1440,7 +1440,7 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* caster, uint16 spell_type) {
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_Mez);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::Mez);
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
if (
@ -1548,7 +1548,7 @@ BotSpell Bot::GetBestBotMagicianPetSpell(Bot* caster, uint16 spell_type) {
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_SummonPet);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::SummonPet);
std::string pet_type = GetBotMagicianPetType(caster);
for(std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
@ -1638,7 +1638,7 @@ std::string Bot::GetBotMagicianPetType(Bot* caster) {
continue;
}
if (!IsEffectInSpell(s.SpellId, SE_SummonPet)) {
if (!IsEffectInSpell(s.SpellId, SpellEffect::SummonPet)) {
continue;
}
@ -1683,7 +1683,7 @@ std::string Bot::GetBotMagicianPetType(Bot* caster) {
if (bot_level >= water_min_level) {
result = std::string("SumWater");
}
found = true;
break;
case SumFire:
@ -1730,7 +1730,7 @@ BotSpell Bot::GetBestBotSpellForNukeByTargetType(Bot* caster, SpellTargetType ta
}
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SE_CurrentHP, target_type);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SpellEffect::CurrentHP, target_type);
for(std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
if (IsPureNukeSpell(bot_spell_list_itr->SpellId) || IsDamageSpell(bot_spell_list_itr->SpellId)) {
@ -1777,7 +1777,7 @@ BotSpell Bot::GetBestBotSpellForStunByTargetType(Bot* caster, SpellTargetType ta
if (caster)
{
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SE_Stun, target_type);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SpellEffect::Stun, target_type);
for(std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr)
{
@ -1835,7 +1835,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* caster, Mob* target,
}
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SE_CurrentHP, ST_Target);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SpellEffect::CurrentHP, ST_Target);
BotSpell first_wizard_magic_nuke_spell_found;
first_wizard_magic_nuke_spell_found.SpellId = 0;
@ -1855,32 +1855,32 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* caster, Mob* target,
}
else if (!select_lure_nuke && IsPureNukeSpell(bot_spell_list_itr->SpellId)) {
if (
((target->GetMR() < target->GetCR()) || (target->GetMR() < target->GetFR())) &&
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) &&
((target->GetMR() < target->GetCR()) || (target->GetMR() < target->GetFR())) &&
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) &&
(spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) &&
caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type)
) {
spell_selected = true;
}
else if (
((target->GetCR() < target->GetMR()) || (target->GetCR() < target->GetFR())) &&
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_COLD) &&
(spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) &&
((target->GetCR() < target->GetMR()) || (target->GetCR() < target->GetFR())) &&
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_COLD) &&
(spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) &&
caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type)
) {
spell_selected = true;
}
else if (
((target->GetFR() < target->GetCR()) || (target->GetFR() < target->GetMR())) &&
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_FIRE) &&
(spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) &&
((target->GetFR() < target->GetCR()) || (target->GetFR() < target->GetMR())) &&
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_FIRE) &&
(spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) &&
caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type)
) {
spell_selected = true;
}
else if (
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) &&
(spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) &&
(GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) &&
(spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) &&
caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type)
) {
first_wizard_magic_nuke_spell_found.SpellId = bot_spell_list_itr->SpellId;
@ -1998,11 +1998,11 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* caster, Mob *tar, uint16 spell
if (
(bot_spell_list[i].type == BotSpellTypes::Debuff || IsResistDebuffSpell(bot_spell_list[i].spellid)) &&
(
(needs_magic_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistMagic) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) ||
(needs_cold_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistCold) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) ||
(needs_fire_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistFire) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) ||
(needs_poison_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistPoison) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) ||
(needs_disease_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistDisease) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll)))
(needs_magic_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistMagic) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) ||
(needs_cold_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistCold) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) ||
(needs_fire_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistFire) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) ||
(needs_poison_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistPoison) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) ||
(needs_disease_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistDisease) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll)))
) &&
!tar->IsImmuneToSpell(bot_spell_list[i].spellid, caster) &&
tar->CanBuffStack(bot_spell_list[i].spellid, caster->GetLevel(), true) >= 0 &&
@ -2033,7 +2033,7 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) {
if (caster) {
std::vector<BotSpell_wPriority> bot_spell_list_itr = GetPrioritizedBotSpellsBySpellType(caster, spell_type, tar);
if (IsGroupBotSpellType(spell_type)) {
int count_needs_cured = 0;
uint16 count_poisoned = 0;
@ -2049,16 +2049,16 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) {
for (Mob* m : (IsGroupBotSpellType(spell_type) ? caster->GetSpellTargetList() : caster->GetSpellTargetList(true))) {
if (caster->GetNeedsCured(m)) {
if (caster->CastChecks(itr->SpellId, m, spell_type, true, IsGroupBotSpellType(spell_type))) {
if (m->FindType(SE_PoisonCounter)) {
if (m->FindType(SpellEffect::PoisonCounter)) {
++count_poisoned;
}
if (m->FindType(SE_DiseaseCounter)) {
if (m->FindType(SpellEffect::DiseaseCounter)) {
++count_diseased;
}
if (m->FindType(SE_CurseCounter)) {
if (m->FindType(SpellEffect::CurseCounter)) {
++count_cursed;
}
if (m->FindType(SE_CorruptionCounter)) {
if (m->FindType(SpellEffect::CorruptionCounter)) {
++count_corrupted;
}
}
@ -2066,10 +2066,10 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) {
}
if (
(count_poisoned >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) ||
(count_diseased >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) ||
(count_cursed >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) ||
(count_corrupted >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter))
(count_poisoned >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::PoisonCounter)) ||
(count_diseased >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::DiseaseCounter)) ||
(count_cursed >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::CurseCounter)) ||
(count_corrupted >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::CorruptionCounter))
) {
result.SpellId = itr->SpellId;
result.SpellIndex = itr->SpellIndex;
@ -2086,10 +2086,10 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) {
}
if (
tar->FindType(SE_PoisonCounter) && IsEffectInSpell(itr->SpellId, SE_PoisonCounter) ||
tar->FindType(SE_DiseaseCounter) && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter) ||
tar->FindType(SE_CurseCounter) && IsEffectInSpell(itr->SpellId, SE_CurseCounter) ||
tar->FindType(SE_CorruptionCounter) && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)
tar->FindType(SpellEffect::PoisonCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::PoisonCounter) ||
tar->FindType(SpellEffect::DiseaseCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::DiseaseCounter) ||
tar->FindType(SpellEffect::CurseCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::CurseCounter) ||
tar->FindType(SpellEffect::CorruptionCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::CorruptionCounter)
) {
result.SpellId = itr->SpellId;
result.SpellIndex = itr->SpellIndex;
@ -2146,13 +2146,13 @@ uint8 Bot::GetChanceToCastBySpellType(uint16 spell_type)
case BotSpellTypes::Dispel:
return RuleI(Bots, PercentChanceToCastDispel);
case BotSpellTypes::InCombatBuff:
return RuleI(Bots, PercentChanceToCastInCombatBuff);
return RuleI(Bots, PercentChanceToCastInCombatBuff);
case BotSpellTypes::HateLine:
return RuleI(Bots, PercentChanceToCastHateLine);
case BotSpellTypes::Mez:
return RuleI(Bots, PercentChanceToCastMez);
return RuleI(Bots, PercentChanceToCastMez);
case BotSpellTypes::Slow:
return RuleI(Bots, PercentChanceToCastSlow);
return RuleI(Bots, PercentChanceToCastSlow);
case BotSpellTypes::Debuff:
return RuleI(Bots, PercentChanceToCastDebuff);
case BotSpellTypes::Cure:
@ -2161,7 +2161,7 @@ uint8 Bot::GetChanceToCastBySpellType(uint16 spell_type)
case BotSpellTypes::GroupCures:
return RuleI(Bots, PercentChanceToCastGroupCure);
case BotSpellTypes::HateRedux:
return RuleI(Bots, PercentChanceToCastHateRedux);
return RuleI(Bots, PercentChanceToCastHateRedux);
case BotSpellTypes::Fear:
return RuleI(Bots, PercentChanceToCastFear);
case BotSpellTypes::RegularHeal:
@ -2758,8 +2758,8 @@ bool Bot::IsValidSpellRange(uint16 spell_id, Mob* tar) {
) {
range = GetAOERange(spell_id);
}
if (RuleB(Bots, EnableBotTGB) && IsTGBCompatibleSpell(spell_id) && IsGroupSpell(spell_id)) {
if (RuleB(Bots, EnableBotTGB) && IsTGBCompatibleSpell(spell_id) && IsGroupSpell(spell_id)) {
range = spells[spell_id].aoe_range;
}
@ -2838,7 +2838,7 @@ BotSpell Bot::GetBestBotSpellForRez(Bot* caster, Mob* target, uint16 spell_type)
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_Revive);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::Revive);
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
if (
@ -2865,7 +2865,7 @@ BotSpell Bot::GetBestBotSpellForCharm(Bot* caster, Mob* target, uint16 spell_typ
result.ManaCost = 0;
if (caster) {
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_Charm);
std::list<BotSpell> bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::Charm);
for (std::list<BotSpell>::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) {
if (

View File

@ -1391,7 +1391,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
}
case ChatChannel_Shout: { /* Shout */
Mob *sender = this;
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft))
sender = GetPet();
entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
@ -1429,7 +1429,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
else if(!RuleB(Chat, ServerWideAuction)) {
Mob *sender = this;
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft))
sender = GetPet();
entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
@ -1476,7 +1476,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
{
Mob *sender = this;
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft))
sender = GetPet();
entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
@ -1606,7 +1606,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
}
Mob* sender = this;
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) {
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft)) {
sender = GetPet();
}
@ -6415,17 +6415,17 @@ void Client::SuspendMinion(int value)
// TODO: These pet command states need to be synced ...
// Will just fix them for now
if (m_ClientVersionBit & EQ::versions::maskUFAndLater) {
SetPetCommandState(PET_BUTTON_SIT, 0);
SetPetCommandState(PET_BUTTON_STOP, 0);
SetPetCommandState(PET_BUTTON_REGROUP, 0);
SetPetCommandState(PET_BUTTON_FOLLOW, 1);
SetPetCommandState(PET_BUTTON_GUARD, 0);
SetPetCommandState(PetButton::Sit, PetButtonState::Off);
SetPetCommandState(PetButton::Stop, PetButtonState::Off);
SetPetCommandState(PetButton::Regroup, PetButtonState::Off);
SetPetCommandState(PetButton::Follow, PetButtonState::On);
SetPetCommandState(PetButton::Guard, PetButtonState::Off);
// Taunt saved on client side for logging on with pet
// In our db for when we zone.
SetPetCommandState(PET_BUTTON_HOLD, 0);
SetPetCommandState(PET_BUTTON_GHOLD, 0);
SetPetCommandState(PET_BUTTON_FOCUS, 0);
SetPetCommandState(PET_BUTTON_SPELLHOLD, 0);
SetPetCommandState(PetButton::Hold, PetButtonState::Off);
SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off);
SetPetCommandState(PetButton::Focus, PetButtonState::Off);
SetPetCommandState(PetButton::SpellHold, PetButtonState::Off);
}
}
else
@ -6906,9 +6906,9 @@ void Client::CheckLDoNHail(NPC* n)
auto pet = GetPet();
if (pet) {
if (pet->GetPetType() == petCharmed) {
pet->BuffFadeByEffect(SE_Charm);
} else if (pet->GetPetType() == petNPCFollow) {
if (pet->GetPetType() == PetType::Charmed) {
pet->BuffFadeByEffect(SpellEffect::Charm);
} else if (pet->GetPetType() == PetType::Follow) {
pet->SetOwnerID(0);
} else {
pet->Depop();
@ -8445,7 +8445,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
merchant->SayString(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6));
} else if (lowestvalue == fmod.race_mod) { // race biggest
// Non-standard race (ex. illusioned to wolf)
if (GetRace() > PLAYER_RACE_COUNT) {
if (!IsPlayerRace(GetRace())) {
messageid = zone->random.Int(1, 3); // these aren't sequential StringIDs :(
switch (messageid) {
case 1:
@ -9450,12 +9450,15 @@ void Client::ProcessAggroMeter()
}
}
void Client::SetPetCommandState(int button, int state)
void Client::SetPetCommandState(uint8 button, uint8 state)
{
auto app = new EQApplicationPacket(OP_PetCommandState, sizeof(PetCommandState_Struct));
auto pcs = (PetCommandState_Struct *)app->pBuffer;
pcs->button_id = button;
pcs->state = state;
auto s = (PetCommandState_Struct*) app->pBuffer;
s->button_id = button;
s->state = state;
FastQueuePacket(&app);
}
@ -10655,7 +10658,7 @@ void Client::MovePCDynamicZone(const std::string& zone_name, int zone_version, b
}
void Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls, bool calculate_speed) {
BuffFadeByEffect(SE_Levitate);
BuffFadeByEffect(SpellEffect::Levitate);
if (CheckLosFN(target_x, target_y, target_z, 6.0f) || ignore_los) {
auto p = new EQApplicationPacket(OP_Fling, sizeof(fling_struct));
auto* f = (fling_struct*) p->pBuffer;
@ -10720,7 +10723,7 @@ std::vector<int> Client::GetLearnableDisciplines(uint8 min_level, uint8 max_leve
continue;
}
if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) {
if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SpellEffect::CHA) {
continue;
}
@ -10791,7 +10794,7 @@ std::vector<int> Client::GetScribeableSpells(uint8 min_level, uint8 max_level) {
continue;
}
if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) {
if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SpellEffect::CHA) {
continue;
}
@ -11433,7 +11436,7 @@ void Client::SummonBaggedItems(uint32 bag_item_id, const std::vector<LootItem>&
return;
}
// todo: maybe some common functions for SE_SummonItem and SE_SummonItemIntoBag
// todo: maybe some common functions for SpellEffect::SummonItem and SpellEffect::SummonItemIntoBag
const EQ::ItemData* bag_item = database.GetItem(bag_item_id);
if (!bag_item)

View File

@ -326,6 +326,7 @@ public:
void TraderStartTrader(const EQApplicationPacket *app);
// void TraderPriceUpdate(const EQApplicationPacket *app);
uint8 WithCustomer(uint16 NewCustomer);
std::vector<uint32> GetKeyRing() { return keyring; }
void KeyRingLoad();
bool KeyRingAdd(uint32 item_id);
bool KeyRingCheck(uint32 item_id);
@ -523,7 +524,7 @@ public:
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
void ReloadExpansionProfileSetting();
void SetPetCommandState(int button, int state);
void SetPetCommandState(uint8 button, uint8 state);
bool AutoAttackEnabled() const { return auto_attack; }
bool AutoFireEnabled() const { return auto_fire; }

View File

@ -693,7 +693,7 @@ int64 Client::CalcManaRegen(bool bCombat)
}
regen += aabonuses.ManaRegen;
// add in + 1 bonus for SE_CompleteHeal, but we don't do anything for it yet?
// add in + 1 bonus for SpellEffect::CompleteHeal, but we don't do anything for it yet?
int item_bonus = itembonuses.ManaRegen; // this is capped already
item_bonus += itembonuses.heroic_mana_regen;
@ -1011,52 +1011,52 @@ int32 Client::CalcMR()
{
//racial bases
switch (GetBaseRace()) {
case HUMAN:
case Race::Human:
MR = 25;
break;
case BARBARIAN:
case Race::Barbarian:
MR = 25;
break;
case ERUDITE:
case Race::Erudite:
MR = 30;
break;
case WOOD_ELF:
case Race::WoodElf:
MR = 25;
break;
case HIGH_ELF:
case Race::HighElf:
MR = 25;
break;
case DARK_ELF:
case Race::DarkElf:
MR = 25;
break;
case HALF_ELF:
case Race::HalfElf:
MR = 25;
break;
case DWARF:
case Race::Dwarf:
MR = 30;
break;
case TROLL:
case Race::Troll:
MR = 25;
break;
case OGRE:
case Race::Ogre:
MR = 25;
break;
case HALFLING:
case Race::Halfling:
MR = 25;
break;
case GNOME:
case Race::Gnome:
MR = 25;
break;
case IKSAR:
case Race::Iksar:
MR = 25;
break;
case VAHSHIR:
case Race::VahShir:
MR = 25;
break;
case FROGLOK:
case Race::Froglok2:
MR = 30;
break;
case DRAKKIN:
case Race::Drakkin:
{
MR = 25;
if (GetDrakkinHeritage() == 2)
@ -1085,52 +1085,52 @@ int32 Client::CalcFR()
{
//racial bases
switch (GetBaseRace()) {
case HUMAN:
case Race::Human:
FR = 25;
break;
case BARBARIAN:
case Race::Barbarian:
FR = 25;
break;
case ERUDITE:
case Race::Erudite:
FR = 25;
break;
case WOOD_ELF:
case Race::WoodElf:
FR = 25;
break;
case HIGH_ELF:
case Race::HighElf:
FR = 25;
break;
case DARK_ELF:
case Race::DarkElf:
FR = 25;
break;
case HALF_ELF:
case Race::HalfElf:
FR = 25;
break;
case DWARF:
case Race::Dwarf:
FR = 25;
break;
case TROLL:
case Race::Troll:
FR = 5;
break;
case OGRE:
case Race::Ogre:
FR = 25;
break;
case HALFLING:
case Race::Halfling:
FR = 25;
break;
case GNOME:
case Race::Gnome:
FR = 25;
break;
case IKSAR:
case Race::Iksar:
FR = 30;
break;
case VAHSHIR:
case Race::VahShir:
FR = 25;
break;
case FROGLOK:
case Race::Froglok2:
FR = 25;
break;
case DRAKKIN:
case Race::Drakkin:
{
FR = 25;
if (GetDrakkinHeritage() == 0)
@ -1171,52 +1171,52 @@ int32 Client::CalcDR()
{
//racial bases
switch (GetBaseRace()) {
case HUMAN:
case Race::Human:
DR = 15;
break;
case BARBARIAN:
case Race::Barbarian:
DR = 15;
break;
case ERUDITE:
case Race::Erudite:
DR = 10;
break;
case WOOD_ELF:
case Race::WoodElf:
DR = 15;
break;
case HIGH_ELF:
case Race::HighElf:
DR = 15;
break;
case DARK_ELF:
case Race::DarkElf:
DR = 15;
break;
case HALF_ELF:
case Race::HalfElf:
DR = 15;
break;
case DWARF:
case Race::Dwarf:
DR = 15;
break;
case TROLL:
case Race::Troll:
DR = 15;
break;
case OGRE:
case Race::Ogre:
DR = 15;
break;
case HALFLING:
case Race::Halfling:
DR = 20;
break;
case GNOME:
case Race::Gnome:
DR = 15;
break;
case IKSAR:
case Race::Iksar:
DR = 15;
break;
case VAHSHIR:
case Race::VahShir:
DR = 15;
break;
case FROGLOK:
case Race::Froglok2:
DR = 15;
break;
case DRAKKIN:
case Race::Drakkin:
{
DR = 15;
if (GetDrakkinHeritage() == 1)
@ -1263,52 +1263,52 @@ int32 Client::CalcPR()
{
//racial bases
switch (GetBaseRace()) {
case HUMAN:
case Race::Human:
PR = 15;
break;
case BARBARIAN:
case Race::Barbarian:
PR = 15;
break;
case ERUDITE:
case Race::Erudite:
PR = 15;
break;
case WOOD_ELF:
case Race::WoodElf:
PR = 15;
break;
case HIGH_ELF:
case Race::HighElf:
PR = 15;
break;
case DARK_ELF:
case Race::DarkElf:
PR = 15;
break;
case HALF_ELF:
case Race::HalfElf:
PR = 15;
break;
case DWARF:
case Race::Dwarf:
PR = 20;
break;
case TROLL:
case Race::Troll:
PR = 15;
break;
case OGRE:
case Race::Ogre:
PR = 15;
break;
case HALFLING:
case Race::Halfling:
PR = 20;
break;
case GNOME:
case Race::Gnome:
PR = 15;
break;
case IKSAR:
case Race::Iksar:
PR = 15;
break;
case VAHSHIR:
case Race::VahShir:
PR = 15;
break;
case FROGLOK:
case Race::Froglok2:
PR = 30;
break;
case DRAKKIN:
case Race::Drakkin:
{
PR = 15;
if (GetDrakkinHeritage() == 3)
@ -1355,52 +1355,52 @@ int32 Client::CalcCR()
{
//racial bases
switch (GetBaseRace()) {
case HUMAN:
case Race::Human:
CR = 25;
break;
case BARBARIAN:
case Race::Barbarian:
CR = 35;
break;
case ERUDITE:
case Race::Erudite:
CR = 25;
break;
case WOOD_ELF:
case Race::WoodElf:
CR = 25;
break;
case HIGH_ELF:
case Race::HighElf:
CR = 25;
break;
case DARK_ELF:
case Race::DarkElf:
CR = 25;
break;
case HALF_ELF:
case Race::HalfElf:
CR = 25;
break;
case DWARF:
case Race::Dwarf:
CR = 25;
break;
case TROLL:
case Race::Troll:
CR = 25;
break;
case OGRE:
case Race::Ogre:
CR = 25;
break;
case HALFLING:
case Race::Halfling:
CR = 25;
break;
case GNOME:
case Race::Gnome:
CR = 25;
break;
case IKSAR:
case Race::Iksar:
CR = 15;
break;
case VAHSHIR:
case Race::VahShir:
CR = 25;
break;
case FROGLOK:
case Race::Froglok2:
CR = 25;
break;
case DRAKKIN:
case Race::Drakkin:
{
CR = 25;
if (GetDrakkinHeritage() == 4)
@ -1482,24 +1482,24 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id)
Bard Spell Effects
Mod uses the highest bonus from either of these for each instrument
SPA 179 SE_AllInstrumentMod is used for instrument spellbonus.______Mod. This applies to ALL instrument mods (Puretones Discipline)
SPA 260 SE_AddSingingMod is used for instrument spellbonus.______Mod. This applies to indiviual instrument mods. (Instrument mastery AA)
SPA 179 SpellEffect::AllInstrumentMod is used for instrument spellbonus.______Mod. This applies to ALL instrument mods (Puretones Discipline)
SPA 260 SpellEffect::AddSingingMod is used for instrument spellbonus.______Mod. This applies to indiviual instrument mods. (Instrument mastery AA)
-Example usage: From AA a value of 4 = 40%
SPA 118 SE_Amplification is a stackable singing mod, on live it exists as both spell and AA bonus (stackable)
SPA 118 SpellEffect::Amplification is a stackable singing mod, on live it exists as both spell and AA bonus (stackable)
- Live Behavior: Amplifcation can be modified by singing mods and amplification itself, thus on the second cast of Amplification you will recieve
the mod from the first cast, this continues until you reach the song mod cap.
SPA 261 SE_SongModCap raises song focus cap (No longer used on live)
SPA 270 SE_BardSongRange increase range of beneficial bard songs (Sionachie's Crescendo)
SPA 261 SpellEffect::SongModCap raises song focus cap (No longer used on live)
SPA 270 SpellEffect::BardSongRange increase range of beneficial bard songs (Sionachie's Crescendo)
SPA 413 SE_FcBaseEffects focus effect that replaced item instrument mods
SPA 413 SpellEffect::FcBaseEffects focus effect that replaced item instrument mods
Issues 10-15-21:
Bonuses are not applied, unless song is stopped and restarted due to pulse keeping it continues. -> Need to recode songs to recast when duration ends.
Formula Live Bards:
mod = (10 + (aabonus.____Mod [SPA 260 AA Instrument Mastery]) + (SE_FcBaseEffect[SPA 413])/10 + (spellbonus.______Mod [SPA 179 Puretone Disc]) + (Amplication [SPA 118])/10
mod = (10 + (aabonus.____Mod [SPA 260 AA Instrument Mastery]) + (SpellEffect::FcBaseEffect[SPA 413])/10 + (spellbonus.______Mod [SPA 179 Puretone Disc]) + (Amplication [SPA 118])/10
TODO: Spell Table Fields that need to be implemented
Field 225 //float base_effects_focus_slope; // -- BASE_EFFECTS_FOCUS_SLOPE
@ -1567,7 +1567,7 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id)
else
effectmod = spellbonuses.singingMod;
if (IsBardSong(spell_id))
effectmod += aabonuses.singingMod + (spellbonuses.Amplification + itembonuses.Amplification + aabonuses.Amplification); //SPA 118 SE_Amplification
effectmod += aabonuses.singingMod + (spellbonuses.Amplification + itembonuses.Amplification + aabonuses.Amplification); //SPA 118 SpellEffect::Amplification
break;
default:
effectmod = 10;
@ -1584,7 +1584,7 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id)
if (effectmodcap) {
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; //SPA 261 SE_SongModCap (not used on live)
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; //SPA 261 SpellEffect::SongModCap (not used on live)
//Incase a negative modifier is used.
if (effectmodcap <= 0) {

View File

@ -671,7 +671,7 @@ void Client::CompleteConnect()
for (int x1 = 0; x1 < EFFECT_COUNT; x1++) {
switch (spell.effect_id[x1]) {
case SE_Illusion: {
case SpellEffect::Illusion: {
if (GetIllusionBlock()) {
break;
}
@ -682,41 +682,41 @@ void Client::CompleteConnect()
}
break;
}
case SE_SummonHorse: {
case SpellEffect::SummonHorse: {
if (RuleB(Character, PreventMountsFromZoning) || !zone->CanCastOutdoor()) {
BuffFadeByEffect(SE_SummonHorse);
BuffFadeByEffect(SpellEffect::SummonHorse);
} else {
SummonHorse(buffs[j1].spellid);
}
break;
}
case SE_Silence:
case SpellEffect::Silence:
{
Silence(true);
break;
}
case SE_Amnesia:
case SpellEffect::Amnesia:
{
Amnesia(true);
break;
}
case SE_DivineAura:
case SpellEffect::DivineAura:
{
invulnerable = true;
break;
}
case SE_Invisibility2:
case SE_Invisibility:
case SpellEffect::Invisibility2:
case SpellEffect::Invisibility:
{
SendAppearancePacket(AppearanceType::Invisibility, Invisibility::Invisible);
break;
}
case SE_Levitate:
case SpellEffect::Levitate:
{
if (!zone->CanLevitate()) {
if (!GetGM()) {
SendAppearancePacket(AppearanceType::FlyMode, 0);
BuffFadeByEffect(SE_Levitate);
BuffFadeByEffect(SpellEffect::Levitate);
Message(Chat::Red, "You can't levitate in this zone.");
break;
}
@ -737,18 +737,18 @@ void Client::CompleteConnect()
break;
}
case SE_AddMeleeProc:
case SE_WeaponProc:
case SpellEffect::AddMeleeProc:
case SpellEffect::WeaponProc:
{
AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
break;
}
case SE_DefensiveProc:
case SpellEffect::DefensiveProc:
{
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
break;
}
case SE_RangedProc:
case SpellEffect::RangedProc:
{
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
break;
@ -955,17 +955,17 @@ void Client::CompleteConnect()
// TODO: load these states
// We at least will set them to the correct state for now
if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) {
SetPetCommandState(PET_BUTTON_SIT, 0);
SetPetCommandState(PET_BUTTON_STOP, 0);
SetPetCommandState(PET_BUTTON_REGROUP, 0);
SetPetCommandState(PET_BUTTON_FOLLOW, 1);
SetPetCommandState(PET_BUTTON_GUARD, 0);
SetPetCommandState(PetButton::Sit, PetButtonState::Off);
SetPetCommandState(PetButton::Stop, PetButtonState::Off);
SetPetCommandState(PetButton::Regroup, PetButtonState::Off);
SetPetCommandState(PetButton::Follow, PetButtonState::On);
SetPetCommandState(PetButton::Guard, PetButtonState::Off);
// Taunt saved on client side for logging on with pet
// In our db for when we zone.
SetPetCommandState(PET_BUTTON_HOLD, 0);
SetPetCommandState(PET_BUTTON_GHOLD, 0);
SetPetCommandState(PET_BUTTON_FOCUS, 0);
SetPetCommandState(PET_BUTTON_SPELLHOLD, 0);
SetPetCommandState(PetButton::Hold, PetButtonState::Off);
SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off);
SetPetCommandState(PetButton::Focus, PetButtonState::Off);
SetPetCommandState(PetButton::SpellHold, PetButtonState::Off);
}
database.LoadAuras(this); // this ends up spawning them so probably safer to load this later (here)
@ -1515,23 +1515,23 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
switch (race)
{
case OGRE:
case Race::Ogre:
size = 9; break;
case TROLL:
case Race::Troll:
size = 8; break;
case VAHSHIR: case BARBARIAN:
case Race::VahShir: case Race::Barbarian:
size = 7; break;
case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN:
case Race::Human: case Race::HighElf: case Race::Erudite: case Race::Iksar: case Race::Drakkin:
size = 6; break;
case HALF_ELF:
case Race::HalfElf:
size = 5.5; break;
case WOOD_ELF: case DARK_ELF: case FROGLOK:
case Race::WoodElf: case Race::DarkElf: case Race::Froglok2:
size = 5; break;
case DWARF:
case Race::Dwarf:
size = 4; break;
case HALFLING:
case Race::Halfling:
size = 3.5; break;
case GNOME:
case Race::Gnome:
size = 3; break;
default:
size = 0;
@ -1713,7 +1713,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (zone->IsPVPZone())
m_pp.pvp = 1;
/* Time entitled on Account: Move to account */
m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440;
m_pp.timeentitledonaccount = CharacterDataRepository::GetTotalTimePlayed(database, AccountID()) / 1440;
/* Reset rest timer if the durations have been lowered in the database */
if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate)))
m_pp.RestTimer = 0;
@ -4259,7 +4259,7 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app)
uint16 SpellID = m->GetSpellIDFromSlot(brrs->SlotID);
if (SpellID && (GetGM() || ((IsBeneficialSpell(SpellID) || IsEffectInSpell(SpellID, SE_BindSight)) && !spells[SpellID].no_remove))) {
if (SpellID && (GetGM() || ((IsBeneficialSpell(SpellID) || IsEffectInSpell(SpellID, SpellEffect::BindSight)) && !spells[SpellID].no_remove))) {
m->BuffFadeBySlot(brrs->SlotID, true);
}
}
@ -5078,7 +5078,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
// Dismount horses when entering water
if (GetHorseId() && RuleB(Character, DismountWater)) {
SetHorseId(0);
BuffFadeByEffect(SE_SummonHorse);
BuffFadeByEffect(SpellEffect::SummonHorse);
}
}
CheckRegionTypeChanges();
@ -7988,7 +7988,7 @@ void Client::Handle_OP_GuildCreate(const EQApplicationPacket *app)
if ((Admin() < RuleI(Guild, PlayerCreationRequiredStatus)) ||
(GetLevel() < RuleI(Guild, PlayerCreationRequiredLevel)) ||
(database.GetTotalTimeEntitledOnAccount(AccountID()) < (unsigned int)RuleI(Guild, PlayerCreationRequiredTime)))
(CharacterDataRepository::GetTotalTimePlayed(database, AccountID()) < (unsigned int)RuleI(Guild, PlayerCreationRequiredTime)))
{
Message(Chat::Red, "Your status, level or time playing on this account are insufficient to use this feature.");
return;
@ -11073,6 +11073,7 @@ void Client::Handle_OP_PDeletePetition(const EQApplicationPacket *app)
return;
}
void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
{
if (app->size != sizeof(PetCommand_Struct)) {
@ -11263,7 +11264,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
// eqlive ignores this command
// we could just remove the charm
// and continue
mypet->BuffFadeByEffect(SE_Charm);
mypet->BuffFadeByEffect(SpellEffect::Charm);
break;
}
else {
@ -11730,7 +11731,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
break;
}
}
void Client::Handle_OP_Petition(const EQApplicationPacket *app)
{
if (app->size <= 1)
@ -13987,7 +13987,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app)
Recast is 3 minutes.
For custom use cases, Mob::ShieldAbility can be used in quests with all parameters being altered. This functional
is also used for SPA 201 SE_PetShield, which functions in a simalar manner with pet shielding owner.
is also used for SPA 201 SpellEffect::PetShield, which functions in a simalar manner with pet shielding owner.
Note: If either the shielder or the shield target die all variables are reset on both.
@ -15749,7 +15749,7 @@ void Client::Handle_OP_TradeSkillRecipeInspect(const EQApplicationPacket* app)
const auto& v = TradeskillRecipeEntriesRepository::GetWhere(
content_db,
fmt::format(
"`recipe_id` = {} AND `componentcount` = 0 AND `successcount` > 0 LIMIT 1",
"`recipe_id` = {} AND `componentcount` = 0 AND `successcount` > 0 ORDER BY `id` ASC LIMIT 1",
s->recipe_id
)
);
@ -16818,6 +16818,7 @@ void Client::RecordStats()
r.endurance_regen = GetEnduranceRegen() - GetSpellBonuses().EnduranceRegen;
r.shielding = GetShielding() - GetSpellBonuses().MeleeMitigation;
r.spell_damage = GetSpellDmg() - GetSpellBonuses().SpellDmg;
r.heal_amount = GetHealAmt() - GetSpellBonuses().HealAmt;
r.spell_shielding = GetSpellShield() - GetSpellBonuses().SpellShield;
r.strikethrough = GetStrikeThrough() - GetSpellBonuses().StrikeThrough;
r.stun_resist = GetStunResist() - GetSpellBonuses().StunResist;

View File

@ -1571,7 +1571,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
if (from_bucket == &m_pp.platinum_shared)
amount_to_add = 0 - amount_to_take;
database.SetSharedPlatinum(AccountID(),amount_to_add);
database.AddSharedPlatinum(AccountID(),amount_to_add);
}
}
else{
@ -1648,7 +1648,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
//#pragma GCC push_options
//#pragma GCC optimize ("O0")
for (int sk = EQ::skills::Skill1HBlunt; sk <= EQ::skills::HIGHEST_SKILL; ++sk) {
if (sk == EQ::skills::SkillTinkering && GetRace() != GNOME) {
if (sk == EQ::skills::SkillTinkering && GetRace() != Race::Gnome) {
gmtrain->skills[sk] = 0; //Non gnomes can't tinker!
} else {
gmtrain->skills[sk] = GetMaxSkillAfterSpecializationRules((EQ::skills::SkillType)sk, MaxSkill((EQ::skills::SkillType)sk, GetClass(), RuleI(Character, MaxLevel)));

View File

@ -3,6 +3,7 @@
#include "../common/types.h"
#include "../common/spdat.h"
#include "../common/emu_constants.h"
#include <cereal/cereal.hpp>
@ -45,55 +46,6 @@ namespace Archetype {
//Maximum distance from a zone point if zone was specified
#define ZONEPOINT_ZONE_RANGE 40000.0f
// Defines based on the RoF2 Client
#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window
#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window
#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window
#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window
#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window
#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window
#define PET_SIT 6 // 0x06 - /pet sit or Pet Window
#define PET_SITDOWN 7 // 0x07 - /pet sit on
#define PET_STANDUP 8 // 0x08 - /pet sit off
#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented
#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented
#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented
#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window
#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on
#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off
#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking
#define PET_HOLD_ON 16 // 0x10 - /pet hold on
#define PET_HOLD_OFF 17 // 0x11 - /pet hold off
#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to
#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on
#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off
#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window
#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on
#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off
#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window
#define PET_FOCUS_ON 25 // 0x19 - /pet focus on
#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off
#define PET_FEIGN 27 // 0x1b - /pet feign
#define PET_BACKOFF 28 // 0x1c - /pet back off
#define PET_GETLOST 29 // 0x1d - /pet get lost
#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet
#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list
#define PET_REGROUP_ON 32 // 0x20 - /pet regroup on, turns on regroup
#define PET_REGROUP_OFF 33 // 0x21 - /pet regroup off, turns off regroup
#define PET_MAXCOMMANDS PET_REGROUP_OFF + 1
// can change the state of these buttons with a packet
#define PET_BUTTON_SIT 0
#define PET_BUTTON_STOP 1
#define PET_BUTTON_REGROUP 2
#define PET_BUTTON_FOLLOW 3
#define PET_BUTTON_GUARD 4
#define PET_BUTTON_TAUNT 5
#define PET_BUTTON_HOLD 6
#define PET_BUTTON_GHOLD 7
#define PET_BUTTON_FOCUS 8
#define PET_BUTTON_SPELLHOLD 9
#define AURA_HARDCAP 2
#define WEAPON_STANCE_TYPE_MAX 2
@ -101,50 +53,50 @@ namespace Archetype {
#define SHIELD_ABILITY_RECAST_TIME 180
typedef enum { //focus types
focusSpellHaste = 1, //@Fc, SPA: 127, SE_IncreaseSpellHaste, On Caster, cast time mod pct, base: pct
focusSpellDuration, //@Fc, SPA: 128, SE_IncreaseSpellDuration, On Caster, spell duration mod pct, base: pct
focusRange, //@Fc, SPA: 129, SE_IncreaseRange, On Caster, spell range mod pct, base: pct
focusReagentCost, //@Fc, SPA: 131, SE_ReduceReagentCost, On Caster, do not consume reagent pct chance, base: min pct, limit: max pct
focusManaCost, //@Fc, SPA: 132, SE_ReduceManaCost, On Caster, reduce mana cost by pct, base: min pct, limt: max pct
focusImprovedHeal, //@Fc, SPA: 125, SE_ImprovedHeal, On Caster, spell healing mod pct, base: min pct, limit: max pct
focusImprovedDamage, //@Fc, SPA: 124, SE_ImprovedDamage, On Caster, spell damage mod pct, base: min pct, limit: max pct
focusImprovedDamage2, //@Fc, SPA: 461, SE_ImprovedDamage2, On Caster, spell damage mod pct, base: min pct, limit: max pct
focusFcDamagePctCrit, //@Fc, SPA: 302, SE_FcDamagePctCrit, On Caster, spell damage mod pct, base: min pct, limit: max pct
focusPetPower, //@Fc, SPA: 167, SE_PetPowerIncrease, On Caster, pet power mod, base: value
focusResistRate, //@Fc, SPA: 126, SE_SpellResistReduction, On Caster, casted spell resist mod pct, base: min pct, limit: max pct
focusSpellHateMod, //@Fc, SPA: 130, SE_SpellHateMod, On Caster, spell hate mod pct, base: min pct, limit: max pct
focusTriggerOnCast, //@Fc, SPA: 339, SE_TriggerOnCast, On Caster, cast on spell use, base: chance pct limit: spellid
focusSpellVulnerability, //@Fc, SPA: 296, SE_FcSpellVulnerability, On Target, spell damage taken mod pct, base: min pct, limit: max pct
focusFcSpellDamagePctIncomingPC, //@Fc, SPA: 483, SE_Fc_Spell_Damage_Pct_IncomingPC, On Target, spell damage taken mod pct, base: min pct, limit: max pct
focusTwincast, //@Fc, SPA: 399, SE_FcTwincast, On Caster, chance cast spell twice, base: chance pct
focusSympatheticProc, //@Fc, SPA: 383, SE_SympatheticProc, On Caster, cast on spell use, base: variable proc chance on cast time, limit: spellid
focusFcDamageAmt, //@Fc, SPA: 286, SE_FcDamageAmt, On Caster, spell damage mod flat amt, base: amt
focusFcDamageAmt2, //@Fc, SPA: 462, SE_FcDamageAmt2, On Caster, spell damage mod flat amt, base: amt
focusFcDamageAmtCrit, //@Fc, SPA: 303, SE_FFcDamageAmtCrit, On Caster, spell damage mod flat amt, base: amt
focusSpellDurByTic, //@Fc, SPA: 287, SE_SpellDurationIncByTic, On Caster, spell buff duration mod, base: tics
focusSwarmPetDuration, //@Fc, SPA: 398, SE_SwarmPetDuration, On Caster, swarm pet duration mod, base: milliseconds
focusReduceRecastTime, //@Fc, SPA: 310, SE_ReduceReuseTimer, On Caster, disc reuse time mod, base: milliseconds
focusBlockNextSpell, //@Fc, SPA: 335, SE_BlockNextSpellFocus, On Caster, chance to block next spell, base: chance
focusFcHealPctIncoming, //@Fc, SPA: 393, SE_FcHealPctIncoming, On Target, heal received mod pct, base: pct
focusFcDamageAmtIncoming, //@Fc, SPA: 297, SE_FcDamageAmtIncoming, On Target, damage taken flat amt, base: amt
focusFcSpellDamageAmtIncomingPC, //@Fc, SPA: 484, SE_Fc_Spell_Damage_Amt_IncomingPC, On Target, damage taken flat amt, base: amt
focusFcCastSpellOnLand, //@Fc, SPA: 481, SE_Fc_Cast_Spell_On_Land, On Target, cast spell if hit by spell, base: chance pct, limit: spellid
focusFcHealAmtIncoming, //@Fc, SPA: 394, SE_FcHealAmtIncoming, On Target, heal received mod flat amt, base: amt
focusFcBaseEffects, //@Fc, SPA: 413, SE_FcBaseEffects, On Caster, base spell effectiveness mod pct, base: pct
focusIncreaseNumHits, //@Fc, SPA: 421, SE_FcIncreaseNumHits, On Caster, numhits mod flat amt, base: amt
focusFcLimitUse, //@Fc, SPA: 420, SE_FcLimitUse, On Caster, numhits mod pct, base: pct
focusFcMute, //@Fc, SPA: 357, SE_FcMute, On Caster, prevents spell casting, base: chance pct
focusFcTimerRefresh, //@Fc, SPA: 389, SE_FcTimerRefresh, On Caster, reset spell recast timer, base: 1
focusFcTimerLockout, //@Fc, SPA: 390, SE_FcTimerLockout, On Caster, set a spell to be on recast timer, base: recast duration milliseconds
focusFcStunTimeMod, //@Fc, SPA: 133, SE_FcStunTimeMod, On Caster, stun time mod pct, base: chance pct
focusFcResistIncoming, //@Fc, SPA: 510, SE_Fc_Resist_Incoming, On Target, resist modifier, base: amt
focusFcAmplifyMod, //@Fc, SPA: 507, SE_Fc_Amplify_Mod, On Caster, damage-heal-dot mod pct, base: pct
focusFcAmplifyAmt, //@Fc, SPA: 508, SE_Fc_Amplify_Amt, On Caster, damage-heal-dot mod flat amt, base: amt
focusFcCastTimeMod2, //@Fc, SPA: 500, SE_Fc_CastTimeMod2, On Caster, cast time mod pct, base: pct
focusFcCastTimeAmt, //@Fc, SPA: 501, SE_Fc_CastTimeAmt, On Caster, cast time mod flat amt, base: milliseconds
focusFcHealPctCritIncoming, //@Fc, SPA: 395, SE_FcHealPctCritIncoming, On Target, spell healing mod pct, base: pct
focusFcHealAmt, //@Fc, SPA: 392, SE_FcHealAmt, On Caster, spell healing mod flat amt, base: amt
focusFcHealAmtCrit, //@Fc, SPA: 396, SE_FcHealAmtCrit, On Caster, spell healing mod flat amt, base: amt
focusSpellHaste = 1, //@Fc, SPA: 127, SpellEffect::IncreaseSpellHaste, On Caster, cast time mod pct, base: pct
focusSpellDuration, //@Fc, SPA: 128, SpellEffect::IncreaseSpellDuration, On Caster, spell duration mod pct, base: pct
focusRange, //@Fc, SPA: 129, SpellEffect::IncreaseRange, On Caster, spell range mod pct, base: pct
focusReagentCost, //@Fc, SPA: 131, SpellEffect::ReduceReagentCost, On Caster, do not consume reagent pct chance, base: min pct, limit: max pct
focusManaCost, //@Fc, SPA: 132, SpellEffect::ReduceManaCost, On Caster, reduce mana cost by pct, base: min pct, limt: max pct
focusImprovedHeal, //@Fc, SPA: 125, SpellEffect::ImprovedHeal, On Caster, spell healing mod pct, base: min pct, limit: max pct
focusImprovedDamage, //@Fc, SPA: 124, SpellEffect::ImprovedDamage, On Caster, spell damage mod pct, base: min pct, limit: max pct
focusImprovedDamage2, //@Fc, SPA: 461, SpellEffect::ImprovedDamage2, On Caster, spell damage mod pct, base: min pct, limit: max pct
focusFcDamagePctCrit, //@Fc, SPA: 302, SpellEffect::FcDamagePctCrit, On Caster, spell damage mod pct, base: min pct, limit: max pct
focusPetPower, //@Fc, SPA: 167, SpellEffect::PetPowerIncrease, On Caster, pet power mod, base: value
focusResistRate, //@Fc, SPA: 126, SpellEffect::SpellResistReduction, On Caster, casted spell resist mod pct, base: min pct, limit: max pct
focusSpellHateMod, //@Fc, SPA: 130, SpellEffect::SpellHateMod, On Caster, spell hate mod pct, base: min pct, limit: max pct
focusTriggerOnCast, //@Fc, SPA: 339, SpellEffect::TriggerOnCast, On Caster, cast on spell use, base: chance pct limit: spellid
focusSpellVulnerability, //@Fc, SPA: 296, SpellEffect::FcSpellVulnerability, On Target, spell damage taken mod pct, base: min pct, limit: max pct
focusFcSpellDamagePctIncomingPC, //@Fc, SPA: 483, SpellEffect::Fc_Spell_Damage_Pct_IncomingPC, On Target, spell damage taken mod pct, base: min pct, limit: max pct
focusTwincast, //@Fc, SPA: 399, SpellEffect::FcTwincast, On Caster, chance cast spell twice, base: chance pct
focusSympatheticProc, //@Fc, SPA: 383, SpellEffect::SympatheticProc, On Caster, cast on spell use, base: variable proc chance on cast time, limit: spellid
focusFcDamageAmt, //@Fc, SPA: 286, SpellEffect::FcDamageAmt, On Caster, spell damage mod flat amt, base: amt
focusFcDamageAmt2, //@Fc, SPA: 462, SpellEffect::FcDamageAmt2, On Caster, spell damage mod flat amt, base: amt
focusFcDamageAmtCrit, //@Fc, SPA: 303, SpellEffect::FFcDamageAmtCrit, On Caster, spell damage mod flat amt, base: amt
focusSpellDurByTic, //@Fc, SPA: 287, SpellEffect::SpellDurationIncByTic, On Caster, spell buff duration mod, base: tics
focusSwarmPetDuration, //@Fc, SPA: 398, SpellEffect::SwarmPetDuration, On Caster, swarm pet duration mod, base: milliseconds
focusReduceRecastTime, //@Fc, SPA: 310, SpellEffect::ReduceReuseTimer, On Caster, disc reuse time mod, base: milliseconds
focusBlockNextSpell, //@Fc, SPA: 335, SpellEffect::BlockNextSpellFocus, On Caster, chance to block next spell, base: chance
focusFcHealPctIncoming, //@Fc, SPA: 393, SpellEffect::FcHealPctIncoming, On Target, heal received mod pct, base: pct
focusFcDamageAmtIncoming, //@Fc, SPA: 297, SpellEffect::FcDamageAmtIncoming, On Target, damage taken flat amt, base: amt
focusFcSpellDamageAmtIncomingPC, //@Fc, SPA: 484, SpellEffect::Fc_Spell_Damage_Amt_IncomingPC, On Target, damage taken flat amt, base: amt
focusFcCastSpellOnLand, //@Fc, SPA: 481, SpellEffect::Fc_Cast_Spell_On_Land, On Target, cast spell if hit by spell, base: chance pct, limit: spellid
focusFcHealAmtIncoming, //@Fc, SPA: 394, SpellEffect::FcHealAmtIncoming, On Target, heal received mod flat amt, base: amt
focusFcBaseEffects, //@Fc, SPA: 413, SpellEffect::FcBaseEffects, On Caster, base spell effectiveness mod pct, base: pct
focusIncreaseNumHits, //@Fc, SPA: 421, SpellEffect::FcIncreaseNumHits, On Caster, numhits mod flat amt, base: amt
focusFcLimitUse, //@Fc, SPA: 420, SpellEffect::FcLimitUse, On Caster, numhits mod pct, base: pct
focusFcMute, //@Fc, SPA: 357, SpellEffect::FcMute, On Caster, prevents spell casting, base: chance pct
focusFcTimerRefresh, //@Fc, SPA: 389, SpellEffect::FcTimerRefresh, On Caster, reset spell recast timer, base: 1
focusFcTimerLockout, //@Fc, SPA: 390, SpellEffect::FcTimerLockout, On Caster, set a spell to be on recast timer, base: recast duration milliseconds
focusFcStunTimeMod, //@Fc, SPA: 133, SpellEffect::FcStunTimeMod, On Caster, stun time mod pct, base: chance pct
focusFcResistIncoming, //@Fc, SPA: 510, SpellEffect::Fc_Resist_Incoming, On Target, resist modifier, base: amt
focusFcAmplifyMod, //@Fc, SPA: 507, SpellEffect::Fc_Amplify_Mod, On Caster, damage-heal-dot mod pct, base: pct
focusFcAmplifyAmt, //@Fc, SPA: 508, SpellEffect::Fc_Amplify_Amt, On Caster, damage-heal-dot mod flat amt, base: amt
focusFcCastTimeMod2, //@Fc, SPA: 500, SpellEffect::Fc_CastTimeMod2, On Caster, cast time mod pct, base: pct
focusFcCastTimeAmt, //@Fc, SPA: 501, SpellEffect::Fc_CastTimeAmt, On Caster, cast time mod flat amt, base: milliseconds
focusFcHealPctCritIncoming, //@Fc, SPA: 395, SpellEffect::FcHealPctCritIncoming, On Target, spell healing mod pct, base: pct
focusFcHealAmt, //@Fc, SPA: 392, SpellEffect::FcHealAmt, On Caster, spell healing mod flat amt, base: amt
focusFcHealAmtCrit, //@Fc, SPA: 396, SpellEffect::FcHealAmtCrit, On Caster, spell healing mod flat amt, base: amt
} focusType; //Any new FocusType needs to be added to the Mob::IsFocus function
#define HIGHEST_FOCUS focusFcHealAmtCrit //Should always be last focusType in enum
@ -617,7 +569,7 @@ struct StatBonuses {
uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill.
int16 NoBreakAESneak; // Percent value
int16 FeignedCastOnChance; // Percent Value
bool PetCommands[PET_MAXCOMMANDS]; // SPA 267
bool PetCommands[PetCommand::Max]; // SPA 267
int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD
int GrantForage; // affects max skill of forage as well as granting non-forage classes forage
int aura_slots;
@ -781,16 +733,6 @@ enum {
GridRandomPath
};
typedef enum {
petFamiliar, //only listens to /pet get lost
petAnimation, //does not listen to any commands
petOther,
petCharmed,
petNPCFollow,
petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands
petNone = 0xFF // not a pet
} PetType;
typedef enum {
SingleTarget, // causes effect to spell_target
AETarget, // causes effect in aerange of target + target
@ -912,6 +854,66 @@ struct DataBucketCache
uint32_t bucket_expires;
};
// Defines based on the RoF2 Client
#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window
#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window
#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window
#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window
#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window
#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window
#define PET_SIT 6 // 0x06 - /pet sit or Pet Window
#define PET_SITDOWN 7 // 0x07 - /pet sit on
#define PET_STANDUP 8 // 0x08 - /pet sit off
#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented
#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented
#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented
#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window
#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on
#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off
#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking
#define PET_HOLD_ON 16 // 0x10 - /pet hold on
#define PET_HOLD_OFF 17 // 0x11 - /pet hold off
#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to
#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on
#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off
#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window
#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on
#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off
#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window
#define PET_FOCUS_ON 25 // 0x19 - /pet focus on
#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off
#define PET_FEIGN 27 // 0x1b - /pet feign
#define PET_BACKOFF 28 // 0x1c - /pet back off
#define PET_GETLOST 29 // 0x1d - /pet get lost
#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet
#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list
#define PET_REGROUP_ON 32 // 0x20 - /pet regroup on, turns on regroup
#define PET_REGROUP_OFF 33 // 0x21 - /pet regroup off, turns off regroup
#define PET_MAXCOMMANDS PET_REGROUP_OFF + 1
// can change the state of these buttons with a packet
#define PET_BUTTON_SIT 0
#define PET_BUTTON_STOP 1
#define PET_BUTTON_REGROUP 2
#define PET_BUTTON_FOLLOW 3
#define PET_BUTTON_GUARD 4
#define PET_BUTTON_TAUNT 5
#define PET_BUTTON_HOLD 6
#define PET_BUTTON_GHOLD 7
#define PET_BUTTON_FOCUS 8
#define PET_BUTTON_SPELLHOLD 9
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath };
typedef enum {
petFamiliar, //only listens to /pet get lost
petAnimation, //does not listen to any commands
petOther,
petCharmed,
petNPCFollow,
petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands
petNone = 0xFF // not a pet
} PetTypeOld;
#endif

View File

@ -263,7 +263,7 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_
chance += itembonuses.CriticalDoTChance + spellbonuses.CriticalDoTChance + aabonuses.CriticalDoTChance;
if (spellbonuses.CriticalDotDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay);
chance += GetDecayEffectValue(spell_id, SpellEffect::CriticalDotDecay);
if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance)
chance = spells[spell_id].override_crit_chance;
@ -429,14 +429,14 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr
critical_chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
if (spellbonuses.CriticalHealDecay) {
critical_chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
critical_chance += GetDecayEffectValue(spell_id, SpellEffect::CriticalHealDecay);
}
}
else {
critical_chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime;
if (spellbonuses.CriticalRegenDecay) {
critical_chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
critical_chance += GetDecayEffectValue(spell_id, SpellEffect::CriticalRegenDecay);
}
}
@ -596,7 +596,7 @@ int32 Mob::GetActSpellCost(uint16 spell_id, int32 cost)
if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS)
continue;
if(IsEffectInSpell(buffs[buffSlot].spellid, SE_ReduceManaCost)) {
if(IsEffectInSpell(buffs[buffSlot].spellid, SpellEffect::ReduceManaCost)) {
if(CalcFocusEffect(focusManaCost, buffs[buffSlot].spellid, spell_id) == 100)
cost = 1;
}
@ -1105,8 +1105,8 @@ void EntityList::AESpell(
IsTargetableAESpell(spell_id) &&
is_detrimental_spell &&
!is_npc &&
!IsEffectInSpell(spell_id, SE_Lull) &&
!IsEffectInSpell(spell_id, SE_Mez)
!IsEffectInSpell(spell_id, SpellEffect::Lull) &&
!IsEffectInSpell(spell_id, SpellEffect::Mez)
) {
max_targets_allowed = RuleI(Spells, TargetedAOEMaxTargets);
} else if (

View File

@ -207,6 +207,9 @@ const char* QuestEventSubroutines[_LargestEventID] = {
"EVENT_AA_LOSS",
"EVENT_SPELL_BLOCKED",
"EVENT_READ_ITEM",
"EVENT_PET_COMMAND",
"EVENT_CHARM_START",
"EVENT_CHARM_END",
// Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT",
@ -998,11 +1001,13 @@ int PerlembParser::SendCommands(
int ret_value = 0;
RunningQuest q;
q.owner = other;
q.questitem = inst;
q.questspell = spell;
if (mob && mob->IsClient()) {
q.owner = other;
q.initiator = mob->CastToClient();
q.questitem = inst;
q.questspell = spell;
}
if (zone) {
@ -2530,6 +2535,12 @@ void PerlembParser::ExportEventVariables(
break;
}
case EVENT_PET_COMMAND: {
ExportVar(package_name.c_str(), "pet_command", extra_data);
ExportVar(package_name.c_str(), "pet_command_name", data);
break;
}
default: {
break;
}

View File

@ -6039,6 +6039,16 @@ perl::array Perl__get_timers(Mob* m)
return a;
}
std::string Perl__get_pet_command_name(uint8 pet_command)
{
return PetCommand::GetName(pet_command);
}
std::string Perl__get_pet_type_name(uint8 pet_type)
{
return PetType::GetName(pet_type);
}
void perl_register_quest()
{
perl::interpreter perl(PERL_GET_THX);
@ -6729,6 +6739,8 @@ void perl_register_quest()
package.add("getgroupidbycharid", &Perl__getgroupidbycharid);
package.add("getinventoryslotname", &Perl__getinventoryslotname);
package.add("get_paused_timers", &Perl__get_paused_timers);
package.add("get_pet_command_name", &Perl__get_pet_command_name);
package.add("get_pet_type_name", &Perl__get_pet_type_name);
package.add("getraididbycharid", &Perl__getraididbycharid);
package.add("get_race_bitmask", &Perl__get_race_bitmask);
package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs);

View File

@ -56,8 +56,6 @@ extern volatile bool is_zone_loaded;
extern WorldServer worldserver;
extern uint32 numclients;
extern char errorname[32];
Entity::Entity()
{
id = 0;
@ -1391,7 +1389,7 @@ void EntityList::SendZoneSpawnsBulk(Client *client)
bool is_delayed_packet = (
DistanceSquared(client_position, spawn_position) > distance_max ||
(spawn->IsClient() && (spawn->GetRace() == MINOR_ILL_OBJ || spawn->GetRace() == TREE))
(spawn->IsClient() && (spawn->GetRace() == Race::MinorIllusion || spawn->GetRace() == Race::Tree))
);
if (is_delayed_packet) {
@ -1415,7 +1413,7 @@ void EntityList::SendZoneSpawnsBulk(Client *client)
*
* Illusion races on PCs don't work as a mass spawn
* But they will work as an add_spawn AFTER CLIENT_CONNECTED.
* if (spawn->IsClient() && (race == MINOR_ILL_OBJ || race == TREE)) {
* if (spawn->IsClient() && (race == Race::MinorIllusion || race == Race::Tree)) {
* app = new EQApplicationPacket;
* spawn->CreateSpawnPacket(app);
* client->QueuePacket(app, true, Client::CLIENT_CONNECTED);

View File

@ -145,6 +145,9 @@ typedef enum {
EVENT_AA_LOSS,
EVENT_SPELL_BLOCKED,
EVENT_READ_ITEM,
EVENT_PET_COMMAND,
EVENT_CHARM_START,
EVENT_CHARM_END,
// Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT,

View File

@ -130,7 +130,7 @@ uint64 Client::CalcEXP(uint8 consider_level, bool ignore_modifiers) {
if (
GetClass() == Class::Warrior ||
GetClass() == Class::Rogue ||
GetBaseRace() == HALFLING
GetBaseRace() == Race::Halfling
) {
total_modifier *= 1.05;
}
@ -291,7 +291,7 @@ void Client::CalculateStandardAAExp(uint64 &add_aaxp, uint8 conlevel, bool resex
// Shouldn't race not affect AA XP?
if (RuleB(Character, UseRaceClassExpBonuses))
{
if (GetBaseRace() == HALFLING) {
if (GetBaseRace() == Race::Halfling) {
aatotalmod *= 1.05;
}
@ -439,7 +439,7 @@ void Client::CalculateExp(uint64 in_add_exp, uint64 &add_exp, uint64 &add_aaxp,
if (RuleB(Character, UseRaceClassExpBonuses))
{
if (GetBaseRace() == HALFLING) {
if (GetBaseRace() == Race::Halfling) {
totalmod *= 1.05;
}
@ -1057,13 +1057,13 @@ uint32 Client::GetEXPForLevel(uint16 check_level)
if(RuleB(Character,UseOldRaceExpPenalties))
{
float racemod = 1.0;
if(GetBaseRace() == TROLL || GetBaseRace() == IKSAR) {
if(GetBaseRace() == Race::Troll || GetBaseRace() == Race::Iksar) {
racemod = 1.2;
} else if(GetBaseRace() == OGRE) {
} else if(GetBaseRace() == Race::Ogre) {
racemod = 1.15;
} else if(GetBaseRace() == BARBARIAN) {
} else if(GetBaseRace() == Race::Barbarian) {
racemod = 1.05;
} else if(GetBaseRace() == HALFLING) {
} else if(GetBaseRace() == Race::Halfling) {
racemod = 0.95;
}

View File

@ -365,7 +365,7 @@ void Mob::CalculateNewFearpoint()
// fallback logic if pathing system can't be used
bool inliquid = zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(GetPosition())) || zone->IsWaterZone(GetZ());
bool stay_inliquid = (inliquid && IsNPC() && CastToNPC()->IsUnderwaterOnly());
bool levitating = IsClient() && (FindType(SE_Levitate) || flymode != GravityBehavior::Ground);
bool levitating = IsClient() && (FindType(SpellEffect::Levitate) || flymode != GravityBehavior::Ground);
bool open_outdoor_zone = !zone->CanCastOutdoor() && !zone->IsCity();
int loop = 0;

View File

@ -83,7 +83,7 @@ void command_feature(Client *c, const Seperator *sep)
feature_changed = "Beard Color";
value_changed = f.beardcolor;
} else if (is_details) {
if (t->GetRace() != DRAKKIN) {
if (t->GetRace() != Race::Drakkin) {
c->Message(Chat::White, "You must target a Drakkin to use this command.");
return;
}
@ -116,7 +116,7 @@ void command_feature(Client *c, const Seperator *sep)
feature_changed = "Helmet Texture";
value_changed = helm_texture;
} else if (is_heritage) {
if (t->GetRace() != DRAKKIN) {
if (t->GetRace() != Race::Drakkin) {
c->Message(Chat::White, "You must target a Drakkin to use this command.");
return;
}
@ -148,7 +148,7 @@ void command_feature(Client *c, const Seperator *sep)
feature_changed = "Size";
value_changed = size;
} else if (is_tattoo) {
if (t->GetRace() != DRAKKIN) {
if (t->GetRace() != Race::Drakkin) {
c->Message(Chat::White, "You must target a Drakkin to use this command.");
return;
}

View File

@ -1,5 +1,6 @@
#include "../client.h"
#include "find/aa.cpp"
#include "find/account.cpp"
#include "find/body_type.cpp"
#include "find/bot.cpp"
#include "find/bug_category.cpp"
@ -38,6 +39,7 @@ void command_find(Client *c, const Seperator *sep)
std::vector<Cmd> commands = {
Cmd{.cmd = "aa", .u = "aa [Search Criteria]", .fn = FindAA, .a = {"#findaa"}},
Cmd{.cmd = "account", .u = "account [Search Criteria]", .fn = FindAccount, .a = {"#findaccount"}},
Cmd{.cmd = "body_type", .u = "body_type [Search Criteria]", .fn = FindBodyType, .a = {"#findbodytype"}},
Cmd{.cmd = "bug_category", .u = "bug_category [Search Criteria]", .fn = FindBugCategory, .a = {"#findbugcategory"}},
Cmd{.cmd = "character", .u = "character [Search Criteria]", .fn = FindCharacter, .a = {"#findcharacter"}},
@ -72,7 +74,7 @@ void command_find(Client *c, const Seperator *sep)
commands.emplace_back(
Cmd{.cmd = "bot", .u = "bot [Search Criteria]", .fn = FindBot, .a = {"#findbot"}}
);
std::sort(commands.begin(), commands.end(), [](const Cmd& a, const Cmd& b) {
return a.cmd < b.cmd;
});

View File

@ -0,0 +1,50 @@
#include "../../client.h"
#include "../../common/repositories/account_repository.h"
void FindAccount(Client *c, const Seperator *sep)
{
const uint16 arguments = sep->argnum;
if (arguments < 2) {
c->Message(Chat::White, "Usage: #find account [Character Name]");
c->Message(Chat::White, "Note: Used to print the account ID and name of the account a character belongs to.");
return;
}
const std::string& character_name = sep->arg[2];
const auto& e = CharacterDataRepository::FindByName(database, character_name);
if (!e.id) {
c->Message(
Chat::White,
fmt::format(
"Character '{}' does not exist.",
character_name
).c_str()
);
return;
}
auto a = AccountRepository::FindOne(database, e.account_id);
if (!a.id) {
c->Message(
Chat::White,
fmt::format(
"Character '{}' is not attached to an account.",
character_name
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(
"Account {} ({}) owns the character {}.",
a.name,
a.id,
character_name
).c_str()
);
}

View File

@ -110,6 +110,7 @@ void SendNPCEditSubCommands(Client *c)
c->Message(Chat::White, "Usage: #npcedit setanimation [Animation ID] - Sets an NPC's Animation on Spawn (Stored in spawn2 table)");
c->Message(Chat::White, "Usage: #npcedit respawntime [Respawn Time] - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)");
c->Message(Chat::White, "Usage: #npcedit set_grid [Grid ID] - Sets an NPC's Grid ID");
c->Message(Chat::White, "Usage: #npcedit npc_tint_id [NPC Tint ID] - Sets an NPC's Tint ID (0 to 78 for RoF2)");
}
void command_npcedit(Client *c, const Seperator *sep)
@ -1836,4 +1837,4 @@ void command_npcedit(Client *c, const Seperator *sep)
}
c->Message(Chat::White, d.c_str());
}
}

View File

@ -8,7 +8,7 @@ void command_randomfeatures(Client *c, const Seperator *sep)
}
auto target = c->GetTarget();
if (target->RandomizeFeatures()) {
c->Message(
Chat::White,

View File

@ -44,6 +44,19 @@ void SetRace(Client *c, const Seperator *sep)
}
);
if (race_id == Race::Doug) {
c->Message(
Chat::White,
fmt::format(
"{} {} been returned to {} base race.",
c->GetTargetDescription(t, TargetDescriptionType::UCYou),
c == t ? "have" : "has",
c == t ? "your" : "their"
).c_str()
);
return;
}
c->Message(
Chat::White,
fmt::format(

View File

@ -9,7 +9,7 @@ void ShowIPLookup(Client *c, const Seperator *sep)
auto pack = new ServerPacket(
ServerOP_IPLookup,
sizeof(ServerGenericWorldQuery_Struct) + ip_length + 1
sizeof(ServerGenericWorldQuery_Struct) + ip_length
);
auto s = (ServerGenericWorldQuery_Struct *) pack->pBuffer;

View File

@ -16,17 +16,17 @@ void ShowNetwork(Client *c, const Seperator *sep)
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Max Packet Size") +
DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.max_packet_size))
DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.max_packet_size))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Max Connection Count") +
DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.max_connection_count))
DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.max_connection_count))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Keep Alive Delay") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.keepalive_delay_ms))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.keepalive_delay_ms))
);
popup_table += DialogueWindow::TableRow(
@ -34,64 +34,64 @@ void ShowNetwork(Client *c, const Seperator *sep)
DialogueWindow::TableCell(
fmt::format(
"{:.2f}",
opts.daybreak_options.resend_delay_factor
opts.reliable_stream_options.resend_delay_factor
)
)
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Resend Delay") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_delay_ms))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_delay_ms))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Resend Delay Minimum") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_delay_min))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_delay_min))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Resend Delay Maximum") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_delay_max))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_delay_max))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Connect Delay") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.connect_delay_ms))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.connect_delay_ms))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Connect Stale") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.connect_stale_ms))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.connect_stale_ms))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Stale Connection") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.stale_connection_ms))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.stale_connection_ms))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("CRC Length") +
DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.crc_length))
DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.crc_length))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Hold Size") +
DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.hold_size))
DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.hold_size))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Hold Length") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.hold_length_ms))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.hold_length_ms))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Simulated In Packet Loss") +
DialogueWindow::TableCell(std::to_string(opts.daybreak_options.simulated_in_packet_loss))
DialogueWindow::TableCell(std::to_string(opts.reliable_stream_options.simulated_in_packet_loss))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Simulated Out Packet Loss") +
DialogueWindow::TableCell(std::to_string(opts.daybreak_options.simulated_out_packet_loss))
DialogueWindow::TableCell(std::to_string(opts.reliable_stream_options.simulated_out_packet_loss))
);
popup_table += DialogueWindow::TableRow(
@ -99,34 +99,34 @@ void ShowNetwork(Client *c, const Seperator *sep)
DialogueWindow::TableCell(
fmt::format(
"{:.2f}",
opts.daybreak_options.tic_rate_hertz
opts.reliable_stream_options.tic_rate_hertz
)
)
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Resend Timeout") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_timeout))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_timeout))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Connection Close Time") +
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.connection_close_time))
DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.connection_close_time))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Encode Passes (1)") +
DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.encode_passes[0]))
DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.encode_passes[0]))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Encode Passes (2)") +
DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.encode_passes[1]))
DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.encode_passes[1]))
);
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Port") +
DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.port))
DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.port))
);
popup_table = DialogueWindow::Table(popup_table);

View File

@ -7,7 +7,7 @@ void ShowNetworkStats(Client *c, const Seperator *sep)
const auto opts = connection->GetManager()->GetOptions();
const auto eqs_stats = connection->GetStats();
const auto& stats = eqs_stats.DaybreakStats;
const auto& stats = eqs_stats.ReliableStreamStats;
const auto sec_since_stats_reset = std::chrono::duration_cast<std::chrono::duration<double>>(
EQ::Net::Clock::now() - stats.created
@ -217,7 +217,7 @@ void ShowNetworkStats(Client *c, const Seperator *sep)
)
);
if (opts.daybreak_options.outgoing_data_rate > 0.0) {
if (opts.reliable_stream_options.outgoing_data_rate > 0.0) {
popup_table += DialogueWindow::TableRow(
DialogueWindow::TableCell("Outgoing Link Saturation") +
DialogueWindow::TableCell(
@ -229,14 +229,14 @@ void ShowNetworkStats(Client *c, const Seperator *sep)
1.0 -
(
(
opts.daybreak_options.outgoing_data_rate -
opts.reliable_stream_options.outgoing_data_rate -
stats.datarate_remaining
) /
opts.daybreak_options.outgoing_data_rate
opts.reliable_stream_options.outgoing_data_rate
)
)
),
opts.daybreak_options.outgoing_data_rate
opts.reliable_stream_options.outgoing_data_rate
)
)
);

View File

@ -10,7 +10,7 @@ void ShowRecipe(Client *c, const Seperator *sep)
return;
}
const uint16 recipe_id = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[2]));
const uint32 recipe_id = Strings::ToUnsignedInt(sep->arg[2]);
const auto& re = TradeskillRecipeEntriesRepository::GetWhere(
content_db,

View File

@ -4607,26 +4607,32 @@ void Client::SummonItemIntoInventory(
return;
}
const bool is_arrow = inst->GetItem()->ItemType == EQ::item::ItemTypeArrow;
const int16 slot_id = m_inv.FindFreeSlot(
inst->IsClassBag(),
true,
inst->GetItem()->Size,
is_arrow
);
// Try stacking first if the item is stackable, then fall back to finding a free slot
if (!PutItemInInventoryWithStacking(inst)) {
// PutItemInInventoryWithStacking failed, fall back to original behavior
const bool is_arrow = inst->GetItem()->ItemType == EQ::item::ItemTypeArrow;
const int16 slot_id = m_inv.FindFreeSlot(
inst->IsClassBag(),
true,
inst->GetItem()->Size,
is_arrow
);
SummonItem(
item_id,
charges,
aug1,
aug2,
aug3,
aug4,
aug5,
aug6,
is_attuned,
slot_id
);
SummonItem(
item_id,
charges,
aug1,
aug2,
aug3,
aug4,
aug5,
aug6,
is_attuned,
slot_id
);
}
safe_delete(inst);
}
bool Client::HasItemOnCorpse(uint32 item_id)

View File

@ -3608,6 +3608,22 @@ void Lua_Client::EnableTitleSet(uint32 title_set) {
self->EnableTitle(title_set);
}
luabind::object Lua_Client::GetKeyRing(lua_State* L)
{
auto lua_table = luabind::newtable(L);
if (d_) {
auto self = reinterpret_cast<NativeType *>(d_);
int index = 1;
for (const uint32& item_id: self->GetKeyRing()) {
lua_table[index] = item_id;
index++;
}
}
return lua_table;
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@ -3838,6 +3854,7 @@ luabind::scope lua_register_client() {
.def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage)
.def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt)
.def("GetItemCooldown", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetItemCooldown)
.def("GetKeyRing", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetKeyRing)
.def("GetLDoNLosses", (int(Lua_Client::*)(void))&Lua_Client::GetLDoNLosses)
.def("GetLDoNLossesTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNLossesTheme)
.def("GetLDoNPointsTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNPointsTheme)

View File

@ -525,6 +525,7 @@ public:
bool KeyRingRemove(uint32 item_id);
bool CompleteTask(int task_id);
bool UncompleteTask(int task_id);
luabind::object GetKeyRing(lua_State* L);
// account data buckets
void SetAccountBucket(std::string bucket_name, std::string bucket_value);

View File

@ -5701,6 +5701,16 @@ luabind::object lua_get_timers(lua_State* L, Mob* m) {
return t;
}
std::string lua_get_pet_command_name(uint8 pet_command)
{
return PetCommand::GetName(pet_command);
}
std::string lua_get_pet_type_name(uint8 pet_type)
{
return PetType::GetName(pet_type);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@ -6514,6 +6524,8 @@ luabind::scope lua_register_general() {
luabind::def("handin", &lua_handin),
luabind::def("get_paused_timers", &lua_get_paused_timers),
luabind::def("get_timers", &lua_get_timers),
luabind::def("get_pet_command_name", &lua_get_pet_command_name),
luabind::def("get_pet_type_name", &lua_get_pet_type_name),
/*
Cross Zone
*/
@ -6979,7 +6991,10 @@ luabind::scope lua_register_events() {
luabind::value("entity_variable_set", static_cast<int>(EVENT_ENTITY_VARIABLE_SET)),
luabind::value("entity_variable_update", static_cast<int>(EVENT_ENTITY_VARIABLE_UPDATE)),
luabind::value("aa_loss", static_cast<int>(EVENT_AA_LOSS)),
luabind::value("read", static_cast<int>(EVENT_READ_ITEM))
luabind::value("read", static_cast<int>(EVENT_READ_ITEM)),
luabind::value("pet_command", static_cast<int>(EVENT_PET_COMMAND)),
luabind::value("charm_start", static_cast<int>(EVENT_CHARM_START)),
luabind::value("charm_end", static_cast<int>(EVENT_CHARM_END))
)];
}

View File

@ -1241,12 +1241,12 @@ float Lua_Mob::GetAssistRange() {
return self->GetAssistRange();
}
void Lua_Mob::SetPetOrder(int order) {
void Lua_Mob::SetPetOrder(uint8 pet_order) {
Lua_Safe_Call_Void();
self->SetPetOrder(static_cast<Mob::eStandingPetOrder>(order));
self->SetPetOrder(pet_order);
}
int Lua_Mob::GetPetOrder() {
uint8 Lua_Mob::GetPetOrder() {
Lua_Safe_Call_Int();
return self->GetPetOrder();
}
@ -3512,6 +3512,24 @@ luabind::object Lua_Mob::GetTimers(lua_State* L) {
return t;
}
uint8 Lua_Mob::GetPetType()
{
Lua_Safe_Call_Int();
return self->GetPetType();
}
std::string Lua_Mob::GetPetTypeName()
{
Lua_Safe_Call_String();
return PetType::GetName(self->GetPetType());
}
void Lua_Mob::SetPetType(uint8 pet_type)
{
Lua_Safe_Call_Void();
self->SetPetType(pet_type);
}
luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>())
@ -3854,7 +3872,9 @@ luabind::scope lua_register_mob() {
.def("GetPR", &Lua_Mob::GetPR)
.def("GetPausedTimers", &Lua_Mob::GetPausedTimers)
.def("GetPet", &Lua_Mob::GetPet)
.def("GetPetOrder", (int(Lua_Mob::*)(void))&Lua_Mob::GetPetOrder)
.def("GetPetOrder", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetPetOrder)
.def("GetPetType", &Lua_Mob::GetPetType)
.def("GetPetTypeName", &Lua_Mob::GetPetTypeName)
.def("GetPhR", &Lua_Mob::GetPhR)
.def("GetRace", &Lua_Mob::GetRace)
.def("GetRaceName", &Lua_Mob::GetRaceName)
@ -4049,7 +4069,8 @@ luabind::scope lua_register_mob() {
.def("SetMana", &Lua_Mob::SetMana)
.def("SetOOCRegen", (void(Lua_Mob::*)(int64))&Lua_Mob::SetOOCRegen)
.def("SetPet", &Lua_Mob::SetPet)
.def("SetPetOrder", (void(Lua_Mob::*)(int))&Lua_Mob::SetPetOrder)
.def("SetPetOrder", (void(Lua_Mob::*)(uint8))&Lua_Mob::SetPetOrder)
.def("SetPetType", &Lua_Mob::SetPetType)
.def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot)
.def("SetRace", (void(Lua_Mob::*)(uint16))&Lua_Mob::SetRace)
.def("SetRunning", (void(Lua_Mob::*)(bool))&Lua_Mob::SetRunning)

View File

@ -280,8 +280,8 @@ public:
bool IsAIControlled();
float GetAggroRange();
float GetAssistRange();
void SetPetOrder(int order);
int GetPetOrder();
void SetPetOrder(uint8 pet_order);
uint8 GetPetOrder();
bool IsRoamer();
bool IsRooted();
bool IsEngaged();
@ -614,6 +614,9 @@ public:
void BuffFadeSongs();
luabind::object GetPausedTimers(lua_State* L);
luabind::object GetTimers(lua_State* L);
uint8 GetPetType();
std::string GetPetTypeName();
void SetPetType(uint8 pet_type);
};
#endif

View File

@ -945,10 +945,16 @@ bool Lua_NPC::IsResumedFromZoneSuspend()
return self->IsResumedFromZoneSuspend();
}
void Lua_NPC::SetNPCTintIndex(uint32 id)
void Lua_NPC::SetNPCTintIndex(uint32 index)
{
Lua_Safe_Call_Void();
self->SendAppearancePacket(AppearanceType::NPCTintIndex, id);
self->SetNPCTintIndex(index);
}
uint32 Lua_NPC::GetNPCTintIndex()
{
Lua_Safe_Call_Int();
return self->GetNPCTintIndex();
}
luabind::scope lua_register_npc() {
@ -1018,6 +1024,7 @@ luabind::scope lua_register_npc() {
.def("GetNPCSpellsEffectsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsEffectsID)
.def("GetNPCSpellsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID)
.def("GetNPCStat", (float(Lua_NPC::*)(std::string))&Lua_NPC::GetNPCStat)
.def("GetNPCTintIndex", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCTintIndex)
.def("GetPetSpellID", (int(Lua_NPC::*)(void))&Lua_NPC::GetPetSpellID)
.def("GetPlatinum", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetPlatinum)
.def("GetPrimSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetPrimSkill)

View File

@ -200,6 +200,7 @@ public:
Lua_Spawn GetSpawn(lua_State* L);
bool IsResumedFromZoneSuspend();
void SetNPCTintIndex(uint32 id);
uint32 GetNPCTintIndex();
};

View File

@ -188,7 +188,10 @@ const char *LuaEvents[_LargestEventID] = {
"event_entity_variable_update",
"event_aa_loss",
"event_spell_blocked",
"event_read_item"
"event_read_item",
"event_pet_command",
"event_charm_start",
"event_charm_end"
};
extern Zone *zone;
@ -264,6 +267,9 @@ LuaParser::LuaParser() {
NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_SET] = handle_npc_entity_variable;
NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_npc_entity_variable;
NPCArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_npc_spell_blocked;
NPCArgumentDispatch[EVENT_PET_COMMAND] = handle_npc_pet_command;
NPCArgumentDispatch[EVENT_CHARM_START] = handle_npc_single_mob;
NPCArgumentDispatch[EVENT_CHARM_END] = handle_npc_single_mob;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
@ -355,6 +361,7 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_player_spell_blocked;
PlayerArgumentDispatch[EVENT_READ_ITEM] = handle_player_read_item;
PlayerArgumentDispatch[EVENT_CONNECT] = handle_player_connect;
PlayerArgumentDispatch[EVENT_PET_COMMAND] = handle_player_pet_command;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;

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